Skip to content
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
wants to merge 35 commits into from
Closed
Show file tree
Hide file tree
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 Apr 19, 2018
a5123cf
Merge pull request #1 from Splyse/NFT
hal0x2328 Apr 19, 2018
d70627c
resolves conflicts
May 22, 2018
7315094
formatting changes and a few text modifications
May 22, 2018
fb3adde
amend
May 22, 2018
43dd18a
add events
May 22, 2018
84dbfb0
change state to accepted
erikzhang Oct 27, 2018
22b3a26
Amend `Transfer` event
erikzhang May 20, 2019
8dfa5e7
Ament `tokenURI()` method
erikzhang May 20, 2019
ee7a803
Support data URI scheme
erikzhang May 21, 2019
4947667
Restrictions on JSON file
erikzhang May 22, 2019
d0a10d9
Merge remote-tracking branch 'upstream/master' into nft
Jul 11, 2019
ec6125d
Initial rework
Jul 12, 2019
b3891af
Moved tokenURI to end. Added properties for immutable onchain properties
Jul 12, 2019
094c65b
Removed rationale section
Jul 12, 2019
4bda135
No reason for name to be required in tokenURI
Jul 12, 2019
4ea348b
Move metadata schema to its own section
Jul 12, 2019
46e2854
Fix formatting
Jul 12, 2019
77f078f
Change title for metadata schema
Jul 12, 2019
034a9b2
Added word optionally
Jul 12, 2019
052d4c9
Finish tokensOf
Jul 12, 2019
9b838e4
Merge pull request #2 from WyattMufson/nft
hal0x2328 Jul 18, 2019
208d630
Remove tokenURI
Jul 29, 2019
f1ff9f5
Merge pull request #3 from WyattMufson/nft
hal0x2328 Jul 29, 2019
dc0a4c2
Remove uri
Jul 30, 2019
3eebf67
Merge remote-tracking branch 'upstream/master' into nft
Jul 30, 2019
74c6b42
Merge pull request #4 from WyattMufson/nft
hal0x2328 Jul 30, 2019
982f6a6
Update tokensOf and the metadata schema
Aug 2, 2019
f0c7e99
Merge pull request #5 from WyattMufson/nft
hal0x2328 Aug 2, 2019
aab08d8
Add examples to json sschema
corollari Aug 7, 2019
cbfd0a7
Fix minor grammar issues
corollari Aug 7, 2019
57ec7ea
Merge pull request #6 from corollari/patch-2
hal0x2328 Aug 7, 2019
61e53a0
Merge pull request #7 from corollari/patch-3
hal0x2328 Aug 7, 2019
471aaf0
Merge branch 'master' into master
erikzhang Jan 14, 2021
5c68859
Merge branch 'master' into master
erikzhang Jan 14, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 15 additions & 15 deletions README.mediawiki
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ First review [[nep-1.mediawiki|NEP-1]]. Then clone the repository and add your N
|-
| [https://github.com/neo-project/proposals/pull/41 11]
| Non-fungible Token Standard
| Joe Stewart, Shane Mann
| Joe Stewart, Shane Mann, Wyatt Mufson
| Standard
| Accepted
|-
Expand All @@ -75,45 +75,45 @@ First review [[nep-1.mediawiki|NEP-1]]. Then clone the repository and add your N
| Standard
| Accepted
|-
|
|
| Dynamic Sharding
|
|
| Standard
| Stub
|-
|
|
| Compact Block Relay
|
|
| Standard
| Stub
|-
|
|
| Peer Authentication
|
|
| Standard
| Stub
|-
|
|
| Aggregate Signature
|
|
| Standard
| Stub
|-
|
|
| Homomorphic Encryption
|
|
| Standard
| Stub
|-
|
|
| Zero-knowledge proof
|
|
| Standard
| Stub
|-
|
|
| Stealth Addresses
|
|
| Standard
| Stub
|}
242 changes: 242 additions & 0 deletions nep-11.mediawiki
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()
Copy link
Member

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?

</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==