Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: V2 FungibleToken Standard #77

Closed
wants to merge 59 commits into from
Closed
Show file tree
Hide file tree
Changes from 56 commits
Commits
Show all changes
59 commits
Select commit Hold shift + click to select a range
e7f717c
first real draft of v2 token standard
joshuahannan Jul 18, 2022
db9cc2d
Merge branch 'master' of github.com:onflow/flow-ft into new-standard
joshuahannan Jul 18, 2022
1718595
add transfer
joshuahannan Jul 18, 2022
03527c0
fix total supply field
joshuahannan Jul 18, 2022
5bf65e5
add createEmptyVault to resource definition
joshuahannan Jul 18, 2022
61d4243
PR comments
joshuahannan Jul 18, 2022
b39028c
updating paths
joshuahannan Jul 18, 2022
1bb20b6
change type array to dictionary, add transfer event, and use capabili…
joshuahannan Jul 19, 2022
1ae18bf
add conditional for destroy
joshuahannan Jul 21, 2022
7a102a8
Create FungibleTokenMetadataViews contract, include MetadataViews con…
alilloig Sep 1, 2022
32c0010
Apply suggestions from code review
alilloig Sep 2, 2022
093318d
Fix CI
alilloig Sep 2, 2022
079d367
Remove unnecesary init parameter on ftvaultdata
alilloig Sep 7, 2022
13b5b0d
Fix CI
alilloig Sep 7, 2022
fccd93c
Remove thumbnail and images from FTDisplay, add logo as only image an…
alilloig Sep 7, 2022
ba9bf2e
Merge branch 'alilloig/example-token-metadata-views' of github.com:on…
alilloig Sep 15, 2022
a6fdcb7
Restore files after the testing crisis
alilloig Sep 15, 2022
90395f4
Fix setup account from view test
alilloig Sep 15, 2022
f461448
Add auxiliary function for returning views and the case for returning…
alilloig Sep 15, 2022
ecc811e
Merge remote-tracking branch 'origin/master' into alilloig/ft-metadat…
alilloig Sep 15, 2022
306a1fe
Change logo (media) for logos (medias) at FTView
alilloig Sep 15, 2022
ead9c82
Update from logo to logos
alilloig Sep 15, 2022
e8b7f56
Fix spelling typos
alilloig Sep 16, 2022
58c157b
FT metadata docs section
alilloig Sep 19, 2022
c70204c
Add comments and use of getFTView function instead of resolveView
alilloig Sep 19, 2022
7aee404
Add scripts for read metadata
alilloig Sep 19, 2022
51bfed4
Merge remote-tracking branch 'origin/alilloig/example-token-metadata-…
alilloig Sep 19, 2022
1933db4
Finish docs
alilloig Sep 19, 2022
8d70279
Delete returnview functions
alilloig Sep 20, 2022
8c4a3c4
Switch to MetadataPublicPath
alilloig Sep 20, 2022
089b9fb
Add metadata path
alilloig Sep 20, 2022
7545b02
Merge remote-tracking branch 'origin/alilloig/ft-metadata-views' into…
alilloig Sep 20, 2022
4e5f87d
Change balance for metadata path at transactions. Fix FTVaultData con…
alilloig Sep 20, 2022
a0d375b
Add default implementation for MetadataViews.Resolver methods
alilloig Sep 20, 2022
1082bac
Merge remote-tracking branch 'origin/alilloig/ft-metadata-views' into…
alilloig Sep 20, 2022
0aadea8
Merge remote-tracking branch 'origin/alilloig/example-token-metadata-…
alilloig Sep 20, 2022
5b06fd7
Update contracts/FungibleTokenMetadataViews.cdc
alilloig Sep 30, 2022
21203f2
Update contracts/FungibleToken.cdc
alilloig Sep 30, 2022
5e2328d
Update contracts/FungibleToken.cdc
alilloig Sep 30, 2022
84880ef
Update contracts/FungibleTokenMetadataViews.cdc
alilloig Sep 30, 2022
eb5637a
Update contracts/FungibleTokenMetadataViews.cdc
alilloig Sep 30, 2022
e6de7ef
Update contracts/FungibleTokenMetadataViews.cdc
alilloig Sep 30, 2022
ad86e87
Update contracts/FungibleToken.cdc
alilloig Sep 30, 2022
81b0e9e
Update contracts/FungibleTokenMetadataViews.cdc
alilloig Sep 30, 2022
b58c49d
Update contracts/FungibleTokenMetadataViews.cdc
alilloig Sep 30, 2022
a31fd46
Update contracts/FungibleTokenMetadataViews.cdc
alilloig Sep 30, 2022
541764b
Update contracts/FungibleTokenMetadataViews.cdc
alilloig Sep 30, 2022
f24f5f2
Update contracts/FungibleTokenMetadataViews.cdc
alilloig Sep 30, 2022
50f777c
Update contracts/FungibleTokenMetadataViews.cdc
alilloig Sep 30, 2022
24763ca
Apply review suggestions
alilloig Sep 30, 2022
c5fd8b5
Add consistency about vaultData field name
alilloig Sep 30, 2022
54b8066
Merge
alilloig Sep 30, 2022
abe2080
move everything into the interface
joshuahannan Oct 4, 2022
2045a1d
Merge pull request #93 from onflow/alilloig/docs-metadata-views
alilloig Oct 5, 2022
1f32f2e
Merge pull request #91 from onflow/alilloig/example-token-metadata-views
alilloig Oct 5, 2022
e70eaaf
integrate metadata views
joshuahannan Oct 5, 2022
b924625
add metadata functions and optional returns
joshuahannan Dec 6, 2022
c742c6d
align with FLIP
joshuahannan Dec 16, 2022
051b966
WIP: V2 FungibleToken Standard (#126)
joshuahannan Mar 14, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 63 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ Right now we are using unsigned 64-bit fixed point numbers `UFix64` as the type

6 - Destroying a Vault

If a `Vault` is explicitly destroyed using Cadence's `destroy` keyword, the balance of the destroyed vault must be subracted from the total supply.
If a `Vault` is explicitly destroyed using Cadence's `destroy` keyword, the balance of the destroyed vault must be subtracted from the total supply.

7 - Standard for Token Metadata

Expand All @@ -135,10 +135,60 @@ This spec covers much of the same ground that a spec like ERC-20 covers, but wit
- Transfers can trigger actions because users can define custom `Receivers` to execute certain code when a token is sent.
- Cadence integer types protect against overflow and underflow, so a `SafeMath`-equivalent library is not needed.

### Metadata
## FT Metadata

A standard for token metadata is still an unsolved problem in the general blockchain world and we are still thinking about ways to solve it in Cadence. We hope to be able to store all metadata on-chain and are open to any ideas or feedback on how this could be implemented.
FT Metadata is represented in a flexible and modular way using both the [standard proposed in FLIP-0636](https://github.com/onflow/flow/blob/master/flips/20210916-nft-metadata.md) and the [standard proposed in FLIP-1087](https://github.com/onflow/flips/blob/main/flips/20220811-fungible-tokens-metadata.md).

When writing an NFT contract, you should implement the [`MetadataViews.Resolver`](contracts/utilityContracts/MetadataViews.cdc#L20-L23) interface, 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.

### Fungible token Metadata Views

The [Example Token contract](contracts/ExampleToken.cdc) defines three new views that can used to communicate any fungible token information:

1. `FTView` A view that wraps the two other views that actually contain the data.
1. `FTDisplay` The view that contains all the information that will be needed by other dApps to display the fungible token: name, symbol, description, external URL, logos and links to social media.
1. `FTVaultData` The view that can be used by other dApps to interact programmatically with the fungible token, providing the information about the public and private paths used by default by the token, the public and private linked types for exposing capabilities and the function for creating new empty vaults. You can use this view to [setup an account using the vault stored in other account without the need of importing the actual token contract.](transactions/setup_account_from_vault_reference.cdc)

### How to implement metadata

The [Example Token contract](contracts/ExampleToken.cdc) shows how to implement metadata views for fungible tokens.

### How to read metadata

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).

First step will be to borrow a reference to the token's vault stored in some account:

```cadence
let vaultRef = account
.getCapability(ExampleToken.ResolverPublicPath)
.borrow<&{MetadataViews.Resolver}>()
?? panic("Could not borrow a reference to the vault resolver")
```

Latter using that reference you can call methods defined in the [Fungible Token Metadata Views contract](contracts/FungibleTokenMetadataViews.cdc) that will return you the structure containing the desired information:

```cadence
let ftView = FungibleTokenMetadataViews.getFTView(viewResolver: vaultRef)
```

Alternatively you could call directly the `resolveView(_ view: Type): AnyStruct?` method on the `ExampleToken.Vault`, but the `getFTView(viewResolver: &{MetadataViews.Resolver}): FTView`, `getFTDisplay(_ viewResolver: &{MetadataViews.Resolver}): FTDisplay?` and `getFTVaultData(_ viewResolver: &{MetadataViews.Resolver}): FTVaultData?` defined on the `FungibleMetadataViews` contract will ease the process of dealing with optional types when retrieving this views.

Finally you can return the whole of structure or just log some values from the views depending on what you are aiming for:

```cadence
return ftView
````

```cadence
/*
When you retrieve a FTView both the FTDisplay and the FTVaultData views contained on it are optional values, meaning that the token could not be implementing then.
*/
log(ftView.ftDisplay!.symbol)
```

## Bonus Features

Expand Down Expand Up @@ -178,7 +228,7 @@ A standard for token metadata is still an unsolved problem in the general blockc

To use the Flow Token contract as is, you need to follow these steps:

1. If you are using the Playground, you need to deploy the `FungibleToken` definition to account 1 yourself and import it in `ExampleToken`. It is a predeployed interface in the emulator, testnet, and mainnet and you can import definition from those accounts:
1. If you are using the Playground, you need to deploy the `FungibleToken` definition to account 1 yourself and import it in `ExampleToken`. It is a pre-deployed interface in the emulator, testnet, and mainnet and you can import definition from those accounts:
- `0xee82856bf20e2aa6` on emulator
- `0x9a0766d93b6608b7` on testnet
- `0xf233dcee88fe0abe` on mainnet
Expand All @@ -202,15 +252,15 @@ To use the Flow Token contract as is, you need to follow these steps:

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 acomplished 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,
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.

## Adding a new vault to the switchboard
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:

1. Adding a single capability using `addNewVault(capability: Capability<&{FungibleToken.Receiver}>)`
* Before calling this method on a transaction you should first retrieve the capability to the token's vault you are
willing to add to the switchboard, as is done in the template transaction `transactions/switchboard/add_vault_capabilty.cdc`.
willing to add to the switchboard, as is done in the template transaction `transactions/switchboard/add_vault_capability.cdc`.

```cadence
transaction {
Expand All @@ -219,7 +269,7 @@ To use the Flow Token contract as is, you need to follow these steps:

prepare(signer: AuthAccount) {
// Get the example token vault capability from the signer's account
self.exampleTokenVaultCapabilty =
self.exampleTokenVaultCapability =
signer.getCapability<&{FungibleToken.Receiver}>
(ExampleToken.ReceiverPublicPath)
// Get a reference to the signers switchboard
Expand All @@ -230,7 +280,7 @@ To use the Flow Token contract as is, you need to follow these steps:

execute {
// Add the capability to the switchboard using addNewVault method
self.switchboardRef.addNewVault(capability: self.exampleTokenVaultCapabilty)
self.switchboardRef.addNewVault(capability: self.exampleTokenVaultCapability)
}
}
```
Expand Down Expand Up @@ -279,7 +329,7 @@ This can be observed in the template transaction `transactions/switchboard/remov

prepare(signer: AuthAccount) {
// Get the example token vault capability from the signer's account
self.exampleTokenVaultCapabilty = signer.getCapability
self.exampleTokenVaultCapability = signer.getCapability
<&{FungibleToken.Receiver}>(ExampleToken.ReceiverPublicPath)
// Get a reference to the signers switchboard
self.switchboardRef = signer.borrow<&FungibleTokenSwitchboard.Switchboard>
Expand All @@ -291,14 +341,14 @@ This can be observed in the template transaction `transactions/switchboard/remov
execute {
// Remove the capability from the switchboard using the
// removeVault method
self.switchboardRef.removeVault(capability: self.exampleTokenVaultCapabilty)
self.switchboardRef.removeVault(capability: self.exampleTokenVaultCapability)
}
}
```
This function will panic if is not possible to `.borrow()` a reference to a `&{FungibleToken.Receiver}` from the passed capability.

## Transfering tokens through the switchboard
The Fungible Token Switchboad 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`:
## Transferring tokens through the switchboard
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`:

1. 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.
Expand Down Expand Up @@ -336,7 +386,7 @@ This can be observed in the template transaction `transactions/switchboard/remov
}
```

2. 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 sucessfully 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 allways have to deal with the returned resource. An example of this can be found on `transactions/switchboard/safe_transfer_tokens.cdc`:
2. 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`:
```cadence
transaction(to: Address, amount: UFix64) {
// The reference to the vault from the payer's account
Expand Down
Loading