aptos-core
aptos-core copied to clipboard
Coin metadata considered harmful
The Coin standard should be slimmed down to only include decimals
and supply
in its metadata. The fields name
and symbol
should be removed.
Justification
Metadata should be a separate concern from the primal interface for coins. Here are some reasons why coupling metadata to the coin standard may not be an optimal design decision:
- Not all coins have a name or symbol. Sometimes coins are implementation details for internal bookkeeping, and not meant for public discovery.
- Some people will not find it intuitive that a coin has both a name & a symbol.
- Some people will want richer metadata (such as logo URLs or longform description). 3a. A versioned metadata standard is better suited to this kind of evolving feature. 3b. Given that developers will use an additional on-chain metadata registry anyway to store logo URLs (etc), it is cleaner to shift all non-essential metadata to a built-to-purpose coin registry.
- The name and symbol of coins should be upgradeable. For example, a project may change its branding but wants to retain the same coin type. If the coin standard has
name
&symbol
, then it should provide an interface to alter them -- but this growing complexity is creeping beyond the scope of the standard. - The standard does not enforce uniqueness of name nor symbol. This is a possible source of confusion & debate, and best to be avoided when designing this fundamental interface.
- The extra metadata requires extra storage. This is not likely a huge issue, but it is still best to be parsimonious with basic interfaces.
- The datatype for name & symbol may not be future proof. Its type was already changed once (to
String
). It would be better to have this kind of coupling to datatypes done with a versioned metadata program. - The attributes
name
andsymbol
have a different quality thandecimals
. Thedecimals
attribute is practically required in all cases to know the value of a coin. But most programs can (and should!) effectively ignorename
andsymbol
. There are no constraints nor uniqueness guarantees forname
andsymbol
, so they cannot be used to index coin types. These arbitrary strings are more akin to "tags", and when viewed as such, it is strange to have only 2 of them.
Suggestion
Create a versioned metadata registry that can store coin information on-chain. Owners of coins may opt-in to publishing their metadata. In the inevitable event that the metadata standard requires an update, a new on-chain version can run in parallel to the old.
This registry will take on the complexity of updates to coin metadata, enforcing constraints, and making the data available.
Counter-arguments
- Justification item 1 is wrong -- all coins do have a name & symbol.
- A separate coin registry is extra work.
- With a separate registry module, creating a coin & posting its metadata will take 2 transactions instead of 1.
- Changing this now will cause a lot of developer headache.
Hey,
I appreciate you summarized it all in one place.
What I can add there is I saw already several times how developers are trying to use coin symbols as some ID in their code, like:
let symbol = coin::symbol<T>();
if (symbol == b"USDT") { do something };
As the symbol and name are not unique, it's an easy way to make a mistake in a smart contract which will eventually lead to security issues.
Yikes. Yes, I can imagine that the symbol
attribute can be a source of confusion for people.
The funny thing is that name
and symbol
almost certainly should be ignored by on-chain programs, since there are no guarantees as to their value's uniqueness nor their meaning.
Which indicates that name
& symbol
are mostly a matter of "off-chain" concern.
Thanks for this issue!
I'm not going to argue about the notion of name and symbol, I don't follow the logic where they might not have one or the other or it might be unintuitive to not have both. You also argued with yourself :smile: .
While we can leave this issue open, we won't be changing it for myriad reasons:
- We have entered a point in contracts where we can no longer change the ABI.
- Someone could just as well use
string::utf8(type_info::struct_name(type_info::type_of<T>())
to get some other name - The use of on-chain metadata for what the coin is intended to represent is valuable. My only regret is that we didn't put a URL in there for folks to identify it... maybe we need to add a CoinInfo v2 -- never too late :)
- A central registry is not something that I think we should be building at the start, it becomes a land grab exercise and requires attention. I would love to see the community come together to build this.
If we notice that there are practical (not theoretical) security concerns around name and symbol, we can minimally abort on those functions and prevent further use of them.
This is a decentralized framework. NFTs also can have the same name and collection name. Individuals can easily be confused if they ignore the TokenId and just use collection name or name alone.
I reckon there is no right or wrong way here. My perspective is we should have richer data on chain in ChainInfo. I wish we had added a field for URL as well. :slightly_frowning_face: ... I think ultimately the longer term solution is to have an on-chain registry.
Also it is worth noting that we can easily update CoinInfo to CoinInfov2 with more fields. We would then check the existence of v2 first and then v1 if it didn't exist. We could also add migration capability... so in the event that we want to revamp the coin standard.. there's infinite possibility, but let's iterate a bit and see what other things we overlooked.
Thanks for the discussion & keeping the issue alive.
One way to boil down the argument is to ask: when should an on-chain program make use of the name
or symbol
? I can't come up with an example. Since neither of these can uniquely identify a coin, and any filter based on symbol/name can fall victim to spoofing, these fields are almost certainly red herrings for on-chain logic.
A corollary is that metadata around a coin is only for off chain concerns. And that's why a URL makes so much sense! Solana adopted this pattern - where the on-chain coin type only had the barest metadata (decimal precision, owner).
Now, it's certainly nice to have on-chain storage for coin metadata, since that storage can be a single source of truth. But once we go down that route, then we need to have logic for administering it. And that can get pretty hairy for 1 module, especially a primitive module like Coin
.
As for the "landgrab" quality of a registry, I'd suggest that the semantics should never guarantee uniqueness for URL/name/symbol or anything besides the primary key for a coin (which is its "type"). The only ownership we can check on-chain is whether the signer has the same address and the type, and so there's no practical way to regulate that this coin is the real USDT, anyway.
It's not really important that the registry is "centralized" -- just that coin metadata administration is a separate concern, warranting a separate module. This way, as the coin metadata gets richer, the raw CoinInfo
would stay the same. People can just opt in to storing their metadata on chain.
Great arguments. I can see we are arguing on opposite ends of the spectrum. In one case, you prefer more off-chain, but I feel very much like that's way too centralized and leads open to questions of what am I looking at. You are right in that we currently don't have any admin functionality around coins, but we could theoretically add it at some point in time for future coins.