| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Name | Name | Last commit date | ||
|---|---|---|---|---|
This is a description of the Flow standard for fungible token contracts. It is meant to contain the minimum requirements to implement a safe, secure, easy to understand, and easy to use fungible token contract. It also includes an example implementation to show how a concrete smart contract would actually implement the interface.
Flow is a new blockchain for open worlds. Read more about it here.
Cadence is a new Resource-oriented programming language for developing smart contracts for the Flow Blockchain. Read more about it here and see its implementation here
We recommend that anyone who is reading this should have already completed the Cadence Tutorials so they can build a basic understanding of the programming language.
Resource-oriented programming, and by extension Cadence, is the perfect programming environment for currencies, because users are able to store their tokens directly in their accounts and transact peer-to-peer. Please see the blog post about resources to understand why they are perfect for digital assets.
The FungibleToken, FungibleTokenMetadataViews, and FungibleTokenSwitchboard contracts are already deployed on various networks. You can import them in your contracts from these addresses. There is no need to deploy them yourself.
| Network | Contract Address |
|---|---|
| Emulator | 0xee82856bf20e2aa6 |
| Testnet | 0x9a0766d93b6608b7 |
| Sandboxnet | 0xe20612a0776ca4bf |
| Mainnet | 0xf233dcee88fe0abe |
The Burner contract is also deployed to these addresses, but should only be used in Cadence 1.0 FungibleToken implementations of the standard.
The code for the standard is in contracts/FungibleToken.cdc. An example implementation of the standard that simulates what a simple token would be like is in contracts/ExampleToken.cdc.
The exact smart contract that is used for the official Flow Network Token (FlowToken) is in the flow-core-contracts repository.
Example transactions that users could use to interact with fungible tokens are located in the transactions/ directory. These templates are mostly generic and can be used with any fungible token implementation by providing the correct addresses, names, and values.
The standard consists of a contract interface called FungibleToken that defines important functionality for token implementations. Contracts are expected to define a resource that implement the FungibleToken.Vault resource interface. A Vault represents the tokens that an account owns. Each account that owns tokens will have a Vault stored in its account storage. Users call functions on each other's Vaults to send and receive tokens.
The standard uses unsigned 64-bit fixed point numbers UFix64 as the type to represent token balance information. This type has 8 decimal places and cannot represent negative numbers.
Specifies that the implementing type must have a UFix64 balance field.
Defines a withdraw function for withdrawing a specific amount of tokens as amount.
Defines an isAvailableToWithdraw() function to ask a Provider if the specified number of tokens can be withdrawn from the implementing type.
Defines functionality to depositing fungible tokens into a resource object.
Defines Functionality for Getting Supported Vault Types
Users could create custom Receivers to trigger special code when transfers to them happen, like forwarding the tokens to another account, splitting them up, and much more.
Interface that inherits from Provider, Receiver, Balance, ViewResolver.Resolver, and Burner.Burnable and provides additional pre and post conditions.
The ViewResolver.Resolver interface defines functionality for retrieving metadata about a particular resource object. Fungible Token metadata is described below.
See the comments in the Burner contract for context about it. Basically, it defines functionality for tokens to have custom logic when those tokens are destroyed.
Defines functionality in the contract to create a new empty vault of of the contract's defined type.
This spec covers much of the same ground that a spec like ERC-20 covers, but without most of the downsides.
FT Metadata is represented in a flexible and modular way using both the standard proposed in FLIP-0636 and the standard proposed in FLIP-1087.
A guide for NFT metadata is provided on the docs site. Many of the concepts described there also apply to fungible tokens, so it is useful to read for any Cadence developer.
When writing an FT contract interface, your contract will implement the FungibleToken contract interface which already inherits from the ViewResolver contract interface, so you will be required to implement the metadata functions. Additionally, your Vault will also implement the ViewResolver.Resolver by default, which allows your Vault resource to implement one or more metadata types called views.
Views do not specify or require how to store your metadata, they only specify the format to query and return them, so projects can still be flexible with how they store their data.
The FungibleTokenMetadataViews contract defines four new views that can used to communicate any fungible token information:
The Example Token contract shows how to implement metadata views for fungible tokens.
In this repository you can find examples on how to read metadata, accessing the ExampleToken display (name, symbol, logos, etc.) and its vault data (paths, linked types and the method to create a new vault).
Latter using that reference you can call methods defined in the Fungible Token Metadata Views contract that will return you the structure containing the desired information:
The following features could each be defined as a separate standard. It would be good to make standards for these, but not necessary to include in the main standard interface and are not currently defined in this example.
Scoped Provider This refers to restricting a Provider capability to only be able to withdraw a specific amount of tokens from someone else's Vault This is currently being worked on.
Pausing Token transfers (maybe a way to prevent the contract from being imported)
Cloning the token to create a new token with the same distribution
Restricted ownership (For accredited investors and such)
allowlisting
denylisting
To use the Flow Token contract as is, you need to follow these steps:
FungibleTokenSwitchboard.cdc, allows users to receive payments in different fungible tokens using a single &{FungibleToken.Receiver} placed in a standard receiver path /public/GenericFTReceiver.
Users willing to use the Fungible Token Switchboard will need to setup their accounts by creating a new FungibleTokenSwitchboard.Switchboard resource and saving it to their accounts at the FungibleTokenSwitchboard.StoragePath path.
This can be accomplished by executing the transaction found in this repository transactions/switchboard/setup_account.cdc. This transaction will create and save a Switchboard resource to the signer's account, and it also will create the needed public capabilities to access it. After setting up their switchboard, in order to make it support receiving a certain token, users will need to add the desired token's receiver capability to their switchboard resource.
When a user wants to receive a new fungible token through their switchboard, they will need to add a new public capability linked to said FT to their switchboard resource. This can be accomplished in two different ways:
Adding a single capability using addNewVault(capability: Capability<&{FungibleToken.Receiver}>)
This function will panic if is not possible to .borrow() a reference to a &{FungibleToken.Receiver} from the passed capability.
Adding one or more capabilities using the paths where they are stored using addNewVaultsByPath(paths: [PublicPath], address: Address). This is shown in the batch_add_vault_wrapper_capabilities.cdc transaction
This function won't panic, instead it will just not add to the @Switchboard any capability which can not be retrieved from any of the provided PublicPaths. It will also ignore any type of &{FungibleToken.Receiver} that is already present on the @Switchboard
Adding a capability to a receiver specifying which type of token will be deposited there using addNewVaultWrapper(capability: Capability<&{FungibleToken.Receiver}>, type: Type). This method can be used to link a token forwarder or any other wrapper to the switchboard. Once the Forwarder has been properly created containing the capability to an actual @FungibleToken.Vault, this method can be used to link the @Forwarder to the switchboard to deposit the specified type of Fungible Token. In the template transaction switchboard/add_vault_wrapper_capability.cdc, we assume that the signer has a forwarder containing a capability to an @ExampleToken.Vault resource:
If a user no longer wants to be able to receive deposits from a certain FT, or if they want to update the provided capability for one of them, they will need to remove the vault from the switchboard. This can be accomplished by using removeVault(capability: Capability<&{FungibleToken.Receiver}>). This can be observed in the template transaction transactions/switchboard/remove_vault_capability.cdc:
This function will panic if is not possible to .borrow() a reference to a &{FungibleToken.Receiver} from the passed capability.
The Fungible Token Switchboard provides two different ways of depositing tokens to it, using the deposit(from: @{FungibleToken.Vault}) method enforced by the {FungibleToken.Receiver} or using the safeDeposit(from: @FungibleToken.Vault): @FungibleToken:
Using the first method will be just the same as depositing to &{FungibleToken.Receiver}. The path for the Switchboard receiver is defined in FungibleTokenSwitchboard.ReceiverPublicPath, the generic receiver path /public/GenericFTReceiver that can also be obtained from the NFT MetadataViews contract. An example of how to do this can be found in the transaction template on this repo transactions/switchboard/transfer_tokens.cdc.
The safeDeposit(from: @FungibleToken.Vault): @FungibleToken works in a similar way, with the difference that it will not panic if the desired FT Vault can not be obtained from the Switchboard. The method will return the passed vault, empty if the funds were deposited successfully or still containing the funds if the transfer of the funds was not possible. Keep in mind that when using this method on a transaction you will always have to deal with the returned resource. An example of this can be found on transactions/switchboard/safe_transfer_tokens.cdc:
There are two sets of tests in the repo, Cadence tests and Go tests. The Cadence tests are much more straightforward and are all written in Cadence, so we recommend following those.
The Cadence tests are located in the tests/ repository. They are written in Cadence and can be run directly from the command line using the Flow CLI. Make sure you are using the latest Cadence 1.0 CLI verion.
flow test --cover --covercode="contracts" tests/*.cdc
You can find automated tests in the lib/go/test/token_test.go file. It uses the transaction templates that are contained in the lib/go/templates/transaction_templates.go file. You can run them by navigating to the lib/go/test/ directory and running go test -v. If you make changes to the contracts or transactions in between running tests, you will need to run make generate from the lib/go/ directory to generate the assets used in the tests.
The works in these folders are under the Unlicense:
Q: What is the FungibleToken standard? A: It is a Cadence contract interface that defines the minimum requirements for fungible token contracts on Flow, including the Vault, Provider, Receiver, and Balance interfaces.
Q: Do I need to deploy FungibleToken myself? A: No. The FungibleToken, FungibleTokenMetadataViews, and FungibleTokenSwitchboard contracts are already deployed on emulator, testnet, and mainnet. Import them from the addresses listed in the Import Addresses table.
Q: How is this different from ERC-20? A: Tokens cannot be sent to accounts that lack a Vault, so no safetransfer is needed. The approve/transferFrom pattern is replaced by capability-based Provider references, which avoids common double-spend issues. Cadence integer types also protect against overflow and underflow.
Q: How do I add metadata to my token? A: Implement the metadata views defined in FungibleTokenMetadataViews.cdc (FTView, FTDisplay, FTVaultData, TotalSupply). The ExampleToken contract shows a working pattern.
Q: What is the FungibleTokenSwitchboard? A: A resource that lets a user accept many fungible token types through a single &{FungibleToken.Receiver} capability placed at /public/GenericFTReceiver.
Q: How do I run the tests? A: Cadence tests run with flow test --cover --covercode="contracts" tests/*.cdc. Go tests run via go test -v from lib/go/test/ (run make generate from lib/go/ first if contracts or transactions changed).
Q: Where can I ask questions or report issues? A: Open an issue on this repo, join the Flow Discord, or start a thread on the Flow Forum.
This repo is part of the Flow network, a Layer 1 blockchain built for consumer applications, AI Agents, and DeFi at scale.
| Back | FazBrowse Home | New Git URL |