From 556730d5a7fe95fc839fcba0e8b11f180761729d Mon Sep 17 00:00:00 2001 From: Hank Stoever Date: Mon, 25 Jan 2021 18:01:13 -0800 Subject: [PATCH 01/15] feat: proposed fungible token trait --- .../sip-010-fungible-token-standard.md | 120 ++++++++++++++++++ 1 file changed, 120 insertions(+) create mode 100644 sips/sip-010/sip-010-fungible-token-standard.md diff --git a/sips/sip-010/sip-010-fungible-token-standard.md b/sips/sip-010/sip-010-fungible-token-standard.md new file mode 100644 index 00000000..98fae8b9 --- /dev/null +++ b/sips/sip-010/sip-010-fungible-token-standard.md @@ -0,0 +1,120 @@ +## Preamble + +- Sip Number: 010 +- Title: Standard Trait Definition for Non-Fungibe Tokens +- Author: Hank Stoever (hstove@gmail.com) +- Consideration: Technical +- Type: Standard +- Status: Draft +- Created: 2021-01-25 +- License: CC0-1.0 +- Sign-off: + +## Abstract + +Fungible tokens are digital assets that can be sent, received, combined, and divided. Most forms of currency and cryptocurrencies are fungible tokens. They have become a building block of almost all blockchains. This SIP aims to provide a flexible and easy to implement standard that can be used by developers on the Stacks blockchain when creating their own tokens. + +## License and Copyright + +This SIP is made available under the terms of the Creative Commons CC0 1.0 Universal license, available at https://creativecommons.org/publicdomain/zero/1.0/ +This SIP’s copyright is held by the Stacks Open Internet Foundation. + +## Introduction + +Perhaps the oldest, and most well known, standard for fungible tokens is Ethereum's [ERC20](https://ethereum.org/en/developers/docs/standards/tokens/erc-20/) standard. It has become one of the strongest building blocks for the Ethereum ecosystem. When all fungible tokens follow the same standard, any wallet or application developer can interact with it without having to create custom logic for handling each individual token. + +Fungible tokens have become so popular that the Clarity smart contracting language has support for basic fungible token operations built-in. In fact, as you might see in this proposal's reference implementation, very little code is required to implement a fungible token. The important part of this standard is defining a Clarity trait that all fungible tokens can implement. Even though Clarity has fungible token operations built-in, it is important for each contract to define the same methods so that their contracts are easy to integrate. + +## Specification + +The fungible token trait, `ft-trait`, has a few methods: + +### Transfer + +`(transfer ((recipient principal) (amount uint)) (response bool uint))` + +Transfer the fungible token from the sender of this transaction to the recipient. The `amount` is an unsigned integer. It is recommended that implementing contracts use the built-in `ft-transfer` Clarity method. If the sender does not have enough tokens to complete the transaction, the transaction should abort and return an `(err uint)`. + +### Name + +`(name () (response (string-ascii 32) uint))` + +Return a human-readable name for the contract, such as "CoolPoints", etc. + +### Symbol + +`(symbol () (response (string-ascii 32) uint))` + +Return a symbol that allows for a shorter representation of your token. This is sometimes referred to as a "ticker". Examples: "STX", "COOL", etc. Typically, your token could be referred to as $SYMBOL when referencing it in writing. + +### Decimals + +`(decimals () (response uint uint))` + +The number of decimal places in your token. All fungible token balances must be represented as integers, but providing the number of decimals provides for an abstraction of your token that humans are more familiar dealing with. For example, the US Dollar has 2 decimals, if the base unit is "cents", as is typically done in accounting. Stacks has 6 decimals, Bitcoin has 8 decimals, and so on. + +As another example, if your token has 4 decimals, and the `balance-of` a particular user returns `100345000`, wallets and exchanges would likely represent that value as `10034.5`. + +### Balance of + +`(balance-of (principal) (response uint uint))` + +Return the balance of a particular principal (also known as "address" or "account"). Implementations should typically use the built-in Clarity method `ft-get-balance`. + +### Total supply + +`(total-supply () (response uint uint))` + +Return the total supply of this token. Implementations should typically use the built-in Clarity method `ft-get-supply`. + +## Trait implementation + +An implementation of the proposed trait is provided below. + +```clarity +(define-trait ft-trait + ( + ;; Transfer from the caller to a new principal + (transfer (principal uint) (response bool uint)) + + ;; the human readable name of the token + (name () (response (string-ascii 32) uint)) + + ;; the ticker symbol, or empty if none + (symbol () (response (string-ascii 32) uint)) + + ;; the number of decimals used, e.g. 6 would mean 1_000_000 represents 1 token + (decimals () (response uint uint)) + + ;; the balance of the passed principal + (balance-of (principal) (response uint uint)) + + ;; the current total supply (which does not need to be a constant) + (total-supply () (response uint uint)) + ) +) +``` + +## Example implementation + +I have provided a simple implementation along with a Javascript client and tests. https://github.com/hstove/stacks-fungible-token + +## Credit + +Credit for the work behind this proposal belongs to [@psq](https://github.com/psq), who wrote almost all of this code originally for use in his projects (such as [Flexr](https://github.com/psq/flexr)). I am simply re-packaging his existing code in a format that can be shared in this proposal. + +## Implementing in wallets and other applications + +Developers who with to interact with a fungible token contract should first be provided, or keep track of, various different fungible token implementations. When validating a fungible token contract, they should fetch the interface and/or source code for that contract. If the contract implements the trait, then the wallet can use this standard's contract interface for making transfers and getting balances. + +### Use of post conditions + +In addition to fantastic built-in methods for fungible token contracts, the Stacks blockchain includes an innovation known as Post Conditions. By defining post conditions, users can create transactions that include pre-defined guarantees about what might happen in that contract. + +One such post condition could be "I will transfer exactly 100 of X token", where "X token" is referenced as a specific contract's fungible token. When wallets and applications implement the `transfer` method, they should _always_ use post conditions to specify that the user will transfer exactly the amount of tokens that they specify in the `amount` argument of the `transfer` function. Only in very specific circumstances should such a post condition not be included. + +## Related work + +- [@psq's trait and implementation](https://github.com/psq/flexr/blob/master/contracts/src20-trait.clar) +- [@friedger's fungible token implementation](https://github.com/friedger/clarity-smart-contracts/blob/master/contracts/tokens/fungible-token.clar) +- [Ethereum ERC20 standard](https://ethereum.org/en/developers/docs/standards/tokens/erc-20/) From cc6e3a430c902c9fb8e49ff4ec03b86bfd0cebc3 Mon Sep 17 00:00:00 2001 From: Hank Stoever Date: Mon, 25 Jan 2021 18:42:43 -0800 Subject: [PATCH 02/15] fix: add notes about when to use read-only --- sips/sip-010/sip-010-fungible-token-standard.md | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/sips/sip-010/sip-010-fungible-token-standard.md b/sips/sip-010/sip-010-fungible-token-standard.md index 98fae8b9..a8ed7bc4 100644 --- a/sips/sip-010/sip-010-fungible-token-standard.md +++ b/sips/sip-010/sip-010-fungible-token-standard.md @@ -35,18 +35,24 @@ The fungible token trait, `ft-trait`, has a few methods: Transfer the fungible token from the sender of this transaction to the recipient. The `amount` is an unsigned integer. It is recommended that implementing contracts use the built-in `ft-transfer` Clarity method. If the sender does not have enough tokens to complete the transaction, the transaction should abort and return an `(err uint)`. +This method must be defined with `define-public`, as it alters state, and should be externally callable. + ### Name `(name () (response (string-ascii 32) uint))` Return a human-readable name for the contract, such as "CoolPoints", etc. +This method should be defined as read-only, i.e. `define-read-only`. + ### Symbol `(symbol () (response (string-ascii 32) uint))` Return a symbol that allows for a shorter representation of your token. This is sometimes referred to as a "ticker". Examples: "STX", "COOL", etc. Typically, your token could be referred to as $SYMBOL when referencing it in writing. +This method should be defined as read-only, i.e. `define-read-only`. + ### Decimals `(decimals () (response uint uint))` @@ -55,18 +61,24 @@ The number of decimal places in your token. All fungible token balances must be As another example, if your token has 4 decimals, and the `balance-of` a particular user returns `100345000`, wallets and exchanges would likely represent that value as `10034.5`. +This method should be defined as read-only, i.e. `define-read-only`. + ### Balance of `(balance-of (principal) (response uint uint))` Return the balance of a particular principal (also known as "address" or "account"). Implementations should typically use the built-in Clarity method `ft-get-balance`. +This method should be defined as read-only, i.e. `define-read-only`. + ### Total supply `(total-supply () (response uint uint))` Return the total supply of this token. Implementations should typically use the built-in Clarity method `ft-get-supply`. +This method should be defined as read-only, i.e. `define-read-only`. + ## Trait implementation An implementation of the proposed trait is provided below. @@ -105,7 +117,7 @@ Credit for the work behind this proposal belongs to [@psq](https://github.com/ps ## Implementing in wallets and other applications -Developers who with to interact with a fungible token contract should first be provided, or keep track of, various different fungible token implementations. When validating a fungible token contract, they should fetch the interface and/or source code for that contract. If the contract implements the trait, then the wallet can use this standard's contract interface for making transfers and getting balances. +Developers who wish to interact with a fungible token contract should first be provided, or keep track of, various different fungible token implementations. When validating a fungible token contract, they should fetch the interface and/or source code for that contract. If the contract implements the trait, then the wallet can use this standard's contract interface for making transfers and getting balances. ### Use of post conditions From 53636c9bf9a2c13dc55c8ddbfd0d7b7de31fcdf2 Mon Sep 17 00:00:00 2001 From: Hank Stoever Date: Tue, 26 Jan 2021 23:44:16 -0800 Subject: [PATCH 03/15] feat: changed `transfer` signature, improved formatting, language --- .../sip-010-fungible-token-standard.md | 102 ++++++++++++------ 1 file changed, 71 insertions(+), 31 deletions(-) diff --git a/sips/sip-010/sip-010-fungible-token-standard.md b/sips/sip-010/sip-010-fungible-token-standard.md index a8ed7bc4..9665dd4e 100644 --- a/sips/sip-010/sip-010-fungible-token-standard.md +++ b/sips/sip-010/sip-010-fungible-token-standard.md @@ -1,42 +1,69 @@ -## Preamble +# Preamble -- Sip Number: 010 -- Title: Standard Trait Definition for Non-Fungibe Tokens -- Author: Hank Stoever (hstove@gmail.com) -- Consideration: Technical -- Type: Standard -- Status: Draft -- Created: 2021-01-25 -- License: CC0-1.0 -- Sign-off: +Sip Number: 010 -## Abstract +Title: Standard Trait Definition for Non-Fungibe Tokens -Fungible tokens are digital assets that can be sent, received, combined, and divided. Most forms of currency and cryptocurrencies are fungible tokens. They have become a building block of almost all blockchains. This SIP aims to provide a flexible and easy to implement standard that can be used by developers on the Stacks blockchain when creating their own tokens. +Author: Hank Stoever (hstove@gmail.com) -## License and Copyright +Consideration: Technical + +Type: Standard + +Status: Draft + +Created: 25 January 2021 + +License: CC0-1.0 + +Sign-off: + +Layer: Traits + +Discussions-To: https://github.com/stacksgov/sips + +# Abstract + +Fungible tokens are digital assets that can be sent, received, combined, and divided. Most forms of currency and cryptocurrencies are fungible tokens. They have become a building block of almost all blockchains. This SIP aims to provide a flexible and easy-to-implement standard that can be used by developers on the Stacks blockchain when creating their own tokens. + +# License and Copyright This SIP is made available under the terms of the Creative Commons CC0 1.0 Universal license, available at https://creativecommons.org/publicdomain/zero/1.0/ This SIP’s copyright is held by the Stacks Open Internet Foundation. -## Introduction +# Introduction -Perhaps the oldest, and most well known, standard for fungible tokens is Ethereum's [ERC20](https://ethereum.org/en/developers/docs/standards/tokens/erc-20/) standard. It has become one of the strongest building blocks for the Ethereum ecosystem. When all fungible tokens follow the same standard, any wallet or application developer can interact with it without having to create custom logic for handling each individual token. +Digital assets can be divided into two categories, based on the token's fungibility. A _fungible_ token can be broken down into small units and added together. An owner of a fungible asset only needs to care about their balance, that is, the total amount of a particular fungible asset that they own. Most well-known currencies are fungible. + +For example, if a user owns 10 units of a fungible asset, they may send 2 units to a different user. At this point, their balance is 8 units. If they later receive more units, their total balance will be updated. For fungible tokens, there is no difference between any two different amounts of the fungible token. -Fungible tokens have become so popular that the Clarity smart contracting language has support for basic fungible token operations built-in. In fact, as you might see in this proposal's reference implementation, very little code is required to implement a fungible token. The important part of this standard is defining a Clarity trait that all fungible tokens can implement. Even though Clarity has fungible token operations built-in, it is important for each contract to define the same methods so that their contracts are easy to integrate. +On blockchains, fungible tokens are a core component. Blockchains with smart contracts, including the Stacks blockchain, allow developers and users to create and interact with smart contracts that use fungible tokens. -## Specification +# Specification -The fungible token trait, `ft-trait`, has a few methods: +The fungible token trait, `ft-trait`, has a few functions: + +## Trait functions ### Transfer -`(transfer ((recipient principal) (amount uint)) (response bool uint))` +`(transfer ((amount uint) (sender principal) (recipient principal)) (response bool uint))` Transfer the fungible token from the sender of this transaction to the recipient. The `amount` is an unsigned integer. It is recommended that implementing contracts use the built-in `ft-transfer` Clarity method. If the sender does not have enough tokens to complete the transaction, the transaction should abort and return an `(err uint)`. This method must be defined with `define-public`, as it alters state, and should be externally callable. +Contract implementers should take note to perform authorization of the `transfer` method. For example, most fungible token contracts should enforce that the `sender` argument is equal to the `tx-sender` keyword in Clarity. + +When returning an error in this function, the error codes should follow the same patterns as the built-in `ft-transfer?` and `stx-transfer?` functions. + +| error code | reason | +| ---------- | ----------------------------------------------- | +| u1 | `sender` does not have enough balance | +| u2 | `sender` and `recipient` are the same principal | +| u3 | `sender` and `recipient` are the same principal | +| u4 | `sender` is not the same as `tx-sender` | + ### Name `(name () (response (string-ascii 32) uint))` @@ -87,7 +114,7 @@ An implementation of the proposed trait is provided below. (define-trait ft-trait ( ;; Transfer from the caller to a new principal - (transfer (principal uint) (response bool uint)) + (transfer (uint principal principal) (response bool uint)) ;; the human readable name of the token (name () (response (string-ascii 32) uint)) @@ -107,26 +134,39 @@ An implementation of the proposed trait is provided below. ) ``` -## Example implementation +## Implementing in wallets and other applications -I have provided a simple implementation along with a Javascript client and tests. https://github.com/hstove/stacks-fungible-token +Developers who wish to interact with a fungible token contract should first be provided, or keep track of, various different fungible token implementations. When validating a fungible token contract, they should fetch the interface and/or source code for that contract. If the contract implements the trait, then the wallet can use this standard's contract interface for making transfers and getting balances. -## Credit +## Use of post conditions -Credit for the work behind this proposal belongs to [@psq](https://github.com/psq), who wrote almost all of this code originally for use in his projects (such as [Flexr](https://github.com/psq/flexr)). I am simply re-packaging his existing code in a format that can be shared in this proposal. +In addition to built-in methods for fungible token contracts, the Stacks blockchain includes a feature known as Post Conditions. By defining post conditions, users can create transactions that include pre-defined guarantees about what might happen in that contract. -## Implementing in wallets and other applications +One such post condition could be "I will transfer exactly 100 of X token", where "X token" is referenced as a specific contract's fungible token. When wallets and applications implement the `transfer` method, they should _always_ use post conditions to specify that the user will transfer exactly the amount of tokens that they specify in the `amount` argument of the `transfer` function. Only in very specific circumstances should such a post condition not be included. -Developers who wish to interact with a fungible token contract should first be provided, or keep track of, various different fungible token implementations. When validating a fungible token contract, they should fetch the interface and/or source code for that contract. If the contract implements the trait, then the wallet can use this standard's contract interface for making transfers and getting balances. +# Related work -### Use of post conditions +## Ethereum ERC20 -In addition to fantastic built-in methods for fungible token contracts, the Stacks blockchain includes an innovation known as Post Conditions. By defining post conditions, users can create transactions that include pre-defined guarantees about what might happen in that contract. +[Ethereum ERC20 standard](https://ethereum.org/en/developers/docs/standards/tokens/erc-20/) -One such post condition could be "I will transfer exactly 100 of X token", where "X token" is referenced as a specific contract's fungible token. When wallets and applications implement the `transfer` method, they should _always_ use post conditions to specify that the user will transfer exactly the amount of tokens that they specify in the `amount` argument of the `transfer` function. Only in very specific circumstances should such a post condition not be included. +Perhaps the oldest, and most well known, standard for fungible tokens is Ethereum's [ERC20](https://ethereum.org/en/developers/docs/standards/tokens/erc-20/) standard. It has become one of the strongest building blocks for the Ethereum ecosystem. When all fungible tokens follow the same standard, any wallet or application developer can interact with it without having to create custom logic for handling each individual token. + +Fungible tokens have become so popular that the Clarity smart contracting language has support for basic fungible token operations built-in. In fact, as can be seen in this proposal's reference implementation, very little code is required to implement a fungible token. The important part of this standard is defining a Clarity trait that all fungible tokens can implement. Even though Clarity has fungible token operations built-in, it is important for each contract to define the same methods so that their contracts are easy to integrate. + +# Backwards Compatibility + +Not applicable + +# Activation + +This trait will be considered activated when this trait is deployed to mainnet, and 3 contracts from different developers on implement this trait on mainnet. + +# Reference Implementations + +An example implementation has been submitted with this proposal, along with a Javascript client and tests. https://github.com/hstove/stacks-fungible-token -## Related work +Other examples of Clarity contracts that implement fungible tokens, although not exactly according to this specification: - [@psq's trait and implementation](https://github.com/psq/flexr/blob/master/contracts/src20-trait.clar) - [@friedger's fungible token implementation](https://github.com/friedger/clarity-smart-contracts/blob/master/contracts/tokens/fungible-token.clar) -- [Ethereum ERC20 standard](https://ethereum.org/en/developers/docs/standards/tokens/erc-20/) From d69b1f6fbc261b7e389e5e290e21917dea4166b1 Mon Sep 17 00:00:00 2001 From: Hank Stoever Date: Wed, 17 Feb 2021 11:50:00 -0800 Subject: [PATCH 04/15] feat: update FT SIP from feedback - update activation criteria - fix `u3` error description for `transfer - Remove 'you/your' language - fix typo in SIP title - add note about non-uniqueness of `name` and `symbol` --- .../sip-010-fungible-token-standard.md | 26 +++++++++++-------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/sips/sip-010/sip-010-fungible-token-standard.md b/sips/sip-010/sip-010-fungible-token-standard.md index 9665dd4e..2138a9b9 100644 --- a/sips/sip-010/sip-010-fungible-token-standard.md +++ b/sips/sip-010/sip-010-fungible-token-standard.md @@ -2,7 +2,7 @@ Sip Number: 010 -Title: Standard Trait Definition for Non-Fungibe Tokens +Title: Standard Trait Definition for Fungible Tokens Author: Hank Stoever (hstove@gmail.com) @@ -24,7 +24,7 @@ Discussions-To: https://github.com/stacksgov/sips # Abstract -Fungible tokens are digital assets that can be sent, received, combined, and divided. Most forms of currency and cryptocurrencies are fungible tokens. They have become a building block of almost all blockchains. This SIP aims to provide a flexible and easy-to-implement standard that can be used by developers on the Stacks blockchain when creating their own tokens. +Fungible tokens are digital assets that can be sent, received, combined, and divided. Most forms of cryptocurrencies are fungible tokens. They have become a building block of almost all blockchains. This SIP aims to provide a flexible and easy-to-implement standard that can be used by developers on the Stacks blockchain when creating their own tokens. # License and Copyright @@ -33,15 +33,17 @@ This SIP’s copyright is held by the Stacks Open Internet Foundation. # Introduction -Digital assets can be divided into two categories, based on the token's fungibility. A _fungible_ token can be broken down into small units and added together. An owner of a fungible asset only needs to care about their balance, that is, the total amount of a particular fungible asset that they own. Most well-known currencies are fungible. +Digital assets can have the property to be fungible. A _fungible_ token can be broken down into small units and added together. An owner of a fungible asset only needs to care about their balance, that is, the total amount of a particular fungible asset that they own. Most well-known currencies are fungible. For fungible tokens, there is no difference between any two different amounts of the fungible token. -For example, if a user owns 10 units of a fungible asset, they may send 2 units to a different user. At this point, their balance is 8 units. If they later receive more units, their total balance will be updated. For fungible tokens, there is no difference between any two different amounts of the fungible token. +For example, if a user owns 10 units of a fungible asset, they may send 2 units to a different user. At this point, their balance is 8 units. If they later receive more units, their total balance will be updated. On blockchains, fungible tokens are a core component. Blockchains with smart contracts, including the Stacks blockchain, allow developers and users to create and interact with smart contracts that use fungible tokens. +The Stacks blockchain has a native fungible token: the Stacks token (STX). In addition to the native STX token, the Stacks blockchain's programming language for developing smart contracts, Clarity, has built-in language primitives to define and use fungible tokens. Although those primitives exists, there is value in defining a common interface (known in Clarity as a "trait") that allows different smart contracts to interoperate with fungible token contracts in a reusable way. This SIP defines that trait. + # Specification -The fungible token trait, `ft-trait`, has a few functions: +The fungible token trait, `ft-trait`, has a 6 functions: ## Trait functions @@ -53,7 +55,7 @@ Transfer the fungible token from the sender of this transaction to the recipient This method must be defined with `define-public`, as it alters state, and should be externally callable. -Contract implementers should take note to perform authorization of the `transfer` method. For example, most fungible token contracts should enforce that the `sender` argument is equal to the `tx-sender` keyword in Clarity. +Contract implementers should take note to perform authorization of the `transfer` method. For example, a fungible token contract that wants to make sure that only the transaction's sender is able to move the requested tokens might first check that the sender argument is equal to tx-sender. When returning an error in this function, the error codes should follow the same patterns as the built-in `ft-transfer?` and `stx-transfer?` functions. @@ -61,7 +63,7 @@ When returning an error in this function, the error codes should follow the same | ---------- | ----------------------------------------------- | | u1 | `sender` does not have enough balance | | u2 | `sender` and `recipient` are the same principal | -| u3 | `sender` and `recipient` are the same principal | +| u3 | `amount` is non-positive | | u4 | `sender` is not the same as `tx-sender` | ### Name @@ -76,7 +78,7 @@ This method should be defined as read-only, i.e. `define-read-only`. `(symbol () (response (string-ascii 32) uint))` -Return a symbol that allows for a shorter representation of your token. This is sometimes referred to as a "ticker". Examples: "STX", "COOL", etc. Typically, your token could be referred to as $SYMBOL when referencing it in writing. +Return a symbol that allows for a shorter representation of a token. This is sometimes referred to as a "ticker". Examples: "STX", "COOL", etc. Typically, a token could be referred to as $SYMBOL when referencing it in writing. This method should be defined as read-only, i.e. `define-read-only`. @@ -84,9 +86,9 @@ This method should be defined as read-only, i.e. `define-read-only`. `(decimals () (response uint uint))` -The number of decimal places in your token. All fungible token balances must be represented as integers, but providing the number of decimals provides for an abstraction of your token that humans are more familiar dealing with. For example, the US Dollar has 2 decimals, if the base unit is "cents", as is typically done in accounting. Stacks has 6 decimals, Bitcoin has 8 decimals, and so on. +The number of decimal places in a token. All fungible token balances must be represented as integers, but providing the number of decimals provides for an abstraction of a token that humans are more familiar dealing with. For example, the US Dollar has 2 decimals, if the base unit is "cents", as is typically done in accounting. Stacks has 6 decimals, Bitcoin has 8 decimals, and so on. -As another example, if your token has 4 decimals, and the `balance-of` a particular user returns `100345000`, wallets and exchanges would likely represent that value as `10034.5`. +As another example, if a token has 4 decimals, and the `balance-of` a particular user returns `100345000`, wallets and exchanges would likely represent that value as `10034.5`. This method should be defined as read-only, i.e. `define-read-only`. @@ -138,6 +140,8 @@ An implementation of the proposed trait is provided below. Developers who wish to interact with a fungible token contract should first be provided, or keep track of, various different fungible token implementations. When validating a fungible token contract, they should fetch the interface and/or source code for that contract. If the contract implements the trait, then the wallet can use this standard's contract interface for making transfers and getting balances. +Downstream consumers of contracts that implement this trait should be aware that the `name` and `symbol` function are not guaranteed to be globally unique. Because of this, consumers should be advised that `name` and `token` are only hints to provide a more human-readable experience. Care should always be taken to verify that a contract's identifier matches that of the token a client is intending to interact with. + ## Use of post conditions In addition to built-in methods for fungible token contracts, the Stacks blockchain includes a feature known as Post Conditions. By defining post conditions, users can create transactions that include pre-defined guarantees about what might happen in that contract. @@ -160,7 +164,7 @@ Not applicable # Activation -This trait will be considered activated when this trait is deployed to mainnet, and 3 contracts from different developers on implement this trait on mainnet. +This trait will be considered activated when this trait is deployed to mainnet, and 3 different implementations of the trait have been deployed to mainnet, no later than Bitcoin block 680000. # Reference Implementations From f7f5c90206a89240d9da587709eaec68912b66a9 Mon Sep 17 00:00:00 2001 From: Hank Stoever Date: Wed, 17 Feb 2021 21:07:44 -0800 Subject: [PATCH 05/15] feat: extend activation period, add note for fail-proof functions --- sips/sip-010/sip-010-fungible-token-standard.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sips/sip-010/sip-010-fungible-token-standard.md b/sips/sip-010/sip-010-fungible-token-standard.md index 2138a9b9..830ba12a 100644 --- a/sips/sip-010/sip-010-fungible-token-standard.md +++ b/sips/sip-010/sip-010-fungible-token-standard.md @@ -142,6 +142,8 @@ Developers who wish to interact with a fungible token contract should first be p Downstream consumers of contracts that implement this trait should be aware that the `name` and `symbol` function are not guaranteed to be globally unique. Because of this, consumers should be advised that `name` and `token` are only hints to provide a more human-readable experience. Care should always be taken to verify that a contract's identifier matches that of the token a client is intending to interact with. +All of the functions in this trait return the `response` type, which is a requirement of trait definitions in Clarity. However, some of these functions should be "fail-proof", in the sense that they should never return an error. These "fail-proof" functions are those that have been recommended as read-only. If a contract that implements this trait returns an error for these functions, it may be an indication of a faulty contract, and consumers of those contracts should proceed with caution. + ## Use of post conditions In addition to built-in methods for fungible token contracts, the Stacks blockchain includes a feature known as Post Conditions. By defining post conditions, users can create transactions that include pre-defined guarantees about what might happen in that contract. @@ -164,7 +166,7 @@ Not applicable # Activation -This trait will be considered activated when this trait is deployed to mainnet, and 3 different implementations of the trait have been deployed to mainnet, no later than Bitcoin block 680000. +This trait will be considered activated when this trait is deployed to mainnet, and 3 different implementations of the trait have been deployed to mainnet, no later than Bitcoin block 700000. # Reference Implementations From 96998dd8950a473cba8020d8ef17ba6e7c9f89dc Mon Sep 17 00:00:00 2001 From: Hank Stoever Date: Fri, 5 Mar 2021 14:50:44 -0800 Subject: [PATCH 06/15] feat: add `get-` prefix to read-only, adds `get-token-uri` --- .../sip-010-fungible-token-standard.md | 71 +++++++++++++++---- 1 file changed, 59 insertions(+), 12 deletions(-) diff --git a/sips/sip-010/sip-010-fungible-token-standard.md b/sips/sip-010/sip-010-fungible-token-standard.md index 830ba12a..1e4cfa29 100644 --- a/sips/sip-010/sip-010-fungible-token-standard.md +++ b/sips/sip-010/sip-010-fungible-token-standard.md @@ -68,7 +68,7 @@ When returning an error in this function, the error codes should follow the same ### Name -`(name () (response (string-ascii 32) uint))` +`(get-name () (response (string-ascii 32) uint))` Return a human-readable name for the contract, such as "CoolPoints", etc. @@ -76,7 +76,7 @@ This method should be defined as read-only, i.e. `define-read-only`. ### Symbol -`(symbol () (response (string-ascii 32) uint))` +`(get-symbol () (response (string-ascii 32) uint))` Return a symbol that allows for a shorter representation of a token. This is sometimes referred to as a "ticker". Examples: "STX", "COOL", etc. Typically, a token could be referred to as $SYMBOL when referencing it in writing. @@ -84,17 +84,17 @@ This method should be defined as read-only, i.e. `define-read-only`. ### Decimals -`(decimals () (response uint uint))` +`(get-decimals () (response uint uint))` The number of decimal places in a token. All fungible token balances must be represented as integers, but providing the number of decimals provides for an abstraction of a token that humans are more familiar dealing with. For example, the US Dollar has 2 decimals, if the base unit is "cents", as is typically done in accounting. Stacks has 6 decimals, Bitcoin has 8 decimals, and so on. -As another example, if a token has 4 decimals, and the `balance-of` a particular user returns `100345000`, wallets and exchanges would likely represent that value as `10034.5`. +As another example, if a token has 4 decimals, and the `get-balance-of` method a particular user returns `100345000`, wallets and exchanges would likely represent that value as `10034.5`. This method should be defined as read-only, i.e. `define-read-only`. ### Balance of -`(balance-of (principal) (response uint uint))` +`(get-balance-of (principal) (response uint uint))` Return the balance of a particular principal (also known as "address" or "account"). Implementations should typically use the built-in Clarity method `ft-get-balance`. @@ -102,12 +102,43 @@ This method should be defined as read-only, i.e. `define-read-only`. ### Total supply -`(total-supply () (response uint uint))` +`(get-total-supply () (response uint uint))` Return the total supply of this token. Implementations should typically use the built-in Clarity method `ft-get-supply`. This method should be defined as read-only, i.e. `define-read-only`. +### Token URI + +`(get-token-uri () (response (optional (string-utf8 256)) uint))` + +Returns an optional string that is a valid URI which resolves to this token's metadata. This allows your token to provide off-chain metadata about the contract, such as a description and an image icon. + +The JSON schema for this metadata is as follows: + +```json +{ + "title": "Asset Metadata", + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Identifies the asset to which this token represents" + }, + "description": { + "type": "string", + "description": "Describes the asset to which this token represents" + }, + "image": { + "type": "string", + "description": "A URI pointing to a resource with mime type image/* representing the asset to which this token represents. Consider making any images at a width between 320 and 1080 pixels and aspect ratio between 1.91:1 and 4:5 inclusive." + } + } +} +``` + +Clients that fetch this data should prefer any on-chain data, such as the name of the token, over metadata provided in `get-token-uri`. + ## Trait implementation An implementation of the proposed trait is provided below. @@ -119,19 +150,22 @@ An implementation of the proposed trait is provided below. (transfer (uint principal principal) (response bool uint)) ;; the human readable name of the token - (name () (response (string-ascii 32) uint)) + (get-name () (response (string-ascii 32) uint)) ;; the ticker symbol, or empty if none - (symbol () (response (string-ascii 32) uint)) + (get-symbol () (response (string-ascii 32) uint)) ;; the number of decimals used, e.g. 6 would mean 1_000_000 represents 1 token - (decimals () (response uint uint)) + (get-decimals () (response uint uint)) ;; the balance of the passed principal - (balance-of (principal) (response uint uint)) + (get-balance-of (principal) (response uint uint)) ;; the current total supply (which does not need to be a constant) - (total-supply () (response uint uint)) + (get-total-supply () (response uint uint)) + + ;; an optional URI that represents metadata of this token + (get-token-uri () (response (optional (string-utf8 256)) uint)) ) ) ``` @@ -140,10 +174,23 @@ An implementation of the proposed trait is provided below. Developers who wish to interact with a fungible token contract should first be provided, or keep track of, various different fungible token implementations. When validating a fungible token contract, they should fetch the interface and/or source code for that contract. If the contract implements the trait, then the wallet can use this standard's contract interface for making transfers and getting balances. -Downstream consumers of contracts that implement this trait should be aware that the `name` and `symbol` function are not guaranteed to be globally unique. Because of this, consumers should be advised that `name` and `token` are only hints to provide a more human-readable experience. Care should always be taken to verify that a contract's identifier matches that of the token a client is intending to interact with. +Downstream consumers of contracts that implement this trait should be aware that the `get-name` and `get-symbol` function are not guaranteed to be globally unique. Because of this, consumers should be advised that `get-name` and `get-token` are only hints to provide a more human-readable experience. Care should always be taken to verify that a contract's identifier matches that of the token a client is intending to interact with. All of the functions in this trait return the `response` type, which is a requirement of trait definitions in Clarity. However, some of these functions should be "fail-proof", in the sense that they should never return an error. These "fail-proof" functions are those that have been recommended as read-only. If a contract that implements this trait returns an error for these functions, it may be an indication of a faulty contract, and consumers of those contracts should proceed with caution. +## Use of native asset functions + +Although it is not possible to mandate in a Clarity trait, contract implementers should always use the built-in native assets that are provided as Clarity primitives. This allows clients to use Post Conditions (explained below), and takes advantages of other benefits, like native support for these asset balances and transfers through `stacks-blockchain-api`. The reference implementations included in this SIP use the native asset primitives, and provide a good boilerplate for their usage. + +The native asset primitives include: + +- `define-fungible-token` +- `ft-burn?` +- `ft-get-balance` +- `ft-get-supply` +- `ft-mint?` +- `ft-transfer?` + ## Use of post conditions In addition to built-in methods for fungible token contracts, the Stacks blockchain includes a feature known as Post Conditions. By defining post conditions, users can create transactions that include pre-defined guarantees about what might happen in that contract. From 670839143ac1fc4adf089d39b0c1581435bfc777 Mon Sep 17 00:00:00 2001 From: Jude Nelson Date: Fri, 12 Mar 2021 12:24:48 -0500 Subject: [PATCH 07/15] move to Activation-in-Progress status --- sips/sip-010/sip-010-fungible-token-standard.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sips/sip-010/sip-010-fungible-token-standard.md b/sips/sip-010/sip-010-fungible-token-standard.md index 1e4cfa29..c2dc59d3 100644 --- a/sips/sip-010/sip-010-fungible-token-standard.md +++ b/sips/sip-010/sip-010-fungible-token-standard.md @@ -1,6 +1,6 @@ # Preamble -Sip Number: 010 +SIP Number: 010 Title: Standard Trait Definition for Fungible Tokens @@ -10,7 +10,7 @@ Consideration: Technical Type: Standard -Status: Draft +Status: Activation-in-Progress Created: 25 January 2021 From 462755b71d7bd82265011c9df8a4c13bee19a063 Mon Sep 17 00:00:00 2001 From: Hank Stoever Date: Sat, 13 Mar 2021 19:44:22 -0800 Subject: [PATCH 08/15] feat: adds @psq as contributor --- sips/sip-010/sip-010-fungible-token-standard.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sips/sip-010/sip-010-fungible-token-standard.md b/sips/sip-010/sip-010-fungible-token-standard.md index 1e4cfa29..b19fd8d8 100644 --- a/sips/sip-010/sip-010-fungible-token-standard.md +++ b/sips/sip-010/sip-010-fungible-token-standard.md @@ -4,7 +4,7 @@ Sip Number: 010 Title: Standard Trait Definition for Fungible Tokens -Author: Hank Stoever (hstove@gmail.com) +Author: Hank Stoever (hstove@gmail.com), Pascal Belloncle (psq@nanorails.com) Consideration: Technical From 557602cd52c6fa276fffd6d5466c1bf542c2ba0b Mon Sep 17 00:00:00 2001 From: Hank Stoever Date: Tue, 16 Mar 2021 14:19:24 -0700 Subject: [PATCH 09/15] feat: add mainnet trait --- sips/sip-010/sip-010-fungible-token-standard.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sips/sip-010/sip-010-fungible-token-standard.md b/sips/sip-010/sip-010-fungible-token-standard.md index b19fd8d8..79c1cc09 100644 --- a/sips/sip-010/sip-010-fungible-token-standard.md +++ b/sips/sip-010/sip-010-fungible-token-standard.md @@ -213,6 +213,8 @@ Not applicable # Activation +This trait has been deployed to mainnet: [SP3FBR2AGK5H9QBDH3EEN6DF8EK8JY7RX8QJ5SVTE.sip-10-ft-standard](https://explorer.stacks.co/txid/SP3FBR2AGK5H9QBDH3EEN6DF8EK8JY7RX8QJ5SVTE.sip-10-ft-standard?chain=mainnet) + This trait will be considered activated when this trait is deployed to mainnet, and 3 different implementations of the trait have been deployed to mainnet, no later than Bitcoin block 700000. # Reference Implementations From ff100716e9bbe632604b259e34d66e42b5a990ee Mon Sep 17 00:00:00 2001 From: Jude Nelson Date: Wed, 17 Mar 2021 12:34:07 -0400 Subject: [PATCH 10/15] sign-offs and email formatting --- sips/sip-010/sip-010-fungible-token-standard.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sips/sip-010/sip-010-fungible-token-standard.md b/sips/sip-010/sip-010-fungible-token-standard.md index 46690752..e3047af1 100644 --- a/sips/sip-010/sip-010-fungible-token-standard.md +++ b/sips/sip-010/sip-010-fungible-token-standard.md @@ -4,7 +4,7 @@ SIP Number: 010 Title: Standard Trait Definition for Fungible Tokens -Author: Hank Stoever (hstove@gmail.com), Pascal Belloncle (psq@nanorails.com) +Author: Hank Stoever , Pascal Belloncle Consideration: Technical @@ -16,7 +16,7 @@ Created: 25 January 2021 License: CC0-1.0 -Sign-off: +Sign-off: Jude Nelson , Technical Steering Committee Chair Layer: Traits From 19d0d53e1c8843e70234806c38e41b6970f793ce Mon Sep 17 00:00:00 2001 From: Ludo Galabru Date: Wed, 12 May 2021 18:29:30 -0400 Subject: [PATCH 11/15] feat: add spec for memo --- .../sip-010-fungible-token-standard.md | 22 ++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/sips/sip-010/sip-010-fungible-token-standard.md b/sips/sip-010/sip-010-fungible-token-standard.md index e3047af1..78427225 100644 --- a/sips/sip-010/sip-010-fungible-token-standard.md +++ b/sips/sip-010/sip-010-fungible-token-standard.md @@ -43,15 +43,15 @@ The Stacks blockchain has a native fungible token: the Stacks token (STX). In ad # Specification -The fungible token trait, `ft-trait`, has a 6 functions: +The fungible token trait, `sip10-trait`, has 7 functions: ## Trait functions ### Transfer -`(transfer ((amount uint) (sender principal) (recipient principal)) (response bool uint))` +`(transfer ((amount uint) (sender principal) (recipient principal) (memo (optional (buff 34)))) (response bool uint))` -Transfer the fungible token from the sender of this transaction to the recipient. The `amount` is an unsigned integer. It is recommended that implementing contracts use the built-in `ft-transfer` Clarity method. If the sender does not have enough tokens to complete the transaction, the transaction should abort and return an `(err uint)`. +Transfer the fungible token from the sender of this transaction to the recipient. The `amount` is an unsigned integer. It is recommended that implementing contracts use the built-in `ft-transfer?` Clarity method. If the sender does not have enough tokens to complete the transaction, the transaction should abort and return an `(err uint)`. This method must be defined with `define-public`, as it alters state, and should be externally callable. @@ -66,6 +66,18 @@ When returning an error in this function, the error codes should follow the same | u3 | `amount` is non-positive | | u4 | `sender` is not the same as `tx-sender` | + +Contract implementers should take note that in Stacks 2.0, the memo field won't be included in the event emitted by successful `ft-transfer?` operations. As a consequence, if compliance with exchanges is a requirement, it is recommended to emit an event including the memo, by adding a `print` statement if the `ft-transfer?` is successful. + +Exemple: + +``` + ... + (try! (ft-transfer? token amount sender recipient)) + (print memo) + ... +``` + ### Name `(get-name () (response (string-ascii 32) uint))` @@ -144,10 +156,10 @@ Clients that fetch this data should prefer any on-chain data, such as the name o An implementation of the proposed trait is provided below. ```clarity -(define-trait ft-trait +(define-trait sip10-trait ( ;; Transfer from the caller to a new principal - (transfer (uint principal principal) (response bool uint)) + (transfer (uint principal principal (optional (buff 34))) (response bool uint)) ;; the human readable name of the token (get-name () (response (string-ascii 32) uint)) From 7301efda6f77b985d8bc0ceea009635ae8c31eea Mon Sep 17 00:00:00 2001 From: Ludo Galabru Date: Wed, 12 May 2021 19:02:40 -0400 Subject: [PATCH 12/15] fix: update trait name --- sips/sip-010/sip-010-fungible-token-standard.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sips/sip-010/sip-010-fungible-token-standard.md b/sips/sip-010/sip-010-fungible-token-standard.md index 78427225..4440a13c 100644 --- a/sips/sip-010/sip-010-fungible-token-standard.md +++ b/sips/sip-010/sip-010-fungible-token-standard.md @@ -43,7 +43,7 @@ The Stacks blockchain has a native fungible token: the Stacks token (STX). In ad # Specification -The fungible token trait, `sip10-trait`, has 7 functions: +The fungible token trait, `sip-010-trait`, has 7 functions: ## Trait functions @@ -156,7 +156,7 @@ Clients that fetch this data should prefer any on-chain data, such as the name o An implementation of the proposed trait is provided below. ```clarity -(define-trait sip10-trait +(define-trait sip-010-trait ( ;; Transfer from the caller to a new principal (transfer (uint principal principal (optional (buff 34))) (response bool uint)) From 0429c32291e50e069a3b65eb6f10c3f78d82098c Mon Sep 17 00:00:00 2001 From: Ludo Galabru Date: Mon, 17 May 2021 12:08:04 -0400 Subject: [PATCH 13/15] Update sips/sip-010/sip-010-fungible-token-standard.md Co-authored-by: Hank Stoever --- sips/sip-010/sip-010-fungible-token-standard.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sips/sip-010/sip-010-fungible-token-standard.md b/sips/sip-010/sip-010-fungible-token-standard.md index 4440a13c..2f861d70 100644 --- a/sips/sip-010/sip-010-fungible-token-standard.md +++ b/sips/sip-010/sip-010-fungible-token-standard.md @@ -69,7 +69,7 @@ When returning an error in this function, the error codes should follow the same Contract implementers should take note that in Stacks 2.0, the memo field won't be included in the event emitted by successful `ft-transfer?` operations. As a consequence, if compliance with exchanges is a requirement, it is recommended to emit an event including the memo, by adding a `print` statement if the `ft-transfer?` is successful. -Exemple: +Example: ``` ... From 836e95a0fcd9b0c6874a0b43692c93e3fd688de5 Mon Sep 17 00:00:00 2001 From: Hank Stoever Date: Fri, 28 May 2021 13:20:44 -0700 Subject: [PATCH 14/15] fix: updated links for mainnet/testnet trait deploys --- sips/sip-010/sip-010-fungible-token-standard.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sips/sip-010/sip-010-fungible-token-standard.md b/sips/sip-010/sip-010-fungible-token-standard.md index 2f861d70..f0f340a9 100644 --- a/sips/sip-010/sip-010-fungible-token-standard.md +++ b/sips/sip-010/sip-010-fungible-token-standard.md @@ -66,7 +66,6 @@ When returning an error in this function, the error codes should follow the same | u3 | `amount` is non-positive | | u4 | `sender` is not the same as `tx-sender` | - Contract implementers should take note that in Stacks 2.0, the memo field won't be included in the event emitted by successful `ft-transfer?` operations. As a consequence, if compliance with exchanges is a requirement, it is recommended to emit an event including the memo, by adding a `print` statement if the `ft-transfer?` is successful. Example: @@ -225,7 +224,8 @@ Not applicable # Activation -This trait has been deployed to mainnet: [SP3FBR2AGK5H9QBDH3EEN6DF8EK8JY7RX8QJ5SVTE.sip-10-ft-standard](https://explorer.stacks.co/txid/SP3FBR2AGK5H9QBDH3EEN6DF8EK8JY7RX8QJ5SVTE.sip-10-ft-standard?chain=mainnet) +This trait has been deployed to mainnet: [SP1X6M947Z7E58CNE0H8YJVJTVKS9VW0PHD4Q0A5F.sip-010](https://explorer.stacks.co/txid/SP1X6M947Z7E58CNE0H8YJVJTVKS9VW0PHD4Q0A5F.sip-010?chain=mainnet) +testnet: [ST1X6M947Z7E58CNE0H8YJVJTVKS9VW0PHEG3NHN3.sip-010](https://explorer.stacks.co/txid/ST1X6M947Z7E58CNE0H8YJVJTVKS9VW0PHEG3NHN3.sip-010?chain=testnet) This trait will be considered activated when this trait is deployed to mainnet, and 3 different implementations of the trait have been deployed to mainnet, no later than Bitcoin block 700000. From 4dd02c8be1e83ee385ea47275f2bd1ca09df9871 Mon Sep 17 00:00:00 2001 From: Hank Stoever Date: Sat, 29 May 2021 09:20:53 -0700 Subject: [PATCH 15/15] fix: updated deployed trait urls --- sips/sip-010/sip-010-fungible-token-standard.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/sips/sip-010/sip-010-fungible-token-standard.md b/sips/sip-010/sip-010-fungible-token-standard.md index f0f340a9..dc7904ed 100644 --- a/sips/sip-010/sip-010-fungible-token-standard.md +++ b/sips/sip-010/sip-010-fungible-token-standard.md @@ -99,13 +99,13 @@ This method should be defined as read-only, i.e. `define-read-only`. The number of decimal places in a token. All fungible token balances must be represented as integers, but providing the number of decimals provides for an abstraction of a token that humans are more familiar dealing with. For example, the US Dollar has 2 decimals, if the base unit is "cents", as is typically done in accounting. Stacks has 6 decimals, Bitcoin has 8 decimals, and so on. -As another example, if a token has 4 decimals, and the `get-balance-of` method a particular user returns `100345000`, wallets and exchanges would likely represent that value as `10034.5`. +As another example, if a token has 4 decimals, and the `get-balance` method a particular user returns `100345000`, wallets and exchanges would likely represent that value as `10034.5`. This method should be defined as read-only, i.e. `define-read-only`. ### Balance of -`(get-balance-of (principal) (response uint uint))` +`(get-balance (principal) (response uint uint))` Return the balance of a particular principal (also known as "address" or "account"). Implementations should typically use the built-in Clarity method `ft-get-balance`. @@ -170,7 +170,7 @@ An implementation of the proposed trait is provided below. (get-decimals () (response uint uint)) ;; the balance of the passed principal - (get-balance-of (principal) (response uint uint)) + (get-balance (principal) (response uint uint)) ;; the current total supply (which does not need to be a constant) (get-total-supply () (response uint uint)) @@ -224,8 +224,8 @@ Not applicable # Activation -This trait has been deployed to mainnet: [SP1X6M947Z7E58CNE0H8YJVJTVKS9VW0PHD4Q0A5F.sip-010](https://explorer.stacks.co/txid/SP1X6M947Z7E58CNE0H8YJVJTVKS9VW0PHD4Q0A5F.sip-010?chain=mainnet) -testnet: [ST1X6M947Z7E58CNE0H8YJVJTVKS9VW0PHEG3NHN3.sip-010](https://explorer.stacks.co/txid/ST1X6M947Z7E58CNE0H8YJVJTVKS9VW0PHEG3NHN3.sip-010?chain=testnet) +This trait has been deployed to mainnet: [SP3FBR2AGK5H9QBDH3EEN6DF8EK8JY7RX8QJ5SVTE.sip-010-trait-ft-standard](https://explorer.stacks.co/txid/0x99e01721e57adc2c24f7d371b9d302d581dba1d27250c7e25ea5f241af14c387?chain=mainnet) +testnet: [STR8P3RD1EHA8AA37ERSSSZSWKS9T2GYQFGXNA4C.sip-010-trait-ft-standard](https://explorer.stacks.co/txid/0xef2ac1126e16f4706843228b14830e19eb7599129edff392cab9e65ae83a45c0?chain=testnet) This trait will be considered activated when this trait is deployed to mainnet, and 3 different implementations of the trait have been deployed to mainnet, no later than Bitcoin block 700000.