Streamlined Token Standards Proposal

@flowjosh one more comment here that I left in the flow-ft PR. We should consider a model where providers don’t have unchecked access to anything. For FTs that’s some kind of allowance, for NFTs that’s some kind of set of IDs that are approved. My assumption is that if we’re ever able to make that kind of change, it’s now

1 Like

Here’s a forums post for scoped providers so we can have that discussion:

1 Like

@flowjosh Could you please provide a summary of the current discussion, i.e. what the current sentiment is, and if and what any outstanding questions are? Thanks!

1 Like

We’ve only gotten feedback from a few people, so it is hard to know what the sentiment would truly be, but there are a lot of outstanding questions still:

  • Is getting rid of a nested type requirements actually better for the developer and are they actually a problem currently? (makes knowing what types the contract implements more difficult, discoverability without standard naming, etc)
  • Should events be defined at the contract level or within vault types? (this would need to be implemented in cadence)
  • Should the createEmptyVault function be at the contract level or in each vault? We need static functions for this, so it would also require new cadence work.
  • We also need interfaces to be able to implement other interfaces
  • We also need default implementations

Of the few people who have responded here, the basics of the proposal seem to be fairly popular in a vacuum. Most of the people here do not support using a generic collection for NFTs though, so that will probably be removed.

The biggest concern though is over the breaking changes. Making these changes would be huge and require significant changes to most fungible token and non-fungible token contracts on Flow. It isn’t clear yet if these changes are truly worth it or if there is a version that sacrifices some of the improvements to support an easier upgrade path.

1 Like

My thoughts on a few of the topics here:

NFT IDs

It’d be really great to ditch custom id fields and use uuid. Maybe I’m missing something, but given that all existing NFTs have a uuid field, would it be possible to allow users to upgrade to use the new Collection interface seamlessly?

Technical feasibility aside, I am still concerned about creating a split between V1 and V2 NFTs in the ecosystem. Is that something that’s still avoidable with this standard?

NFT collections

I see two general asks related to collections:

  1. Ease of use for users
  • Discoverability: it should be easy to know which NFTs a user owns.
  • Simple transfers: it should be easy to send an NFT to somebody without requiring them to set up a specific collection.
  • Safety: it should be hard for users to lose their NFTs to an exploit or become victims of a DoS (denial of storage :grinning_face_with_smiling_eyes:) attack.
  1. Flexibility for developers
  • Developers should be able to have control over the implementation of their project’s collection(s).

Of course ease of use and flexibility are always at odds with each other. But in this case I would argue that ease of use is far more important because we have an opportunity to drastically simplify NFT ownership for Flow end-users. I worry we may be prioritizing the needs of a small number of developers over the needs of a large number of users. Please don’t take that the wrong way; I love developers! :heart:

I don’t have numbers, but I’d guess that 95% of NFT projects on Flow copy the sample Collection implementation. From my perspective, custom collections are most useful for back-of-house operations (e.g. splitting minted NFTs into separate buckets, storing large numbers of NFTs).

some [developers] will still implement their own collections because they want to add certain features.

@jacob Do you have any examples of when it is beneficial for a user to store their NFTs in a custom collection written by the NFT developer? I’m trying to learn more about how custom collections are used in practice.

NFT transfer function

Right now I think the transfer function should be a helper function rather than a new interface. From what I can tell, these are the current pain points with transfers:

  1. There’s lots of boilerplate code in a simple transfer transaction. Calling a single function is much easier.
  2. Transferring to an account without the correct receiving collection fails.

Point 1 is solved by a helper function.

Point 2 is the real pain point IMO. But ultimately it’s solved by a universal receiving collection.

  • If the transfer function accepts a Receiver, then you still need to write the code to borrow the right receiver, which is the majority of the boilerplate anyways.
  • If the transfer function accepts an address, then the transfer function needs to be smart enough to know where the NFT should be deposited. This is really hard without a universal receiver.

NFT transfer events

I also don’t think there should be a new Transfer event.

I’m concerned about introducing additional complexity for NFT indexers. Currently an NFT indexer needs to watch for Withdraw and Deposit events. If both are seen in the same transaction, it can derive that a transfer occurred.

But that makes the new Transfer event redundant. Given that NFTs can move between accounts without without emitting Transfer (i.e. by calling withdraw and deposit directly), an indexer would need to either:

  1. Only listen to Transfer events and miss out on some transfers.
  2. Only listen to Withdraw and Deposit events, which would make me question the value of the Transfer event.
  3. Listen to all three events and resolve redundancies off chain, which is more complexity than required.
1 Like

@pete I’m a little confused about some of your comments, but I’ll go through them and we can try to get on the same page:

It’d be really great to ditch custom id fields and use uuid .

We don’t require that NFTs have a custom field any more, we just have the getID() method. If an NFT wants to just return the uuid for that, that is fine. Upgrading to the new collection interface should be fairly straightforward either way.

Technical feasibility aside, I am still concerned about creating a split between V1 and V2 NFTs in the ecosystem. Is that something that’s still avoidable with this standard?

The goal is to upgrade the standards to these new ones, not to deploy them alongside the old ones. So all projects would break and need to upgrade.

To your point about custom collections vs generic collections, I’m mostly with you. I think the ease of use of a generic collection beats out the desire for developers to have the flexibility to define their own, but I am sympathetic to wanting to avoid spam. If users have to pay for their own storage, then if they get spammed a bunch of NFTs, then they have to pay for it. But maybe that isn’t a concern if they have an easy way to clean up their collection. We’ve removed it from this proposal for now though because it isn’t part of the core proposal and was distracting too much from the other parts. I do want to put up another generic collection proposal soon though

Right now I think the transfer function should be a helper function rather than a new interface

I could probably get on board with this, though I am curious to hear what others think

I also don’t think there should be a new Transfer event.

Those are good points about the redundancy, but I think some others had some points that were valid about including transfer events that I have forgotten, so I’d love to have those summarized again.

Anyone else have thoughts on Peter’s comments?

1 Like

few comments:

  • ID uuid change : I think uuid can be better choice. We can get rid of id and getID both. It makes life much easier.

  • V1-V2 change seems can be non breaking as is

  • I was pro generic collection, but unfortunately we are not optimized enough yet for big collections. Gas usage is a bit mess.

  • in general generic collections can be harmful to the user too, we need onchain support contracts to limit access etc. some filters for providers / receivers etc

1 Like

We don’t require that NFTs have a custom field any more, we just have the getID() method

@flowjosh Sorry to clarify, I was proposing that we don’t use id or getID and instead just rely on the default uuid field. NFTs wouldn’t have the option of choosing their own ID.

The goal is to upgrade the standards to these new ones, not to deploy them alongside the old ones. So all projects would break and need to upgrade.

Got it, that makes sense!

1 Like

For getting rid of id and uuid, I totally agree that i would be better in a vacuum, but I worry about that breaking a lot of apps that already exist. I’m not concerned about breaking smart contracts, but a lot of different apps have their entire backends and such build around using the old ids for classification and interactions. It could potentially be extremely difficult for them to migrate to using uuid for everything. I really wish we could get their opinions on this so we could know.

V1-V2 change seems can be non breaking as is

There are definitely still breaking changes, but so far, they won’t be that bad.

1 Like

@flowjosh Is the intention here that a developer should be able to update an old nft v1 contract to make it compatible with v2? If that is the case I see your concern with getid josh.

I would just like to point out that there is a Serial view and the id semantics can be there. Also creating a helper functionality to map from serial → uuid is a little bit of work but not much.

@pete regarding new events. If the intention is to have the interface emit new events and not the implementation indexer semantics will change.

1 Like

@bjartek you’re correct. The goal is to upgrade the v1 standards. In that case, everyone would have to upgrade their contracts to be compatible with the new standards, so I’d like to design it so that the upgrade process is fairly smooth. We’re still open to deploying separate standards for v2, but since we still haven’t reached the stable cadence milestone yet, we’re still open to breaking changes to avoid complexity down the line with multiple token standards

1 Like

Thanks to everyone who came to the open house. Definitely a good discussion! The slides for the call are here and we’ll share the recording soon.

2 Likes

For the event requirements, I want to do a quick informal poll to see how people are feeling after seeing the initial proposals. I’ll link to the relevant github issues for the proposals if there are some. Please join in the discussion there if you have thoughts!

To recap, for Stable Cadence, we’d like to remove nested type requirements, but this would make it so our current event requirements for token contracts won’t be enforced, so we’d like to figure out how to continue to have standard events for tokens and not break app integrations with event listeners.

Vote in the poll below to indicate your support for one or more of them

This poll is not final or anything. We just want to take the temperature to see what people are generally feeling.
Thank you for your input!

1 Like
Event Enforcement
  • Keep Nested Type requirements only for events
  • Don’t enforce event requirements at all
  • Allow composite types to inherit events from interfaces
  • Allow interfaces to emit events

0 voters

1 Like

I just want to give a quick update here.

We’ve made a lot of good progress on the token standards in the past few months and I believe were nearing a solid final draft that we can align on, test thoroughly, and begin making a migration plan for.

The PRs are up to date with the latest drafts, so please check those out and give feedback! I want to have another community workshop again soon to bring up some remaining questions. I have a list that I still want to chat about and most of the topics are fairly minor, so I want to see if there are any more major concerns that we have before starting to finalize it.

This forum post is fairly out of date now too, so I’d like to move most of the discussion to the FLIPs from now on, so if you have comments, please leave them there.

Thanks for the help!

Another quick update! The token standards are basically complete and are in the latest emulator versions and in previewnet. I’m looking for approvals on the FLIPs and the PRs in the token standard repos, so anyone who has some time to look through them would be much appreciated!

NFT: FLIP 56: Non-Fungible Token Standard Version 2 by joshuahannan · Pull Request #56 · onflow/flips · GitHub
FT: FLIP 55: Fungible Token Standard Version 2 by joshuahannan · Pull Request #55 · onflow/flips · GitHub

1 Like