ESDT improvement proposal
Problem statement: a set of functionalities are limited/we do not allow them when we speak about NFT metadata (creator, URIs, attributes). Builders made a few informal proposals wanting more features. Plus we can think about some of the attributes and properties of an NFT/SFT/MetaESDT as resources, which can be modified by the contract owner.
New built in functions:
-
ESDTModifyRoyalties@tokenID@nonce@newRoyalty:
a. Built in function which will rewrite the royalties on the given tokenID
b. Only if the account has that tokenID and only for NFTs
c. New Role to be added ESDTRoleNFTModifyRoyalties -
ESDTNFTSetNewURIs@tokenID@nonce@list(URI)
a. Built in function which will rewrite URIs
b. Only if the account has tokenID and only for NFTs
c. New Role to be added ESDTRoleNFTSetNewURIs -
ESDTNFTModifyCreator@tokenID@nonce
a. Change the creator to the current caller
b. Only if it is allowed, new role to be checked
ESDTMetaData structure contains: URIs, Royalties, Attributes, Name, Creator, Hash, and when NFT is created it needs to have all the arguments in the ESDTNFTCreateFunction. We can improve the Rust framework with Macro Magic as to give the default inputs when the user does not provide it. But that can be discussed in another thread.
Another remark here: as of now, only NFTs can have attributes/URIs modified, as in case of SFTs/metaESDTs they can be on multiple shards and it would be somewhat of an inconsistency issue. But we can resolve those with this improvement proposal, and we can further enhance the customizability of Tokens with MetaData.
Now change the narrative and think about ESDTs as Resources and enable SC developer to do customized things on those:
https://twitter.com/BL0CKRUNNER/status/1709833870152269928 this tweet made us think that we could simply implement the listed features directly in the protocol.
Came with a response: https://twitter.com/SasuRobert/status/1709843514962391461
Right now you can do the following:
Launch a token and create tokens without actual attributes, keep resources under Nonce storage inside the smart contract. You send the token to the user (tokenID and nonce) as a representation of a resource which is managed at the SC level. The SC has a map of (tokenID, nonce) to attributes, internal structure, thus the SC can manage anything, while the user has only a representation. To enable interoperability, the SC could write in the attributes of the tokens a set of Query functions (as hooks) for other SCs/Microservices to interpret it.
But as needs evolve, builders build more complex projects, the underlying protocol should evolve as well. Thus we propose to improve the ESDT Metadata and its functions for all tokens, making those dynamic if the project wants.
First important point of enhancing customizability: enable change of attributes/URIs/royalties for SFTs/metaESDTs and add automatic versioning as well.
On the ESDTData structure we have an unused field - named Reserved. This is an open byte array. We can use this as a versioning mechanism for all the ESDTMetaData out there. ESDTMetaData structure contains: URIs, Royalties, Attributes, Name, Creator, Hash. All of which should be enabled to be changed using the existing and the new functions.
The paradigm change will be the following:
-
We enable changing metaData for SFTs/metaESDTs and in case of transfers, we always rewrite the old versions with the new one.
a. There is the chance of having an SFT at multiple users,
b. The contract decides to update the attributes of an SFT, this update will be reflected on the contract shard, and if the contract sends to a user, it will be reflected on the shard of the user.
c. In case there is a cross shard transfer, in which one systemAccount has one type of ESDTMetaData and on the transferData we have another type of ESDTMetaData, we will always write and use the one with the higher version.
d. Handling of rewriting the data in case of transfer depending on the version of the ESDTMetadata is easy. -
This means on all the functions which can change the MetaData of a token we increase the version of the token.
-
This also means that there can always be only ONE address which has the role of updating attributes.
This change does not affect any existing DeFi application, these updates/upgrades can be used for other types of financial services/dApps.
Second important point of enhancing customizability: enable the change of metaData even if the token is not in the balance of the SC. In case of ERC/other token based contract, the contract can change the attributes of the tokenMetadata as the SC dictates.
So, building from the previous point we can enable the function of ESDTMetaDataRecreate to be called even if the contract who calls this endpoint does not have the tokenID+nonce in his balance. We can add a special type of roles and identification on the ESDT system SC level, in which we can show that a token is built in such a way that the attributes can be rewritten by the smart contract with the rewrite role, even if it does not have that token in his balance.
Thus we create new tokenTypes only on ESDTSystemSmartContract level appending to the existing token type versions the name “dynamic”. In the case of “dynamic” tokenType (NFTDynamic, SFTDynamic, metaESDTDynamic), we create a new set of roles by appending the dynamic name to the ESDTRoleNFTRecreate. ESDTRoleNFTRecreateDynamic.
In the built in functions mentioned in the first page, we check for the balance of the contract only if the dynamic role is missing. If the dynamic role is in this contract, there is no need to check for balance. Dynamic role can be given to only one SC per tokenID.
As you can see, this will greatly enhance all dynamicNFT usecases, or all game useCases. One can level up my character, SC will rewrite the attributes of the new character, and I do not have to call the SC to upgrade my NFT every time. One can do it when one wants, on the first interaction. It makes building games/dynamic NFTs easier.
We propose a new set of functions for upgrade/recreate:
-
ESDTMetaDataRecreate@ATTR@newAttr@URI@newURIs@CREATOR@address@ROYALTIES@newRoyalties:
a. This recreates all the attributes from zero. If an argument is not received, that field is set to zero. -
ESDTMetadataUpdate@ATTR@newAttr@URI@newURIs@CREATOR@address@ROYALTIES@newRoyalties:
a. If nothing is received for a given attribute we keep the old version of that.