ERC-721o: a token standard for financial derivatives
Composable Multiclass Fungible Token Standard
It is with great pleasure that we release our open source proposal for token standards for exchange-traded products, such as derivatives and portfolios of financial products. This is part of the Opium Protocol — a universal protocol to create, settle and trade virtually all derivatives and financial instruments in a professional and trustless way. We will release the protocol, front end, and more innovative financial features in the coming weeks.
The need for a new standard
During the development of the universal derivative protocol, the team found that at the moment there is no token standard that allows professional management of derivatives and exchange-traded instruments. We were inspired by the financial markets and created a token standard that can represent such financial instruments. Until now there was no standard that represents exchange-traded products and their features, such as combined orders, portfolio management, and interchangeability within a class. We believe that the blockchain ecosystem is already mature enough for such products: there are solid stablecoins, reliable oracle solutions, and the volumes that are trading in DeFi are growing fast.
Until now, there was no standard that represents exchange-traded products and their features such as combined orders, portfolio management and interchangeability within a class.
An exchange-traded product is a standardised financial instrument that is traded on an organized exchange. Therefore, such products are interchangeable with identical standardised products. Standardisation of products means setting parameters such as underlying asset, price source, maturity, quantity, documentation, and regulation.
From one side, two future contracts on gold with the same standardised parameters are absolutely identical and can be represented by ERC-20 tokens, but they are different from similar futures on, let’s say, silver. From another side, the standardised products with different parameters are different from each other and can be well represented using the ERC-721 token standard. In reality, we need to combine both standards to be able to represent real exchange-traded products.
We have created a standard that enables all kinds of different non-interchangeable tokens, much like ERC-721, where each can be minted in any quantity, and is interchangeable with its “twins”.
We were inspired by the ERC-721x proposal, however, we added more very specific financial features to our standard to perfectly fit it with financial markets and derivatives.
One of the most desired features was to combine financial instruments into portfolios for management, transfers or execution of combined orders. We have implemented this need in our standard as a wrapping function: if you have n-tokens on your balance you can combine them into one portfolio and you can operate it as if it is one token.
One of the most needed features is to combine financial instruments into portfolios for management, transfers or execution of combined orders.
We introduce three portfolio functions:
- compose: creates a portfolio out of tokens
- decompose: recreates tokens out of a portfolio
- recompose: adds/takes several tokens to/from an existing portfolio in a gas efficient way
Once you compose several tokens into a portfolio, it is added to the owner’s account and the corresponding tokens are deleted from the blockchain. When a portfolio is decomposed it is deleted from the blockchain and corresponding tokens are added to the balance of the owner.
It was an interesting question how to save information about tokens that were composed into portfolios. We have chosen an elegant and simple solution:
Technical notes: we simplified the formula here for convenience. Strictly speaking, all tokenIDs should be sorted in ascending order during the composition and recomposition, amounts must be divided by the greatest common divisor, which is then used as a quantity and divided amounts used as a ratio. This is not strictly required in our smart contracts, however, it is part of our standard and it brings consistency to the compose and recompose methods. Different sorting and ratios of tokenIDs result in a different portfolioID. A derivativeID is a unique derivative identifier (hash) of the derivative. See more on our GitHub…
Tokens that are deleted from the blockchain are not stored in any balance anymore and only a hash of that combination is saved on-chain. To decompose the portfolio one will need to send all tokenIDs that belong to this portfolio to decompose function as arguments. The equation (2) will be checked on-chain and in case of success, individual tokens will be created instead of the portfolio token. TokenIDs can be found off-chain with historical analysis of the blockchain or collected from the Ethereum events, but there is no need to store them on the blockchain as long as the total hash is stored.
Another function of the ERC-721o standard is: recompose. New derivative tokens can be added to the existing portfolio tokens, but derivative tokens can also be taken out of the portfolio token. When a user wants to add several tokens to the portfolio to the same layer with other tokens he can use this function. It allows to add or withdraw tokens without consequent decomposition and new composition. This function was introduced to reduce gas costs on composing and decomposing. It calculates the difference between initial and final portfolio compositions, so only the difference is changed and we have more efficient EVM state changes.
There are minting and burning functions which are private (which initially could not be called externally) and their specific use cases depend on token standard implementation. These functions are the only ones that can emit or burn tokens and should be implemented into financial logic of implementation, so no derivatives can be created outside the financial logic of the implementation protocol. In our reference implementation in the Opium Protocol we have introduced several different cases:
- _mint(_tokenId, _to, _quantity)
- _mint(_buyer, _seller, _derivativeHash, _quantity)
- _mintLong(_buyer, _derivativeHash, _quantity)
- _mintShort(_seller, _derivativeHash, _quantity)
- _burn(_tokenOwner, _tokenId, _quantity)
Besides the newly introduced portfolio functions, we inherit several functions from the ERC-721x token standard:
- transferFrom: sends a particular amount of a specific token ID from one address to another
- batchTransferFrom: allows you to send multiple non-identical tokens with different amounts in one transaction
- setApprovalForAll: grants someone else permission to spend any amount of any tokenId on the owner’s behalf
ERC721 Backward compatibility
Even though our proposed standard differs from ERC721, we tried to keep it backwards compatible as much as possible.
- ownerOf() and getApproved() won’t work as expected in the ERC721 token standard, since any tokenId could have many owners and approved accounts. Those functions return zero address if a tokenId does not exist and the address of the Token contract in case it does exist.
- transferFrom() and safeTransferFrom() functions work the same as in ERC721, but under the hood they are transferring aspecific tokenId in amounts of 1.
- approve() grants someone else permission to spend any amount of a specific tokenId on the owner’s behalf
- We have the additional getApproved() function, which also accepts tokenOwner and returns the address, which was approved() by owner
ERC721x Backward compatibility
- NFT-part of ERC721x implementation was removed completely and doesn’t have backward compatibility
- FT-part behaves the same way. All transfer functions are backward compatible
The ERC721o token standard makes use of the batchTransferFrom() function. This function enables transferring of multiple non-identical tokens with different amounts in one transaction. This enhances the user experience by not having to send separate transactions for each token transfer and therefore significantly reduces gas usage.
Besides the batchTransferFrom() function, we work with packing of balances. Storing data on the blockchain is one of the most expensive operations and by packing multiple balances together this reduces costs significantly. In our current implementation, we store 16 balances of token classes in a uint256 where every balance occupies 16 bits. This means that 16 token balances that are stored together can be updated in one transaction. By packing, there is a limit of 65,546 (2¹⁶) of tokens that can be stored on a balance. The current implementation is still under discussion, and we would like to ask feedback from the community on this limitation.
We have introduced a new token standard that we designed during the development of our universal derivative protocol. It can easily represent both exchange-traded and OTC derivatives, supports wraps and operations with portfolios and it is backwards compatible to ERC-721 so can be fitted into the existing ecosystem of DeFi projects as much as possible in a native manner.
The reference implementation and more details can be found on the project GitHub.
The Opium Team develops innovative financial products that use new technology to challenge the traditional financial sector. The team was founded by professional traders, portfolio managers and world-class mathematicians who believe that innovation should change the most conservative sector of the global economy.
We look forward to getting feedback regarding our proposal. It is already implemented into alpha-version of Opium Protocol that will be released over the next few weeks after more heavy testing on a test net. To get early access, contribute and help us to test and improve the Opium Protocol please subscribe to our Telegram group.