-
Notifications
You must be signed in to change notification settings - Fork 113
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Draft NEP 26 and Draft NEP 27: New NEPs describing onNEPXXPayment cal…
…lbacks (#169) * *: new NEPs describing onNEPXXPayment callbacks Fixes #168. Signed-off-by: Roman Khimov <roman@nspcc.ru> * nep-Z: add bNEO example Signed-off-by: Roman Khimov <roman@nspcc.ru> * nep*: mention ASSERT as well bNEO uses it and we can't say it's wrong. Signed-off-by: Roman Khimov <roman@nspcc.ru> * nep*: fix formatting Mediawiki is not Markdown. Signed-off-by: Roman Khimov <roman@nspcc.ru> * Update nep-Y.mediawiki Co-authored-by: Jimmy <jinghui@wayne.edu> * Update nep-Y.mediawiki Co-authored-by: Jimmy <jinghui@wayne.edu> * Rename nep-Y.mediawiki to nep-25.mediawiki * Update and rename nep-Z.mediawiki to nep-26.mediawiki * Update nep-25.mediawiki Co-authored-by: Jimmy <jinghui@wayne.edu> * Update nep-26.mediawiki Co-authored-by: Jimmy <jinghui@wayne.edu> * Update and rename nep-26.mediawiki to nep-27.mediawiki * Update and rename nep-25.mediawiki to nep-26.mediawiki * nep-26/27: clarify failure mode for unimplemented onNEPXXPayment Add a bit more details, signify the need for script hash check. Signed-off-by: Roman Khimov <roman@nspcc.ru> --------- Signed-off-by: Roman Khimov <roman@nspcc.ru> Co-authored-by: Shargon <shargon@gmail.com> Co-authored-by: Jimmy <jinghui@wayne.edu>
- Loading branch information
1 parent
69ccc34
commit c0e1fd5
Showing
2 changed files
with
204 additions
and
0 deletions.
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
<pre> | ||
NEP: 26 | ||
Title: Smart contract transfer callback for non-fungible tokens | ||
Author: Erik Zhang <erik@neo.org>, Roman Khimov <roman@nspcc.ru>, Jaime Kindelan <jaime@red4sec.com>, Jimmy Liao <jimmy@r3e.network> | ||
Type: Informational | ||
Status: Accepted | ||
Created: 2024-03-03 | ||
Requires: 11 | ||
</pre> | ||
|
||
==Abstract== | ||
|
||
This proposal describes the callback method used by Neo smart contracts to | ||
process transfers of non-fungible [[nep-11.mediawiki|NEP-11]] tokens to their addresses. | ||
|
||
==Motivation== | ||
|
||
While the original [[nep-11.mediawiki|NEP-11]] already defines this method, it | ||
lacks some details relevant specifically to the receiver contract and it doesn't | ||
allow for easy reference. This standard can be used in <code>supportedstandards</code> | ||
section of [[nep-15.mediawiki|NEP-15 manifest]] or in any other situation to | ||
refer to contracts able to receive [[nep-11.mediawiki|NEP-11]] tokens (but not | ||
necessarily being [[nep-11.mediawiki|NEP-11]] themselves). Typical use cases | ||
for this functionality are: depositing/staking (with contract locking and | ||
managing tokens according to some rules) or exchange/minting (contract accepting | ||
transfer to itself, but returning some different token to the sender). | ||
|
||
==Specification== | ||
|
||
Smart contracts that need to receive and own [[nep-11.mediawiki|NEP-11]] tokens | ||
MUST implement <code>onNEP11Payment</code> method with the following signature: | ||
|
||
<pre> | ||
{ | ||
"name": "onNEP11Payment", | ||
"parameters": [ | ||
{ | ||
"name": "from", | ||
"type": "Hash160" | ||
}, | ||
{ | ||
"name": "amount", | ||
"type": "Integer" | ||
}, | ||
{ | ||
"name": "tokenId", | ||
"type": "ByteString" | ||
}, | ||
{ | ||
"name": "data", | ||
"type": "Any" | ||
} | ||
], | ||
"returntype": "Void" | ||
} | ||
</pre> | ||
|
||
A contract that doesn't implement this method will not be able to receive | ||
[[nep-11.mediawiki|NEP-11]] tokens (standard requires this method to be called | ||
unconditionally which will fail at the system call level if it's not implemented | ||
which then leads to a complete transaction failure). This method is called by | ||
[[nep-11.mediawiki|NEP-11]] contracts which tokens are being transferred. A | ||
particular token can be obtained via the <code>System.Runtime.GetCallingScriptHash</code> | ||
system call. Notice that technically this method MAY be called by entry scripts or | ||
non-[[nep-11.mediawiki|NEP-11]] contracts as well, so contracts SHOULD check for | ||
caller script hash to match their expectations like allowed/accepted tokens. | ||
Processing this call means that contract trusts the caller to implement | ||
[[nep-11.mediawiki|NEP-11]] correctly. | ||
|
||
<code>from</code> parameter specifies the sender of tokens and can be <code>null</code> | ||
for minted tokens. | ||
|
||
<code>amount</code> is the amount of tokens transferred to the contract. It's | ||
always 1 for non-divisible [[nep-11.mediawiki|NEP-11]] tokens. | ||
|
||
<code>tokenId</code> is the transferred token ID. | ||
|
||
<code>data</code> is the same <code>data</code>parameter that was given to the | ||
[[nep-11.mediawiki|NEP-11]] <code>transfer</code> call. Contract can interpret | ||
it in any application-specific way including imposing any restrictions on | ||
accepted <code>data</code> contents. | ||
|
||
If the contract implementing this NEP can't accept the transfer (for reasons like | ||
unexpected token, wrong amount, forbidden sender, wrong <code>data</code> | ||
parameter or any other) it MUST call <code>ABORT</code> or <code>ABORTMSG</code> | ||
VM opcode to fail the transaction. This is the only way to ensure contract | ||
won't own transferred tokens, because the method doesn't return any value | ||
and exceptions can be handled by calling contract. Contact MAY also check for | ||
various conditions with <code>ASSERT</code> or <code>ASSERTMSG</code> opcodes. | ||
|
||
==Rationale== | ||
|
||
This NEP just follows and explains [[nep-11.mediawiki|NEP-11]] semantics, no | ||
design decisions made here. | ||
|
||
==Backwards Compatibility== | ||
|
||
This NEP is completely compatible with [[nep-11.mediawiki|NEP-11]], there are | ||
just two extensions to it: | ||
* addition of <code>ABORTMSG</code> opcode that didn't exist at the time of [[nep-11.mediawiki|NEP-11]] creation, but it's the same thing as <code>ABORT</code> semantically. | ||
* explicit <code>ASSERT</code> and <code>ASSERTMSG</code> opcode allowance that was not a part of [[nep-11.mediawiki|NEP-11]], but also has the same function as <code>ABORT</code> for failed conditions. | ||
==Implementation== | ||
|
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,100 @@ | ||
<pre> | ||
NEP: 27 | ||
Title: Smart contract transfer callback for fungible tokens | ||
Author: Erik Zhang <erik@neo.org>, Roman Khimov <roman@nspcc.ru>, Jaime Kindelan <jaime@red4sec.com>, Jimmy Liao <jimmy@r3e.network> | ||
Type: Informational | ||
Status: Accepted | ||
Created: 2024-03-03 | ||
Requires: 17 | ||
</pre> | ||
|
||
==Abstract== | ||
|
||
This proposal describes the callback method used by Neo smart contracts to | ||
process transfers of fungible [[nep-17.mediawiki|NEP-17]] tokens to their addresses. | ||
|
||
==Motivation== | ||
|
||
While the original [[nep-17.mediawiki|NEP-17]] already defines this method, it | ||
lacks some details relevant specifically to the receiver contract and it doesn't | ||
allow for easy reference. This standard can be used in <code>supportedstandards</code> | ||
section of [[nep-15.mediawiki|NEP-15 manifest]] or in any other situation to | ||
refer to contracts able to receive [[nep-17.mediawiki|NEP-17]] tokens (but not | ||
necessarily being [[nep-17.mediawiki|NEP-17]] themselves). Typical use cases | ||
for this functionality are: depositing/staking (with contract locking and | ||
managing tokens according to some rules) or exchange/minting (contract accepting | ||
transfer to itself, but returning some different token to the sender). | ||
|
||
==Specification== | ||
|
||
Smart contracts that need to receive and own [[nep-17.mediawiki|NEP-17]] tokens | ||
MUST implement <code>onNEP17Payment</code> method with the following signature: | ||
|
||
<pre> | ||
{ | ||
"name": "onNEP17Payment", | ||
"parameters": [ | ||
{ | ||
"name": "from", | ||
"type": "Hash160" | ||
}, | ||
{ | ||
"name": "amount", | ||
"type": "Integer" | ||
}, | ||
{ | ||
"name": "data", | ||
"type": "Any" | ||
} | ||
], | ||
"returntype": "Void" | ||
} | ||
</pre> | ||
|
||
A contract that doesn't implement this method will not be able to receive | ||
[[nep-17.mediawiki|NEP-17]] tokens standard requires this method to be called | ||
unconditionally which will fail at the system call level if it's not implemented | ||
which then leads to a complete transaction failure). This method is called by | ||
[[nep-17.mediawiki|NEP-17]] contracts which tokens are being transferred. A | ||
particular token can be obtained via the <code>System.Runtime.GetCallingScriptHash</code> | ||
system call. Notice that technically this method MAY be called by entry scripts or | ||
non-[[nep-17.mediawiki|NEP-17]] contracts as well, so contracts SHOULD check for | ||
caller script hash to match their expectations like allowed/accepted tokens. | ||
Processing this call means that contract trusts the caller to implement | ||
[[nep-17.mediawiki|NEP-17]] correctly. | ||
|
||
<code>from</code> parameter specifies the sender of tokens and can be <code>null</code> | ||
for minted tokens. | ||
|
||
<code>amount</code> is the amount of tokens transferred to the contract. | ||
|
||
<code>data</code> is the same <code>data</code>parameter that was given to the | ||
[[nep-17.mediawiki|NEP-17]] <code>transfer</code> call. Contract can interpret | ||
it in any application-specific way including imposing any restrictions on | ||
accepted <code>data</code> contents. | ||
|
||
If the contract implementing this NEP can't accept the transfer (for reasons like | ||
unexpected token, wrong amount, forbidden sender, wrong <code>data</code> | ||
parameter or any other) it MUST call <code>ABORT</code> or <code>ABORTMSG</code> | ||
VM opcode to fail the transaction. This is the only way to ensure contract | ||
won't own transferred tokens, because the method doesn't return any value | ||
and exceptions can be handled by calling contract. Contact MAY also check for | ||
various conditions with <code>ASSERT</code> or <code>ASSERTMSG</code> opcodes. | ||
|
||
==Rationale== | ||
|
||
This NEP just follows and explains [[nep-17.mediawiki|NEP-17]] semantics, no | ||
design decisions made here. | ||
|
||
==Backwards Compatibility== | ||
|
||
This NEP is completely compatible with [[nep-17.mediawiki|NEP-17]], there are | ||
just two extensions to it: | ||
* addition of <code>ABORTMSG</code> opcode that didn't exist at the time of [[nep-17.mediawiki|NEP-17]] creation, but it's the same thing as <code>ABORT</code> semantically. | ||
* explicit <code>ASSERT</code> and <code>ASSERTMSG</code> opcode allowance that was not a part of [[nep-17.mediawiki|NEP-17]], but also has the same function as <code>ABORT</code> for failed conditions. | ||
==Implementation== | ||
|
||
* https://github.com/nspcc-dev/neo-go/blob/8d67f17943553740fe4caa31c3e9efcf7921aba2/examples/nft-nd/nft.go#L213 | ||
* https://github.com/nspcc-dev/neofs-contract/blob/91962f2c5625d8aab42adde138f2411c52393382/contracts/neofs/contract.go#L237 | ||
* https://github.com/neoburger/code/blob/beb433288bd7b0da9d2245e2a0ae5af5309da7ed/BurgerNEO.cs#L42 |