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

SRC-20 Token Standard #13

Merged
merged 12 commits into from
Aug 31, 2023
6 changes: 2 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ If you don't find what you're looking for, feel free to create an issue and prop

## Standards

- [SRC-20; Token Standard](https://github.com/FuelLabs/sway-standards/issues/1) is currently in draft
- [SRC-20; Token Standard](./standards/src_20/) defines the implementation of a standard API for [Native Assets](https://fuellabs.github.io/sway/v0.38.0/book/blockchain-development/native_assets.html) using the Sway Language.
bitzoic marked this conversation as resolved.
Show resolved Hide resolved
- [SRC-2; Inline Documentation](./standards/src_2/) defines how to document your Sway files.
- [SRC-5; Ownership Standard](./standards/src_5/) is used to restrict function calls to admin users in contracts.

Expand All @@ -54,11 +54,9 @@ use standard::<standard_abi>;
For example, to import the SRC-20 Token Standard use the following statement:

```rust
use standard::src_20;
use src20::SRC20;
```

> **NOTE** The SRC-20 standard is currently in draft. This cannot be imported until the standard is finalized. You may implement your own abi using the standard in order to prepare for the standard's release.

> **Note**
> All standards currently use `forc v0.38.0`.

Expand Down
2 changes: 1 addition & 1 deletion standards/Forc.toml
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
[workspace]
members = ["src_5"]
members = ["src_5", "src_20"]
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 5 additions & 0 deletions standards/src_20/Forc.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[project]
authors = ["Fuel Labs <contact@fuel.sh>"]
entry = "src_20.sw"
license = "Apache-2.0"
name = "src_20"
83 changes: 83 additions & 0 deletions standards/src_20/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
<p align="center">
<picture>
<source media="(prefers-color-scheme: dark)" srcset=".docs/src-20-logo-dark-theme.png">
<img alt="SRC-5 logo" width="400px" src=".docs/src-20-logo-light-theme.png">
</picture>
</p>

# Abstract

The following standard allows for the implementation of a standard API for [Native Assets](https://fuellabs.github.io/sway/v0.38.0/book/blockchain-development/native_assets.html) using the Sway Language. This standard provides basic functionality as well as on-chain metadata for other applications to use.

# Motivation

A standard interface for [Native Assets](https://fuellabs.github.io/sway/v0.38.0/book/blockchain-development/native_assets.html) on Fuel allows external applications to interact with the token, whether that be decentralized exchanges, wallets, or Fuel's [Scripts](https://fuellabs.github.io/sway/v0.38.0/book/sway-program-types/scripts.html) and [Predicates](https://fuellabs.github.io/sway/v0.38.0/book/sway-program-types/predicates.html).

# Prior Art

The SRC-20 Fungible Token Standard naming pays homage to the [ERC-20 Token Standard](https://eips.ethereum.org/EIPS/eip-20) seen on Ethereum. While there is functionality we may use as reference, it is noted that Fuel's [Native Assets](https://fuellabs.github.io/sway/v0.38.0/book/blockchain-development/native_assets.html) are fundamentally different than Ethereum's tokens.
bitzoic marked this conversation as resolved.
Show resolved Hide resolved

There has been a discussion of the Fungile Token Standard on the [Fuel Forum](https://forum.fuel.network/). This discussion can be found [here](https://forum.fuel.network/t/src-20-fungible-token-standard/186).

There has also been a Fungible Token Standard and Non-Fungible Token Standard implementations added to the [Sway-Libs](https://github.com/FuelLabs/sway-libs) repository before the creation of the [Sway-Standards](https://github.com/FuelLabs/sway-standards) repository. The introduction of this standard in the [Sway-Standards](https://github.com/FuelLabs/sway-standards) repository will deprecate the Sway-Libs Fungible Token Standard.

# Specification

## Required Public Functions

The following functions MUST be implemented to follow the SRC-20 standard:

### `fn name(asset: AssetId) -> String`
bitzoic marked this conversation as resolved.
Show resolved Hide resolved
Returns the name of the asset, such as “Ether”.
bitzoic marked this conversation as resolved.
Show resolved Hide resolved

### `fn total_supply(asset: b256) -> u64`
bitzoic marked this conversation as resolved.
Show resolved Hide resolved
Returns the total supply of tokens that have been minted for an asset.
bitzoic marked this conversation as resolved.
Show resolved Hide resolved

### `fn total_assets() -> u64`
Returns the total number of assets that have been minted for this contract.
bitzoic marked this conversation as resolved.
Show resolved Hide resolved
bitzoic marked this conversation as resolved.
Show resolved Hide resolved

### `fn decimals(asset: AssetId) -> u8`
Returns the number of decimals the asset uses - e.g. 8, means to divide the token amount by 100000000 to get its user representation.
bitzoic marked this conversation as resolved.
Show resolved Hide resolved

### `fn symbol(asset: AssetId) -> String`
Returns the symbol of the asset, such as “ETH”.
bitzoic marked this conversation as resolved.
Show resolved Hide resolved

## Non-Fungible Token Restrictions

Non-Fungible Tokens(NFT) on Fuel are Native Assets and thus follow the same standard as Fungible Tokens with applied restrictions. For a Native Asset on Fuel to be deemed an NFT, the following must be applied:
bitzoic marked this conversation as resolved.
Show resolved Hide resolved

* Non-Fungible Tokens SHALL have a total supply of one per asset.
* Non-Fungible Tokens SHALL have a decimal of `0u8`.

# Rationale

As the SRC-20 Token Standard leverages Native Assets on Fuel, we do not require the implementation of certain functions such as transfer or approval. This is done directly within the FuelVM and there is no smart contract that requires updating of balances. As Fuel is UTXO based, any transfer events may be indexed on transaction receipts.

Following this, we have omitted the inclusion of any transfer functions or events. The provided specification outlines only the required functions and events to implement fully functional tokens on the Fuel Network. Additional functionality and properties may be added as needed.

# Backwards Compatibility

This standard is compatible with Fuel's [Native Assets](https://fuellabs.github.io/sway/v0.38.0/book/blockchain-development/native_assets.html). There are no other standards that require compatibility.

# Security Considerations

This standard does not introduce any security concerns, as it does not call external contracts, nor does it define any mutations of the contract state.

# Example ABI

```rust
abi MyToken {
#[storage(read)]
fn total_supply(asset: AssetId) -> u64;
#[storage(read)]
fn total_assets() -> u64;
#[storage(read)]
fn decimals(asset: AssetId) -> u8;
#[storage(read)]
fn name(asset: AssetId) -> String;
#[storage(read)]
fn symbol(asset: AssetId) -> String;
}
```

This draft standard is to be released as `v0.1`.
125 changes: 125 additions & 0 deletions standards/src_20/src/src_20.sw
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
library;

use std::string::String;

abi SRC20 {
/// Returns the total number of assets that have been minted for this contract.
bitzoic marked this conversation as resolved.
Show resolved Hide resolved
///
/// # Returns
///
/// * [u64] - The number of assets that this contract has minted.
///
/// # Examples
///
/// ```sway
/// use src20::SRC20;
///
/// fn foo(contract: ContractId) {
/// let contract_abi = abi(SRC20, contract);
/// let total_assets = contract_abi.total_assets();
/// assert(total_assets != 0);
/// }
/// ```
#[storage(read)]
fn total_assets() -> u64;

/// Returns the total supply of tokens that have been minted for an asset.
///
/// # Arguments
///
/// * `asset`: [AssetId] - The asset of which to query the total supply.
///
/// # Returns
///
/// * [u64] - The total supply of tokens for `asset`.
///
/// # Examples
///
/// ```sway
/// use src20::SRC20;
///
/// fn foo(contract: ContractId, asset: AssetId) {
/// let contract_abi = abi(SRC20, contract);
/// let total_supply = contract_abi.total_supply(asset);
/// assert(total_supply != 0);
/// }
/// ```
#[storage(read)]
fn total_supply(asset: AssetId) -> u64;

/// Returns the name of the asset, such as “Ether”.
///
/// # Arguments
///
/// * `asset`: [AssetId] - The asset of which to query the name.
///
/// # Returns
///
/// * [String] - The name of `asset`.
///
/// # Examples
///
/// ```sway
/// use src20::SRC20;
/// use std::string::String;
///
/// fn foo(contract: ContractId, asset: AssetId) {
/// let contract_abi = abi(SRC20, contract);
/// let name = contract_abi.name(asset);
/// assert(name.len() != 0);
/// }
/// ```
#[storage(read)]
fn name(asset: AssetId) -> String;
/// Returns the symbol of the asset, such as “ETH”.
bitzoic marked this conversation as resolved.
Show resolved Hide resolved
///
/// # Arguments
///
/// * `asset`: [AssetId] - The asset of which to query the symbol.
///
/// # Returns
///
/// * [String] - The symbol of `asset`.
///
/// # Examples
///
/// ```sway
/// use src20::SRC20;
/// use std::string::String;
///
/// fn foo(contract: ContractId, asset: AssetId) {
/// let contract_abi = abi(SRC20, contract);
/// let symbol = contract_abi.symbol(asset);
/// assert(symbol.len() != 0);
/// }
/// ```
#[storage(read)]
fn symbol(asset: AssetId) -> String;
/// Returns the number of decimals the asset uses.
bitzoic marked this conversation as resolved.
Show resolved Hide resolved
///
/// # Additional Information
///
/// e.g. 8, means to divide the token amount by 100000000 to get its user representation.
///
/// # Arguments
///
/// * `asset`: [AssetId] - The asset of which to query the decimals.
///
/// # Returns
///
/// * [u8] - The decimal precision used by `asset`.
///
/// # Examples
///
/// ```sway
/// use src20::SRC20;
///
/// fn foo(contract: ContractId, asset: AssedId) {
/// let contract_abi = abi(SRC20, contract);
/// let decimals = contract_abi.decimals(asset);
/// assert(decimals == 8);
/// }
/// ```
#[storage(read)]
fn decimals(asset: AssetId) -> u8;
}