w3f / PSPs

Polkadot Smart Contract Proposals
Creative Commons Zero v1.0 Universal
158 stars 68 forks source link

Fungible Token standard Proposal (WASM ERC20) #22

Closed 0xMarkian closed 3 years ago

0xMarkian commented 3 years ago

We think there is a need for a Fungible Token Standard in ink!. So we have developed a proposal and its implementation.

Summary

A standard interface for Ink! tokens.

This proposal aims to define the standard token in ink! smart contracts, just like EIP-20 for Ethereum ecosystem.

Importance

Currently, while there is no standard, every contract will have different signature. Thus, no interoperability is possible. This proposal aims to resolve that by having one trait(interface) that shares the same trait naming between all implementations, as naming of trait affects the identifiers of functions in this trait.

Implementation

Example implementation:

Motivation

A standard interface allows any Ink! tokens on Polkadot/Kusama to be re-used by other applications: from wallets to decentralized exchanges.

Motivation for having a standard separate from ERC20

Due to different nature of ink!, the standard should have ink!-specific rules and methods, therefore PSP-20 differs from ERC-20 in its implementation.

Also, this standard proposal defines an extensive method list in the trait (interface). Unlike ERC20, it includes increase_allowance & decrease_allowance, and defines metadata fields as part of a separate trait. Another difference is that it has PSP17Receiver trait, and on_received method is called at the end of transfer if the recipient is a contract.

The whole proposal can be found in PR

cmichi commented 3 years ago

Thanks for creating this PSP!

Since this is (AFAIK) the first effort for standardization in the ink! ecosystem, I think it makes sense to discuss the general approach we want to take here. My biggest concern is that by defining this standard on the layer of ink!, we restrict ourselves (and the ecosystem) unnecessarily.

The contracts pallet ‒ which is one layer below ink! ‒ is agnostic to the language/framework which compiles to the contract Wasm bytecode that uses its API. Hence, we would get the most benefit by defining the standard on that layer instead. So for your PSP this basically means that the specification would be the contract's ABI instead of ink! code:

$ cat psp-22.contract | jq '.spec | keys[]'
"constructors"
"docs"
"events"
"messages"

By defining the PSP on that layer it would be possible for other languages, frameworks, etc. to implement the standard as well.

What do you think?

0xMarkian commented 3 years ago

Hey @cmichi ! thanks a lot for replying. I agree, we are on uncharted territory here. We would like to contribute towards figuring out the most efficient process and approach. Have a few questions myself. Was wondering if there is a standard adoption/approval process somewhere defined/agreed upon? Or it has to be figured out?

Great point about the layer. It definitely makes sense to define standards on an ABI layer. However, because the ABI interface could be difficult to understand I would leave an ink's layer also in the section below, with the name Ink! layer example for example. How does that sound?

cmichi commented 3 years ago

Was wondering if there is a standard adoption/approval process somewhere defined/agreed upon? Or it has to be figured out?

I'm not aware of anything besides this repository. I think after we've merged the PSP it would be a good follow-up to adapt ink!'s erc20 example to implement this proposal and highlight that it exists. So that it becomes clearer that there is a specification for it.

Great point about the layer. It definitely makes sense to define standards on an ABI layer. However, because the ABI interface could be difficult to understand I would leave an ink's layer also in the section below, with the name Ink! layer example for example. How does that sound?

Sounds good, it should just be clear that the specification of the standard is what you find in the JSON fields of the ABI. So my suggestion is that you take the fields from the ABI (constructor, docs, events, messages) and make those the specification of this PSP.

0xMarkian commented 3 years ago

@cmichi thanks for a quick reply!

I think after we've merged the PSP it would be a good follow-up to adapt ink!'s erc20 example to implement this proposal and highlight that it exists. So that it becomes clearer that there is a specification for it.

If I have got you correctly Openbrush is doing an implementation of this proposal https://github.com/Supercolony-net/openbrush-contracts/blob/main/contracts/token/psp20/traits.rs

xgreenx commented 3 years ago

Sounds good, it should just be clear that the specification of the standard is what you find in the JSON fields of the ABI. So my suggestion is that you take the fields from the ABI (constructor, docs, events, messages) and make those the specification of this PSP.

Right, we will not include trait definition in the proposal. It will contain only links to examples of implementation of this standard.

Another topic which we want to discuss(it is described in the proposal but we want to highlight it). In the proposal, we described that transactions will revert on error instead of returning Result with error.

We agree that Rust provides more features than Solidity and it allows us to use Result. It provides more control during cross-contract calls. With this feature, someone can try to do a transfer, get an error, and try to process it(for example insufficient balance) again via another transfer with another amount.

But in the case of fungible tokens is seems over architected. It requires:

Result can be used in other contracts. But for fungible tokens, we prefer to simply revert.

athei commented 3 years ago

In the proposal, we described that transactions will revert on error instead of returning Result with error.

It is not exclusive. You can revert and still return an error. In fact this is what ink! should do when it returns an error. Returning an error when reverting is optional, though. One can just revert and not pass any data back. Then it is not really different from an unreachable. However, I would still use an revert in this case. unreachable should be reserved for exceptional errors (bugs basically).

xgreenx commented 3 years ago

@cmichi We've updated proposal to use ABI. But we have the question about events. Do we need to include identifiers of events and topics of these events? At the moment ink! doesn't add it to ABI.

0xMarkian commented 3 years ago

Hey @cmichi @athei ! do you think it makes sense at this point to merge this proposal to a draft directory and change the status to a Call for Feedback?

Noc2 commented 3 years ago

@themarkian Regardless of the call for feedback,I don’t think it hurts to merge a draft, but could you move the file into the drafts folder? Once this is done, I will merge it.

0xMarkian commented 3 years ago

@Noc2 moved the file. Would like to highlight that we are highly interested in leading & moving this process forward. We are prepared and planning to share it across different community channels, iterate, discuss, polish, and finally achieve a stable standard.