What is a non-fungible token?

A non-fungible token (NFT) can be thought of like a property deed - each one is unique and carries some non-mutable information (e.g. the physical address of the property) although other information, such as the owner of the property can be changed. An NFT smart contract is useful to track ownership of real-world items, as well as in online gaming, allowing users to posess unique characters or items of a limited supply, that can be transferred between users without requiring the permission of the game owner.

The NFT proposal standard for the Neo Smart Economy is currently in development. This is example in C# showing how such a smart contract might be written. There is some overlap between NEP-5 (fungible) token functionality to make adoption easier by API writers.

Methods

name

public static string name()

Returns the name of the token. e.g. "MyNFT".

This method MUST always return the same value every time it is invoked.

symbol

public static string symbol()

Returns a short string symbol of the token managed in this contract. e.g. "MNFT". This symbol SHOULD be short (3-8 characters is recommended), with no whitespace characters or new-lines and SHOULD be limited to the uppercase latin alphabet (i.e. the 26 letters used in English).

This method MUST always return the same value every time it is invoked.

totalSupply

public static BigInteger totalSupply()

Returns the total token supply deployed in the system.

decimals

public static byte decimals()

Returns the number of decimals used by the token - e.g. 8, means to divide the token amount by 100,000,000 to get its user representation.

If the token managed in this contract is indivisible, the function SHOULD return 0.

If the function returns a non-zero value, all of the ‘‘OPTIONAL’’ methods in this standard MUST be implemented.

This method MUST always return the same value every time it is invoked.

tokens

public static enumerator tokens()

Returns an enumerator that contains all the tokens that have been issued in this contract.

transfer

public static bool transfer(byte[] to, byte[] tokenid)

Transfers token with id tokenid to address to.

The parameter tokenid SHOULD be a valid NFT. If not, this method SHOULD throw an exception.

The parameter to SHOULD be a 20-byte address. If not, this method SHOULD throw an exception.

The function SHOULD return false if the token that will be transferred has more than one owner.

If the method succeeds, it MUST fire the transfer event, and MUST return true, even if the token is sent to the owner himself.

The function SHOULD check whether the owner address equals the caller contract hash. If so, the transfer SHOULD be processed; If not, the function SHOULD use the SYSCALL Neo.Runtime.CheckWitness to verify the transfer.

If the to address is a deployed contract, the function SHOULD check the payable flag of this contract to decide whether it should transfer the tokens to this contract.

If the transfer is not processed, the function SHOULD return false.

public static bool transfer(byte[] from, byte[] to, BigInteger amount, byte[] tokenid)

'’OPTIONAL’’: This method MUST be implemented if decimals() > 0.

Transfers an amount of tokens with id tokenid from address from to address to.

The parameter tokenid SHOULD be a valid NFT. If not, this method SHOULD throw an exception.

The parameters from and to SHOULD be 20-byte addresses. If not, this method SHOULD throw an exception.

The parameter amount SHOULD be greater than or equal to 0 and SHOULD be less than or equal to pow(10, decimals()). If not, this method SHOULD throw an exception.

The function SHOULD return false if the from account balance does not have enough tokens to spend.

If the method succeeds, it MUST fire the transfer event, and MUST return true, even if the amount is 0, or the token is sent to the owner himself.

The function SHOULD check whether the from address equals the caller contract hash. If so, the transfer SHOULD be processed; If not, the function SHOULD use the SYSCALL Neo.Runtime.CheckWitness to verify the transfer.

If the to address is a deployed contract, the function SHOULD check the payable flag of this contract to decide whether it should transfer the tokens to this contract.

If the transfer is not processed, the function SHOULD return false.

ownerOf

public static enumerator ownerOf(byte[] tokenid)

Returns an enumerator that contains all the co-owners that own the specified token.

The parameter tokenid SHOULD be a valid NFT. If not, this method SHOULD throw an exception.

tokenURI

public static string tokenURI(byte[] tokenid)

Returns a distinct Uniform Resource Identifier (URI) for a given asset. The URI data of a token supplies a reference to get more information about a specific token or its data.

The parameter tokenid SHOULD be a valid NFT. If not, this method SHOULD throw an exception.

balanceOf

public static BigInteger balanceOf(byte[] owner, byte[] tokenid)

Returns the balance of the specified token for the specified owner’s account.

The parameter tokenid SHOULD be a valid NFT. If not, this method SHOULD throw an exception.

The parameter owner SHOULD be a 20-byte address. If not, this method SHOULD throw an exception.

If the owner is an unused address, or it’s not the owner of the specified token, this method SHOULD return 0.

tokensOfOwner

public static enumerator tokensOfOwner(byte[] owner)

Returns an enumerator that contains all the tokens owned by the specified address.

The parameter owner SHOULD be a 20-byte address. If not, this method SHOULD throw an exception.

Events

transfer

public static event transfer(byte[] from, byte[] to, BigInteger amount, byte[] tokenid)

MUST trigger when tokens are transferred, including zero value transfers.

A token contract which creates new tokens SHOULD trigger a transfer event with the from address set to null when tokens are created.