NFT & SFT tokens
Introduction
MultiversX NFTs(non-fungible tokens) are a breed of digital assets that are revolutionizing the world of art, collectibles, and more. These NFTs are unique, one-of-a-kind tokens that are built on blockchain technology, allowing for secure ownership and transfer of these assets. With MultiversX NFTs, every token is assigned a unique identification code(ticker) and metadata that distinguishes it from every other token, making each NFT truly one-of-a-kind. Read the full page for a comprehensive guide on how to brand, issue, transfer, assign roles and many other features, for both NFTs and SFTs.
NFT and SFT
The MultiversX protocol introduces native NFT support by adding metadata and attributes on top of the already existing Fungible tokens. This way, one can issue a semi-fungible token or a non-fungible token which is quite similar to an ESDT, but has a few more attributes, as well as an assignable URI. Once owning a quantity of a NFT/SFT, users will have their data store directly under their account, inside the trie. All the fields available inside a NFT/SFT token can be found here.
The flow of issuing and transferring non-fungible or semi-fungible tokens is:
- register/issue the token
- set roles to the address that will create the NFT/SFTs
- create the NFT/SFT
- transfer quantity(es)
Meta ESDT
In addition to NFTs and SFTs, MultiversX introduced Meta ESDTs. Meta ESDTs are a special case of semi-fungible-tokens. They can be seen as regular ESDT fungible tokens that also have properties. In a particular example, LKMEX or XMEX are MetaESDTs and their properties help implement the release schedule.
Branding
Anyone can create NFTs and SFTs tokens on MultiversX Network. There are also no limits in tokens names or tickers. For example,
one issues an AliceToken
with the ticker ALC
. Anyone else is free to create a new token with the same token name and
the same token ticker. The only difference will be the random sequence of the token identifier. So the "original" token
could have received the random sequence 1q2w3e
resulting in the ALC-1q2w3e
identifier, while the second token could
have received the sequence 3e4r5t
resulting in ALC-3e4r5t
.
In order to differentiate between an original token and other tokens with the same name or ticker, we have introduced a branding mechanism that allows tokens owners to provide a logo, a description, a website, as well as social link for their tokens. MultiversX products such as Explorer, Wallet and so on will display tokens in accordance to their branding, if any.
A token owner can submit a branding request by opening a Pull Request on https://github.com/multiversx/mx-assets.
Submitting a branding request
Token owners can create a PR to the https://github.com/multiversx/mx-assets with the logo in .png and .svg format, as well as a .json file containing all the relevant information.
Here’s a prefilled template for the .json file to get you started:
{
"website": "https://www.multiversxtoken.com",
"description": "MultiversX Token is a collection of 10.000 unique and randomly generated tokens.",
"social": {
"email": "mxt-token@multiversxtoken.com",
"blog": "https://www.multiversxtoken.com/MXT-token-blog",
"twitter": "https://twitter.com/MXT-token-twitter"
},
"status": "active"
}
Issuance of Non-Fungible Tokens
One has to perform an issuance transaction in order to register a non-fungible token. Non-Fungible Tokens are issued via a request to the Metachain, which is a transaction submitted by the Account which will manage the tokens. When issuing a token, one must provide a token name, a ticker and optionally additional properties. This transaction has the form:
IssuanceTransaction {
Sender: <account address of the token manager>
Receiver: erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u
Value: 50000000000000000 # (0.05 EGLD)
GasLimit: 60000000
Data: "issueNonFungible" +
"@" + <token name in hexadecimal encoding> +
"@" + <token ticker in hexadecimal encoding>
}
For more details about how arguments have to be encoded, check here.
Optionally, the properties can be set when issuing a token. Example:
IssuanceTransaction {
Sender: <account address of the token manager>
Receiver: erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u
Value: 50000000000000000 # (0.05 EGLD)
GasLimit: 60000000
Data: "issueNonFungible" +
"@" + <token name in hexadecimal encoding> +
"@" + <token ticker in hexadecimal encoding> +
"@" + <"canFreeze" hexadecimal encoded> + "@" + <"true" or "false" hexadecimal encoded> +
"@" + <"canWipe" hexadecimal encoded> + "@" + <"true" or "false" hexadecimal encoded> +
"@" + <"canPause" hexadecimal encoded> + "@" + <"true" or "false" hexadecimal encoded> +
"@" + <"canTransferNFTCreateRole" hexadecimal encoded> + "@" + <"true" or "false" hexadecimal encoded> +
"@" + <"canChangeOwner" hexadecimal encoded> + "@" + <"true" or "false" hexadecimal encoded> +
"@" + <"canUpgrade" hexadecimal encoded> + "@" + <"true" or "false" hexadecimal encoded> +
"@" + <"canAddSpecialRoles" hexadecimal encoded> + "@" + <"true" or "false" hexadecimal encoded> +
...
}
For more details about how arguments have to be encoded, check here.
The receiver address erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u
is a built-in system smart contract (not a VM-executable contract), which only handles token issuance and other token management operations, and does not handle any transfers.
The contract will add a random string to the ticker thus creating the token identifier. The random string starts with “-” and has 6 more random characters. For example, a token identifier could look like ALC-6258d2.
Issuance of Semi-Fungible Tokens
One has to perform an issuance transaction in order to register a semi-fungible token. Semi-Fungible Tokens are issued via a request to the Metachain, which is a transaction submitted by the Account which will manage the tokens. When issuing a semi-fungible token, one must provide a token name, a ticker and optionally additional properties. This transaction has the form:
IssuanceTransaction {
Sender: <account address of the token manager>
Receiver: erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u
Value: 50000000000000000 # (0.05 EGLD)
GasLimit: 60000000
Data: "issueSemiFungible" +
"@" + <token name in hexadecimal encoding> +
"@" + <token ticker in hexadecimal encoding>
}
For more details about how arguments have to be encoded, check here.
Optionally, the properties can be set when issuing a token. Example:
IssuanceTransaction {
Sender: <account address of the token manager>
Receiver: erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u
Value: 50000000000000000 # (0.05 EGLD)
GasLimit: 60000000
Data: "issueSemiFungible" +
"@" + <token name in hexadecimal encoding> +
"@" + <token ticker in hexadecimal encoding> +
"@" + <"canFreeze" hexadecimal encoded> + "@" + <"true" or "false" hexadecimal encoded> +
"@" + <"canWipe" hexadecimal encoded> + "@" + <"true" or "false" hexadecimal encoded> +
"@" + <"canPause" hexadecimal encoded> + "@" + <"true" or "false" hexadecimal encoded> +
"@" + <"canTransferNFTCreateRole" hexadecimal encoded> + "@" + <"true" or "false" hexadecimal encoded> +
"@" + <"canChangeOwner" hexadecimal encoded> + "@" + <"true" or "false" hexadecimal encoded> +
"@" + <"canUpgrade" hexadecimal encoded> + "@" + <"true" or "false" hexadecimal encoded> +
"@" + <"canAddSpecialRoles" hexadecimal encoded> + "@" + <"true" or "false" hexadecimal encoded> +
...
}
For more details about how arguments have to be encoded, check here.
The receiver address erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u
is a built-in system smart contract (not a VM-executable contract), which only handles token issuance and other token management operations, and does not handle any transfers.
The contract will add a random string to the ticker thus creating the token identifier. The random string starts with “-” and has 6 more random characters. For example, a token identifier could look like ALC-6258d2.
Issuance of Meta-ESDT Tokens
One has to perform an issuance transaction in order to register a Meta-ESDT token. Meta-ESDT Tokens are issued via a request to the Metachain, which is a transaction submitted by the Account which will manage the tokens. When issuing a semi-fungible token, one must provide a token name, a ticker and optionally additional properties. This transaction has the form:
IssuanceTransaction {
Sender: <account address of the token manager>
Receiver: erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u
Value: 50000000000000000 # (0.05 EGLD)
GasLimit: 60000000
Data: "registerMetaESDT" +
"@" + <token name in hexadecimal encoding> +
"@" + <token ticker in hexadecimal encoding> +
"@" + <number of decimals in hexadecimal encoding>
}
For more details about how arguments have to be encoded, check here.
Optionally, the properties can be set when issuing a token. Example:
IssuanceTransaction {
Sender: <account address of the token manager>
Receiver: erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u
Value: 50000000000000000 # (0.05 EGLD)
GasLimit: 60000000
Data: "registerMetaESDT" +
"@" + <token name in hexadecimal encoding> +
"@" + <token ticker in hexadecimal encoding> +
"@" + <number of decimals in hexadecimal encoding>
"@" + <"canFreeze" hexadecimal encoded> + "@" + <"true" or "false" hexadecimal encoded> +
"@" + <"canWipe" hexadecimal encoded> + "@" + <"true" or "false" hexadecimal encoded> +
"@" + <"canPause" hexadecimal encoded> + "@" + <"true" or "false" hexadecimal encoded> +
"@" + <"canTransferNFTCreateRole" hexadecimal encoded> + "@" + <"true" or "false" hexadecimal encoded> +
"@" + <"canChangeOwner" hexadecimal encoded> + "@" + <"true" or "false" hexadecimal encoded> +
"@" + <"canUpgrade" hexadecimal encoded> + "@" + <"true" or "false" hexadecimal encoded> +
"@" + <"canAddSpecialRoles" hexadecimal encoded> + "@" + <"true" or "false" hexadecimal encoded> +
...
}
For more details about how arguments have to be encoded, check here.
The receiver address erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u
is a built-in system smart contract (not a VM-executable contract), which only handles token issuance and other token management operations, and does not handle any transfers.
The contract will add a random string to the ticker thus creating the token identifier. The random string starts with “-” and has 6 more random characters. For example, a token identifier could look like ALC-6258d2.
Converting an SFT into Meta-ESDT
An already existing semi-fungible token can be converted into a Meta-ESDT token if the owner sends the following transaction:
ConvertSftToMetaESDTTransaction {
Sender: <account address of the token manager>
Receiver: erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u
Value: 0
GasLimit: 60000000
Data: "changeSFTToMetaESDT" +
"@" + <token name in hexadecimal encoding> +
"@" + <number of decimals in hexadecimal encoding>
}
For more details about how arguments have to be encoded, check here.
Parameters format
Token Name:
- length between 3 and 50 characters
- alphanumeric characters only
Token Ticker:
- length between 3 and 10 characters
- alphanumeric UPPERCASE only
Issuance examples
For example, a user named Alice wants to issue an ESDT called "AliceTokens" with the ticker "ALC". The issuance transaction would be:
IssuanceTransaction {
Sender: erd1sg4u62lzvgkeu4grnlwn7h2s92rqf8a64z48pl9c7us37ajv9u8qj9w8xg
Receiver: erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u
Value: 50000000000000000 # (0.05 EGLD)
GasLimit: 60000000
Data: "issueSemiFungible" +
"@416c696365546f6b656e73" +
"@414c43" +
}
For more details about how arguments have to be encoded, check here.
Once this transaction is processed by the Metachain, Alice becomes the designated manager of AliceTokens. She can add quantity later using ESDTNFTCreate
. For more operations available to ESDT token managers, see Token management.
In that smart contract result, the data
field will contain a transfer syntax which is explained below. What is important to note is that the token identifier can be fetched from
here in order to use it for transfers. Alternatively, the token identifier can be fetched from the API (explained also in section REST API - Get NFT data ).
Roles
In order to be able to perform actions over a token, one needs to have roles assigned. The existing roles are:
For NFT:
- ESDTRoleNFTCreate : this role allows one to create a new NFT
- ESDTRoleNFTBurn : this role allows one to burn a specific NFT
- ESDTRoleNFTUpdateAttributes : this role allows one to change the attributes of a specific NFT
- ESDTRoleNFTAddURI : this role allows one add URIs for a specific NFT
- ESDTTransferRole : this role enables transfer only to specified addresses. The addresses with the transfer role can transfer anywhere.
- ESDTRoleNFTUpdate : this role allows one to update meta data attributes of a specific NFT
- ESDTRoleModifyRoyalties : this role allows one to modify royalities of a specific NFT
- ESDTRoleSetNewURI : this role allows one to set new uris of a specific NFT
- ESDTRoleModifyCreator : this role allows one to rewrite the creator of a specific token
- ESDTRoleNFTRecreate : this role allows one to recreate the whole NFT with new attributes
For SFT:
- ESDTRoleNFTCreate : this role allows one to create a new SFT
- ESDTRoleNFTBurn : this role allows one to burn quantity of a specific SFT
- ESDTRoleNFTAddQuantity : this role allows one to add quantity of a specific SFT
- ESDTTransferRole : this role enables transfer only to specified addresses. The addresses with the transfer role can transfer anywhere.
- ESDTRoleNFTUpdate : this role allows one to update meta data attributes of a specific SFT
- ESDTRoleModifyRoyalties : this role allows one to modify royalities of a specific SFT
- ESDTRoleSetNewURI : this role allows one to set new uris of a specific SFT
- ESDTRoleModifyCreator : this role allows one to rewrite the creator of a specific token
- ESDTRoleNFTRecreate : this role allows one to recreate the whole NFT with new attributes
To see how roles can be assigned, please refer to this section.
Assigning roles
Roles can be assigned by sending a transaction to the Metachain from the ESDT manager.
Within a transaction of this kind, any number of roles can be assigned (minimum 1).
RolesAssigningTransaction {
Sender: <address of the ESDT manager>
Receiver: erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u
Value: 0
GasLimit: 60000000
Data: "setSpecialRole" +
"@" + <token identifier in hexadecimal encoding> +
"@" + <address to assign the role(s) in a hexadecimal encoding> +
"@" + <role in hexadecimal encoding> +
"@" + <role in hexadecimal encoding> +
...
}
For more details about how arguments have to be encoded, check here.
For example, ESDTRoleNFTCreate
= 45534454526f6c654e4654437265617465
Unset transactions are very similar. You can find an example here.
NFT/SFT fields
Below you can find the fields involved when creating an NFT.
NFT Name
- The name of the NFT or SFT
Quantity
- The quantity of the token. If NFT, it must be
1
Royalties
- Allows the creator to receive royalties for any transaction involving their NFT
- Base format is a numeric value between 0 an 10000 (0 meaning 0% and 10000 meaning 100%)
Hash
- Arbitrary field that should contain the hash of the NFT metadata
- Optional filed, should be left
null
when building the transaction to create the NFT
Attributes
- Represents additional information about the NFT or SFT, like picture traits or tags for your NFT/collection
- The field should follow a
metadata:ipfsCID/fileName.json;tags:tag1,tag2,tag3
format - Below you can find a sample for the extra metadata format that should be stored on IPFS:
{
"description": "This is a sample description",
"attributes": [
{
"trait_type": "Background",
"value": "Yellow",
"{key}": "{value}",
"{...}": "{...}",
"{key}": "{value}"
},
{
"trait_type": "Headwear",
"value": "BlackBeanie"
},
{
"trait_type": "SampleTrait3",
"value": "SampleValue3"
}
],
"collection": "ipfsCID/fileName.json"
}
URI(s)
- Mandatory field that represents the URL to a supported media file ending with the file extension as described in the example below
- Field should contain the
Uniform Resource Identifier
Note: As a best practice, we recommend storing the files for media & extra metadata(from attributes field) within same folder on your storage provider, ideally IPFS. Also, in order to have a thumbnail generated for the uploaded file the size of the file should be less or equal to 64MB.
Please note that each argument must be encoded in hexadecimal format with an even number of characters.