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

Update to use latest SRC-20 and SRC-3 specs #811

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ Description of the upcoming release here.
### Changed

- [#809](https://github.com/FuelLabs/sway-applications/issues/809) Set Devrel team as codeowners
- Something changed here 2
- [#811](https://github.com/FuelLabs/sway-applications/pull/811) Updates the NFT, Fractional NFT, and Native Asset apps to the latest SRC-20 and SRC-3 specs.

### Fixed

Expand Down
13 changes: 9 additions & 4 deletions NFT/Forc.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
name = "NFT-contract"
source = "member"
dependencies = [
"standards",
"standards git+https://github.com/FuelLabs/sway-standards?tag=v0.6.1#792639cdf391565e6e6a02482ea8a46d9604a6f5",
"std",
"sway_libs",
]
Expand All @@ -13,7 +13,12 @@ source = "path+from-root-E19CE48B3E858B72"

[[package]]
name = "standards"
source = "git+https://github.com/FuelLabs/sway-standards?tag=v0.4.3#6f63eb7dff2458a7d976184e565b5cbf26f61da2"
source = "git+https://github.com/FuelLabs/sway-standards?tag=v0.6.0#65e09f95ea8b9476b171a66c8a47108f352fa32c"
dependencies = ["std"]

[[package]]
name = "standards"
source = "git+https://github.com/FuelLabs/sway-standards?tag=v0.6.1#792639cdf391565e6e6a02482ea8a46d9604a6f5"
dependencies = ["std"]

[[package]]
Expand All @@ -23,8 +28,8 @@ dependencies = ["core"]

[[package]]
name = "sway_libs"
source = "git+https://github.com/FuelLabs/sway-libs?tag=v0.21.0#6a227ed34c86fe1ebd334dbdfeccf66c43e3915b"
source = "git+https://github.com/FuelLabs/sway-libs?tag=v0.24.0#e19f96f85ae12426d20adc176b70aa38fd9a2a5b"
dependencies = [
"standards",
"standards git+https://github.com/FuelLabs/sway-standards?tag=v0.6.0#65e09f95ea8b9476b171a66c8a47108f352fa32c",
"std",
]
4 changes: 2 additions & 2 deletions NFT/NFT-contract/Forc.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@ license = "Apache-2.0"
name = "NFT-contract"

[dependencies]
standards = { git = "https://github.com/FuelLabs/sway-standards", tag = "v0.4.3" }
sway_libs = { git = "https://github.com/FuelLabs/sway-libs", tag = "v0.21.0" }
standards = { git = "https://github.com/FuelLabs/sway-standards", tag = "v0.6.1" }
sway_libs = { git = "https://github.com/FuelLabs/sway-libs", tag = "v0.24.0" }
1 change: 1 addition & 0 deletions NFT/NFT-contract/src/errors.sw
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ pub enum MintError {
CannotMintMoreThanOneNFTWithSubId: (),
MaxNFTsMinted: (),
NFTAlreadyMinted: (),
SubIdNone: (),
}

pub enum SetError {
Expand Down
45 changes: 40 additions & 5 deletions NFT/NFT-contract/src/main.sw
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,21 @@ mod interface;

use errors::{MintError, SetError};
use interface::Constructor;
use standards::{src20::SRC20, src3::SRC3, src5::{SRC5, State}, src7::{Metadata, SRC7},};
use standards::{
src20::{
SetDecimalsEvent,
SRC20,
},
src3::SRC3,
src5::{
SRC5,
State,
},
src7::{
Metadata,
SRC7,
},
};
use sway_libs::{
asset::{
base::{
Expand Down Expand Up @@ -232,12 +246,13 @@ impl SRC3 for Contract {
/// # Arguments
///
/// * `recipient`: [Identity] - The user to which the newly minted assets are transferred to.
/// * `sub_id`: [SubId] - The sub-identifier of the newly minted asset.
/// * `sub_id`: [Option<SubId>] - The sub-identifier of the newly minted asset.
/// * `amount`: [u64] - The quantity of coins to mint.
///
/// # Reverts
///
/// * When the contract is paused.
/// * When the `sub_id` is `None`.
/// * When amount is greater than one.
/// * When the asset has already been minted.
/// * When more than the MAX_SUPPLY NFTs have been minted.
Expand All @@ -258,11 +273,12 @@ impl SRC3 for Contract {
/// }
/// ```
#[storage(read, write)]
fn mint(recipient: Identity, sub_id: SubId, amount: u64) {
fn mint(recipient: Identity, sub_id: Option<SubId>, amount: u64) {
require_not_paused();

// Checks to ensure this is a valid mint.
let asset = AssetId::new(ContractId::this(), sub_id);
require(sub_id.is_some(), MintError::SubIdNone);
let asset = AssetId::new(ContractId::this(), sub_id.unwrap());
require(amount == 1, MintError::CannotMintMoreThanOneNFTWithSubId);
require(
storage
Expand All @@ -281,13 +297,15 @@ impl SRC3 for Contract {
);

// Mint the NFT
// NOTE: TotalSupplyEvent is emitted by _mint()
let _ = _mint(
storage
.total_assets,
storage
.total_supply,
recipient,
sub_id,
sub_id
.unwrap(),
amount,
);
}
Expand Down Expand Up @@ -331,6 +349,7 @@ impl SRC3 for Contract {
#[storage(read, write)]
fn burn(sub_id: SubId, amount: u64) {
require_not_paused();
// NOTE: TotalSupplyEvent is emitted by _burn()
_burn(storage.total_supply, sub_id, amount);
}
}
Expand Down Expand Up @@ -446,6 +465,7 @@ impl SetAssetAttributes for Contract {
.is_none(),
SetError::ValueAlreadySet,
);
// NOTE: SetNameEvent is emitted by _set_name()
_set_name(storage.name, asset, name);
}

Expand Down Expand Up @@ -492,6 +512,7 @@ impl SetAssetAttributes for Contract {
.is_none(),
SetError::ValueAlreadySet,
);
// NOTE: SetSymbolEvent is emitted by _set_symbol()
_set_symbol(storage.symbol, asset, symbol);
}

Expand Down Expand Up @@ -552,6 +573,7 @@ impl SetAssetMetadata for Contract {
.is_none(),
SetError::ValueAlreadySet,
);
// NOTE: SetMetadataEvent is emitted by _set_metadata()
_set_metadata(storage.metadata, asset, key, metadata);
}
}
Expand Down Expand Up @@ -673,3 +695,16 @@ impl Constructor for Contract {
initialize_ownership(owner);
}
}

abi EmitSRC20Events {
fn emit_src20_events(asset: AssetId);
}

impl EmitSRC20Events for Contract {
fn emit_src20_events(asset: AssetId) {
// Metadata that is stored as a configurable should only be emitted once.
let sender = msg_sender().unwrap();

SetDecimalsEvent::new(asset, 0u8, sender).log();
}
}
2 changes: 1 addition & 1 deletion NFT/NFT-contract/tests/utils/interface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ pub(crate) async fn mint(
) -> FuelCallResponse<()> {
contract
.methods()
.mint(recipient, sub_id, amount)
.mint(recipient, Some(sub_id), amount)
.append_variable_outputs(1)
.call()
.await
Expand Down
10 changes: 5 additions & 5 deletions NFT/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,15 @@ In this barebones NFT example project, there are a maximum of 100,000 NFTs that

## Standards Implementations

The project implements and follows the [SRC-20; Native Asset](https://github.com/FuelLabs/sway-standards/blob/master/SRCs/src-20.md), [SRC-3; Mint and Burn](https://github.com/FuelLabs/sway-standards/blob/master/SRCs/src-3.md), and [SRC-7; Metadata](https://github.com/FuelLabs/sway-standards/blob/master/SRCs/src-7.md) standards. It also uses the [Native Asset Library](https://fuellabs.github.io/sway-libs/book/asset/index.html) to implement the basic functionality behind the standards.
The project implements and follows the [SRC-20; Native Asset](https://docs.fuel.network/docs/sway-standards/src-20-native-asset/), [SRC-3; Mint and Burn](https://docs.fuel.network/docs/sway-standards/src-3-minting-and-burning/), and [SRC-7; Metadata](https://docs.fuel.network/docs/sway-standards/src-7-asset-metadata/) standards. It also uses the [Native Asset Library](https://docs.fuel.network/docs/sway-libs/asset/) to implement the basic functionality behind the standards.

### SRC-20

The [SRC-20](https://github.com/FuelLabs/sway-standards/blob/master/SRCs/src-20.md) standard requires that there is a maximum number of one coin per NFT asset. It also states that the decimals must be `0u8` for any NFT. This project conforms to both these restrictions and thus can be deemed an NFT on the Fuel Network.
The [SRC-20](https://docs.fuel.network/docs/sway-standards/src-20-native-asset/) standard requires that there is a maximum number of one coin per NFT asset. It also states that the decimals must be `0u8` for any NFT. This project conforms to both these restrictions and thus can be deemed an NFT on the Fuel Network.

Set functions for name and symbol have been provided to the user. While traditionally name and symbol are written into the contract rather than storage, this contract is open to mint new types of assets. This means that every NFT minted by this contract may contain a different name and symbol.

The [SRC-20](https://github.com/FuelLabs/sway-standards/blob/master/SRCs/src-20.md) ABI defined below has also been implemented.
The [SRC-20](https://docs.fuel.network/docs/sway-standards/src-20-native-asset/) ABI defined below has also been implemented.

```sway
abi SRC20 {
Expand All @@ -49,7 +49,7 @@ abi SRC20 {

### SRC-3

The [SRC-3](https://github.com/FuelLabs/sway-standards/blob/master/SRCs/src-3.md) standard defines the ABI for minting and burning. This has been properly implemented.
The [SRC-3](https://docs.fuel.network/docs/sway-standards/src-3-minting-and-burning/) standard defines the ABI for minting and burning. This has been properly implemented.

```sway
abi SRC3 {
Expand All @@ -62,7 +62,7 @@ abi SRC3 {

### SRC-7

The [SRC-7](https://github.com/FuelLabs/sway-standards/blob/master/SRCs/src-7.md) standard defines the ABI for retrieving metadata. This has been properly implemented.
The [SRC-7](https://docs.fuel.network/docs/sway-standards/src-7-asset-metadata/) standard defines the ABI for retrieving metadata. This has been properly implemented.

A set function that uses storage has been provided to allow the user to set their own desired metadata. There is no limit or restrictions to what and the amount of metadata an asset may have.

Expand Down
12 changes: 6 additions & 6 deletions fractional-NFT/Forc.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
name = "NFT-contract"
source = "member"
dependencies = [
"standards git+https://github.com/FuelLabs/sway-standards?tag=v0.4.4#a001d3c248595112aae67e5633a06ef9bc0536ae",
"standards git+https://github.com/FuelLabs/sway-standards?tag=v0.6.1#792639cdf391565e6e6a02482ea8a46d9604a6f5",
"std",
"sway_libs",
]
Expand All @@ -15,18 +15,18 @@ source = "path+from-root-E19CE48B3E858B72"
name = "f-NFT-contract"
source = "member"
dependencies = [
"standards git+https://github.com/FuelLabs/sway-standards?tag=v0.4.4#a001d3c248595112aae67e5633a06ef9bc0536ae",
"standards git+https://github.com/FuelLabs/sway-standards?tag=v0.6.1#792639cdf391565e6e6a02482ea8a46d9604a6f5",
"std",
]

[[package]]
name = "standards"
source = "git+https://github.com/FuelLabs/sway-standards?tag=v0.4.3#6f63eb7dff2458a7d976184e565b5cbf26f61da2"
source = "git+https://github.com/FuelLabs/sway-standards?tag=v0.6.0#65e09f95ea8b9476b171a66c8a47108f352fa32c"
dependencies = ["std"]

[[package]]
name = "standards"
source = "git+https://github.com/FuelLabs/sway-standards?tag=v0.4.4#a001d3c248595112aae67e5633a06ef9bc0536ae"
source = "git+https://github.com/FuelLabs/sway-standards?tag=v0.6.1#792639cdf391565e6e6a02482ea8a46d9604a6f5"
dependencies = ["std"]

[[package]]
Expand All @@ -36,8 +36,8 @@ dependencies = ["core"]

[[package]]
name = "sway_libs"
source = "git+https://github.com/FuelLabs/sway-libs?tag=v0.21.0#6a227ed34c86fe1ebd334dbdfeccf66c43e3915b"
source = "git+https://github.com/FuelLabs/sway-libs?tag=v0.24.0#e19f96f85ae12426d20adc176b70aa38fd9a2a5b"
dependencies = [
"standards git+https://github.com/FuelLabs/sway-standards?tag=v0.4.3#6f63eb7dff2458a7d976184e565b5cbf26f61da2",
"standards git+https://github.com/FuelLabs/sway-standards?tag=v0.6.0#65e09f95ea8b9476b171a66c8a47108f352fa32c",
"std",
]
4 changes: 2 additions & 2 deletions fractional-NFT/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ In this barebones F-NFT example project, where locking a NFT into the vault will

## Standards Implementations

The project implements and follows the [SRC-6; Vault](https://github.com/FuelLabs/sway-standards/blob/master/SRCs/src-6.md) and [SRC-20; Native Asset](https://github.com/FuelLabs/sway-standards/blob/master/SRCs/src-20.md) standards.
The project implements and follows the [SRC-6; Vault](https://github.com/FuelLabs/sway-standards/blob/master/SRCs/src-6.md) and [SRC-20; Native Asset](https://docs.fuel.network/docs/sway-standards/src-20-native-asset/) standards.

### SRC-6

Expand All @@ -47,7 +47,7 @@ abi SRC6 {

### SRC-20

The [SRC-20](https://github.com/FuelLabs/sway-standards/blob/master/SRCs/src-20.md) standard has been implemented for the resulting minted shares when a NFT is locked in the vault. Information on the share assets can be queried with the [SRC-20](https://github.com/FuelLabs/sway-standards/blob/master/SRCs/src-20.md) standard.
The [SRC-20](https://docs.fuel.network/docs/sway-standards/src-20-native-asset/) standard has been implemented for the resulting minted shares when a NFT is locked in the vault. Information on the share assets can be queried with the [SRC-20](https://docs.fuel.network/docs/sway-standards/src-20-native-asset/) standard.

```sway
abi SRC20 {
Expand Down
2 changes: 1 addition & 1 deletion fractional-NFT/f-NFT-contract/Forc.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ license = "Apache-2.0"
name = "f-NFT-contract"

[dependencies]
standards = { git = "https://github.com/FuelLabs/sway-standards", tag = "v0.4.4" }
standards = { git = "https://github.com/FuelLabs/sway-standards", tag = "v0.6.1" }
44 changes: 40 additions & 4 deletions fractional-NFT/f-NFT-contract/src/main.sw
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,20 @@ contract;
mod errors;

use errors::{DepositError, SubIdError, WithdrawError};
use standards::{src20::SRC20, src6::{Deposit, SRC6, Withdraw}};
use standards::{
src20::{
SetDecimalsEvent,
SetNameEvent,
SetSymbolEvent,
SRC20,
TotalSupplyEvent,
},
src6::{
Deposit,
SRC6,
Withdraw,
},
};
use std::{
asset::{
burn,
Expand Down Expand Up @@ -89,19 +102,21 @@ impl SRC6 for Contract {
#[payable]
#[storage(read, write)]
fn deposit(receiver: Identity, vault_sub_id: SubId) -> u64 {
require(vault_sub_id == ZERO_B256, SubIdError::InvalidSubId);
require(vault_sub_id == SubId::zero(), SubIdError::InvalidSubId);
require(msg_amount() == 1, DepositError::InvalidSRC20NFT);

let nft = msg_asset_id();
let f_nft_asset_sub_id = sha256((nft, vault_sub_id));
let f_nft_asset = AssetId::new(ContractId::this(), f_nft_asset_sub_id);
let sender = msg_sender().unwrap();

storage.total_assets.write(storage.total_assets.read() + 1);
storage.vault_asset.insert(f_nft_asset, true);
mint_to(receiver, f_nft_asset_sub_id, SHARES);
TotalSupplyEvent::new(f_nft_asset, SHARES, sender).log();

log(Deposit {
caller: msg_sender().unwrap(),
caller: sender,
receiver: receiver,
underlying_asset: nft,
vault_sub_id: vault_sub_id,
Expand Down Expand Up @@ -159,17 +174,20 @@ impl SRC6 for Contract {
require(vault_sub_id == ZERO_B256, SubIdError::InvalidSubId);

let sent_amount = msg_amount();
let sender = msg_sender().unwrap();
require(sent_amount == SHARES, WithdrawError::AllSharesNotReturned);

let f_nft_asset_sub_id = sha256((underlying_asset, vault_sub_id));
let f_nft_asset = AssetId::new(ContractId::this(), f_nft_asset_sub_id);
require(msg_asset_id() == f_nft_asset, WithdrawError::InvalidAsset);

burn(f_nft_asset_sub_id, SHARES);
TotalSupplyEvent::new(f_nft_asset, 0, sender).log();

transfer(receiver, underlying_asset, 1);

log(Withdraw {
caller: msg_sender().unwrap(),
caller: sender,
receiver,
underlying_asset,
vault_sub_id,
Expand Down Expand Up @@ -468,3 +486,21 @@ impl SRC20 for Contract {
}
}
}

abi EmitSRC20Events {
fn emit_src20_events(asset: AssetId);
}

impl EmitSRC20Events for Contract {
fn emit_src20_events(asset: AssetId) {
// Metadata that is stored as a configurable should only be emitted once.
let sender = msg_sender().unwrap();
let name = Some(String::from_ascii_str(from_str_array(NAME)));
let symbol = Some(String::from_ascii_str(from_str_array(SYMBOL)));

SetNameEvent::new(asset, name, sender).log();
SetSymbolEvent::new(asset, symbol, sender).log();
SetDecimalsEvent::new(asset, DECIMALS, sender).log();
TotalSupplyEvent::new(asset, SHARES, sender).log();
}
}
4 changes: 2 additions & 2 deletions fractional-NFT/f-NFT-contract/tests/utils/setup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,13 +144,13 @@ pub(crate) async fn setup_nft(

let _ = nft
.methods()
.mint(identity, Bits256(*sub_id_1), 1)
.mint(identity, Some(Bits256(*sub_id_1)), 1)
.append_variable_outputs(1)
.call()
.await;
let _ = nft
.methods()
.mint(identity, Bits256(*sub_id_2), 1)
.mint(identity, Some(Bits256(*sub_id_2)), 1)
.append_variable_outputs(1)
.call()
.await;
Expand Down
Loading
Loading