NEP 141 Standard #146
Replies: 12 comments 27 replies
-
@mikedotexe looks like theres a duplicate Question -- where did the discussion end up on namespaced methods? Is that the path forward for other NEPs in the future? |
Beta Was this translation helpful? Give feedback.
-
Why do you call it |
Beta Was this translation helpful? Give feedback.
-
I am putting together a tutorial for NEP-141 and feedback would be appreciated: https://github.com/oysterpack/datahub-learn/blob/master/network-documentation/near/tutorials/stake/2-fungible-token.md |
Beta Was this translation helpful? Give feedback.
-
FYI - I implemented NEP-141 in my STAKE project: Rust implementation and as a heads up when reading the code ... the "low level" API defined by NEP-141 uses The code is unit tested and functional. I did some simple manual ft_transfers on testnet. The only thing I haven't fully tested yet end-to-end is the transfer call flow. |
Beta Was this translation helpful? Give feedback.
-
Let's also move security notes here and the background as well. |
Beta Was this translation helpful? Give feedback.
-
Metadata #148Last part of finalizing the Fungible Token standard is describing an interface for Metadata. Here is the discussion to find the right design: #148 |
Beta Was this translation helpful? Give feedback.
-
(REJECTED) Change proposalRename |
Beta Was this translation helpful? Give feedback.
-
@evgenykuzyakov is there an easy way to check if an account has a contract or not? |
Beta Was this translation helpful? Give feedback.
-
Suggested rewrite:
But is this accurate? Both core change methods say "exactly 1 yoctoNEAR must be attached." This makes it seem like the enforcement of "exactly 1 yoctoNEAR" is part of the standard. |
Beta Was this translation helpful? Give feedback.
-
NEP146 contracts are not required to use such a vault, correct? Is #122 worth mentioning here? I'd prefer we state the security properties without such a link, if possible. As a newcomer to both NEP146 and NEP122, I don't actually understand the security properties here yet, and I'm hesitant to try to figure it out by reading all of the lengthy (and probably mostly irrelevant) discussion in #122. The statement I just pasted seems to contradict an earlier statement in the
This implies the receiver contract can overspend the tokens. But the Security note says that it cannot. Which is it? |
Beta Was this translation helpful? Give feedback.
-
Will we add a "Motivations" section, explaining the intended use of the various calls? Having started with this discussion, I don't understand the intended use-cases of |
Beta Was this translation helpful? Give feedback.
-
Playing around with the NEP-141 standard in our current code base. Problem I'm running into is that I would prefer for users not to have to "pre-pay" storage. I think the standard still holds true but it would be better if in the transfer_and_call method we'd allow for > 1 yocto and assume that all yocto attached would be used to fund storage on the target contract. The implementation would be more similar to this:
I think the pre-paid model is a good fallback model but that it should be optional since it does require an extra step and will throw users / frontend devs off once storage runs out. Maybe this would cause the same issue as we're trying to solve before where a user's deposit would get "stuck" in the token contract if the promise fails but I think this could be handled in resolve_transfer |
Beta Was this translation helpful? Give feedback.
-
THE STANDARD WAS MERGED: https://nomicon.io/Standards/FungibleToken/Core.html
Moving the comments discussion from #141 to here.
API
Function Token Core API
ft_transfer
- Simple transferchange method
Transfers positive
amount
of tokens from theenv::predecessor_account_id
toreceiver_id
.Both accounts must be registered with the contract for transfer to succeed. (See #145)
This method must to be able to accept attached deposits, and must not panic on attached deposit. Exactly 1 yoctoNEAR must be attached. See the Security section of the standard.
Arguments:
receiver_id
- the account ID of the receiver.amount
- the amount of tokens to transfer. Must be a positive number in decimal string representation.memo
- an optional string field in a free form to associate a memo with this transfer.ft_transfer_call
- Transfer to a contract with a callback.change method
Transfers positive
amount
of tokens from theenv::predecessor_account_id
toreceiver_id
account. Thencalls
ft_on_transfer
method onreceiver_id
contract and attaches a callback to resolve this transfer.ft_on_transfer
method must return the amount of tokens unused by the receiver contract, the remaining tokensmust be refunded to the
predecessor_account_id
at the resolve transfer callback.Token contract must pass all the remaining unused gas to the
ft_on_transfer
call.Malicious or invalid behavior by the receiver's contract:
receiver_id
balance is lower than the required refundamount, the remaining balance must be refunded. See the Security section of the standard.
Both accounts must be registered with the contract for transfer to succeed. (See #145)
This method must to be able to accept attached deposits, and must not panic on attached deposit. Exactly 1 yoctoNEAR must be attached. See the Security
section of the standard.
Arguments:
receiver_id
- the account ID of the receiver contract. This contract will be called.amount
- the amount of tokens to transfer. Must be a positive number in a decimal string representation.msg
- a string message that will be passed toft_on_transfer
contract call.memo
- an optional string field in a free form to associate a memo with this transfer.Returns a promise which will result in the amount of tokens withdrawn from sender's account.
ft_total_supply
- Returns total supplyview method
Returns the total supply of the token in a decimal string representation.
ft_balance_of
- Returns account balanceview method
If the account doesn't exist must returns
"0"
.Arguments:
account_id
- the account ID to view the balance.Returns the balance of the given account in a decimal string representation.
Transfer Receiver API
ft_on_transfer
- Callback on transfer callchange method
Called by fungible token contract after
ft_transfer_call
was initiated bysender_id
of the givenamount
with the transfer message given inmsg
field.The
amount
of tokens were already transferred to this contract account and ready to be used.The method must return the amount of tokens that are not used/accepted by this contract from the transferred
amount. Examples:
500
, the contract completely takes it and must return0
.500
, but this transfer call only needs450
for the action passed in themsg
field, then the method must return
50
.500
, but the action inmsg
field has expired and the transfer must becancelled. The method must return
500
or panic.Arguments:
sender_id
- the account ID that initiated the transfer.amount
- the amount of tokens that were transferred to this account in a decimal string representation.msg
- a string message that was passed with this transfer call.Returns the amount of unused tokens that should be returned to sender, in a decimal string representation.
Notes
memo
field is explained in details in #136The goal is to associate some external information with the transfer on chain. It may be needed for compliance in some
jurisdictions.
Security
Requirement for accept attached deposits (
#[payable]
)Due to the nature of function-call permission access keys on NEAR protocol, the method that requires an attached deposit
can't be called by the restricted access key. If the token contract requires an attached deposit of at least 1
yoctoNEAR on transfer methods, then the function-call restricted access key will not be able to call them without going
through the wallet confirmation. This prevents some attacks like fishing through an authorization to a token contract.
This 1 yoctoNEAR is not enforced by this standard, but is encouraged to do. While ability to receive attached deposit
is enforced by this token.
Transfer Call Refunds
If the receiver contract is malicious or incorrectly implemented, then the receiver's promise result may be invalid and
the required balance may not be available on the receiver's account. In this case the refund can't be provided provided
to the sender. This is prevented by #122 standard that locks funds into a temporary
vault and prevents receiver from overspending the funds and later retuning invalid value.
But if this flaw exist in this standard, it's not an issue for the sender account. It only affects the transfer amount
and the receiver's account balance. The receiver can't overspend tokens from the sender outside of sent amount, so this
standard should be considered as safe as #122
Conceptual context
As discussed in the recorded call from January 18th, 2021, some context around gas usage and promises is helpful to add.
This standard mentions using promises to make a cross-contract call and then capture the result. With NEAR, each promises is given an amount of gas. Each promise can therefore have it's "own bucket" of gas separate from other promises. This means that if Contract A calls Contract B, and expects to analyze the result back in Contract A, it can allocate gas accordingly. Put another way, Contract B cannot run an infinite loop that drains all the gas and interfere with the callback on Contract A. This also means that assertions can be written into contracts like the one discussed here, ensuring that there will be enough gas attached to perform all the operations needed.
Beta Was this translation helpful? Give feedback.
All reactions