From 7257ff4de2dc16596c9f78534cd7d2b382e308bc Mon Sep 17 00:00:00 2001 From: bitzoic Date: Wed, 21 Aug 2024 14:18:21 +0800 Subject: [PATCH 01/17] Add event logging to SRC-20 and SRC-7 specification --- docs/src/src-20-native-asset.md | 66 ++++++++++++++++++++++++++++++++ docs/src/src-7-asset-metadata.md | 29 ++++++++++++++ 2 files changed, 95 insertions(+) diff --git a/docs/src/src-20-native-asset.md b/docs/src/src-20-native-asset.md index 2e02fa8..158cbbc 100644 --- a/docs/src/src-20-native-asset.md +++ b/docs/src/src-20-native-asset.md @@ -47,6 +47,70 @@ Non-Fungible Tokens (NFT) or Non-Fungible Assets on Fuel are Native Assets and t * Non-Fungible Assets SHALL have a total supply of one per asset. * Non-Fungible Assets SHALL have a decimal of `0u8`. +### Logging + +The following logs MUST be implemented upon value changes to follow the SRC-20 standard: + +#### SetNameEvent + +The `SetNameEvent` MUST be emitted when the name of an asset has updated. + +There SHALL be the following fields in the `SetNameEvent` struct: + +- `asset`: The `asset` field SHALL be used for the corresponding `AssetId` of the asset has been updated. +- `name`: The `name` field SHALL be used for the corresponding `Option` which represents the name of the asset. +- `sender`: The `sender` field SHALL be used for the corresponding `Identity` which made the function call that has updated the name of the asset. + +Example: + +```sway +pub struct SetNameEvent { + pub asset: AssetId, + pub name: Option, + pub sender: Identity, +} +``` + +#### SetSymbolEvent + +The `SetSymbolEvent` MUST be emitted when the symbol of an asset has updated. + +There SHALL be the following fields in the `SetSymbolEvent` struct: + +- `asset`: The `asset` field SHALL be used for the corresponding `AssetId` of the asset has been updated. +- `symbol`: The `symbol` field SHALL be used for the corresponding `Option` which represents the symbol of the asset. +- `sender`: The `sender` field SHALL be used for the corresponding `Identity` which made the function call that has updated the symbol of the asset. + +Example: + +```sway +pub struct SetSymbolEvent { + pub asset: AssetId, + pub symbol: Option, + pub sender: Identity, +} +``` + +#### SetDecimalsEvent + +The `SetDecimalsEvent` MUST be emitted when the decimals of an asset has updated. + +There SHALL be the following fields in the `SetDecimalsEvent` struct: + +- `asset`: The `asset` field SHALL be used for the corresponding `AssetId` of the asset has been updated. +- `decimals`: The `decimals` field SHALL be used for the corresponding `u8` which represents the decimals of the asset. +- `sender`: The `sender` field SHALL be used for the corresponding `Identity` which made the function call that has updated the decimals of the asset. + +Example: + +```sway +pub struct SetDecimalsEvent { + pub asset: AssetId, + pub decimals: u8, + pub sender: Identity, +} +``` + ## Rationale As the SRC-20 Native Asset 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. @@ -61,6 +125,8 @@ This standard is compatible with Fuel's [Native Assets](https://docs.fuel.networ 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. +It should be noted that if a contract embeds metadata into the contract and does not update the name, symbol, or decimals in a function call, no logs will be emitted. + ## Example ABI ```sway diff --git a/docs/src/src-7-asset-metadata.md b/docs/src/src-7-asset-metadata.md index 0dcb7df..ea7db3a 100644 --- a/docs/src/src-7-asset-metadata.md +++ b/docs/src/src-7-asset-metadata.md @@ -44,6 +44,33 @@ The `String` variant SHALL be used when the stored metadata for the correspondin This function MUST return valid metadata for the corresponding `asset` and `key`, where the data is either a `B256`, `Bytes`, `Int`, or `String` variant. If the asset does not exist or no metadata exists, the function MUST return `None`. + +### Logging + +The following logs MUST be implemented upon value changes to follow the SRC-7 standard: + +#### SetMetadataEvent + +The `SetMetadataEvent` MUST be emitted when the metadata of an asset has updated. + +There SHALL be the following fields in the `SetMetadataEvent` struct: + +- `asset`: The `asset` field SHALL be used for the corresponding `AssetId` of the asset has been updated. +- `metadata`: The `metadata` field SHALL be used for the corresponding `Option` which represents the metadata of the asset. +- `key`: The `key` field SHALL be used for the corresponding `String` which represents the key used for storing the metadata. +- `sender`: The `sender` field SHALL be used for the corresponding `Identity` which made the function call that has updated the metadata of the asset. + +Example: + +```sway +pub struct SetMetadataEvent { + pub asset: AssetId, + pub metadata: Option, + pub key: String, + pub sender: Identity, +} +``` + ## Rationale The SRC-7 standard should allow for data-rich assets to interact with one another in a safe manner. @@ -56,6 +83,8 @@ This standard is compatible with Fuel's [Native Assets](https://docs.fuel.networ 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. +It should be noted that if a contract embeds metadata into the contract and does not update the metadata in a function call, no logs will be emitted. + ## Example ABI ```sway From 0d71669c807f506fb68096f9ddfde6e8923e86ae Mon Sep 17 00:00:00 2001 From: bitzoic Date: Wed, 21 Aug 2024 14:18:39 +0800 Subject: [PATCH 02/17] Add event logging structs to SRC-20 and SRC-7 --- standards/src/src20.sw | 18 ++++++++++++++++++ standards/src/src7.sw | 12 ++++++++++++ 2 files changed, 30 insertions(+) diff --git a/standards/src/src20.sw b/standards/src/src20.sw index 89cff77..c115c3a 100644 --- a/standards/src/src20.sw +++ b/standards/src/src20.sw @@ -123,3 +123,21 @@ abi SRC20 { #[storage(read)] fn decimals(asset: AssetId) -> Option; } + +pub struct SetNameEvent { + pub asset: AssetId, + pub name: Option, + pub sender: Identity, +} + +pub struct SetSymbolEvent { + pub asset: AssetId, + pub symbol: Option, + pub sender: Identity, +} + +pub struct SetDecimalsEvent { + pub asset: AssetId, + pub decimals: u8, + pub sender: Identity, +} diff --git a/standards/src/src7.sw b/standards/src/src7.sw index e307d11..443163f 100644 --- a/standards/src/src7.sw +++ b/standards/src/src7.sw @@ -43,6 +43,18 @@ pub enum Metadata { String: String, } +/// The event emitted when metadata is set via a function call. +pub struct SetMetadataEvent { + /// The asset for which metadata is set. + pub asset: AssetId, + /// The `Identity` of the caller that set the metadata. + pub sender: Identity, + /// The Metadata that is set. + pub metadata: Option, + /// The key used for the metadata. + pub key: String, +} + impl core::ops::Eq for Metadata { fn eq(self, other: Self) -> bool { match (self, other) { From 9675d4f29925e3d098fd167a45391f027b9af85b Mon Sep 17 00:00:00 2001 From: bitzoic Date: Wed, 21 Aug 2024 14:24:56 +0800 Subject: [PATCH 03/17] Update CHANGELOG --- CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a248bf6..55248de 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,8 +9,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Added Unreleased -- Something new here 1 -- Something new here 2 +- [#130](https://github.com/FuelLabs/sway-standards/pull/130) Adds the `SetNameEvent`, `SetSymbolEvent`, and `SetDecimalsEvent` to the SRC-20 standard. +- [#130](https://github.com/FuelLabs/sway-standards/pull/130) Adds the `SetMetadataEvent` to the SRC-7 standard. ### Changed Unreleased From 2f45385d097cc8d43c24e6fd09c28350ef7f1775 Mon Sep 17 00:00:00 2001 From: bitzoic Date: Wed, 21 Aug 2024 14:30:36 +0800 Subject: [PATCH 04/17] Add inline docs to SRC-20 events --- standards/src/src20.sw | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/standards/src/src20.sw b/standards/src/src20.sw index c115c3a..cfa347c 100644 --- a/standards/src/src20.sw +++ b/standards/src/src20.sw @@ -124,20 +124,32 @@ abi SRC20 { fn decimals(asset: AssetId) -> Option; } +/// The event emitted when the name is set via a function call. pub struct SetNameEvent { + /// The asset for which name is set. pub asset: AssetId, + /// The name that is set. pub name: Option, + /// The caller that set the name. pub sender: Identity, } +/// The event emitted when the symbol is set via a function call. pub struct SetSymbolEvent { + /// The asset for which symbol is set. pub asset: AssetId, + /// The symbol that is set. pub symbol: Option, + /// The caller that set the symbol. pub sender: Identity, } +/// The event emitted when the decimals is set via a function call. pub struct SetDecimalsEvent { + /// The asset for which decimals is set. pub asset: AssetId, + /// The decimals that is set. pub decimals: u8, + /// The caller that set the decimals. pub sender: Identity, } From 988b802f7c125510c6b5e1bbeaf2ab4d84a6735f Mon Sep 17 00:00:00 2001 From: bitzoic Date: Wed, 21 Aug 2024 14:32:40 +0800 Subject: [PATCH 05/17] Fix CI --- docs/spell-check-custom-words.txt | 6 +++++- docs/src/src-20-native-asset.md | 18 +++++++++--------- docs/src/src-7-asset-metadata.md | 1 - 3 files changed, 14 insertions(+), 11 deletions(-) diff --git a/docs/spell-check-custom-words.txt b/docs/spell-check-custom-words.txt index e85a196..0e12413 100644 --- a/docs/spell-check-custom-words.txt +++ b/docs/spell-check-custom-words.txt @@ -260,4 +260,8 @@ OGA glTF GLB Uninitalized -upgradeability \ No newline at end of file +upgradeability +SetMetadataEvent +SetNameEvent +SetSymbolEvent +SetDecimalsEvent \ No newline at end of file diff --git a/docs/src/src-20-native-asset.md b/docs/src/src-20-native-asset.md index 158cbbc..c34fa13 100644 --- a/docs/src/src-20-native-asset.md +++ b/docs/src/src-20-native-asset.md @@ -57,9 +57,9 @@ The `SetNameEvent` MUST be emitted when the name of an asset has updated. There SHALL be the following fields in the `SetNameEvent` struct: -- `asset`: The `asset` field SHALL be used for the corresponding `AssetId` of the asset has been updated. -- `name`: The `name` field SHALL be used for the corresponding `Option` which represents the name of the asset. -- `sender`: The `sender` field SHALL be used for the corresponding `Identity` which made the function call that has updated the name of the asset. +* `asset`: The `asset` field SHALL be used for the corresponding `AssetId` of the asset has been updated. +* `name`: The `name` field SHALL be used for the corresponding `Option` which represents the name of the asset. +* `sender`: The `sender` field SHALL be used for the corresponding `Identity` which made the function call that has updated the name of the asset. Example: @@ -77,9 +77,9 @@ The `SetSymbolEvent` MUST be emitted when the symbol of an asset has updated. There SHALL be the following fields in the `SetSymbolEvent` struct: -- `asset`: The `asset` field SHALL be used for the corresponding `AssetId` of the asset has been updated. -- `symbol`: The `symbol` field SHALL be used for the corresponding `Option` which represents the symbol of the asset. -- `sender`: The `sender` field SHALL be used for the corresponding `Identity` which made the function call that has updated the symbol of the asset. +* `asset`: The `asset` field SHALL be used for the corresponding `AssetId` of the asset has been updated. +* `symbol`: The `symbol` field SHALL be used for the corresponding `Option` which represents the symbol of the asset. +* `sender`: The `sender` field SHALL be used for the corresponding `Identity` which made the function call that has updated the symbol of the asset. Example: @@ -97,9 +97,9 @@ The `SetDecimalsEvent` MUST be emitted when the decimals of an asset has updated There SHALL be the following fields in the `SetDecimalsEvent` struct: -- `asset`: The `asset` field SHALL be used for the corresponding `AssetId` of the asset has been updated. -- `decimals`: The `decimals` field SHALL be used for the corresponding `u8` which represents the decimals of the asset. -- `sender`: The `sender` field SHALL be used for the corresponding `Identity` which made the function call that has updated the decimals of the asset. +* `asset`: The `asset` field SHALL be used for the corresponding `AssetId` of the asset has been updated. +* `decimals`: The `decimals` field SHALL be used for the corresponding `u8` which represents the decimals of the asset. +* `sender`: The `sender` field SHALL be used for the corresponding `Identity` which made the function call that has updated the decimals of the asset. Example: diff --git a/docs/src/src-7-asset-metadata.md b/docs/src/src-7-asset-metadata.md index ea7db3a..60b800f 100644 --- a/docs/src/src-7-asset-metadata.md +++ b/docs/src/src-7-asset-metadata.md @@ -44,7 +44,6 @@ The `String` variant SHALL be used when the stored metadata for the correspondin This function MUST return valid metadata for the corresponding `asset` and `key`, where the data is either a `B256`, `Bytes`, `Int`, or `String` variant. If the asset does not exist or no metadata exists, the function MUST return `None`. - ### Logging The following logs MUST be implemented upon value changes to follow the SRC-7 standard: From d082972b3edc99796a3f4e9e79579cd1f5a1c585 Mon Sep 17 00:00:00 2001 From: bitzoic Date: Thu, 22 Aug 2024 13:31:47 +0800 Subject: [PATCH 06/17] Require that logs of metadata are emitted even with contants --- docs/src/src-20-native-asset.md | 27 ++++++++++++++++++++++++--- docs/src/src-7-asset-metadata.md | 7 ++++--- 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/docs/src/src-20-native-asset.md b/docs/src/src-20-native-asset.md index c34fa13..9a89c14 100644 --- a/docs/src/src-20-native-asset.md +++ b/docs/src/src-20-native-asset.md @@ -49,7 +49,10 @@ Non-Fungible Tokens (NFT) or Non-Fungible Assets on Fuel are Native Assets and t ### Logging -The following logs MUST be implemented upon value changes to follow the SRC-20 standard: +The following logs MUST be implemented and emitted to follow the SRC-20 standard. + +* IF a value is updated via a function call, a log MUST be emitted. +* IF a value is embedded in a contract as a constant, configurable, or other manner, an event MUST be emitted at least once. #### SetNameEvent @@ -111,6 +114,26 @@ pub struct SetDecimalsEvent { } ``` +#### UpdateTotalSupplyEvent + +The `UpdateTotalSupplyEvent` MUST be emitted when the total supply of an asset has updated. + +There SHALL be the following fields in the `UpdateTotalSupplyEvent` struct: + +* `asset`: The `asset` field SHALL be used for the corresponding `AssetId` of the asset has been updated. +* `supply`: The `supply` field SHALL be used for the corresponding `u64` which represents the total supply of the asset. +* `sender`: The `sender` field SHALL be used for the corresponding `Identity` which made the function call that has updated the total supply of the asset. + +Example: + +```sway +pub struct UpdateTotalSupplyEvent { + pub asset: AssetId, + pub supply: u64, + pub sender: Identity, +} +``` + ## Rationale As the SRC-20 Native Asset 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. @@ -125,8 +148,6 @@ This standard is compatible with Fuel's [Native Assets](https://docs.fuel.networ 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. -It should be noted that if a contract embeds metadata into the contract and does not update the name, symbol, or decimals in a function call, no logs will be emitted. - ## Example ABI ```sway diff --git a/docs/src/src-7-asset-metadata.md b/docs/src/src-7-asset-metadata.md index 60b800f..150dce5 100644 --- a/docs/src/src-7-asset-metadata.md +++ b/docs/src/src-7-asset-metadata.md @@ -46,7 +46,10 @@ This function MUST return valid metadata for the corresponding `asset` and `key` ### Logging -The following logs MUST be implemented upon value changes to follow the SRC-7 standard: +The following logs MUST be implemented and emitted to follow the SRC-7 standard. + +* IF a value is updated via a function call, a log MUST be emitted. +* IF a value is embedded in a contract as a constant, configurable, or other manner, an event MUST be emitted at least once. #### SetMetadataEvent @@ -82,8 +85,6 @@ This standard is compatible with Fuel's [Native Assets](https://docs.fuel.networ 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. -It should be noted that if a contract embeds metadata into the contract and does not update the metadata in a function call, no logs will be emitted. - ## Example ABI ```sway From 68ad09a8f4eeb542e0967a8ef1562a20214b35cb Mon Sep 17 00:00:00 2001 From: bitzoic Date: Thu, 22 Aug 2024 13:32:02 +0800 Subject: [PATCH 07/17] Update standards with additional log and ordering --- standards/src/src20.sw | 16 +++++++++++++--- standards/src/src7.sw | 4 ++-- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/standards/src/src20.sw b/standards/src/src20.sw index cfa347c..8dbb264 100644 --- a/standards/src/src20.sw +++ b/standards/src/src20.sw @@ -124,7 +124,7 @@ abi SRC20 { fn decimals(asset: AssetId) -> Option; } -/// The event emitted when the name is set via a function call. +/// The event emitted when the name is set. pub struct SetNameEvent { /// The asset for which name is set. pub asset: AssetId, @@ -134,7 +134,7 @@ pub struct SetNameEvent { pub sender: Identity, } -/// The event emitted when the symbol is set via a function call. +/// The event emitted when the symbol is set. pub struct SetSymbolEvent { /// The asset for which symbol is set. pub asset: AssetId, @@ -144,7 +144,7 @@ pub struct SetSymbolEvent { pub sender: Identity, } -/// The event emitted when the decimals is set via a function call. +/// The event emitted when the decimals is set. pub struct SetDecimalsEvent { /// The asset for which decimals is set. pub asset: AssetId, @@ -153,3 +153,13 @@ pub struct SetDecimalsEvent { /// The caller that set the decimals. pub sender: Identity, } + +/// The event emitted when the total supply is updated. +pub struct UpdateTotalSupplyEvent { + /// The asset for which supply is updated. + pub asset: AssetId, + /// The supply that is set. + pub supply: u64, + /// The caller that modified the supply. + pub sender: Identity, +} diff --git a/standards/src/src7.sw b/standards/src/src7.sw index 443163f..9bd030e 100644 --- a/standards/src/src7.sw +++ b/standards/src/src7.sw @@ -47,12 +47,12 @@ pub enum Metadata { pub struct SetMetadataEvent { /// The asset for which metadata is set. pub asset: AssetId, - /// The `Identity` of the caller that set the metadata. - pub sender: Identity, /// The Metadata that is set. pub metadata: Option, /// The key used for the metadata. pub key: String, + /// The `Identity` of the caller that set the metadata. + pub sender: Identity, } impl core::ops::Eq for Metadata { From 0a2e0fdd34cbe68cc37e8d3fe890eab7f70da92d Mon Sep 17 00:00:00 2001 From: bitzoic Date: Thu, 22 Aug 2024 13:32:14 +0800 Subject: [PATCH 08/17] Update examples to follow new specs --- .../multi_asset/src/multi_asset.sw | 43 ++++++++- .../single_asset/src/single_asset.sw | 40 +++++++- .../multi_asset/src/multi_asset.sw | 54 ++++++++++- .../single_asset/src/single_asset.sw | 44 ++++++++- .../multi_asset/src/multi_asset.sw | 91 ++++++++++++++++++- .../single_asset/src/single_asset.sw | 71 ++++++++++++++- 6 files changed, 334 insertions(+), 9 deletions(-) diff --git a/examples/src20-native-asset/multi_asset/src/multi_asset.sw b/examples/src20-native-asset/multi_asset/src/multi_asset.sw index e20a95e..3a8d8ca 100644 --- a/examples/src20-native-asset/multi_asset/src/multi_asset.sw +++ b/examples/src20-native-asset/multi_asset/src/multi_asset.sw @@ -1,6 +1,6 @@ contract; -use standards::src20::SRC20; +use standards::src20::{SRC20, SetNameEvent, SetSymbolEvent, SetDecimalsEvent, UpdateTotalSupplyEvent}; use std::{hash::Hash, storage::storage_string::*, string::String}; storage { @@ -171,3 +171,44 @@ impl SRC20 for Contract { storage.decimals.get(asset).try_read() } } + +abi SetSRC20Data { + #[storage(read)] + fn setSRC20Data(asset: AssetId, total_supply: u64, name: String, symbol: String, decimals: u8); +} + +impl SetSRC20Data for Contract { + #[storage(read)] + fn setSRC20Data(asset: AssetId, supply: u64, name: String, symbol: String, decimals: u8) { + // NOTE: There are no checks for if the caller has permissions to update the metadata + // If this asset does not exist, revert + if storage.total_supply.get(asset).try_read().is_none() { + revert(0); + } + let sender = msg_sender().unwrap(); + + log(SetNameEvent { + asset, + name: Some(name), + sender, + }); + + log(SetSymbolEvent { + asset, + symbol: Some(symbol), + sender, + }); + + log(SetDecimalsEvent { + asset, + decimals, + sender, + }); + + log(UpdateTotalSupplyEvent{ + asset, + supply, + sender + }); + } +} diff --git a/examples/src20-native-asset/single_asset/src/single_asset.sw b/examples/src20-native-asset/single_asset/src/single_asset.sw index a2c51bf..bfb6064 100644 --- a/examples/src20-native-asset/single_asset/src/single_asset.sw +++ b/examples/src20-native-asset/single_asset/src/single_asset.sw @@ -1,7 +1,7 @@ contract; -use standards::src20::SRC20; -use std::string::String; +use standards::src20::{SRC20, SetNameEvent, SetSymbolEvent, SetDecimalsEvent, UpdateTotalSupplyEvent}; +use std::{auth::msg_sender, string::String}; configurable { /// The total supply of coins for the asset minted by this contract. @@ -165,3 +165,39 @@ impl SRC20 for Contract { } } } + +abi EmitSRC20Events { + fn emitSRC20Events(); +} + +impl EmitSRC20Events for Contract { + fn emitSRC20Events() { + // Metadata that is stored as a configurable should only be emitted once. + let asset = AssetId::default(); + let sender = msg_sender().unwrap(); + + log(SetNameEvent { + asset, + name: Some(String::from_ascii_str(from_str_array(NAME))), + sender, + }); + + log(SetSymbolEvent { + asset, + symbol: Some(String::from_ascii_str(from_str_array(SYMBOL))), + sender, + }); + + log(SetDecimalsEvent { + asset, + decimals: DECIMALS, + sender, + }); + + log(UpdateTotalSupplyEvent{ + asset, + supply: TOTAL_SUPPLY, + sender + }); + } +} diff --git a/examples/src3-mint-burn/multi_asset/src/multi_asset.sw b/examples/src3-mint-burn/multi_asset/src/multi_asset.sw index b8af9ba..68e1eb7 100644 --- a/examples/src3-mint-burn/multi_asset/src/multi_asset.sw +++ b/examples/src3-mint-burn/multi_asset/src/multi_asset.sw @@ -1,11 +1,12 @@ contract; -use standards::{src20::SRC20, src3::SRC3}; +use standards::{src20::{SRC20, SetNameEvent, SetSymbolEvent, SetDecimalsEvent, UpdateTotalSupplyEvent}, src3::SRC3}; use std::{ asset::{ burn, mint_to, }, + auth::msg_sender, call_frames::msg_asset_id, context::msg_amount, hash::Hash, @@ -69,9 +70,17 @@ impl SRC3 for Contract { } // Increment total supply of the asset and mint to the recipient. + let new_supply = amount + asset_supply.unwrap_or(0); storage .total_supply - .insert(asset_id, amount + asset_supply.unwrap_or(0)); + .insert(asset_id, new_supply); + + log(UpdateTotalSupplyEvent{ + asset: asset_id, + supply: new_supply, + sender: msg_sender().unwrap() + }); + mint_to(recipient, sub_id, amount); } @@ -158,3 +167,44 @@ impl SRC20 for Contract { } } } + +abi SetSRC20Data { + #[storage(read)] + fn setSRC20Data(asset: AssetId, total_supply: u64); +} + +impl SetSRC20Data for Contract { + #[storage(read)] + fn setSRC20Data(asset: AssetId, supply: u64) { + // NOTE: There are no checks for if the caller has permissions to update the metadata + // If this asset does not exist, revert + if storage.total_supply.get(asset).try_read().is_none() { + revert(0); + } + let sender = msg_sender().unwrap(); + + log(SetNameEvent { + asset, + name: Some(String::from_ascii_str(from_str_array(NAME))), + sender, + }); + + log(SetSymbolEvent { + asset, + symbol: Some(String::from_ascii_str(from_str_array(SYMBOL))), + sender, + }); + + log(SetDecimalsEvent { + asset, + decimals: DECIMALS, + sender, + }); + + log(UpdateTotalSupplyEvent{ + asset, + supply, + sender + }); + } +} diff --git a/examples/src3-mint-burn/single_asset/src/single_asset.sw b/examples/src3-mint-burn/single_asset/src/single_asset.sw index d21b31c..732b26c 100644 --- a/examples/src3-mint-burn/single_asset/src/single_asset.sw +++ b/examples/src3-mint-burn/single_asset/src/single_asset.sw @@ -1,11 +1,12 @@ contract; -use standards::{src20::SRC20, src3::SRC3}; +use standards::{src20::{SRC20, SetNameEvent, SetSymbolEvent, SetDecimalsEvent, UpdateTotalSupplyEvent}, src3::SRC3}; use std::{ asset::{ burn, mint_to, }, + auth::msg_sender, call_frames::msg_asset_id, constants::DEFAULT_SUB_ID, context::msg_amount, @@ -60,9 +61,18 @@ impl SRC3 for Contract { require(sub_id == DEFAULT_SUB_ID, "Incorrect Sub Id"); // Increment total supply of the asset and mint to the recipient. + let new_supply = amount + storage.total_supply.read(); storage .total_supply - .write(amount + storage.total_supply.read()); + .write(new_supply); + + + log(UpdateTotalSupplyEvent{ + asset: AssetId::new(ContractId::this(), DEFAULT_SUB_ID), + supply: new_supply, + sender: msg_sender().unwrap() + }); + mint_to(recipient, DEFAULT_SUB_ID, amount); } @@ -160,3 +170,33 @@ impl SRC20 for Contract { } } } + +abi EmitSRC20Events { + fn emitSRC20Events(); +} + +impl EmitSRC20Events for Contract { + fn emitSRC20Events() { + // Metadata that is stored as a configurable should only be emitted once. + let asset = AssetId::default(); + let sender = msg_sender().unwrap(); + + log(SetNameEvent { + asset, + name: Some(String::from_ascii_str(from_str_array(NAME))), + sender, + }); + + log(SetSymbolEvent { + asset, + symbol: Some(String::from_ascii_str(from_str_array(SYMBOL))), + sender, + }); + + log(SetDecimalsEvent { + asset, + decimals: DECIMALS, + sender, + }); + } +} diff --git a/examples/src7-metadata/multi_asset/src/multi_asset.sw b/examples/src7-metadata/multi_asset/src/multi_asset.sw index e658bbc..7785094 100644 --- a/examples/src7-metadata/multi_asset/src/multi_asset.sw +++ b/examples/src7-metadata/multi_asset/src/multi_asset.sw @@ -1,6 +1,6 @@ contract; -use standards::{src20::SRC20, src7::{Metadata, SRC7}}; +use standards::{src20::{SRC20, SetNameEvent, SetSymbolEvent, SetDecimalsEvent, UpdateTotalSupplyEvent}, src7::{Metadata, SRC7, SetMetadataEvent}}; use std::{hash::Hash, storage::storage_string::*, string::String}; @@ -56,11 +56,19 @@ impl SRC7 for Contract { /// ``` #[storage(read)] fn metadata(asset: AssetId, key: String) -> Option { + // If this asset does not exist, return None + if storage.total_supply.get(asset).try_read().is_none() { + return None + } + if key == String::from_ascii_str("social:x") { + // The "social:x" for all assets minted by this contract are the same. Some(Metadata::String(String::from_ascii_str(from_str_array(SOCIAL_X)))) } else if key == String::from_ascii_str("site:forum") { + // The "site:forums" for all assets minted by this contract are the same. Some(Metadata::String(String::from_ascii_str(from_str_array(SITE_FORUM)))) } else if key == String::from_ascii_str("image:svg") { + // The SVG image is stored as a String in storage for each asset let svg_image = storage.svg_images.get(asset).read_slice(); match svg_image { @@ -68,6 +76,7 @@ impl SRC7 for Contract { None => None, } } else if key == String::from_ascii_str("attr:health") { + // The health attribute is stored as a u64 in storage for each asset let health_attribute = storage.health_attributes.get(asset).try_read(); match health_attribute { @@ -80,6 +89,51 @@ impl SRC7 for Contract { } } +abi SetSRC7Events { + #[storage(read, write)] + fn setSRC7Events(asset: AssetId, svg_image: String, health_attribute: u64); +} + +impl SetSRC7Events for Contract { + #[storage(read, write)] + fn setSRC7Events(asset: AssetId, svg_image: String, health_attribute: u64) { + // NOTE: There are no checks for if the caller has permissions to update the metadata + // If this asset does not exist, revert + if storage.total_supply.get(asset).try_read().is_none() { + revert(0); + } + let sender = msg_sender().unwrap(); + + log(SetMetadataEvent { + asset, + metadata: Some(Metadata::String(String::from_ascii_str(from_str_array(SOCIAL_X)))), + key: String::from_ascii_str("social:x"), + sender, + }); + + log(SetMetadataEvent { + asset, + metadata: Some(Metadata::String(String::from_ascii_str(from_str_array(SITE_FORUM)))), + key: String::from_ascii_str("site:forum"), + sender, + }); + + log(SetMetadataEvent { + asset, + metadata: Some(Metadata::String(svg_image)), + key: String::from_ascii_str("image:svg"), + sender, + }); + + log(SetMetadataEvent { + asset, + metadata: Some(Metadata::Int(health_attribute)), + key: String::from_ascii_str("attr:health"), + sender, + }); + } +} + // SRC7 extends SRC20, so this must be included impl SRC20 for Contract { #[storage(read)] @@ -116,3 +170,38 @@ impl SRC20 for Contract { } } } + +abi SetSRC20Data { + fn setSRC20Data(asset: AssetId, total_supply: u64); +} + +impl SetSRC20Data for Contract { + fn setSRC20Data(asset: AssetId, supply: u64) { + // NOTE: There are no checks for if the caller has permissions to update the metadata + let sender = msg_sender().unwrap(); + + log(SetNameEvent { + asset, + name: Some(String::from_ascii_str(from_str_array(NAME))), + sender, + }); + + log(SetSymbolEvent { + asset, + symbol: Some(String::from_ascii_str(from_str_array(SYMBOL))), + sender, + }); + + log(SetDecimalsEvent { + asset, + decimals: DECIMALS, + sender, + }); + + log(UpdateTotalSupplyEvent{ + asset, + supply, + sender + }); + } +} diff --git a/examples/src7-metadata/single_asset/src/single_asset.sw b/examples/src7-metadata/single_asset/src/single_asset.sw index cc017ff..5780a2a 100644 --- a/examples/src7-metadata/single_asset/src/single_asset.sw +++ b/examples/src7-metadata/single_asset/src/single_asset.sw @@ -1,6 +1,6 @@ contract; -use standards::{src20::SRC20, src7::{Metadata, SRC7}}; +use standards::{src20::{SRC20, SetNameEvent, SetSymbolEvent, SetDecimalsEvent, UpdateTotalSupplyEvent}, src7::{Metadata, SRC7, SetMetadataEvent}}; use std::string::String; @@ -66,6 +66,39 @@ impl SRC7 for Contract { } } +abi EmitSRC7Events { + fn emitSRC7Events(); +} + +impl EmitSRC7Events for Contract { + fn emitSRC7Events() { + let asset = AssetId::default(); + let sender = msg_sender().unwrap(); + + log(SetMetadataEvent { + asset, + metadata: Some(Metadata::String(String::from_ascii_str(from_str_array(SOCIAL_X)))), + key: String::from_ascii_str("social:x"), + sender, + }); + + log(SetMetadataEvent { + asset, + metadata: Some(Metadata::String(String::from_ascii_str(from_str_array(SITE_FORUM)))), + key: String::from_ascii_str("site:forum"), + sender, + }); + + log(SetMetadataEvent { + asset, + metadata: Some(Metadata::Int(ATTR_HEALTH)), + key:String::from_ascii_str("attr:health"), + sender, + }); + } +} + +// SRC7 extends SRC20, so this must be included impl SRC20 for Contract { #[storage(read)] fn total_assets() -> u64 { @@ -108,3 +141,39 @@ impl SRC20 for Contract { } } } + +abi EmitSRC20Events { + fn emitSRC20Events(); +} + +impl EmitSRC20Events for Contract { + fn emitSRC20Events() { + // Metadata that is stored as a configurable should only be emitted once. + let asset = AssetId::default(); + let sender = msg_sender().unwrap(); + + log(SetNameEvent { + asset, + name: Some(String::from_ascii_str(from_str_array(NAME))), + sender, + }); + + log(SetSymbolEvent { + asset, + symbol: Some(String::from_ascii_str(from_str_array(SYMBOL))), + sender, + }); + + log(SetDecimalsEvent { + asset, + decimals: DECIMALS, + sender, + }); + + log(UpdateTotalSupplyEvent{ + asset, + supply: TOTAL_SUPPLY, + sender + }); + } +} From dac562ed91aa8e58a52730a5400a8cec6ef1e545 Mon Sep 17 00:00:00 2001 From: bitzoic Date: Thu, 22 Aug 2024 13:36:08 +0800 Subject: [PATCH 09/17] Add custom word to spell checker --- docs/spell-check-custom-words.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/spell-check-custom-words.txt b/docs/spell-check-custom-words.txt index 0e12413..e2cb87c 100644 --- a/docs/spell-check-custom-words.txt +++ b/docs/spell-check-custom-words.txt @@ -264,4 +264,5 @@ upgradeability SetMetadataEvent SetNameEvent SetSymbolEvent -SetDecimalsEvent \ No newline at end of file +SetDecimalsEvent +UpdateTotalSupplyEvent \ No newline at end of file From 371400ed65d731831d375c4693c5c21acd006cc2 Mon Sep 17 00:00:00 2001 From: bitzoic Date: Thu, 22 Aug 2024 13:36:14 +0800 Subject: [PATCH 10/17] Run formatter --- .../multi_asset/src/multi_asset.sw | 28 +++++++++++++++---- .../single_asset/src/single_asset.sw | 12 ++++++-- .../multi_asset/src/multi_asset.sw | 23 +++++++++------ .../single_asset/src/single_asset.sw | 20 ++++++++----- .../multi_asset/src/multi_asset.sw | 19 +++++++++++-- .../single_asset/src/single_asset.sw | 21 +++++++++++--- 6 files changed, 93 insertions(+), 30 deletions(-) diff --git a/examples/src20-native-asset/multi_asset/src/multi_asset.sw b/examples/src20-native-asset/multi_asset/src/multi_asset.sw index 3a8d8ca..a9de03c 100644 --- a/examples/src20-native-asset/multi_asset/src/multi_asset.sw +++ b/examples/src20-native-asset/multi_asset/src/multi_asset.sw @@ -1,6 +1,12 @@ contract; -use standards::src20::{SRC20, SetNameEvent, SetSymbolEvent, SetDecimalsEvent, UpdateTotalSupplyEvent}; +use standards::src20::{ + SetDecimalsEvent, + SetNameEvent, + SetSymbolEvent, + SRC20, + UpdateTotalSupplyEvent, +}; use std::{hash::Hash, storage::storage_string::*, string::String}; storage { @@ -174,12 +180,24 @@ impl SRC20 for Contract { abi SetSRC20Data { #[storage(read)] - fn setSRC20Data(asset: AssetId, total_supply: u64, name: String, symbol: String, decimals: u8); + fn setSRC20Data( + asset: AssetId, + total_supply: u64, + name: String, + symbol: String, + decimals: u8, + ); } impl SetSRC20Data for Contract { #[storage(read)] - fn setSRC20Data(asset: AssetId, supply: u64, name: String, symbol: String, decimals: u8) { + fn setSRC20Data( + asset: AssetId, + supply: u64, + name: String, + symbol: String, + decimals: u8, + ) { // NOTE: There are no checks for if the caller has permissions to update the metadata // If this asset does not exist, revert if storage.total_supply.get(asset).try_read().is_none() { @@ -205,10 +223,10 @@ impl SetSRC20Data for Contract { sender, }); - log(UpdateTotalSupplyEvent{ + log(UpdateTotalSupplyEvent { asset, supply, - sender + sender, }); } } diff --git a/examples/src20-native-asset/single_asset/src/single_asset.sw b/examples/src20-native-asset/single_asset/src/single_asset.sw index bfb6064..7da1adc 100644 --- a/examples/src20-native-asset/single_asset/src/single_asset.sw +++ b/examples/src20-native-asset/single_asset/src/single_asset.sw @@ -1,6 +1,12 @@ contract; -use standards::src20::{SRC20, SetNameEvent, SetSymbolEvent, SetDecimalsEvent, UpdateTotalSupplyEvent}; +use standards::src20::{ + SetDecimalsEvent, + SetNameEvent, + SetSymbolEvent, + SRC20, + UpdateTotalSupplyEvent, +}; use std::{auth::msg_sender, string::String}; configurable { @@ -194,10 +200,10 @@ impl EmitSRC20Events for Contract { sender, }); - log(UpdateTotalSupplyEvent{ + log(UpdateTotalSupplyEvent { asset, supply: TOTAL_SUPPLY, - sender + sender, }); } } diff --git a/examples/src3-mint-burn/multi_asset/src/multi_asset.sw b/examples/src3-mint-burn/multi_asset/src/multi_asset.sw index 68e1eb7..ef9f5ff 100644 --- a/examples/src3-mint-burn/multi_asset/src/multi_asset.sw +++ b/examples/src3-mint-burn/multi_asset/src/multi_asset.sw @@ -1,6 +1,15 @@ contract; -use standards::{src20::{SRC20, SetNameEvent, SetSymbolEvent, SetDecimalsEvent, UpdateTotalSupplyEvent}, src3::SRC3}; +use standards::{ + src20::{ + SetDecimalsEvent, + SetNameEvent, + SetSymbolEvent, + SRC20, + UpdateTotalSupplyEvent, + }, + src3::SRC3, +}; use std::{ asset::{ burn, @@ -71,14 +80,12 @@ impl SRC3 for Contract { // Increment total supply of the asset and mint to the recipient. let new_supply = amount + asset_supply.unwrap_or(0); - storage - .total_supply - .insert(asset_id, new_supply); + storage.total_supply.insert(asset_id, new_supply); - log(UpdateTotalSupplyEvent{ + log(UpdateTotalSupplyEvent { asset: asset_id, supply: new_supply, - sender: msg_sender().unwrap() + sender: msg_sender().unwrap(), }); mint_to(recipient, sub_id, amount); @@ -201,10 +208,10 @@ impl SetSRC20Data for Contract { sender, }); - log(UpdateTotalSupplyEvent{ + log(UpdateTotalSupplyEvent { asset, supply, - sender + sender, }); } } diff --git a/examples/src3-mint-burn/single_asset/src/single_asset.sw b/examples/src3-mint-burn/single_asset/src/single_asset.sw index 732b26c..9fd48f0 100644 --- a/examples/src3-mint-burn/single_asset/src/single_asset.sw +++ b/examples/src3-mint-burn/single_asset/src/single_asset.sw @@ -1,6 +1,15 @@ contract; -use standards::{src20::{SRC20, SetNameEvent, SetSymbolEvent, SetDecimalsEvent, UpdateTotalSupplyEvent}, src3::SRC3}; +use standards::{ + src20::{ + SetDecimalsEvent, + SetNameEvent, + SetSymbolEvent, + SRC20, + UpdateTotalSupplyEvent, + }, + src3::SRC3, +}; use std::{ asset::{ burn, @@ -62,15 +71,12 @@ impl SRC3 for Contract { // Increment total supply of the asset and mint to the recipient. let new_supply = amount + storage.total_supply.read(); - storage - .total_supply - .write(new_supply); + storage.total_supply.write(new_supply); - - log(UpdateTotalSupplyEvent{ + log(UpdateTotalSupplyEvent { asset: AssetId::new(ContractId::this(), DEFAULT_SUB_ID), supply: new_supply, - sender: msg_sender().unwrap() + sender: msg_sender().unwrap(), }); mint_to(recipient, DEFAULT_SUB_ID, amount); diff --git a/examples/src7-metadata/multi_asset/src/multi_asset.sw b/examples/src7-metadata/multi_asset/src/multi_asset.sw index 7785094..8f5b007 100644 --- a/examples/src7-metadata/multi_asset/src/multi_asset.sw +++ b/examples/src7-metadata/multi_asset/src/multi_asset.sw @@ -1,6 +1,19 @@ contract; -use standards::{src20::{SRC20, SetNameEvent, SetSymbolEvent, SetDecimalsEvent, UpdateTotalSupplyEvent}, src7::{Metadata, SRC7, SetMetadataEvent}}; +use standards::{ + src20::{ + SetDecimalsEvent, + SetNameEvent, + SetSymbolEvent, + SRC20, + UpdateTotalSupplyEvent, + }, + src7::{ + Metadata, + SetMetadataEvent, + SRC7, + }, +}; use std::{hash::Hash, storage::storage_string::*, string::String}; @@ -198,10 +211,10 @@ impl SetSRC20Data for Contract { sender, }); - log(UpdateTotalSupplyEvent{ + log(UpdateTotalSupplyEvent { asset, supply, - sender + sender, }); } } diff --git a/examples/src7-metadata/single_asset/src/single_asset.sw b/examples/src7-metadata/single_asset/src/single_asset.sw index 5780a2a..4778ee1 100644 --- a/examples/src7-metadata/single_asset/src/single_asset.sw +++ b/examples/src7-metadata/single_asset/src/single_asset.sw @@ -1,6 +1,19 @@ contract; -use standards::{src20::{SRC20, SetNameEvent, SetSymbolEvent, SetDecimalsEvent, UpdateTotalSupplyEvent}, src7::{Metadata, SRC7, SetMetadataEvent}}; +use standards::{ + src20::{ + SetDecimalsEvent, + SetNameEvent, + SetSymbolEvent, + SRC20, + UpdateTotalSupplyEvent, + }, + src7::{ + Metadata, + SetMetadataEvent, + SRC7, + }, +}; use std::string::String; @@ -92,7 +105,7 @@ impl EmitSRC7Events for Contract { log(SetMetadataEvent { asset, metadata: Some(Metadata::Int(ATTR_HEALTH)), - key:String::from_ascii_str("attr:health"), + key: String::from_ascii_str("attr:health"), sender, }); } @@ -170,10 +183,10 @@ impl EmitSRC20Events for Contract { sender, }); - log(UpdateTotalSupplyEvent{ + log(UpdateTotalSupplyEvent { asset, supply: TOTAL_SUPPLY, - sender + sender, }); } } From fd1021ce3202e8f98020f70bb4b61efdef391dfd Mon Sep 17 00:00:00 2001 From: bitzoic Date: Thu, 22 Aug 2024 13:37:12 +0800 Subject: [PATCH 11/17] Fix markdown formatting --- docs/src/src-7-asset-metadata.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/src/src-7-asset-metadata.md b/docs/src/src-7-asset-metadata.md index 150dce5..001749d 100644 --- a/docs/src/src-7-asset-metadata.md +++ b/docs/src/src-7-asset-metadata.md @@ -57,10 +57,10 @@ The `SetMetadataEvent` MUST be emitted when the metadata of an asset has updated There SHALL be the following fields in the `SetMetadataEvent` struct: -- `asset`: The `asset` field SHALL be used for the corresponding `AssetId` of the asset has been updated. -- `metadata`: The `metadata` field SHALL be used for the corresponding `Option` which represents the metadata of the asset. -- `key`: The `key` field SHALL be used for the corresponding `String` which represents the key used for storing the metadata. -- `sender`: The `sender` field SHALL be used for the corresponding `Identity` which made the function call that has updated the metadata of the asset. +* `asset`: The `asset` field SHALL be used for the corresponding `AssetId` of the asset has been updated. +* `metadata`: The `metadata` field SHALL be used for the corresponding `Option` which represents the metadata of the asset. +* `key`: The `key` field SHALL be used for the corresponding `String` which represents the key used for storing the metadata. +* `sender`: The `sender` field SHALL be used for the corresponding `Identity` which made the function call that has updated the metadata of the asset. Example: From d7019d1f890af5c4c6c3a23c18d4409334f6d9ab Mon Sep 17 00:00:00 2001 From: bitzoic Date: Fri, 23 Aug 2024 17:16:13 +0800 Subject: [PATCH 12/17] Resolve warnings in examples --- .../src20-native-asset/multi_asset/src/multi_asset.sw | 4 ++-- .../src20-native-asset/single_asset/src/single_asset.sw | 4 ++-- examples/src3-mint-burn/multi_asset/src/multi_asset.sw | 4 ++-- examples/src3-mint-burn/single_asset/src/single_asset.sw | 4 ++-- examples/src7-metadata/multi_asset/src/multi_asset.sw | 8 ++++---- examples/src7-metadata/single_asset/src/single_asset.sw | 8 ++++---- 6 files changed, 16 insertions(+), 16 deletions(-) diff --git a/examples/src20-native-asset/multi_asset/src/multi_asset.sw b/examples/src20-native-asset/multi_asset/src/multi_asset.sw index a9de03c..4e9dc1c 100644 --- a/examples/src20-native-asset/multi_asset/src/multi_asset.sw +++ b/examples/src20-native-asset/multi_asset/src/multi_asset.sw @@ -180,7 +180,7 @@ impl SRC20 for Contract { abi SetSRC20Data { #[storage(read)] - fn setSRC20Data( + fn set_src20_data( asset: AssetId, total_supply: u64, name: String, @@ -191,7 +191,7 @@ abi SetSRC20Data { impl SetSRC20Data for Contract { #[storage(read)] - fn setSRC20Data( + fn set_src20_data( asset: AssetId, supply: u64, name: String, diff --git a/examples/src20-native-asset/single_asset/src/single_asset.sw b/examples/src20-native-asset/single_asset/src/single_asset.sw index 7da1adc..9536867 100644 --- a/examples/src20-native-asset/single_asset/src/single_asset.sw +++ b/examples/src20-native-asset/single_asset/src/single_asset.sw @@ -173,11 +173,11 @@ impl SRC20 for Contract { } abi EmitSRC20Events { - fn emitSRC20Events(); + fn emit_src20_events(); } impl EmitSRC20Events for Contract { - fn emitSRC20Events() { + fn emit_src20_events() { // Metadata that is stored as a configurable should only be emitted once. let asset = AssetId::default(); let sender = msg_sender().unwrap(); diff --git a/examples/src3-mint-burn/multi_asset/src/multi_asset.sw b/examples/src3-mint-burn/multi_asset/src/multi_asset.sw index ef9f5ff..d8c8235 100644 --- a/examples/src3-mint-burn/multi_asset/src/multi_asset.sw +++ b/examples/src3-mint-burn/multi_asset/src/multi_asset.sw @@ -177,12 +177,12 @@ impl SRC20 for Contract { abi SetSRC20Data { #[storage(read)] - fn setSRC20Data(asset: AssetId, total_supply: u64); + fn set_src20_data(asset: AssetId, total_supply: u64); } impl SetSRC20Data for Contract { #[storage(read)] - fn setSRC20Data(asset: AssetId, supply: u64) { + fn set_src20_data(asset: AssetId, supply: u64) { // NOTE: There are no checks for if the caller has permissions to update the metadata // If this asset does not exist, revert if storage.total_supply.get(asset).try_read().is_none() { diff --git a/examples/src3-mint-burn/single_asset/src/single_asset.sw b/examples/src3-mint-burn/single_asset/src/single_asset.sw index 9fd48f0..6cd03f2 100644 --- a/examples/src3-mint-burn/single_asset/src/single_asset.sw +++ b/examples/src3-mint-burn/single_asset/src/single_asset.sw @@ -178,11 +178,11 @@ impl SRC20 for Contract { } abi EmitSRC20Events { - fn emitSRC20Events(); + fn emit_src20_events(); } impl EmitSRC20Events for Contract { - fn emitSRC20Events() { + fn emit_src20_events() { // Metadata that is stored as a configurable should only be emitted once. let asset = AssetId::default(); let sender = msg_sender().unwrap(); diff --git a/examples/src7-metadata/multi_asset/src/multi_asset.sw b/examples/src7-metadata/multi_asset/src/multi_asset.sw index 8f5b007..97641c3 100644 --- a/examples/src7-metadata/multi_asset/src/multi_asset.sw +++ b/examples/src7-metadata/multi_asset/src/multi_asset.sw @@ -104,12 +104,12 @@ impl SRC7 for Contract { abi SetSRC7Events { #[storage(read, write)] - fn setSRC7Events(asset: AssetId, svg_image: String, health_attribute: u64); + fn set_src7_events(asset: AssetId, svg_image: String, health_attribute: u64); } impl SetSRC7Events for Contract { #[storage(read, write)] - fn setSRC7Events(asset: AssetId, svg_image: String, health_attribute: u64) { + fn set_src7_events(asset: AssetId, svg_image: String, health_attribute: u64) { // NOTE: There are no checks for if the caller has permissions to update the metadata // If this asset does not exist, revert if storage.total_supply.get(asset).try_read().is_none() { @@ -185,11 +185,11 @@ impl SRC20 for Contract { } abi SetSRC20Data { - fn setSRC20Data(asset: AssetId, total_supply: u64); + fn set_src20_data(asset: AssetId, total_supply: u64); } impl SetSRC20Data for Contract { - fn setSRC20Data(asset: AssetId, supply: u64) { + fn set_src20_data(asset: AssetId, supply: u64) { // NOTE: There are no checks for if the caller has permissions to update the metadata let sender = msg_sender().unwrap(); diff --git a/examples/src7-metadata/single_asset/src/single_asset.sw b/examples/src7-metadata/single_asset/src/single_asset.sw index 4778ee1..672b665 100644 --- a/examples/src7-metadata/single_asset/src/single_asset.sw +++ b/examples/src7-metadata/single_asset/src/single_asset.sw @@ -80,11 +80,11 @@ impl SRC7 for Contract { } abi EmitSRC7Events { - fn emitSRC7Events(); + fn emit_src7_events(); } impl EmitSRC7Events for Contract { - fn emitSRC7Events() { + fn emit_src7_events() { let asset = AssetId::default(); let sender = msg_sender().unwrap(); @@ -156,11 +156,11 @@ impl SRC20 for Contract { } abi EmitSRC20Events { - fn emitSRC20Events(); + fn emit_src20_events(); } impl EmitSRC20Events for Contract { - fn emitSRC20Events() { + fn emit_src20_events() { // Metadata that is stored as a configurable should only be emitted once. let asset = AssetId::default(); let sender = msg_sender().unwrap(); From d5c23952e08ec362bfb877e3fd23aabf3d705ebf Mon Sep 17 00:00:00 2001 From: bitzoic Date: Fri, 23 Aug 2024 17:17:25 +0800 Subject: [PATCH 13/17] Build CI with release --- .github/workflows/ci.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index a133f9e..f5387cc 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -61,10 +61,10 @@ jobs: run: forc fmt --path standards --check - name: Build All Standards - run: forc build --error-on-warnings --path standards + run: forc build --error-on-warnings --path standards --release - name: Check Sway Formatting Examples run: forc fmt --path examples --check - name: Build All Examples - run: forc build --path examples + run: forc build --path examples --release From 297d0b3091bbb6c45697ee2ecb88d652849d3ac1 Mon Sep 17 00:00:00 2001 From: bitzoic Date: Fri, 23 Aug 2024 17:44:39 +0800 Subject: [PATCH 14/17] Store srv7 metadata to storage --- examples/src7-metadata/multi_asset/src/multi_asset.sw | 3 +++ 1 file changed, 3 insertions(+) diff --git a/examples/src7-metadata/multi_asset/src/multi_asset.sw b/examples/src7-metadata/multi_asset/src/multi_asset.sw index 97641c3..a10c9a4 100644 --- a/examples/src7-metadata/multi_asset/src/multi_asset.sw +++ b/examples/src7-metadata/multi_asset/src/multi_asset.sw @@ -131,6 +131,8 @@ impl SetSRC7Events for Contract { sender, }); + storage.svg_images.try_insert(asset, StorageString {}); + storage.svg_images.get(asset).write_slice(svg_image); log(SetMetadataEvent { asset, metadata: Some(Metadata::String(svg_image)), @@ -138,6 +140,7 @@ impl SetSRC7Events for Contract { sender, }); + storage.health_attributes.insert(asset, health_attribute); log(SetMetadataEvent { asset, metadata: Some(Metadata::Int(health_attribute)), From 5a38aff4c03e94ee38699c1db0c7b8378f85a033 Mon Sep 17 00:00:00 2001 From: bitzoic Date: Fri, 23 Aug 2024 18:16:05 +0800 Subject: [PATCH 15/17] Remove cancel in progress from CI --- .github/workflows/ci.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index f5387cc..efcd55b 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -10,7 +10,6 @@ on: concurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} - cancel-in-progress: true env: CARGO_TERM_COLOR: always From a7098b9d6437d8c2f683c61da6b10575379c71ec Mon Sep 17 00:00:00 2001 From: bitzoic Date: Mon, 26 Aug 2024 12:54:22 +0800 Subject: [PATCH 16/17] Update name for TotalSupplyEvent --- .../multi_asset/src/multi_asset.sw | 10 ++-------- .../single_asset/src/single_asset.sw | 10 ++-------- .../src3-mint-burn/multi_asset/src/multi_asset.sw | 14 ++++---------- .../single_asset/src/single_asset.sw | 4 ++-- .../src7-metadata/multi_asset/src/multi_asset.sw | 4 ++-- .../src7-metadata/single_asset/src/single_asset.sw | 4 ++-- standards/src/src20.sw | 8 ++++---- 7 files changed, 18 insertions(+), 36 deletions(-) diff --git a/examples/src20-native-asset/multi_asset/src/multi_asset.sw b/examples/src20-native-asset/multi_asset/src/multi_asset.sw index 4e9dc1c..62b3ad4 100644 --- a/examples/src20-native-asset/multi_asset/src/multi_asset.sw +++ b/examples/src20-native-asset/multi_asset/src/multi_asset.sw @@ -1,12 +1,6 @@ contract; -use standards::src20::{ - SetDecimalsEvent, - SetNameEvent, - SetSymbolEvent, - SRC20, - UpdateTotalSupplyEvent, -}; +use standards::src20::{SetDecimalsEvent, SetNameEvent, SetSymbolEvent, SRC20, TotalSupplyEvent,}; use std::{hash::Hash, storage::storage_string::*, string::String}; storage { @@ -223,7 +217,7 @@ impl SetSRC20Data for Contract { sender, }); - log(UpdateTotalSupplyEvent { + log(TotalSupplyEvent { asset, supply, sender, diff --git a/examples/src20-native-asset/single_asset/src/single_asset.sw b/examples/src20-native-asset/single_asset/src/single_asset.sw index 9536867..81b0cdf 100644 --- a/examples/src20-native-asset/single_asset/src/single_asset.sw +++ b/examples/src20-native-asset/single_asset/src/single_asset.sw @@ -1,12 +1,6 @@ contract; -use standards::src20::{ - SetDecimalsEvent, - SetNameEvent, - SetSymbolEvent, - SRC20, - UpdateTotalSupplyEvent, -}; +use standards::src20::{SetDecimalsEvent, SetNameEvent, SetSymbolEvent, SRC20, TotalSupplyEvent,}; use std::{auth::msg_sender, string::String}; configurable { @@ -200,7 +194,7 @@ impl EmitSRC20Events for Contract { sender, }); - log(UpdateTotalSupplyEvent { + log(TotalSupplyEvent { asset, supply: TOTAL_SUPPLY, sender, diff --git a/examples/src3-mint-burn/multi_asset/src/multi_asset.sw b/examples/src3-mint-burn/multi_asset/src/multi_asset.sw index d8c8235..ebcadcd 100644 --- a/examples/src3-mint-burn/multi_asset/src/multi_asset.sw +++ b/examples/src3-mint-burn/multi_asset/src/multi_asset.sw @@ -6,7 +6,7 @@ use standards::{ SetNameEvent, SetSymbolEvent, SRC20, - UpdateTotalSupplyEvent, + TotalSupplyEvent, }, src3::SRC3, }; @@ -82,7 +82,7 @@ impl SRC3 for Contract { let new_supply = amount + asset_supply.unwrap_or(0); storage.total_supply.insert(asset_id, new_supply); - log(UpdateTotalSupplyEvent { + log(TotalSupplyEvent { asset: asset_id, supply: new_supply, sender: msg_sender().unwrap(), @@ -177,12 +177,12 @@ impl SRC20 for Contract { abi SetSRC20Data { #[storage(read)] - fn set_src20_data(asset: AssetId, total_supply: u64); + fn set_src20_data(asset: AssetId); } impl SetSRC20Data for Contract { #[storage(read)] - fn set_src20_data(asset: AssetId, supply: u64) { + fn set_src20_data(asset: AssetId) { // NOTE: There are no checks for if the caller has permissions to update the metadata // If this asset does not exist, revert if storage.total_supply.get(asset).try_read().is_none() { @@ -207,11 +207,5 @@ impl SetSRC20Data for Contract { decimals: DECIMALS, sender, }); - - log(UpdateTotalSupplyEvent { - asset, - supply, - sender, - }); } } diff --git a/examples/src3-mint-burn/single_asset/src/single_asset.sw b/examples/src3-mint-burn/single_asset/src/single_asset.sw index 6cd03f2..8b2d0b9 100644 --- a/examples/src3-mint-burn/single_asset/src/single_asset.sw +++ b/examples/src3-mint-burn/single_asset/src/single_asset.sw @@ -6,7 +6,7 @@ use standards::{ SetNameEvent, SetSymbolEvent, SRC20, - UpdateTotalSupplyEvent, + TotalSupplyEvent, }, src3::SRC3, }; @@ -73,7 +73,7 @@ impl SRC3 for Contract { let new_supply = amount + storage.total_supply.read(); storage.total_supply.write(new_supply); - log(UpdateTotalSupplyEvent { + log(TotalSupplyEvent { asset: AssetId::new(ContractId::this(), DEFAULT_SUB_ID), supply: new_supply, sender: msg_sender().unwrap(), diff --git a/examples/src7-metadata/multi_asset/src/multi_asset.sw b/examples/src7-metadata/multi_asset/src/multi_asset.sw index a10c9a4..dfc880d 100644 --- a/examples/src7-metadata/multi_asset/src/multi_asset.sw +++ b/examples/src7-metadata/multi_asset/src/multi_asset.sw @@ -6,7 +6,7 @@ use standards::{ SetNameEvent, SetSymbolEvent, SRC20, - UpdateTotalSupplyEvent, + TotalSupplyEvent, }, src7::{ Metadata, @@ -214,7 +214,7 @@ impl SetSRC20Data for Contract { sender, }); - log(UpdateTotalSupplyEvent { + log(TotalSupplyEvent { asset, supply, sender, diff --git a/examples/src7-metadata/single_asset/src/single_asset.sw b/examples/src7-metadata/single_asset/src/single_asset.sw index 672b665..9e68bc1 100644 --- a/examples/src7-metadata/single_asset/src/single_asset.sw +++ b/examples/src7-metadata/single_asset/src/single_asset.sw @@ -6,7 +6,7 @@ use standards::{ SetNameEvent, SetSymbolEvent, SRC20, - UpdateTotalSupplyEvent, + TotalSupplyEvent, }, src7::{ Metadata, @@ -183,7 +183,7 @@ impl EmitSRC20Events for Contract { sender, }); - log(UpdateTotalSupplyEvent { + log(TotalSupplyEvent { asset, supply: TOTAL_SUPPLY, sender, diff --git a/standards/src/src20.sw b/standards/src/src20.sw index 8dbb264..fe09366 100644 --- a/standards/src/src20.sw +++ b/standards/src/src20.sw @@ -154,12 +154,12 @@ pub struct SetDecimalsEvent { pub sender: Identity, } -/// The event emitted when the total supply is updated. -pub struct UpdateTotalSupplyEvent { +/// The event emitted when the total supply is changed. +pub struct TotalSupplyEvent { /// The asset for which supply is updated. pub asset: AssetId, - /// The supply that is set. + /// The new supply of the asset. pub supply: u64, - /// The caller that modified the supply. + /// The caller that updated the supply. pub sender: Identity, } From e1662c41875226184efbc3423b5dafb7b18c2b05 Mon Sep 17 00:00:00 2001 From: bitzoic Date: Mon, 26 Aug 2024 13:28:03 +0800 Subject: [PATCH 17/17] Split examples into seperate workspace projects --- .github/workflows/ci.yaml | 57 ++++++++++++++++++- CHANGELOG.md | 3 +- examples/Forc.toml | 20 ------- examples/src11-security-information/Forc.toml | 2 + examples/src12-contract-factory/Forc.toml | 2 + examples/src14-simple-proxy/Forc.toml | 2 + examples/src20-native-asset/Forc.toml | 2 + examples/src3-mint-burn/Forc.toml | 2 + examples/src5-ownership/Forc.toml | 2 + examples/src6-vault/Forc.toml | 6 ++ examples/src7-metadata/Forc.toml | 2 + 11 files changed, 75 insertions(+), 25 deletions(-) delete mode 100644 examples/Forc.toml create mode 100644 examples/src11-security-information/Forc.toml create mode 100644 examples/src12-contract-factory/Forc.toml create mode 100644 examples/src14-simple-proxy/Forc.toml create mode 100644 examples/src20-native-asset/Forc.toml create mode 100644 examples/src3-mint-burn/Forc.toml create mode 100644 examples/src5-ownership/Forc.toml create mode 100644 examples/src6-vault/Forc.toml create mode 100644 examples/src7-metadata/Forc.toml diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index efcd55b..a8f67d1 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -10,6 +10,7 @@ on: concurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true env: CARGO_TERM_COLOR: always @@ -20,7 +21,7 @@ env: PATH_TO_SCRIPTS: .github/scripts jobs: - build-sway-lib: + build-sway-standards: runs-on: ubuntu-latest steps: @@ -62,8 +63,58 @@ jobs: - name: Build All Standards run: forc build --error-on-warnings --path standards --release + build-examples: + runs-on: ubuntu-latest + + strategy: + matrix: + project: + [ + "examples/src3-mint-burn", + "examples/src5-ownership", + "examples/src6-vault", + "examples/src7-metadata", + "examples/src11-security-information", + "examples/src12-contract-factory", + "examples/src14-simple-proxy", + "examples/src20-native-asset", + ] + + steps: + - name: Checkout repository + uses: actions/checkout@v2 + + - name: Install Rust toolchain + uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: ${{ env.RUST_VERSION }} + override: true + + - name: Init cache + uses: Swatinem/rust-cache@v1 + + - name: Install a modern linker (mold) + uses: rui314/setup-mold@v1 + + - name: Force Rust to use mold globally for compilation + run: | + touch ~/.cargo/config.toml + echo "[target.x86_64-unknown-linux-gnu]" > ~/.cargo/config.toml + echo 'linker = "clang"' >> ~/.cargo/config.toml + echo 'rustflags = ["-C", "link-arg=-fuse-ld=/usr/local/bin/mold"]' >> ~/.cargo/config.toml + + - name: Install rustfmt + run: rustup component add rustfmt + + - name: Install Fuel toolchain + uses: FuelLabs/action-fuel-toolchain@v0.6.0 + with: + name: my-toolchain + components: forc@${{ env.FORC_VERSION }}, fuel-core@${{ env.CORE_VERSION }} + - name: Check Sway Formatting Examples - run: forc fmt --path examples --check + run: forc fmt --path ${{ matrix.project }} --check - name: Build All Examples - run: forc build --path examples --release + run: forc build --path ${{ matrix.project }} --release diff --git a/CHANGELOG.md b/CHANGELOG.md index 55248de..0017a68 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,8 +14,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Changed Unreleased -- Something changed here 1 -- Something changed here 2 +- [#130](https://github.com/FuelLabs/sway-standards/pull/130) Splits examples into seperate workspace projects for improved continuous integration. ### Fixed Unreleased diff --git a/examples/Forc.toml b/examples/Forc.toml deleted file mode 100644 index 4f5338f..0000000 --- a/examples/Forc.toml +++ /dev/null @@ -1,20 +0,0 @@ -[workspace] -members = [ - "src3-mint-burn/single_asset", - "src3-mint-burn/multi_asset", - "src5-ownership/initialized_example", - "src5-ownership/uninitialized_example", - "src6-vault/multi_asset_vault", - "src6-vault/single_asset_single_sub_vault", - "src6-vault/single_asset_vault", - "src7-metadata/single_asset", - "src7-metadata/multi_asset", - "src11-security-information/hardcoded-information", - "src11-security-information/variable-information", - "src12-contract-factory/with_configurables", - "src12-contract-factory/without_configurables", - "src14-simple-proxy/owned", - "src14-simple-proxy/minimal", - "src20-native-asset/single_asset", - "src20-native-asset/multi_asset", -] diff --git a/examples/src11-security-information/Forc.toml b/examples/src11-security-information/Forc.toml new file mode 100644 index 0000000..343d46d --- /dev/null +++ b/examples/src11-security-information/Forc.toml @@ -0,0 +1,2 @@ +[workspace] +members = ["hardcoded-information", "variable-information"] diff --git a/examples/src12-contract-factory/Forc.toml b/examples/src12-contract-factory/Forc.toml new file mode 100644 index 0000000..9d957df --- /dev/null +++ b/examples/src12-contract-factory/Forc.toml @@ -0,0 +1,2 @@ +[workspace] +members = ["with_configurables", "without_configurables"] diff --git a/examples/src14-simple-proxy/Forc.toml b/examples/src14-simple-proxy/Forc.toml new file mode 100644 index 0000000..6fcc521 --- /dev/null +++ b/examples/src14-simple-proxy/Forc.toml @@ -0,0 +1,2 @@ +[workspace] +members = ["owned", "minimal"] diff --git a/examples/src20-native-asset/Forc.toml b/examples/src20-native-asset/Forc.toml new file mode 100644 index 0000000..c75476c --- /dev/null +++ b/examples/src20-native-asset/Forc.toml @@ -0,0 +1,2 @@ +[workspace] +members = ["single_asset", "multi_asset"] diff --git a/examples/src3-mint-burn/Forc.toml b/examples/src3-mint-burn/Forc.toml new file mode 100644 index 0000000..c75476c --- /dev/null +++ b/examples/src3-mint-burn/Forc.toml @@ -0,0 +1,2 @@ +[workspace] +members = ["single_asset", "multi_asset"] diff --git a/examples/src5-ownership/Forc.toml b/examples/src5-ownership/Forc.toml new file mode 100644 index 0000000..0bf139c --- /dev/null +++ b/examples/src5-ownership/Forc.toml @@ -0,0 +1,2 @@ +[workspace] +members = ["initialized_example", "uninitialized_example"] diff --git a/examples/src6-vault/Forc.toml b/examples/src6-vault/Forc.toml new file mode 100644 index 0000000..dcddd95 --- /dev/null +++ b/examples/src6-vault/Forc.toml @@ -0,0 +1,6 @@ +[workspace] +members = [ + "multi_asset_vault", + "single_asset_single_sub_vault", + "single_asset_vault", +] diff --git a/examples/src7-metadata/Forc.toml b/examples/src7-metadata/Forc.toml new file mode 100644 index 0000000..c75476c --- /dev/null +++ b/examples/src7-metadata/Forc.toml @@ -0,0 +1,2 @@ +[workspace] +members = ["single_asset", "multi_asset"]