-
Notifications
You must be signed in to change notification settings - Fork 113
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
NEP: Non-fungible Token Standard #41
Closed
Closed
Changes from 33 commits
Commits
Show all changes
35 commits
Select commit
Hold shift + click to select a range
db5fe38
Create nep-10.mediawiki
hal0x2328 a5123cf
Merge pull request #1 from Splyse/NFT
hal0x2328 d70627c
resolves conflicts
7315094
formatting changes and a few text modifications
fb3adde
amend
43dd18a
add events
84dbfb0
change state to accepted
erikzhang 22b3a26
Amend `Transfer` event
erikzhang 8dfa5e7
Ament `tokenURI()` method
erikzhang ee7a803
Support data URI scheme
erikzhang 4947667
Restrictions on JSON file
erikzhang d0a10d9
Merge remote-tracking branch 'upstream/master' into nft
ec6125d
Initial rework
b3891af
Moved tokenURI to end. Added properties for immutable onchain properties
094c65b
Removed rationale section
4bda135
No reason for name to be required in tokenURI
4ea348b
Move metadata schema to its own section
46e2854
Fix formatting
77f078f
Change title for metadata schema
034a9b2
Added word optionally
052d4c9
Finish tokensOf
9b838e4
Merge pull request #2 from WyattMufson/nft
hal0x2328 208d630
Remove tokenURI
f1ff9f5
Merge pull request #3 from WyattMufson/nft
hal0x2328 dc0a4c2
Remove uri
3eebf67
Merge remote-tracking branch 'upstream/master' into nft
74c6b42
Merge pull request #4 from WyattMufson/nft
hal0x2328 982f6a6
Update tokensOf and the metadata schema
f0c7e99
Merge pull request #5 from WyattMufson/nft
hal0x2328 aab08d8
Add examples to json sschema
corollari cbfd0a7
Fix minor grammar issues
corollari 57ec7ea
Merge pull request #6 from corollari/patch-2
hal0x2328 61e53a0
Merge pull request #7 from corollari/patch-3
hal0x2328 471aaf0
Merge branch 'master' into master
erikzhang 5c68859
Merge branch 'master' into master
erikzhang File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,242 @@ | ||
<pre> | ||
NEP: 11 | ||
Title: Non-Fungible Token Standard | ||
Author: Joe Stewart <hal0x2328@splyse.tech>, Shane Mann <fetter@splyse.tech>, Wyatt Mufson <wyatt@ryu.games> | ||
Type: Standard | ||
Status: Accepted | ||
Created: 2018-04-18 | ||
</pre> | ||
|
||
==Abstract== | ||
|
||
This NEP defines a standard non-fungible token system for the NEO Smart Economy. | ||
|
||
==Motivation== | ||
|
||
NFTs are required to track, exchange and enforce ownership of digital assets. | ||
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). | ||
Other information, such as the owner of the property, can be changed. | ||
Also, we provide built-in optional divisibility within each non-fungible asset. | ||
This allows for high value objects to be tokenized more effectively. | ||
|
||
==Specification== | ||
|
||
===Methods=== | ||
|
||
====name==== | ||
|
||
<pre> | ||
public static string name() | ||
</pre> | ||
|
||
Returns the name of the token. e.g. <code>"MyNFT"</code>. | ||
|
||
This method MUST always return the same value every time it is invoked. | ||
|
||
====symbol==== | ||
|
||
<pre> | ||
public static string symbol() | ||
</pre> | ||
|
||
Returns a short string symbol of the token managed in this contract. e.g. <code>"MNFT"</code>. | ||
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==== | ||
|
||
<pre> | ||
public static BigInteger totalSupply() | ||
</pre> | ||
|
||
Returns the total token supply currently in the system. | ||
|
||
====decimals==== | ||
|
||
<pre> | ||
public static byte decimals() | ||
erikzhang marked this conversation as resolved.
Show resolved
Hide resolved
|
||
</pre> | ||
|
||
Returns the number of decimals used by the token - e.g. <code>8</code>, means to divide the token amount by <code>100,000,000</code> to get its user representation. | ||
|
||
If the token managed in this contract is indivisible, the function SHOULD return <code>0</code>. | ||
|
||
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. | ||
|
||
====transfer==== | ||
|
||
<pre> | ||
public static bool transfer(byte[] to, byte[] tokenid) | ||
</pre> | ||
|
||
This transfer method is for non-divisible NFTs <code>decimals() == 0</code>. | ||
It transfers the token with id <code>tokenid</code> to address <code>to</code>. | ||
|
||
The parameter <code>tokenid</code> SHOULD be a valid NFT. | ||
If not, this method SHOULD <code>throw</code> an exception. | ||
|
||
The parameter <code>to</code> SHOULD be a 20-byte address. | ||
If not, this method SHOULD <code>throw</code> an exception. | ||
|
||
The function SHOULD return <code>false</code> if the token that will be transferred has more than one owner. | ||
|
||
If the method succeeds, it MUST fire the <code>Transfer</code> event, and MUST return <code>true</code>, even if the token is sent to the owner. | ||
|
||
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 <code>Neo.Runtime.CheckWitness</code> to verify the transfer. | ||
|
||
If the <code>to</code> address is a deployed contract, the function SHOULD check the <code>payable</code> 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 <code>false</code>. | ||
|
||
<pre> | ||
public static bool transfer(byte[] from, byte[] to, BigInteger amount, byte[] tokenid) | ||
</pre> | ||
|
||
This transfer method is for divisible NFTs <code>decimals() > 0</code>. | ||
|
||
It transfers an <code>amount</code> of tokens with id <code>tokenid</code> from address <code>from</code> to address <code>to</code>. | ||
|
||
The parameter <code>tokenid</code> SHOULD be a valid NFT. | ||
If not, this method SHOULD <code>throw</code> an exception. | ||
|
||
The parameters <code>from</code> and <code>to</code> SHOULD be 20-byte addresses. | ||
If not, this method SHOULD <code>throw</code> an exception. | ||
|
||
The parameter <code>amount</code> SHOULD be greater than or equal to <code>0</code> and SHOULD be less than or equal to <code>pow(10, decimals())</code>. | ||
If not, this method SHOULD <code>throw</code> an exception. | ||
|
||
The function SHOULD return <code>false</code> if the <code>from</code> account balance does not have enough tokens to spend. | ||
|
||
If the method succeeds, it MUST fire the <code>Transfer</code> event, and MUST return <code>true</code>, even if the <code>amount</code> is <code>0</code>, or the token is sent to the owner. | ||
|
||
The function SHOULD check whether the <code>from</code> address equals the caller contract hash. | ||
If so, the transfer SHOULD be processed; If not, the function SHOULD use the SYSCALL <code>Neo.Runtime.CheckWitness</code> to verify the transfer. | ||
|
||
If the <code>to</code> address is a deployed contract, the function SHOULD check the <code>payable</code> 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 <code>false</code>. | ||
|
||
====ownerOf==== | ||
|
||
<pre> | ||
public static enumerator ownerOf(byte[] tokenid) | ||
</pre> | ||
|
||
Returns an <code>enumerator</code> that contains all the co-owners that own the specified token. | ||
erikzhang marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
The parameter <code>tokenid</code> SHOULD be a valid NFT. | ||
If not, this method SHOULD <code>throw</code> an exception. | ||
|
||
====balanceOf==== | ||
|
||
<pre> | ||
public static BigInteger balanceOf(byte[] owner) | ||
</pre> | ||
|
||
Returns the total amount of NFTs owned by the specified address. | ||
|
||
The parameter <code>owner</code> SHOULD be a 20-byte address. | ||
If not, this method SHOULD <code>throw</code> an exception. | ||
|
||
<pre> | ||
public static BigInteger balanceOf(byte[] owner, byte[] tokenid) | ||
</pre> | ||
|
||
If the second parameter <code>tokenid</code> is also provided, this method returns the balance of the specified token for the specified owner's account. | ||
|
||
The parameter <code>tokenid</code> SHOULD be a valid NFT. | ||
If not, this method SHOULD <code>throw</code> an exception. | ||
|
||
The parameter <code>owner</code> SHOULD be a 20-byte address. | ||
If not, this method SHOULD <code>throw</code> an exception. | ||
|
||
If the <code>owner</code> is an unused address, or it's not the owner of the specified token, this method SHOULD return <code>0</code>. | ||
|
||
====tokensOf==== | ||
|
||
<pre> | ||
public static enumerator tokensOf(byte[] owner) | ||
</pre> | ||
|
||
Returns an <code>enumerator</code> that contains all of the token ids owned by the specified address. | ||
|
||
The parameter <code>owner</code> SHOULD be a 20-byte address. | ||
If not, this method SHOULD <code>throw</code> an exception. | ||
|
||
====properties==== | ||
|
||
<pre> | ||
public static string properties(byte[] tokenid) | ||
</pre> | ||
|
||
Returns a serialized NVM object containing the properties for the given NFT. | ||
The NVM object must conform to the "NEO NFT Metadata JSON Schema". | ||
|
||
The parameter <code>tokenid</code> SHOULD be a valid NFT. | ||
If not, this method SHOULD <code>throw</code> an exception. | ||
|
||
====NEO NFT Metadata JSON Schema==== | ||
|
||
Following is a description of the JSON Schema: | ||
<pre> | ||
{ | ||
"title": "Asset Metadata", | ||
"type": "object", | ||
"properties": { | ||
erikzhang marked this conversation as resolved.
Show resolved
Hide resolved
|
||
"name": { | ||
"type": "string", | ||
"description": "Identifies the asset to which this NFT represents." | ||
}, | ||
"description": { | ||
"type": "string", | ||
"description": "Describes the asset to which this NFT represents." | ||
}, | ||
"image": { | ||
"type": "string", | ||
"description": "Optional. A URI pointing to a resource with mime type image/* representing the asset to which this NFT represents. Consider making any images at a width between 320 and 1080 pixels and aspect ratio between 1.91:1 and 4:5 inclusive." | ||
}, | ||
"tokenURI": { | ||
"type": "string", | ||
"description": "Optional. A distinct URI for a given asset that adheres to RFC 3986" | ||
} | ||
} | ||
} | ||
</pre> | ||
|
||
Given this schema, the simplest json object that can be constructed is the following: | ||
<pre> | ||
{ | ||
"name": "Slime 1", | ||
"description": "A slime" | ||
} | ||
</pre> | ||
|
||
And if all the properties are included: | ||
<pre> | ||
{ | ||
"name": "Slime 2", | ||
"description": "A slime", | ||
"image": "{some image URI}", | ||
"tokenURI": "{some URI}" | ||
} | ||
</pre> | ||
|
||
===Events=== | ||
|
||
====Transfer==== | ||
|
||
<pre> | ||
public static event Transfer(byte[] from, byte[] to, BigInteger amount, byte[] tokenid) | ||
</pre> | ||
|
||
MUST trigger when tokens are transferred, including zero value transfers. | ||
|
||
A token contract which creates new tokens MUST trigger a <code>Transfer</code> event with the <code>from</code> address set to <code>null</code> when tokens are created. | ||
|
||
A token contract which burns tokens MUST trigger a <code>Transfer</code> event with the <code>to</code> address set to <code>null</code> when tokens are burned. | ||
|
||
==Implementation== |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For example, if we are talking about all cars of a state in Brazil, then,
totalSupply
would return that amount that can increase or decrease based on an entity that is registering that assets, right?