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 …
that are deleted from the 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 will be created instead of the portfolio . TokenIDs can be found off-chain with historical analysis of the or collected from the events, but there is no need to them on the as long as the total hash is stored.
Another function of the ERC-721o standard is: recompose. New derivative can be added to the existing portfolio , but derivative can also be taken out of the portfolio . When a user wants to add several to the portfolio to the same layer with other he can use this function. It allows to add or withdraw 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 standard implementation. These functions are the only ones that can emit or burn 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 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.
Restrictions:
- 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.
Changes:
- 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
Changes:
- 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
Gas optimization
The ERC721o standard makes use of the batchTransferFrom() function. This function enables transferring of multiple non-identical with different amounts in one transaction. This enhances the user experience by not having to send separate transactions for each transfer and therefore significantly reduces gas usage.
Besides the batchTransferFrom() function, we work with packing of balances. Storing data on the is one of the most expensive operations and by packing multiple balances together this reduces costs significantly. In our current implementation, we 16 balances of classes in a uint256 where every balance occupies 16 bits. This means that 16 balances that are stored together can be updated in one transaction. By packing, there is a limit of 65,546 (2¹⁶) of 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.
Conclusion
We have introduced a new 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 .
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 .
Published at Fri, 19 Apr 2019 07:27:02 +0000