-
Notifications
You must be signed in to change notification settings - Fork 142
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
Interactive Fungible Token #136
Comments
Related work: NEP-122 Allowance-free vault-based token standard |
Comparing to #122 this standard doesn't allow to withdraw only a part of tokens during |
@evgenykuzyakov - this is solved by creating a return reminder receipt:
Security wise: in all cases (approve, vault, transfer_call) we can't protect from a greedy contract which will like to take more than it should. |
BTW please the main repository for more details and analysis. Maybe I should paste the whole content of it into this issue description? |
Yes. Please post all details here. Also explain the flow of the If the receiver doesn't have tokens until it returns If you already have tokens, then why do you even need to return So to make this standard more robust, we need to go through a few scenarios where at least some composability is involved. e.g. vault token standard allows for this to happen by separating tokens from sender and receiver accounts before they are accepted and partially/fully used. |
I've updated the description, It's long, so I think it's easier to read it from: https://github.com/robert-zaremba/nep-136-fungible-token |
@evgenykuzyakov here is how it works. Let's say user wants to transfer tokens
IMHO, we need to update balance before calling B to assert proper contract composability. Error scenarios must be handled through promise callbacks.
Right, I will change the |
I also should note that NEP-21 doesn't support smart contract composability through token transfer (adding this to the description). |
@robert-zaremba - thanks and nice job for writing this up. It definitely proposes great ideas that address integration and UX issues. For reference, I posted my feedback and thoughts on the NEP-122 discussion thread. |
I have updated the description:
Please see the Smart contract interface file for more details and function comments. Initially, I made the
But after thinking more about it, I decided to only allow the caller to register itself. |
What do you think if This allows to support vault like functionality, e.g. non-complete withdrawals. It also prevents accidental acceptance.
I've used
Registration is payable, and it maybe beneficial to register your friends account when sending them tokens. Mandatory registration will prevent this. As for compliance, you don't completely solve this. Since once you register, anyone can send you tokens. EDIT: To cross link, here is a comment from NEP-122: #122 (comment) |
@evgenykuzyakov What's the benefit of returning |
It will save a round trip to do this. Since the callback result is already going back to the token contract, then we can just use this almost for free. |
This sounds like a flaw of the wallet. Requiring |
Good comment. It solves only part of it - that I can decide which tokens I want to use. This will be useful for smart contract recipients. I know that Stellar and Algorand requires user opt-in for an asset to allow sending that asset to a user. It's driven there by the storage design and it's also motivated by a spamming protection. Let's think about it more - we can make an additional, optional method: Compliance is a complex thing. Services will have to have compliance rules both on the token contract side and recipient contracts. Thus my require to use only |
Well, for common tokens it will be possible to protect, but users are stupid, so it's possible to trick the user to accept the authorization towards a new contract. |
So, do you suggest that all "critical" user related methods must be |
I guess we don't need to enforce it using payable once there is contract level metadata that can mark methods as require confirmation. This may show a big warning on the Wallet, when an access key with such method is requested. Similarly when you request a full-access key. @vgrichina @kcole16 |
Yes, this is better approach. |
regarding #122 (comment) - to consolidate and reset with new NEPs ... |
Will close it once an alternative will be out |
also it kinda prevents actually granting authorization to token contract if I want. like say if I'm logging in into Berry Club app – I might reasonably want to trust it managing bananas and cucumbers without approve each time |
NEP-141 came through my proposal near#136 as a more robust Interface for Fungible Tokens and reflection from the previous NEP-122. Prior to that we were discussing the pitfalls for ERC20 and a better solution that would serve NEAR ecosystem needs. See Rationale described in near#136. I was part of the core research (together with Evgeny, @oysterpack and @luciotato) designing the NEP-141, where we hardened the design by analyzing the storage use cases and metadata management.
@robert-zaremba Do you believe we can close this issue as resolved given that we have NEP-141 and a few extensions already approved? |
NEP-141 came through my proposal #136 as a more robust Interface for Fungible Tokens and reflection from the previous NEP-122. Prior to that we were discussing the pitfalls for ERC20 and a better solution that would serve NEAR ecosystem needs. See Rationale described in #136. I was part of the core research (together with Evgeny, @oysterpack and @luciotato) designing the NEP-141, where we hardened the design by analyzing the storage use cases and metadata management.
Wow, I thought we closed it 1.5 year ago ;) |
Following early discussion about NEP-21, the work on NEARswap and author work on security tokens in Ethereum ecosystem, we propose a new fungible token standard.
Rationale
The only approved token standard in NEAR ecosystem is NEP-21.
It's an adaptation of ERC-20 token standard from Ethereum. Both NEP-21 and ERC-20 are designed to be minimalistic and functional: provide clear interface for token transfers, allowance management (give access to token transfers to other entities or smart-contract - this is useful if other smart contract wants to withdraw it's allowance for things we buy). The ERC-20 standard is the first standard Ethereum fungible token standard and created lot of legacy. All early tooling (wallets, explorers, token templates) were build with ERC-20 in mind. Over time, the ecosystem listed many problems related to ERC-20 design:
decimals
should be required, rather than optional. This is essential to user-friendly token amount handling.transfer
andtransferFrom
are lacking a reference (memo) argument - which is essential for compliance reasons. We need to be able to be able to link the transfer to an an external document (eg: invoice), order ID or other on-chain transaction or simply set a transfer reason.transfers
to smart-contract in general is an error and should be protected. Both in Ethereum in NEAR, smart-contracts are NOT notified if someone is sending them tokens. This causes funds lost, token locked and many critical misbehavior.approve
(allowance creation) andtransferFrom
, which is less intuitive and makes UX more complex: not only we need to create and keep track of right allowance (with all edge cases: user creates allowance, but token is not callingtransferFrom
and makes user to create another allowance).approve
+transferFrom
, the business provider has to make an additional transaction (transferFrom) and calculate it in the operation cost.There are few articles analyzing ERC-20 flaws (and NEP-21): What’s Wrong With ERC-20 Token?, Critical problems of ERC20 token standard.
And the NEP-110 discussion: #110 addressing same issues in a bit different way.
Related work
Token design
We propose a new token standard to solve issues above. The design goals:
Our work is mostly influenced by the aforementioned ERC-223 and NEP-122: Allowance-free vault-based token standard.
Transfer reference (memo)
We add a required
memo
argument to all transfer functions. Similarly to bank transfer and payment orders, thememo
argument allows to reference transfer to other event (on-chain or off-chain). It is a schema less, so user can use it to reference an external document, invoice, order ID, ticket ID, or other on-chain transaction. Withmemo
you can set a transfer reason, often required for compliance.This is also useful and very convenient for implementing FATA (Financial Action Task Force) guidelines (section 7(b) ). Especially a requirement for VASPs (Virtual Asset Service Providers) to collect and transfer customer information during transactions. VASP is any entity which provides to a user token custody, management, exchange or investment services. With ERC-20 (and NEP-21) it is not possible to do it in atomic way. With
memo
field, we can provide such reference in the same transaction and atomically bind it to the money transfer.Decimal management
Lack of decimals creates difficulty for handling user experience in all sorts of tools
As mentioned in the Rationale, for interactions with tools and assure good UX, we need to know the base of token arithmetic.
ERC-20 has an optional
decimals
contract attribute, other Ethereum standards makes this attribute obligatory. We follow the ERC-777 proposal, and fix the decimals once and for all:granularity
concept from ERC-777: the smallest part of the token that’s (denominated in e18) not divisible. The following rules MUST be applied regarding the granularity:Reactive transfers
Instead of having
approve
+transferFrom
, we propose atransfer_call
function which transfer funds and calls external smart-contract to notify him about the transfer. This function essentially requires that a recipient must implementTransferCallRecipient
interface described below.Security note for
transfer_call
In synchronous like environment (Ethereum EVM and all it's clones), reactive calls (like
transfer_call
, ortransfer
from ERC223) are susceptible for reentrancy attacks. In the discussion below lets denote a transaction for contractA
which calls external smart contractB
(we writeA->B
).An attack vector is to call back the originating smart-contract (
B->A
) in the same transaction - we call it reentrancy. This creates various issues since the reentrance call is happening before all changes have been committed and it's not isolated from the originating call. This leads to many exploits which have been widely discussed and audited.In asynchronous environment like NEAR, an external smart contract call execution is happening in a new, isolated routine once the originating call finished and all state changes have been committed. This eliminates the reentrancy - any call from external smart contract back to the originating smart contract (
A->B->A
) is isolated from the originating smart-contract. The attack vector is limited and essentially it's "almost" reduced to other attacks happening in separate transaction. Almost - because a user still need to manage the callbacks.Handling not accepted calls
If a recipient of
transfer_call
fails, we would like to preserve the tokens from being lost. For that, a token MAY implement pattern developed by NEP-110: when sending tokens throughtransfer_call
, append afinalize_token_call
callback promise to theon_ft_receive
call. This callback will check if the previous one was successful, and if not, it will rollback the transfer.You can check the NEP-110
handle_token_received
implementation (the NEP-110 reference implementation useshandle_token_received
for function name instead offinalize_token_call
). This function shouldn't be called externally.We propose to standarize the final call back:
finalize_token_call
as a function namerecipient.on_ft_receive
, don't pass all NEAR for fees. Reserve some NEAR forfinalize_token_call
to make sure we will be able to handle both scenarios: whenon_ft_receive
succeeds and when it fails.Metadata
NEP-110 stores metadata on chain, and defines a structure for the metadata.
We adopt this concept, but relax on it's content. Metadata should be as minimal as possible. We combine it with other token related data, and require that a contract will have following attributes:
Comparative analysis
We improve the token NEP-110 design by:
We improve the NEP-122 design by:
We improve the NEP-21 design by:
Advantages of NEP-21
The pay to smart-contract flow (
approve
+tranferFrom
), even though it's not very user friendly and prone for wrong allowance, it's very simple. It moves a complexity of handling token-recipient interaction from the contract implementation to the recipient. This makes the contract design simpler and more secure in domains where reentrancy attack is possible.Token interface
Please look at the source code for more details and comments.
The text was updated successfully, but these errors were encountered: