Skip to content

Commit

Permalink
Merge pull request #34 from FuelLabs/bitzoic-src3-example
Browse files Browse the repository at this point in the history
Add SRC-3 Basic Examples
  • Loading branch information
bitzoic authored Nov 3, 2023
2 parents b156ae4 + 765a554 commit 3befaf6
Show file tree
Hide file tree
Showing 5 changed files with 343 additions and 5 deletions.
9 changes: 9 additions & 0 deletions examples/src_3/multi_asset/Forc.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[project]
authors = ["Fuel Labs <[email protected]>"]
entry = "multi_asset.sw"
license = "Apache-2.0"
name = "multi_src3_asset"

[dependencies]
src_20 = { path = "../../../standards/src_20" }
src_3 = { path = "../../../standards/src_3" }
162 changes: 162 additions & 0 deletions examples/src_3/multi_asset/src/multi_asset.sw
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
contract;

use src_3::SRC3;
use src_20::SRC20;
use std::{
call_frames::{
contract_id,
msg_asset_id,
},
context::msg_amount,
hash::Hash,
storage::storage_string::*,
string::String,
token::{
burn,
mint_to,
},
};

// In this example, all assets minted from this contract have the same decimals, name, and symbol
configurable {
/// The decimals of every asset minted by this contract.
DECIMALS: u8 = 9u8,
/// The name of every asset minted by this contract.
NAME: str[12] = __to_str_array("ExampleAsset"),
/// The symbol of every asset minted by this contract.
SYMBOL: str[2] = __to_str_array("EA"),
}

storage {
/// The total number of distinguishable assets this contract has minted.
total_assets: u64 = 0,
/// The total supply of a particular asset.
total_supply: StorageMap<AssetId, u64> = StorageMap {},
}

impl SRC3 for Contract {
/// Unconditionally mints new tokens using the `sub_id` sub-identifier.
///
/// # Arguments
///
/// * `recipient`: [Identity] - The user to which the newly minted tokens are transferred to.
/// * `sub_id`: [SubId] - The sub-identifier of the newly minted token.
/// * `amount`: [u64] - The quantity of tokens to mint.
///
/// # Number of Storage Accesses
///
/// * Reads: `2`
/// * Writes: `2`
///
/// # Examples
///
/// ```sway
/// use src3::SRC3;
/// use std::constants::ZERO_B256;
///
/// fn foo(contract_id: ContractId) {
/// let contract_abi = abi(SR3, contract_id);
/// contract_abi.mint(Identity::ContractId(contract_id), ZERO_B256, 100);
/// }
/// ```
#[storage(read, write)]
fn mint(recipient: Identity, sub_id: SubId, amount: u64) {
let asset_id = AssetId::new(contract_id(), sub_id);

// If this SubId is new, increment the total number of distinguishable assets this contract has minted.
let asset_supply = storage.total_supply.get(asset_id).try_read();
match asset_supply {
None => {
storage.total_assets.write(storage.total_assets.read() + 1)
},
_ => {},
}

// Increment total supply of the asset and mint to the recipient.
storage.total_supply.insert(asset_id, amount + asset_supply.unwrap_or(0));
mint_to(recipient, sub_id, amount);
}

/// Unconditionally burns tokens sent with the `sub_id` sub-identifier.
///
/// # Arguments
///
/// * `sub_id`: [SubId] - The sub-identifier of the token to burn.
/// * `amount`: [u64] - The quantity of tokens to burn.
///
/// # Number of Storage Accesses
///
/// * Reads: `1`
/// * Writes: `1`
///
/// # Reverts
///
/// * When the transaction did not include at least `amount` tokens.
/// * When the asset included in the transaction does not have the SubId `sub_id`.
///
/// # Examples
///
/// ```sway
/// use src3::SRC3;
/// use std::constants::ZERO_B256;
///
/// fn foo(contract_id: ContractId, asset_id: AssetId) {
/// let contract_abi = abi(SR3, contract_id);
/// contract_abi {
/// gas: 10000,
/// coins: 100,
/// asset_id: asset_id,
/// }.burn(ZERO_B256, 100);
/// }
/// ```
#[storage(read, write)]
fn burn(sub_id: SubId, amount: u64) {
let asset_id = AssetId::new(contract_id(), sub_id);
require(msg_amount() == amount, "Incorrect amount provided");
require(msg_asset_id() == asset_id, "Incorrect asset provided");

// Decrement total supply of the asset and burn.
storage.total_supply.insert(asset_id, storage.total_supply.get(asset_id).read() - amount);
burn(sub_id, amount);
}
}

// SRC3 extends SRC20, so this must be included
impl SRC20 for Contract {
#[storage(read)]
fn total_assets() -> u64 {
storage.total_assets.read()
}

#[storage(read)]
fn total_supply(asset: AssetId) -> Option<u64> {
storage.total_supply.get(asset).try_read()
}

#[storage(read)]
fn name(asset: AssetId) -> Option<String> {
if asset == AssetId::default(contract_id()) {
Some(String::from_ascii_str(from_str_array(NAME)))
} else {
None
}
}

#[storage(read)]
fn symbol(asset: AssetId) -> Option<String> {
if asset == AssetId::default(contract_id()) {
Some(String::from_ascii_str(from_str_array(SYMBOL)))
} else {
None
}
}

#[storage(read)]
fn decimals(asset: AssetId) -> Option<u8> {
if asset == AssetId::default(contract_id()) {
Some(DECIMALS)
} else {
None
}
}
}
9 changes: 9 additions & 0 deletions examples/src_3/single_asset/Forc.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[project]
authors = ["Fuel Labs <[email protected]>"]
entry = "single_asset.sw"
license = "Apache-2.0"
name = "single_src3_asset"

[dependencies]
src_20 = { path = "../../../standards/src_20" }
src_3 = { path = "../../../standards/src_3" }
158 changes: 158 additions & 0 deletions examples/src_3/single_asset/src/single_asset.sw
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
contract;

use src_3::SRC3;
use src_20::SRC20;
use std::{
call_frames::{
contract_id,
msg_asset_id,
},
constants::ZERO_B256,
context::msg_amount,
string::String,
token::{
burn,
mint_to,
},
};

configurable {
/// The decimals of the asset minted by this contract.
DECIMALS: u8 = 9u8,
/// The name of the asset minted by this contract.
NAME: str[7] = __to_str_array("MyToken"),
/// The symbol of the asset minted by this contract.
SYMBOL: str[5] = __to_str_array("MYTKN"),
}

storage {
/// The total supply of the asset minted by this contract.
total_supply: u64 = 0,
}

impl SRC3 for Contract {
/// Unconditionally mints new tokens using the default SubId.
///
/// # Arguments
///
/// * `recipient`: [Identity] - The user to which the newly minted tokens are transferred to.
/// * `sub_id`: [SubId] - The default SubId.
/// * `amount`: [u64] - The quantity of tokens to mint.
///
/// # Number of Storage Accesses
///
/// * Reads: `1`
/// * Writes: `1`
///
/// # Reverts
///
/// * When the `sub_id` is not the default SubId.
///
/// # Examples
///
/// ```sway
/// use src3::SRC3;
/// use std::constants::ZERO_B256;
///
/// fn foo(contract_id: ContractId) {
/// let contract_abi = abi(SR3, contract);
/// contract_abi.mint(Identity::ContractId(contract_id), ZERO_B256, 100);
/// }
/// ```
#[storage(read, write)]
fn mint(recipient: Identity, sub_id: SubId, amount: u64) {
require(sub_id == ZERO_B256, "Incorrect Sub Id");

// Increment total supply of the asset and mint to the recipient.
storage.total_supply.write(amount + storage.total_supply.read());
mint_to(recipient, ZERO_B256, amount);
}

/// Unconditionally burns tokens sent with the default SubId.
///
/// # Arguments
///
/// * `sub_id`: [SubId] - The default SubId.
/// * `amount`: [u64] - The quantity of tokens to burn.
///
/// # Number of Storage Accesses
///
/// * Reads: `1`
/// * Writes: `1`
///
/// # Reverts
///
/// * When the `sub_id` is not the default SubId.
/// * When the transaction did not include at least `amount` tokens.
/// * When the transaction did not include the asset minted by this contract.
///
/// # Examples
///
/// ```sway
/// use src3::SRC3;
/// use std::constants::ZERO_B256;
///
/// fn foo(contract_id: ContractId, asset_id: AssetId) {
/// let contract_abi = abi(SR3, contract_id);
/// contract_abi {
/// gas: 10000,
/// coins: 100,
/// asset_id: asset_id,
/// }.burn(ZERO_B256, 100);
/// }
/// ```
#[storage(read, write)]
fn burn(sub_id: SubId, amount: u64) {
require(sub_id == ZERO_B256, "Incorrect Sub Id");
require(msg_amount() >= amount, "Incorrect amount provided");
require(msg_asset_id() == AssetId::default(contract_id()), "Incorrect asset provided");

// Decrement total supply of the asset and burn.
storage.total_supply.write(storage.total_supply.read() - amount);
burn(ZERO_B256, amount);
}
}

// SRC3 extends SRC20, so this must be included
impl SRC20 for Contract {
#[storage(read)]
fn total_assets() -> u64 {
1
}

#[storage(read)]
fn total_supply(asset: AssetId) -> Option<u64> {
if asset == AssetId::default(contract_id()) {
Some(storage.total_supply.read())
} else {
None
}
}

#[storage(read)]
fn name(asset: AssetId) -> Option<String> {
if asset == AssetId::default(contract_id()) {
Some(String::from_ascii_str(from_str_array(NAME)))
} else {
None
}
}

#[storage(read)]
fn symbol(asset: AssetId) -> Option<String> {
if asset == AssetId::default(contract_id()) {
Some(String::from_ascii_str(from_str_array(SYMBOL)))
} else {
None
}
}

#[storage(read)]
fn decimals(asset: AssetId) -> Option<u8> {
if asset == AssetId::default(contract_id()) {
Some(DECIMALS)
} else {
None
}
}
}
10 changes: 5 additions & 5 deletions standards/src_3/src/src_3.sw
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ abi SRC3 {
/// ```sway
/// use src3::SRC3;
///
/// fn foo(contract: ContractId) {
/// fn foo(contract_id: ContractId) {
/// let contract_abi = abi(SR3, contract);
/// contract_abi.mint(Identity::ContractId(this_contract()), ZERO_B256, 100);
/// contract_abi.mint(Identity::ContractId(contract_id), ZERO_B256, 100);
/// }
/// ```
#[storage(read, write)]
Expand All @@ -39,12 +39,12 @@ abi SRC3 {
/// ```sway
/// use src3::SRC3;
///
/// fn foo(contract: ContractId, asset_id: AssetId) {
/// let contract_abi = abi(SR3, contract);
/// fn foo(contract_id: ContractId, asset_id: AssetId) {
/// let contract_abi = abi(SR3, contract_id);
/// contract_abi {
/// gas: 10000,
/// coins: 100,
/// asset_id: AssetId,
/// asset_id: asset_id,
/// }.burn(ZERO_B256, 100);
/// }
/// ```
Expand Down

0 comments on commit 3befaf6

Please sign in to comment.