The main things we need from token standards are minting and burning of fungible and non-fungible tokens, as well as events. We need to now determine if we SHOULD have standard function names for minting and burning, and if so, if they should be in a single standard or two. (For minting, for burning.)
Illia is proposing we do not have function names and instead only events:
Wondering how this will work with NFT contracts "out there" that are using nft_mint
that indexer and Wallet have worked around in order to show them as collectibles.
Question: should mint and burn be in the same extension standard? I believe the same should apply for fungible tokens and non-fungible tokens. Currently, Robert and Blaze have this PR open: near/NEPs#249 which only has minting. I think it's reasonable to have them separate.
What does burning look like on:
- Fungible tokens:
// Returns total supply as stringified uint128
function ft_burn(
account_id: string,
amount: string
): string {
// If burning tokens transfers them to another owner, must use event
// If burning redues the total supply, reduce it and return new value
}
- Non-fungible tokens
Note: it's useful to peek at the OpenZeppelin NFT burn
function and fungible token burnFrom
function.
function nft_burn(
owner_id: string,
token_id: string,
approval_id: number|null
) {
// If burning transfers it to another owner, must use event
}
What does minting look like on:
- Fungible tokens:
Exactly like Robert has here:
near/NEPs#249
with the change of memo
being msg
that contains custom data for the contract.
- Non-fungible tokens:
// This method is expected to mint one NFT. If custom logic exists to mint more than one,
// events must be used in order for indexers to pick this up.
// Arguments:
// * `receiver_id`: the valid NEAR account receiving the newly-minted token.
// * `token_id`: the token ID to mint.
// * `msg`: specifies information needed during the minting process.
// It is up to the contract to parse this extra data.
// If it contains data that is intended to be indexed, it must use an event.
function nft_mint(
receiver_id: string,
token_id: string,
msg: string|null
) {}
See this comment about how folks aren't understanding storage. As we hand this off, seems like we'll need to underscore this. Basically, "don't save key value pairs you don't need to, just use a struct that'll return what's expected." near/NEPs#262 (reply in thread)
See my concerns in this comment as well. Right now we only have people in the NFT discussions who are deep into art NFTs being sold on marketplaces. This is not the only use case for NFTs. Perhaps "metdata versions" isn't a good match and instead we can have "metadata variants" as described here: near/NEPs#262 (comment)
There are a lot of discussions regarding the concerns with metadata being in state. I agree, but it feels like it's being taken too far.
- Decentralized storage has improved, but is not perfect by any means and has single points of failure.
(Source: https://twitter.com/SolanartNFT/status/1426756041967083526)
- There are other NFTs that aren't art, like membership NFTs, where timestamps and other info should be stored on-chain and let's not forget about them.
Lastly, I think this might be a good approach, although I may have failed to explain why:
(from https://gov.near.org/t/improving-customizable-near-contract-standards/5649)
Perhaps this is more on the Rust SDK side, but I have heard this concerns several times from folks making NFTs that it's quite difficult to customize them. I think we should have the standard methods less "magical" and have them in the lib.rs
file instead of created behind the scenes using macros. If someone wants to use all the vetted implementations, then it would look like the first function there (nft_token
) but allow for customization. Note that as Illia pointed out, we likely don't need another crate, but I believe this is what NFT folks would prefer. This comes from feedback I've heard from Matt Lockyer from Satori and Ben Kurrek + Josh Ford from DevRel.