From 06069e65e04f17fe173f9e81741ae6f6201fa4a1 Mon Sep 17 00:00:00 2001 From: Josh Hannan Date: Fri, 16 Dec 2022 16:12:08 -0600 Subject: [PATCH] first draft of ftv2 FLIP --- application/20221219-ft-v2.md | 257 ++++++++++++++++++++++++++++++++++ 1 file changed, 257 insertions(+) create mode 100644 application/20221219-ft-v2.md diff --git a/application/20221219-ft-v2.md b/application/20221219-ft-v2.md new file mode 100644 index 00000000..b4f07f94 --- /dev/null +++ b/application/20221219-ft-v2.md @@ -0,0 +1,257 @@ +--- +status: draft +flip: NNN (do not set) +authors: Joshua Hannan (joshua.hannan@dapperlabs.com) +sponsor: Joshua Hannan (joshua.hannan@dapperlabs.com) +updated: 2022-12-19 +--- + +# Fungible Token Standard V2 + +## Objective + +This FLIP proposes multiple updates to the Flow Fungible Token Standard contracts, +primarily about encapsulating functionality within token resources instead of +with the contracts. There are other smaller quality of life changes to the token standard, +such as integration of metadata, improving error handling, +and including a transfer method and interface. +Some of these changes are dependent on other Cadence FLIPs being approved, +primarily [interface inheritance](https://github.com/onflow/flips/pull/40), +removal of nested type requirements, +and [allowing interfaces to emit events](https://github.com/onflow/cadence/issues/2069). + +Most of the changes proposed here would be breaking for all fungible token implementations +on the Flow blockchain, but should not be for third-party integrations such as +event listeners and apps that interface with the contracts. + +## Motivation + +The current fungible token standard for Flow +was designed in mid 2019, at a time when Cadence itself was still being designed. +The current standard, though functional, leaves much to be desired. + +The current token standard uses contract interfaces. +They are designed in a way which requires each concrete contract +to provide exactly one Vault type. +This means that any project that needs multiple tokens must deploy multiple contracts. +In the case of very simple tokens, this is a lot of complexity for very little value. + +Related to this problem, functionality and metadata associated with some tokens, +such as paths, events, and empty vault creation methods, +is only accessible directly through the contract itself, when it should also +be accessible directly through an instance of a token resource and/or interface. + +In the case of events, currently there is no way for the standard to ensure that +implementations are emitting standardized and correct events, which this upgrade will address. + +Additionally, the usage of nested type requirements creates some confusing +interactions, which are not useful and make learning about +and interacting with token smart contracts more difficult. + +## User Benefit + +With these upgrades, users will now be able to: +* Define multiple tokens in a single contract +* Query all the data about a token directly through the token resource and core interfaces +* Have standard events emitted correctly for important operations + +## Design Proposal + +[The original proposal](https://forum.onflow.org/t/streamlined-token-standards-proposal/3075/1) +is on the Flow Forum. +A [pull request with the suggested code changes](https://github.com/onflow/flow-ft/pull/77) +is in the flow fungible token github repository. + +The main code changes and their implications are described here. +The linked proposals provide more context. + +### Move Event Definitions and emissions to resource interfaces + +Instead of requiring events to be defined in the token implementations contracts, +they will only be defined in the fungible token standard smart contract and will +be emitted in post-conditions from the correct methods +in the resource interfaces defined in the standard. + +This feature is still being designed, so there is not a code sample yet. +See https://github.com/onflow/cadence/issues/2069 for potential examples + +### Add Type and Metadata parameters to events + +Standard events contain more information about the FT that is being transferred, +such as the type of the FT and important metadata about the FT. + +Here is an example of what this could look like: + +```cadence +pub event TokensDeposited(amount: UFix64, to: Address?, type: Type, ftView: FungibleTokenMetadataViews.FTView) +``` + +### Include Transferable Interface with transfer method + +For managing simple transfers, tokens can now implement the transferable interface +and the transfer method. + +```cadence + pub resource interface Transferable { + /// Function for a direct transfer instead of having to do a deposit and withdrawal + /// + pub fun transfer(amount: UFix64, recipient: Capability<&{FungibleToken.Receiver}>) + } +``` + +### Add `getAcceptedTypes()` method to `Receiver` interface + +It is useful to be able to query a fungible token receiver to see what types of tokens +it can accept. + +```cadence + pub resource interface Receiver { + + /// deposit takes a Vault and deposits it into the implementing resource type + /// + pub fun deposit(from: @AnyResource{Vault}) + + /// getAcceptedTypes optionally returns a list of vault types that this receiver accepts + pub fun getAcceptedTypes(): {Type: Bool} + } +``` + +### Remove the requirement for a `balance` field in `Vault` + +The requirement to include a `balance` field in Vault implementations is restrictive +because developers may want the vault balance to be a derived field. +This proposal replaces `balance` with a `getBalance()` method. + +```cadence + pub resource interface Balance { + + /// Method to get the balance + /// The balance could be a derived field, + /// so there is no need to require an explicit field + pub fun getBalance(): UFix64 + } +``` + +This field removal may not be worth the change, +because it will break a lot of scripts and transactions that rely +on borrowing the balance interface capability and querying the `balance` field. + +### Move `createEmptyVault()` to inside the Vault definition in addition to the contract + +It is useful to be able to create a new empty vault directly from a Vault object +instead of having to import the contract and call the method from the contract. + +```cadence +pub resource interface Vault { + + /// createEmptyVault allows any user to create a new Vault that has a zero balance + /// + pub fun createEmptyVault(): @AnyResource{Vault} { + post { + result.getBalance() == 0.0: "The newly created Vault must have zero balance" + } + } +} +``` + +### Add Metadata Views methods to the standard + +Metadata Views for fungible tokens should be easily accessible +from interfaces defined by the standard. Unlike the NFT standard though, +there isn't an obvious interface to add the methods to. + +The two options are: + +1. Add the methods `getViews` and `resolveView` to a new metadata interface. +This would be more logical, but it would require all accounts to update their +linked public capabilities to include the metadata interface, which is cumbersome. + +2. Add the methods `getViews` and `resolveView` to the `Balance` interface. +Calling it `Balance` would no longer be completely accurate, but it would not require +any users to update the links in their accounts. This is the option that seems the best. + + +### Drawbacks + +The main drawback of this upgrade is the breaking changes. +It could cause downtime for some projects who aren't prepared to perform the upgrade +right after stable cadence is enabled, +but that applies to any breaking change in stable cadence. +The updates that developers will have to do are fairly straightforward +and will not require much work. + +Please share any other drawbacks that you may discover with these changes. + +### Alternatives Considered + +1. Keep the standard the same: + * If nested type requirements are removed, this may not be possible + * This would avoid the breaking changes, which would be nice in the short term, but would not be setting up cadence developers for success in the long term. + +### Performance Implications + +All of the methods in the fungible token interface are expected to be O(1), +so there is no performance requirements to enforce with the methods. + +Adding metadata parameters to the standard events could cause event payloads +to be quite large if the metadata contained in the events is large. +We don't believe this will be a significant problem though. + +### Dependencies + +* Adds no new dependencies +* Dependent projects + * All fungible tokens on Flow and some projects that utilize them, + including but not limited to: + * flow-ft + * flow-core-contracts + * NFT Storefront + * kitty items + * usdc, fusd, blocto token, incrementfi, duc, etc.... + +### Engineering Impact + +* Build and test time will stay the same. they are relatively small changes. +* The Flow smart contract engineering team will maintain the code +* The code can be tested on its own once a compatible version of cadence is released. + +### Best Practices + +* Some of the changes illustrate Cadence best practices, such as encapsulating functionality +within resources, avoiding public fields, and giving developers flexibility to write composable code. + +### Tutorials and Examples + +* Coming soon once the proposal reaches a more final state + +### Compatibility + +* FCL, emulator, and other such tools should not be affected besides potentially +having to update standard transactions if they aren't compatible. + +### User Impact + +* The upgrade will go out at the same time as stable cadence if approved + +## Related Issues + +### Scoped Providers + +A critical piece of tooling for fungible tokens would be a struct that contains +a provider capability but restricts the capability to only be able to withdraw +a specified amount of tokens from the underlying vault. +Currently, providers have no limit, but all tokens should be able +to create scoped providers. + +This feature is out of the scope of this proposal, but should definitely be a standard +that lives alongside the main fungible token standard. +We hope to shepard a proposal for these soon. + +## Prior Art + +In combination with the upgrades to the NFT standard, we'd like for users to +be able to utilize more sophisticated functionality in their tokens, such as +what was enabled with an upgrade like ERC-1155 and other such upgrades in Ethereum. +We would greatly appreciate if any developers with ethereum experience could think +about these upgrades from the perspective of being able to create the same kinds +of projects that are possible with other token standards in other languages. \ No newline at end of file