About Flow FT && NFT token standard update

Dec 9, 2022 06:15 AM
notion image

About FT and NFT token standard update

It has been 11 months since the last NFT MetadataView standard was released. Flow Fungible tokens also ushered in MetadataView standard, although is still in the testing stage, We can look forward to the formal adoption of the standard. This upgrade not only brings us the MetadataView standard contract of Fungible tokens. FungibleTokenSwitchboard can implement a general collection of Receiver resources to solve the previous NFTMetadataView Royalty configuration problem.
This upgrade is also carried out in the way of low modification to the standard contract, and the overall design idea is the same as that of NFTMetadataViews. For more details of NFTMetadataViews, you can go here read the introduction article I wrote earlier, and this one is about the design practice and explanation of Flow NFT and FT. This article will be introduced and explained according to two major updates to the FT standard contract.
Main points:
  • This update and upgrade is only deployed in the testnet, and the new features need to be supported by a new spork.
  • The existing FT contract does not force to upgrades, you can choose not to upgrade, which will not affect normal use.
  • The Vault resources that have been initialized by the user do not need to be reinitialized. If the contract implementation upgrades the function, the resources that have been initialized by the user will be inherited automatically.
  • In addition to basic FT information, resource information and type information will also be included (guess is in preparation for information aggregation display on-chain)
  • Similar to NFTMetadataView, FTMetadataView also has the ability to display type extensions to support more Metadata types in the future.
  • FungibleTokenSwitchboard, as an additional routing resource, preserves the FT Receiver resources under the user's account, and can receive multiple type of FT token through one resource as a router.


FungibleTokenMetadataViews.cdc relies on FungibleToken and MetadataViews
The FTView structure is defined, including FTDisplay and FTVaultData
  • FTDisplay contains the information, such as names, symbols, descriptions, external links, Logo links and some social account links needed for FT display, which can be understood as the basic information of Token.
  • FTVaultData this contains the resource information of FTVault and some type information of the interface, as well as an initialization function createEmptyVault to create Vault.
From the perspective of implementation, FTDisplay is designed to enrich the basic information on-chain of FungibleToken, while FTVaultData is designed to facilitate third-party integration to integrate Token on-chain. Various types of FungibleToken can be compatible with the standard MetadataViews interface.
Of course, the premise of this assumption is that FungibleToken has implemented the required interfaces of MetadataViews. Let's see what changes and upgrades have been made to FungibleToken
pub fun getViews(): [Type] {
     return []

pub fun resolveView(_ view: Type): AnyStruct? {
    return nil
In fact, FungibleToken only adds getViews and resolveView functions to the existing Balance interface, and returns the type of optional. The newly added contract dependency is not introduced here, but is introduced in ExampleToken of the example:
Note: the changes of FungibleToken are slightly different here. Because of the addition of the implementation function in the Balance interface type, it will cause problems with the existing resources that inherit FungibleToken.Balance in the network. (normally speaking, a contract that inherits FungibleToken.Balance but does not implement getViews and resolveView cannot be properly deployed.) During a discussion with B.T.Wood, he told me a recent update of Cadence, if you inherit the resources of the interface, even if you do not implement the methods defined by the interface. Cadence will uses the default method of the interface itself, so that the above problems do not occur. This feature will be updated in future spork.
These two new interfaces are implemented in Vault resource:
 pub fun getViews(): [Type]{
     return [Type<FungibleTokenMetadataViews.FTView>(),
Three types of structures, FTView, include FTDisplay and FTVaultData, are defined. After upgrading, we can directly call getViews in the existing Balance interface of FungibleToken to get the current MetadataView types supported by Token, and obtain specific Metadata information through resolveView.
This code structure not only achieves the effect of backward compatibility, but also meets the requirement of dynamically adding Metadata types according to the needs in the future. We can enrich the chain metadata of FT by extending the types supported by FungibleTokenMetadataViews.


We can think of FungibleTokenSwitchboard as an aggregate routing resource in an account. It implements the interface of FungibleToken.Receiver and acts as a universal collection in the standard. Through the receiverCapabilities in the resources, the Receiver of Vault under the user account can be saved and forwarded to the corresponding Receiver with only one path. receiverCapabilities is defined in the Switchboard resource to aggregate the collection resources of FungibleToken:
 pub resource Switchboard: FungibleToken.Receiver, SwitchboardPublic {

        access(contract) var receiverCapabilities: {Type: Capability<&{FungibleToken.Receiver}>}

receiverCapabilities takes Type as the key, and the receipt Capability of Vault as value, that is the core of routing collection
At the same time, it provides a way to manage routes:
  • addNewVault Add a new Vault route to Switchboard via Capability
Because Switchboard inherits FungibleToken.Receiver, the deposit function needs to be implemented.
  pub fun deposit(from: @FungibleToken.Vault) {
            // Get the capability from the ones stored at the switchboard
            let depositedVaultCapability = self
                ?? panic ("The deposited vault is not available on this switchboard")
            // Borrow the reference to the desired vault
            let vaultRef = depositedVaultCapability.borrow()
                ?? panic ("Can not borrow a reference to the the vault")
            vaultRef.deposit(from: <-from)
This deposit function implements a function of forwarding deposits and routes the collection to the specific resources in the configuration. We can also see that if the corresponding value of receiverCapabilities is not found here, the program Panic will cause the transaction of deposit to fail. For the convenience of third parties, the interface type of SwitchboardPublic is defined and three functions are defined:
  • getVaultTypes get the Vault types that supports reception
  • deposit as mention berfore
  • the secure deposit function safeDeposit does not cause Panic even if it fails, but returns the @FungibleToken.Vault resource
  • same as Deposit, receiving @FungibleToken.Vault resource
  • will first determine whether receiverCapabilities has a receiving resource configured for the corresponding resource.
  • if it is not found and the deposit amount is greater than zero, the event of deposit failure will be triggered and the input @ FungibleToken.Vault resource will be returned.
  • otherwise, destroy the top-up resources directly and return nil
 pub fun safeDeposit(from: @FungibleToken.Vault): @FungibleToken.Vault? {
            // Try to get the proper vault capability from the switchboard
            // If the desired vault is present on the switchboard...
            if let depositedVaultCapability = self
                                        .receiverCapabilities[from.getType()] {
                // We try to borrow a reference to the vault from the capability
                // If we can borrow a reference to the vault...
                if let vaultRef =  depositedVaultCapability.borrow() {
                    // We deposit the funds on said vault
                    vaultRef.deposit(from: <-from.withdraw(amount: from.balance))
            // if deposit failed for some reason
            if from.balance > 0.0 {
                emit NotCompletedDeposit(type: from.getType(),
                                        amount: from.balance,
                                        switchboardOwner: self.owner?.address)
                return <-from
            destroy from
            return nil

In short, the Switchboard resource, as a third-party routing resource, provides a general collection method for users, so that the royalty configuration of Royalty in the previous NFTMetadataViews can receive a variety of FT assets. From an application point of view, third-party developers or wallet portals are still required to integrate and introduce new contracts, which makes it easy for users to manually configure and manage the resources in Switchboard.

NFT borrowNFTSafe

Btw, the standard contract of NFT has also released update, has added a borrowNFTSafe function to the resource interface of NFT CollectionPublic to prevent errors in script execution due to the failure to find the NFT of the specific ID under the account during the execution of the query script. Improve the query and development experience of developers.


This update is still in the stage of Test Network deployment, where developers can experience the features of new standards and new contracts. After the future main network spork, these new codes will be deployed. Then FT will have the ability to query Metadata on-chain, and the original FT publishers can implement new functions and upgrade their contracts according to the example FT project.
In this way, catalog products that support FT should not be far away.