diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml
index fd3c74e..4087010 100644
--- a/.github/workflows/ci.yaml
+++ b/.github/workflows/ci.yaml
@@ -77,6 +77,7 @@ jobs:
"examples/src11-security-information",
"examples/src12-contract-factory",
"examples/src14-simple-proxy",
+ "examples/src15-offchain-metadata",
"examples/src20-native-asset",
]
diff --git a/.github/workflows/docs.yaml b/.github/workflows/docs.yaml
index d847721..1a698f9 100644
--- a/.github/workflows/docs.yaml
+++ b/.github/workflows/docs.yaml
@@ -4,8 +4,19 @@ on:
pull_request:
jobs:
- test:
+ spell-check:
+ name: Spell Check
uses: FuelLabs/github-actions/.github/workflows/mdbook-docs.yml@master
with:
- docs-src-path: 'docs/src'
- spellcheck-config-path: 'docs/.spellcheck.yml'
\ No newline at end of file
+ docs-src-path: "docs/src"
+ spellcheck-config-path: "docs/.spellcheck.yml"
+
+ link-check:
+ name: Link Check
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout repo
+ uses: actions/checkout@v3
+
+ - name: Run Markdown Link Check
+ uses: gaurav-nelson/github-action-markdown-link-check@1.0.15
diff --git a/CHANGELOG.md b/CHANGELOG.md
index b1d3c0d..4b1d2ae 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,8 +7,6 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
## [Unreleased]
-Description of the upcoming release here.
-
### Added
- Something new here 1
@@ -24,14 +22,39 @@ Description of the upcoming release here.
- Some fix here 1
- Some fix here 2
-#### Breaking
+### Breaking
- Some breaking change here 1
- Some breaking change here 2
-## [Version 0.6.1]
+## [Version 0.6.2]
+
+### New Standards v0.6.2
+
+- [#159](https://github.com/FuelLabs/sway-standards/pull/159) Defines the SRC-15; Offchain Metadata Standard.
+
+### Added v0.6.2
+
+- [#152](https://github.com/FuelLabs/sway-standards/pull/152) Adds inline documentation examples to the SRC-6 standard.
+- [#159](https://github.com/FuelLabs/sway-standards/pull/159) Adds the SRC-15 standard files and docs.
+- [#162](https://github.com/FuelLabs/sway-standards/pull/162) Adds link checker to CI.
+
+### Changed v0.6.2
-Description of the upcoming release here.
+- [#154](https://github.com/FuelLabs/sway-standards/pull/154) Updates the examples in the standards specififcations to use the offical abi name.
+- [#157](https://github.com/FuelLabs/sway-standards/pull/157) Updates the name of the SRC-7 standard to "Onchain Native Asset Metadata Standard".
+- [#163](https://github.com/FuelLabs/sway-standards/pull/163) Prepares for the v0.6.2 release.
+
+### Fixed v0.6.2
+
+- [#153](https://github.com/FuelLabs/sway-standards/pull/153) Actually write to storage in `set_src20_data()` in the SRC-20 multi asset example.
+- [#160](https://github.com/FuelLabs/sway-standards/pull/160) Fixes a typo in the SRC-7 inline docs.
+
+#### Breaking v0.6.2
+
+- None
+
+## [Version 0.6.1]
### Added v0.6.1
@@ -50,6 +73,8 @@ Description of the upcoming release here.
- [#137](https://github.com/FuelLabs/sway-standards/pull/137) Resolves warnings for SRC-6, SRC-14, and SRC-5 standard examples.
- [#136](https://github.com/FuelLabs/sway-standards/pull/136) Fixes SRC14 to recommend namespacing all non-standardized storage variables under the SRC14 namespace, fixes typos, and improves markdown in docs and inline documentation.
- [#142](https://github.com/FuelLabs/sway-standards/pull/142) Fixes errors in inline documentation for SRC-10, SRC-12, SRC-14, SRC-20, SRC-3, SRC-5, SRC-7 standards.
+- [#151](https://github.com/FuelLabs/sway-standards/pull/151) Fixes SRC-6 standard examples conform to the latest SRC-20 spec of logging values after updates.
+- [#151](https://github.com/FuelLabs/sway-standards/pull/151) Formats code of SRC-6 examples, and fixes some comments.
## [Version 0.6.0]
diff --git a/Cargo.toml b/Cargo.toml
index 28fcf2d..1aed410 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,4 +1,4 @@
[package]
name = "sway-standards"
-version = "0.6.1"
+version = "0.6.2"
edition = "2021"
diff --git a/README.md b/README.md
index 3d91784..2624868 100644
--- a/README.md
+++ b/README.md
@@ -6,8 +6,8 @@
-
-
+
+
@@ -37,7 +37,7 @@ If you don't find what you're looking for, feel free to create an issue and prop
- [SRC-20; Native Asset Standard](https://docs.fuel.network/docs/sway-standards/src-20-native-asset/) defines the implementation of a standard API for [Native Assets](https://docs.fuel.network/docs/sway/blockchain-development/native_assets) using the Sway Language.
- [SRC-3; Mint and Burn](https://docs.fuel.network/docs/sway-standards/src-3-minting-and-burning/) is used to enable mint and burn functionality for fungible assets.
-- [SRC-7; Arbitrary Asset Metadata Standard](https://docs.fuel.network/docs/sway-standards/src-7-asset-metadata/) is used to store metadata for [Native Assets](https://docs.fuel.network/docs/sway/blockchain-development/native_assets).
+- [SRC-7; Onchain Asset Metadata Standard](https://docs.fuel.network/docs/sway-standards/src-7-asset-metadata/) is used to store metadata for [Native Assets](https://docs.fuel.network/docs/sway/blockchain-development/native_assets).
- [SRC-9; Metadata Keys Standard](https://docs.fuel.network/docs/sway-standards/src-9-metadata-keys/) is used to store standardized metadata keys for [Native Assets](https://docs.fuel.network/docs/sway/blockchain-development/native_assets) in combination with the SRC-7 standard.
- [SRC-6; Vault Standard](https://docs.fuel.network/docs/sway-standards/src-6-vault/) defines the implementation of a standard API for asset vaults developed in Sway.
- [SRC-13; Soulbound Address](https://docs.fuel.network/docs/sway-standards/src-13-soulbound-address/) provides a predicate interface to lock [Native Assets](https://docs.fuel.network/docs/sway/blockchain-development/native_assets) as soulbound.
@@ -65,7 +65,7 @@ If you don't find what you're looking for, feel free to create an issue and prop
To import a standard the following should be added to the project's `Forc.toml` file under `[dependencies]` with the most recent release:
```toml
-standards = { git = "https://github.com/FuelLabs/sway-standards", tag = "v0.6.1" }
+standards = { git = "https://github.com/FuelLabs/sway-standards", tag = "v0.6.2" }
```
> **NOTE:**
diff --git a/docs/spell-check-custom-words.txt b/docs/spell-check-custom-words.txt
index 65384a7..74620cc 100644
--- a/docs/spell-check-custom-words.txt
+++ b/docs/spell-check-custom-words.txt
@@ -266,3 +266,8 @@ SetNameEvent
SetSymbolEvent
SetDecimalsEvent
UpdateTotalSupplyEvent
+Onchain
+onchain
+Offchain
+offchain
+MetadataEvent
diff --git a/docs/src/SUMMARY.md b/docs/src/SUMMARY.md
index da0c2b7..a42d26c 100644
--- a/docs/src/SUMMARY.md
+++ b/docs/src/SUMMARY.md
@@ -6,7 +6,7 @@
- [SRC-3: Minting and Burning](./src-3-minting-and-burning.md)
- [SRC-5: Ownership](./src-5-ownership.md)
- [SRC-6: Vault](./src-6-vault.md)
-- [SRC-7: Asset Metadata](./src-7-asset-metadata.md)
+- [SRC-7: Onchain Asset Metadata](./src-7-asset-metadata.md)
- [SRC-8: Bridged Asset](./src-8-bridged-asset.md)
- [SRC-9: Metadata Keys](./src-9-metadata-keys.md)
- [SRC-10: Native Bridge](./src-10-native-bridge.md)
@@ -14,4 +14,5 @@
- [SRC-12: Contract Factory](./src-12-contract-factory.md)
- [SRC-13: Soulbound Address](./src-13-soulbound-address.md)
- [SRC-14: Simple Upgradeable Contract](./src-14-simple-upgradeable-proxies.md)
+- [SRC-15: Offchain Asset Metadata](./src-15-offchain-asset-metadata.md)
- [SRC-20: Native Asset](./src-20-native-asset.md)
diff --git a/docs/src/index.md b/docs/src/index.md
index e7d7b5b..742d95d 100644
--- a/docs/src/index.md
+++ b/docs/src/index.md
@@ -14,7 +14,7 @@ If you don't find what you're looking for, feel free to create an issue and prop
To import a standard the following should be added to the project's `Forc.toml` file under `[dependencies]` with the most recent release:
```toml
-standards = { git = "https://github.com/FuelLabs/sway-standards", tag = "v0.6.1" }
+standards = { git = "https://github.com/FuelLabs/sway-standards", tag = "v0.6.2" }
```
> **NOTE:**
@@ -38,10 +38,11 @@ use standards::src20::SRC20;
- [SRC-20; Native Asset Standard](./src-20-native-asset.md) defines the implementation of a standard API for [Native Assets](https://docs.fuel.network/docs/sway/blockchain-development/native_assets) using the Sway Language.
- [SRC-3; Mint and Burn](./src-3-minting-and-burning.md) is used to enable mint and burn functionality for fungible assets.
-- [SRC-7; Arbitrary Asset Metadata Standard](./src-7-asset-metadata.md) is used to store metadata for [Native Assets](https://docs.fuel.network/docs/sway/blockchain-development/native_assets).
+- [SRC-7; Onchain Asset Metadata Standard](./src-7-asset-metadata.md) is used to store metadata for [Native Assets](https://docs.fuel.network/docs/sway/blockchain-development/native_assets).
- [SRC-9; Metadata Keys Standard](./src-9-metadata-keys.md) is used to store standardized metadata keys for [Native Assets](https://docs.fuel.network/docs/sway/blockchain-development/native_assets) in combination with the SRC-7 standard.
- [SRC-6; Vault Standard](./src-6-vault.md) defines the implementation of a standard API for asset vaults developed in Sway.
- [SRC-13; Soulbound Address](./src-13-soulbound-address.md) defines the implementation of a soulbound address.
+- [SRC-15; Offchain Asset Metadata Standard](./src-15-offchain-asset-metadata.md) is used to associated metadata with [Native Assets](https://docs.fuel.network/docs/sway/blockchain-development/native_assets) offchain.
### Security and Access Control
diff --git a/docs/src/src-15-offchain-asset-metadata.md b/docs/src/src-15-offchain-asset-metadata.md
new file mode 100644
index 0000000..068209b
--- /dev/null
+++ b/docs/src/src-15-offchain-asset-metadata.md
@@ -0,0 +1,73 @@
+# SRC-15: Off-Chain Native Asset Metadata
+
+The following standard attempts to define arbitrary metadata for any [Native Asset](https://docs.fuel.network/docs/sway/blockchain-development/native_assets) that is not required by other contracts onchain, in a stateless manner. Any contract that implements the SRC-15 standard MUST implement the [SRC-20](./src-20-native-asset.md) standard.
+
+## Motivation
+
+The SRC-15 standard seeks to enable data-rich assets on the Fuel Network while maintaining a stateless solution. All metadata queries are done off-chain using the indexer.
+
+## Prior Art
+
+The SRC-7 standard exists prior to the SRC-15 standard and is a stateful solution. The SRC-15 builds off the SRC-7 standard by using the `Metadata` enum however provides a stateless solution.
+
+The use of generic metadata was originally found in the Sway-Lib's [NFT Library](https://github.com/FuelLabs/sway-libs/tree/v0.12.0/libs/nft) which did not use Fuel's [Native Assets](https://docs.fuel.network/docs/sway/blockchain-development/native_assets). This library has since been deprecated.
+
+A previous definition for a metadata standard was written in the original edit of the now defunct [SRC-721](https://github.com/FuelLabs/sway-standards/issues/2). This has since been replaced with the [SRC-20](./src-20-native-asset.md) standard as `SubId` was introduced to enable multiple assets to be minted from a single contract.
+
+## Specification
+
+### Metadata Type
+
+The `Metadata` enum from the SRC-7 standard is also used to represent the metadata in the SRC-15 standard.
+
+### Logging
+
+The following logs MUST be implemented and emitted to follow the SRC-15 standard. Logging MUST be emitted from the contract which minted the asset.
+
+#### SRC15MetadataEvent
+
+The `SRC15MetadataEvent` MUST be emitted at least once for each distinct piece of metadata. The latest emitted `SRC15MetadataEvent` is determined to be the current metadata.
+
+There SHALL be the following fields in the `SRC15MetadataEvent` struct:
+
+* `asset`: The `asset` field SHALL be used for the corresponding `AssetId` for the metadata.
+* `metadata`: The `metadata` field SHALL be used for the corresponding `Metadata` which represents the metadata of the asset.
+
+Example:
+
+```sway
+pub struct SRC15MetadataEvent {
+ pub asset: AssetId,
+ pub metadata: Metadata,
+}
+```
+
+## Rationale
+
+The SRC-15 standard allows for data-rich assets in a stateless manner by associating an asset with some metadata that may later be fetched by the indexer.
+
+## Backwards Compatibility
+
+This standard is compatible with Fuel's [Native Assets](https://docs.fuel.network/docs/sway/blockchain-development/native_assets) and the [SRC-20](./src-20-native-asset.md) standard. This standard is also compatible with the SRC-7 standard which defines a stateful solution. It also maintains compatibility with existing standards in other ecosystems.
+
+## Security Considerations
+
+When indexing for SRC-15 metadata, developers should confirm that the contract that emitted the `SRC15MetadataEvent` is also the contract that minted the asset that the metadata associates with. Additionally, restrictions via access control on who may emit the Metadata should be considered.
+
+## Example Implementation
+
+### Single Native Asset
+
+Example of the SRC-15 implementation where metadata exists for only a single asset with one `SubId`.
+
+```sway
+{{#include ../examples/src15-offchain-metadata/single_asset/src/single_asset.sw}}
+```
+
+### Multi Native Asset
+
+Example of the SRC-15 implementation where metadata exists for multiple assets with differing `SubId` values.
+
+```sway
+{{#include ../examples/src15-offchain-metadata/multi_asset/src/multi_asset.sw}}
+```
diff --git a/docs/src/src-20-native-asset.md b/docs/src/src-20-native-asset.md
index 9a89c14..78b03dd 100644
--- a/docs/src/src-20-native-asset.md
+++ b/docs/src/src-20-native-asset.md
@@ -151,7 +151,7 @@ This standard does not introduce any security concerns, as it does not call exte
## Example ABI
```sway
-abi MyAsset {
+abi SRC20 {
#[storage(read)]
fn total_assets() -> u64;
#[storage(read)]
diff --git a/docs/src/src-3-minting-and-burning.md b/docs/src/src-3-minting-and-burning.md
index c36b177..f749b96 100644
--- a/docs/src/src-3-minting-and-burning.md
+++ b/docs/src/src-3-minting-and-burning.md
@@ -56,7 +56,7 @@ The burn function may also introduce a security consideration if the total suppl
## Example ABI
```sway
-abi MySRC3Asset {
+abi SRC3 {
#[storage(read, write)]
fn mint(recipient: Identity, sub_id: Option, amount: u64);
#[payable]
diff --git a/docs/src/src-7-asset-metadata.md b/docs/src/src-7-asset-metadata.md
index 001749d..b19e7c5 100644
--- a/docs/src/src-7-asset-metadata.md
+++ b/docs/src/src-7-asset-metadata.md
@@ -1,10 +1,10 @@
-# SRC-7: Arbitrary Native Asset Metadata
+# SRC-7: Onchain Native Asset Metadata
-The following standard attempts to define the retrieval of on-chain arbitrary metadata for any [Native Asset](https://docs.fuel.network/docs/sway/blockchain-development/native_assets). Any contract that implements the SRC-7 standard MUST implement the [SRC-20](./src-20-native-asset.md) standard.
+The following standard attempts to define the retrieval of on-chain arbitrary metadata for any [Native Asset](https://docs.fuel.network/docs/sway/blockchain-development/native_assets). This standard should be used if a stateful approach is needed. Any contract that implements the SRC-7 standard MUST implement the [SRC-20](./src-20-native-asset.md) standard.
## Motivation
-The SRC-7 standard seeks to enable data-rich assets on the Fuel Network while maintaining compatibility between multiple assets minted by the same contract. The standard ensures type safety with the use of an `enum` and an `Option`. All metadata queries are done through a single function to facilitate cross-contract calls.
+The SRC-7 standard seeks to enable stateful data-rich assets on the Fuel Network while maintaining compatibility between multiple assets minted by the same contract. The standard ensures type safety with the use of an `enum` and an `Option`. All metadata queries are done through a single function to facilitate cross-contract calls.
## Prior Art
@@ -57,7 +57,7 @@ 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.
+* `asset`: The `asset` field SHALL be used for the corresponding `AssetId` for the asset that 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.
@@ -75,7 +75,7 @@ pub struct SetMetadataEvent {
## Rationale
-The SRC-7 standard should allow for data-rich assets to interact with one another in a safe manner.
+The SRC-7 standard should allow for stateful data-rich assets to interact with one another in a safe manner.
## Backwards Compatibility
@@ -88,7 +88,7 @@ This standard does not introduce any security concerns, as it does not call exte
## Example ABI
```sway
-abi SRC7Metadata {
+abi SRC7 {
#[storage(read)]
fn metadata(asset: AssetId, key: String) -> Option;
}
diff --git a/examples/src15-offchain-metadata/Forc.toml b/examples/src15-offchain-metadata/Forc.toml
new file mode 100644
index 0000000..c75476c
--- /dev/null
+++ b/examples/src15-offchain-metadata/Forc.toml
@@ -0,0 +1,2 @@
+[workspace]
+members = ["single_asset", "multi_asset"]
diff --git a/examples/src15-offchain-metadata/multi_asset/Forc.toml b/examples/src15-offchain-metadata/multi_asset/Forc.toml
new file mode 100644
index 0000000..5eee9ec
--- /dev/null
+++ b/examples/src15-offchain-metadata/multi_asset/Forc.toml
@@ -0,0 +1,8 @@
+[project]
+authors = ["Fuel Labs "]
+entry = "multi_asset.sw"
+license = "Apache-2.0"
+name = "multi_src15_asset"
+
+[dependencies]
+standards = { path = "../../../standards" }
diff --git a/examples/src15-offchain-metadata/multi_asset/src/multi_asset.sw b/examples/src15-offchain-metadata/multi_asset/src/multi_asset.sw
new file mode 100644
index 0000000..96dac73
--- /dev/null
+++ b/examples/src15-offchain-metadata/multi_asset/src/multi_asset.sw
@@ -0,0 +1,123 @@
+contract;
+
+use standards::{
+ src15::{
+ SRC15MetadataEvent,
+ },
+ src20::{
+ SetDecimalsEvent,
+ SetNameEvent,
+ SetSymbolEvent,
+ SRC20,
+ TotalSupplyEvent,
+ },
+ src7::{
+ Metadata,
+ },
+};
+
+use std::{hash::Hash, storage::storage_string::*, string::String};
+
+// 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 = 0u8,
+ /// The name of every asset minted by this contract.
+ NAME: str[7] = __to_str_array("MyAsset"),
+ /// The symbol of every asset minted by this contract.
+ SYMBOL: str[5] = __to_str_array("MYAST"),
+ /// The metadata for the "social:x" key.
+ SOCIAL_X: str[12] = __to_str_array("fuel_network"),
+ /// The metadata for the "site:forum" key.
+ SITE_FORUM: str[27] = __to_str_array("https://forum.fuel.network/"),
+}
+
+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 = StorageMap {},
+}
+
+abi EmitSRC15Events {
+ #[storage(read)]
+ fn emit_src15_events(asset: AssetId, svg_image: String, health_attribute: u64);
+}
+
+impl EmitSRC15Events for Contract {
+ #[storage(read)]
+ fn emit_src15_events(asset: AssetId, svg_image: String, health_attribute: u64) {
+ // NOTE: There are no checks for if the caller has permissions to emit the metadata
+ // NOTE: Nothing is stored in storage and there is no method to retrieve the configurables.
+
+ // If this asset does not exist, revert
+ if storage.total_supply.get(asset).try_read().is_none() {
+ revert(0);
+ }
+
+ let metadata_1 = Metadata::String(String::from_ascii_str(from_str_array(SOCIAL_X)));
+ let metadata_2 = Metadata::String(String::from_ascii_str(from_str_array(SITE_FORUM)));
+ let metadata_3 = Metadata::String(svg_image);
+ let metadata_4 = Metadata::Int(health_attribute);
+
+ SRC15MetadataEvent::new(asset, metadata_1).log();
+ SRC15MetadataEvent::new(asset, metadata_2).log();
+ SRC15MetadataEvent::new(asset, metadata_3).log();
+ SRC15MetadataEvent::new(asset, metadata_4).log();
+ }
+}
+
+// SRC15 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 {
+ storage.total_supply.get(asset).try_read()
+ }
+
+ #[storage(read)]
+ fn name(asset: AssetId) -> Option {
+ match storage.total_supply.get(asset).try_read() {
+ Some(_) => Some(String::from_ascii_str(from_str_array(NAME))),
+ None => None,
+ }
+ }
+
+ #[storage(read)]
+ fn symbol(asset: AssetId) -> Option {
+ match storage.total_supply.get(asset).try_read() {
+ Some(_) => Some(String::from_ascii_str(from_str_array(SYMBOL))),
+ None => None,
+ }
+ }
+
+ #[storage(read)]
+ fn decimals(asset: AssetId) -> Option {
+ match storage.total_supply.get(asset).try_read() {
+ Some(_) => Some(DECIMALS),
+ None => None,
+ }
+ }
+}
+
+abi EmitSRC20Data {
+ fn emit_src20_data(asset: AssetId, total_supply: u64);
+}
+
+impl EmitSRC20Data for Contract {
+ fn emit_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();
+ 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, supply, sender).log();
+ }
+}
diff --git a/examples/src15-offchain-metadata/single_asset/Forc.toml b/examples/src15-offchain-metadata/single_asset/Forc.toml
new file mode 100644
index 0000000..c3566cc
--- /dev/null
+++ b/examples/src15-offchain-metadata/single_asset/Forc.toml
@@ -0,0 +1,8 @@
+[project]
+authors = ["Fuel Labs "]
+entry = "single_asset.sw"
+license = "Apache-2.0"
+name = "single_src15_asset"
+
+[dependencies]
+standards = { path = "../../../standards" }
diff --git a/examples/src15-offchain-metadata/single_asset/src/single_asset.sw b/examples/src15-offchain-metadata/single_asset/src/single_asset.sw
new file mode 100644
index 0000000..ea9d9e8
--- /dev/null
+++ b/examples/src15-offchain-metadata/single_asset/src/single_asset.sw
@@ -0,0 +1,118 @@
+contract;
+
+use standards::{
+ src15::{
+ SRC15MetadataEvent,
+ },
+ src20::{
+ SetDecimalsEvent,
+ SetNameEvent,
+ SetSymbolEvent,
+ SRC20,
+ TotalSupplyEvent,
+ },
+ src7::{
+ Metadata,
+ },
+};
+
+use std::string::String;
+
+configurable {
+ /// The total supply of coins for the asset minted by this contract.
+ TOTAL_SUPPLY: u64 = 100_000_000,
+ /// 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("MyAsset"),
+ /// The symbol of the asset minted by this contract.
+ SYMBOL: str[5] = __to_str_array("MYTKN"),
+ /// The metadata for the "social:x" key.
+ SOCIAL_X: str[12] = __to_str_array("fuel_network"),
+ /// The metadata for the "site:forum" key.
+ SITE_FORUM: str[27] = __to_str_array("https://forum.fuel.network/"),
+ /// The metadata for the "attr:health" key.
+ ATTR_HEALTH: u64 = 100,
+}
+
+abi EmitSRC15Events {
+ fn emit_src15_events();
+}
+
+impl EmitSRC15Events for Contract {
+ fn emit_src15_events() {
+ // NOTE: There are no checks for if the caller has permissions to emit the metadata.
+ // NOTE: Nothing is stored in storage and there is no method to retrieve the configurables.
+ let asset = AssetId::default();
+ let metadata_1 = Metadata::String(String::from_ascii_str(from_str_array(SOCIAL_X)));
+ let metadata_2 = Metadata::String(String::from_ascii_str(from_str_array(SITE_FORUM)));
+ let metadata_3 = Metadata::Int(ATTR_HEALTH);
+
+ SRC15MetadataEvent::new(asset, metadata_1).log();
+ SRC15MetadataEvent::new(asset, metadata_2).log();
+ SRC15MetadataEvent::new(asset, metadata_3).log();
+ }
+}
+
+// SRC15 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 {
+ if asset == AssetId::default() {
+ Some(TOTAL_SUPPLY)
+ } else {
+ None
+ }
+ }
+
+ #[storage(read)]
+ fn name(asset: AssetId) -> Option {
+ if asset == AssetId::default() {
+ Some(String::from_ascii_str(from_str_array(NAME)))
+ } else {
+ None
+ }
+ }
+
+ #[storage(read)]
+ fn symbol(asset: AssetId) -> Option {
+ if asset == AssetId::default() {
+ Some(String::from_ascii_str(from_str_array(SYMBOL)))
+ } else {
+ None
+ }
+ }
+
+ #[storage(read)]
+ fn decimals(asset: AssetId) -> Option {
+ if asset == AssetId::default() {
+ Some(DECIMALS)
+ } else {
+ None
+ }
+ }
+}
+
+abi EmitSRC20Events {
+ fn emit_src20_events();
+}
+
+impl EmitSRC20Events for Contract {
+ fn emit_src20_events() {
+ // Metadata that is stored as a configurable must be emitted once.
+ let asset = AssetId::default();
+ 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, TOTAL_SUPPLY, sender).log();
+ }
+}
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 d8540b7..0fec714 100644
--- a/examples/src20-native-asset/multi_asset/src/multi_asset.sw
+++ b/examples/src20-native-asset/multi_asset/src/multi_asset.sw
@@ -173,7 +173,7 @@ impl SRC20 for Contract {
}
abi SetSRC20Data {
- #[storage(read)]
+ #[storage(read, write)]
fn set_src20_data(
asset: AssetId,
total_supply: u64,
@@ -184,7 +184,7 @@ abi SetSRC20Data {
}
impl SetSRC20Data for Contract {
- #[storage(read)]
+ #[storage(read, write)]
fn set_src20_data(
asset: AssetId,
supply: u64,
@@ -199,9 +199,32 @@ impl SetSRC20Data for Contract {
}
let sender = msg_sender().unwrap();
- SetNameEvent::new(asset, name, sender).log();
- SetSymbolEvent::new(asset, symbol, sender).log();
+ match name {
+ Some(unwrapped_name) => {
+ storage.name.get(asset).write_slice(unwrapped_name);
+ SetNameEvent::new(asset, name, sender).log();
+ },
+ None => {
+ let _ = storage.name.get(asset).clear();
+ SetNameEvent::new(asset, name, sender).log();
+ }
+ }
+
+ match symbol {
+ Some(unwrapped_symbol) => {
+ storage.symbol.get(asset).write_slice(unwrapped_symbol);
+ SetSymbolEvent::new(asset, symbol, sender).log();
+ },
+ None => {
+ let _ = storage.symbol.get(asset).clear();
+ SetSymbolEvent::new(asset, symbol, sender).log();
+ }
+ }
+
+ storage.decimals.get(asset).write(decimals);
SetDecimalsEvent::new(asset, decimals, sender).log();
+
+ storage.total_supply.get(asset).write(supply);
TotalSupplyEvent::new(asset, supply, sender).log();
}
}
diff --git a/examples/src6-vault/multi_asset_vault/src/main.sw b/examples/src6-vault/multi_asset_vault/src/main.sw
index ac964e3..1b249ba 100644
--- a/examples/src6-vault/multi_asset_vault/src/main.sw
+++ b/examples/src6-vault/multi_asset_vault/src/main.sw
@@ -12,7 +12,20 @@ use std::{
string::String,
};
-use standards::{src20::SRC20, src6::{Deposit, SRC6, Withdraw}};
+use standards::{
+ src20::{
+ SetDecimalsEvent,
+ SetNameEvent,
+ SetSymbolEvent,
+ SRC20,
+ TotalSupplyEvent,
+ },
+ src6::{
+ Deposit,
+ SRC6,
+ Withdraw,
+ },
+};
pub struct VaultInfo {
/// Amount of assets currently managed by this vault
@@ -170,6 +183,58 @@ impl SRC20 for Contract {
}
}
+abi SetSRC20Data {
+ #[storage(read, write)]
+ fn set_src20_data(
+ asset: AssetId,
+ name: Option,
+ symbol: Option,
+ decimals: u8,
+ );
+}
+
+impl SetSRC20Data for Contract {
+ #[storage(read, write)]
+ fn set_src20_data(
+ asset: AssetId,
+ name: Option,
+ symbol: Option,
+ 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();
+
+ match name {
+ Some(unwrapped_name) => {
+ storage.name.get(asset).write_slice(unwrapped_name);
+ SetNameEvent::new(asset, name, sender).log();
+ },
+ None => {
+ let _ = storage.name.get(asset).clear();
+ SetNameEvent::new(asset, name, sender).log();
+ }
+ }
+
+ match symbol {
+ Some(unwrapped_symbol) => {
+ storage.symbol.get(asset).write_slice(unwrapped_symbol);
+ SetSymbolEvent::new(asset, symbol, sender).log();
+ },
+ None => {
+ let _ = storage.symbol.get(asset).clear();
+ SetSymbolEvent::new(asset, symbol, sender).log();
+ }
+ }
+
+ storage.decimals.get(asset).write(decimals);
+ SetDecimalsEvent::new(asset, decimals, sender).log();
+ }
+}
+
/// Returns the vault shares assetid and subid for the given assets assetid and the vaults sub id
fn vault_asset_id(asset: AssetId, vault_sub_id: SubId) -> (AssetId, SubId) {
let share_asset_vault_sub_id = sha256((asset, vault_sub_id));
@@ -229,10 +294,11 @@ pub fn _mint(
if supply.is_none() {
storage.total_assets.write(storage.total_assets.read() + 1);
}
- storage
- .total_supply
- .insert(asset_id, supply.unwrap_or(0) + amount);
+ let new_supply = supply.unwrap_or(0) + amount;
+ storage.total_supply.insert(asset_id, new_supply);
mint_to(recipient, vault_sub_id, amount);
+ TotalSupplyEvent::new(asset_id, new_supply, msg_sender().unwrap())
+ .log();
}
#[storage(read, write)]
@@ -245,6 +311,9 @@ pub fn _burn(asset_id: AssetId, vault_sub_id: SubId, amount: u64) {
);
// If we pass the check above, we can assume it is safe to unwrap.
let supply = storage.total_supply.get(asset_id).try_read().unwrap();
- storage.total_supply.insert(asset_id, supply - amount);
+ let new_supply = supply - amount;
+ storage.total_supply.insert(asset_id, new_supply);
burn(vault_sub_id, amount);
+ TotalSupplyEvent::new(asset_id, new_supply, msg_sender().unwrap())
+ .log();
}
diff --git a/examples/src6-vault/single_asset_single_sub_vault/src/main.sw b/examples/src6-vault/single_asset_single_sub_vault/src/main.sw
index 32a43b9..b07c572 100644
--- a/examples/src6-vault/single_asset_single_sub_vault/src/main.sw
+++ b/examples/src6-vault/single_asset_single_sub_vault/src/main.sw
@@ -12,7 +12,20 @@ use std::{
string::String,
};
-use standards::{src20::SRC20, src6::{Deposit, SRC6, Withdraw}};
+use standards::{
+ src20::{
+ SetDecimalsEvent,
+ SetNameEvent,
+ SetSymbolEvent,
+ SRC20,
+ TotalSupplyEvent,
+ },
+ src6::{
+ Deposit,
+ SRC6,
+ Withdraw,
+ },
+};
configurable {
/// The only sub vault that can be deposited and withdrawn from this vault.
@@ -25,6 +38,12 @@ storage {
managed_assets: u64 = 0,
/// The total amount of shares minted by this vault.
total_supply: u64 = 0,
+ /// The name of a specific asset minted by this contract.
+ name: StorageString = StorageString {},
+ /// The symbol of a specific asset minted by this contract.
+ symbol: StorageString = StorageString {},
+ /// The decimals of a specific asset minted by this contract.
+ decimals: u8 = 9,
}
impl SRC6 for Contract {
@@ -153,7 +172,10 @@ impl SRC20 for Contract {
#[storage(read)]
fn name(asset: AssetId) -> Option {
if asset == vault_assetid() {
- Some(String::from_ascii_str("Vault Shares"))
+ match storage.name.read_slice() {
+ Some(name) => Some(name),
+ None => None,
+ }
} else {
None
}
@@ -162,7 +184,10 @@ impl SRC20 for Contract {
#[storage(read)]
fn symbol(asset: AssetId) -> Option {
if asset == vault_assetid() {
- Some(String::from_ascii_str("VLTSHR"))
+ match storage.symbol.read_slice() {
+ Some(symbol) => Some(symbol),
+ None => None,
+ }
} else {
None
}
@@ -171,13 +196,62 @@ impl SRC20 for Contract {
#[storage(read)]
fn decimals(asset: AssetId) -> Option {
if asset == vault_assetid() {
- Some(9_u8)
+ Some(storage.decimals.read())
} else {
None
}
}
}
+abi SetSRC20Data {
+ #[storage(read, write)]
+ fn set_src20_data(
+ asset: AssetId,
+ name: Option,
+ symbol: Option,
+ decimals: u8,
+ );
+}
+
+impl SetSRC20Data for Contract {
+ #[storage(read, write)]
+ fn set_src20_data(
+ asset: AssetId,
+ name: Option,
+ symbol: Option,
+ decimals: u8,
+ ) {
+ // NOTE: There are no checks for if the caller has permissions to update the metadata
+ require(asset == vault_assetid(), "INVALID_ASSET_ID");
+ let sender = msg_sender().unwrap();
+
+ match name {
+ Some(unwrapped_name) => {
+ storage.name.write_slice(unwrapped_name);
+ SetNameEvent::new(asset, name, sender).log();
+ },
+ None => {
+ let _ = storage.name.clear();
+ SetNameEvent::new(asset, name, sender).log();
+ }
+ }
+
+ match symbol {
+ Some(unwrapped_symbol) => {
+ storage.symbol.write_slice(unwrapped_symbol);
+ SetSymbolEvent::new(asset, symbol, sender).log();
+ },
+ None => {
+ let _ = storage.symbol.clear();
+ SetSymbolEvent::new(asset, symbol, sender).log();
+ }
+ }
+
+ storage.decimals.write(decimals);
+ SetDecimalsEvent::new(asset, decimals, sender).log();
+ }
+}
+
/// Returns the vault shares assetid for the given assets assetid and the vaults sub id
fn vault_assetid() -> AssetId {
let share_asset_id = AssetId::new(ContractId::this(), PRE_CALCULATED_SHARE_VAULT_SUB_ID);
@@ -209,8 +283,11 @@ pub fn _mint(recipient: Identity, amount: u64) {
use std::asset::mint_to;
let supply = storage.total_supply.read();
- storage.total_supply.write(supply + amount);
+ let new_supply = supply + amount;
+ storage.total_supply.write(new_supply);
mint_to(recipient, PRE_CALCULATED_SHARE_VAULT_SUB_ID, amount);
+ TotalSupplyEvent::new(vault_assetid(), new_supply, msg_sender().unwrap())
+ .log();
}
#[storage(read, write)]
@@ -223,6 +300,9 @@ pub fn _burn(asset_id: AssetId, amount: u64) {
);
// If we pass the check above, we can assume it is safe to unwrap.
let supply = storage.total_supply.read();
- storage.total_supply.write(supply - amount);
+ let new_supply = supply - amount;
+ storage.total_supply.write(new_supply);
burn(PRE_CALCULATED_SHARE_VAULT_SUB_ID, amount);
+ TotalSupplyEvent::new(vault_assetid(), new_supply, msg_sender().unwrap())
+ .log();
}
diff --git a/examples/src6-vault/single_asset_vault/src/main.sw b/examples/src6-vault/single_asset_vault/src/main.sw
index 2a282b5..9ad6407 100644
--- a/examples/src6-vault/single_asset_vault/src/main.sw
+++ b/examples/src6-vault/single_asset_vault/src/main.sw
@@ -12,7 +12,20 @@ use std::{
string::String,
};
-use standards::{src20::SRC20, src6::{Deposit, SRC6, Withdraw}};
+use standards::{
+ src20::{
+ SetDecimalsEvent,
+ SetNameEvent,
+ SetSymbolEvent,
+ SRC20,
+ TotalSupplyEvent,
+ },
+ src6::{
+ Deposit,
+ SRC6,
+ Withdraw,
+ },
+};
pub struct VaultInfo {
/// Amount of assets currently managed by this vault
@@ -150,7 +163,7 @@ impl SRC6 for Contract {
underlying_asset == AssetId::base(),
storage.vault_info.get(vault_share_asset).try_read(),
) {
- // In this implementation managed_assets and max_withdrawable are the same. However in case of lending out of assets, total_assets should be greater than max_withdrawable.
+ // In this implementation managed_assets and max_withdrawable are the same. However in case of lending out of assets, managed_assets should be greater than max_withdrawable.
(true, Some(vault_info)) => Some(vault_info.managed_assets),
_ => None,
}
@@ -184,6 +197,58 @@ impl SRC20 for Contract {
}
}
+abi SetSRC20Data {
+ #[storage(read, write)]
+ fn set_src20_data(
+ asset: AssetId,
+ name: Option,
+ symbol: Option,
+ decimals: u8,
+ );
+}
+
+impl SetSRC20Data for Contract {
+ #[storage(read, write)]
+ fn set_src20_data(
+ asset: AssetId,
+ name: Option,
+ symbol: Option,
+ 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();
+
+ match name {
+ Some(unwrapped_name) => {
+ storage.name.get(asset).write_slice(unwrapped_name);
+ SetNameEvent::new(asset, name, sender).log();
+ },
+ None => {
+ let _ = storage.name.get(asset).clear();
+ SetNameEvent::new(asset, name, sender).log();
+ }
+ }
+
+ match symbol {
+ Some(unwrapped_symbol) => {
+ storage.symbol.get(asset).write_slice(unwrapped_symbol);
+ SetSymbolEvent::new(asset, symbol, sender).log();
+ },
+ None => {
+ let _ = storage.symbol.get(asset).clear();
+ SetSymbolEvent::new(asset, symbol, sender).log();
+ }
+ }
+
+ storage.decimals.get(asset).write(decimals);
+ SetDecimalsEvent::new(asset, decimals, sender).log();
+ }
+}
+
/// Returns the vault shares assetid and subid for the given assets assetid and the vaults sub id
fn vault_asset_id(underlying_asset: AssetId, vault_sub_id: SubId) -> (AssetId, SubId) {
let share_asset_vault_sub_id = sha256((underlying_asset, vault_sub_id));
@@ -243,11 +308,11 @@ pub fn _mint(
if supply.is_none() {
storage.total_assets.write(storage.total_assets.read() + 1);
}
- let current_supply = supply.unwrap_or(0);
- storage
- .total_supply
- .insert(asset_id, current_supply + amount);
+ let new_supply = supply.unwrap_or(0) + amount;
+ storage.total_supply.insert(asset_id, new_supply);
mint_to(recipient, vault_sub_id, amount);
+ TotalSupplyEvent::new(asset_id, new_supply, msg_sender().unwrap())
+ .log();
}
#[storage(read, write)]
@@ -260,6 +325,9 @@ pub fn _burn(asset_id: AssetId, vault_sub_id: SubId, amount: u64) {
);
// If we pass the check above, we can assume it is safe to unwrap.
let supply = storage.total_supply.get(asset_id).try_read().unwrap();
- storage.total_supply.insert(asset_id, supply - amount);
+ let new_supply = supply - amount;
+ storage.total_supply.insert(asset_id, new_supply);
burn(vault_sub_id, amount);
+ TotalSupplyEvent::new(asset_id, new_supply, msg_sender().unwrap())
+ .log();
}
diff --git a/mlc_config.json b/mlc_config.json
new file mode 100644
index 0000000..26061fe
--- /dev/null
+++ b/mlc_config.json
@@ -0,0 +1,10 @@
+{
+ "ignorePatterns": [
+ {
+ "pattern": "^https://crates\\.io.*"
+ },
+ {
+ "pattern": "https://github.com/FuelLabs/devrel-requests/issues/new/choose"
+ }
+ ]
+}
diff --git a/standards/src/src15.sw b/standards/src/src15.sw
new file mode 100644
index 0000000..7facc3e
--- /dev/null
+++ b/standards/src/src15.sw
@@ -0,0 +1,104 @@
+library;
+
+use ::src7::Metadata;
+
+/// The required event to be emitted for the SRC-15 standard.
+pub struct SRC15MetadataEvent {
+ /// The asset for which metadata is associated with.
+ pub asset: AssetId,
+ /// The Metadata of the SRC-15 event.
+ pub metadata: Metadata,
+}
+
+impl core::ops::Eq for SRC15MetadataEvent {
+ fn eq(self, other: Self) -> bool {
+ self.asset == other.asset && self.metadata == other.metadata
+ }
+}
+
+impl SRC15MetadataEvent {
+ /// Returns a new `SRC15MetadataEvent` event.
+ ///
+ /// # Arguments
+ ///
+ /// * `asset`: [AssetId] - The asset for which metadata is set.
+ /// * `metadata`: [Option] - The Metadata that is set.
+ ///
+ /// # Returns
+ ///
+ /// * [SRC15MetadataEvent] - The new `SRC15MetadataEvent` event.
+ ///
+ /// # Examples
+ ///
+ /// ```sway
+ /// use standards::{src7::Metadata, src15::SRC15MetadataEvent};
+ ///
+ /// fn foo(asset: AssetId, metadata: Metadata) {
+ /// let my_src15_metadata_event = SRC15MetadataEvent::new(asset, metadata);
+ /// assert(my_src15_metadata_event.asset == asset);
+ /// assert(my_src15_metadata_event.metadata == metadata);
+ /// }
+ /// ```
+ pub fn new(asset: AssetId, metadata: Metadata) -> Self {
+ Self {
+ asset,
+ metadata,
+ }
+ }
+
+ /// Returns the asset of the `SRC15MetadataEvent` event.
+ ///
+ /// # Returns
+ ///
+ /// * [AssetId] - The asset for the event.
+ ///
+ /// # Examples
+ ///
+ /// ```sway
+ /// use standards::{src7::Metadata, src15::SRC15MetadataEvent};
+ ///
+ /// fn foo(asset: AssetId, metadata: Metadata) {
+ /// let my_src15_metadata_event = SRC15MetadataEvent::new(asset, metadata);
+ /// assert(my_src15_metadata_event.asset() == asset);
+ /// }
+ /// ```
+ pub fn asset(self) -> AssetId {
+ self.asset
+ }
+
+ /// Returns the metadata of the `SRC15MetadataEvent` event.
+ ///
+ /// # Returns
+ ///
+ /// * [Option] - The metadata for the event.
+ ///
+ /// # Examples
+ ///
+ /// ```sway
+ /// use standards::{src7::Metadata, src15::SRC15MetadataEvent};
+ ///
+ /// fn foo(asset: AssetId, metadata: Metadata) {
+ /// let my_src15_metadata_event = SRC15MetadataEvent::new(asset, metadata);
+ /// assert(my_src15_metadata_event.metadata() == metadata);
+ /// }
+ /// ```
+ pub fn metadata(self) -> Metadata {
+ self.metadata
+ }
+
+ /// Logs the `SRC15MetadataEvent`.
+ ///
+ /// # Examples
+ ///
+ /// ```sway
+ /// use standards::{src7::Metadata, src15::SRC15MetadataEvent};
+ ///
+ /// fn foo(asset: AssetId, metadata: Metadata) {
+ /// let my_event = SRC15MetadataEvent::new(asset, metadata);
+ /// my_event.log();
+ /// }
+ /// ```
+ pub fn log(self) {
+ log(self);
+ }
+}
diff --git a/standards/src/src6.sw b/standards/src/src6.sw
index 5d5fe4a..c0c756e 100644
--- a/standards/src/src6.sw
+++ b/standards/src/src6.sw
@@ -53,6 +53,28 @@ abi SRC6 {
/// * If the asset is not supported by the contract.
/// * If the amount of assets forwarded to the contract is zero.
/// * The user crosses any global or user specific deposit limits.
+ ///
+ /// # Examples
+ ///
+ /// ```sway
+ /// use standards::src6::SRC6;
+ ///
+ /// fn foo(
+ /// contract_id: ContractId,
+ /// receiver: Identity,
+ /// vault_sub_id: SubId,
+ /// amount: u64,
+ /// asset_id: AssetId
+ /// ) {
+ /// let contract_abi = abi(SRC6, contract_id.bits());
+ /// let minted_shares: u64 = contract_abi.deposit {
+ /// gas: 10000,
+ /// coins: amount,
+ /// asset_id: asset_id.bits()
+ /// } (receiver, vault_sub_id);
+ /// assert(minted_shares != 0);
+ /// }
+ /// ```
#[payable]
#[storage(read, write)]
fn deposit(receiver: Identity, vault_sub_id: SubId) -> u64;
@@ -79,6 +101,27 @@ abi SRC6 {
/// * If the amount of shares is zero.
/// * If the transferred shares do not corresspond to the given asset.
/// * The user crosses any global or user specific withdrawal limits.
+ ///
+ /// # Examples
+ ///
+ /// ```sway
+ /// use standards::src6::SRC6;
+ ///
+ /// fn foo(
+ /// contract_id: ContractId,
+ /// receiver: Identity,
+ /// underlying_asset: AssetId,
+ /// vault_sub_id: SubId,
+ /// share_asset_id: AssetId,
+ /// amount: u64
+ /// ) {
+ /// let contract_abi = abi(SRC6, contract_id.bits());
+ /// let withdrawn_amount: u64 = contract_abi.withdraw {
+ /// gas: 10000,
+ /// coins: amount,
+ /// asset_id: share_asset_id.bits()
+ /// } (receiver, underlying_asset, vault_sub_id);
+ /// assert(withdrawn_amount != 0);
#[payable]
#[storage(read, write)]
fn withdraw(
@@ -97,6 +140,22 @@ abi SRC6 {
/// # Returns
///
/// * [u64] - The amount of managed assets of the given asset.
+ ///
+ /// # Examples
+ ///
+ /// ```sway
+ /// use standards::src6::SRC6;
+ ///
+ /// fn foo(
+ /// contract_id: ContractId,
+ /// underlying_asset: AssetId,
+ /// vault_sub_id: SubId
+ /// ) {
+ /// let contract_abi = abi(SRC6, contract_id.bits());
+ /// let managed_assets: u64 = contract_abi.managed_assets(underlying_asset, vault_sub_id);
+ /// assert(managed_assets != 0);
+ /// }
+ /// ```
#[storage(read)]
fn managed_assets(underlying_asset: AssetId, vault_sub_id: SubId) -> u64;
@@ -116,6 +175,23 @@ abi SRC6 {
///
/// * [Some(u64)] - The maximum amount of assets that can be deposited into the contract, for the given asset.
/// * [None] - If the asset is not supported by the contract.
+ ///
+ /// # Examples
+ ///
+ /// ```sway
+ /// use standards::src6::SRC6;
+ ///
+ /// fn foo(
+ /// contract_id: ContractId,
+ /// receiver: Identity,
+ /// underlying_asset: AssetId,
+ /// vault_sub_id: SubId
+ /// ) {
+ /// let contract_abi = abi(SRC6, contract_id.bits());
+ /// let max_depositable: u64 = contract_abi.max_depositable(receiver, underlying_asset, vault_sub_id).unwrap();
+ /// assert(max_depositable != 0);
+ /// }
+ /// ```
#[storage(read)]
fn max_depositable(
receiver: Identity,
@@ -138,6 +214,22 @@ abi SRC6 {
///
/// * [Some(u64)] - The maximum amount of assets that can be withdrawn from the contract, for the given asset.
/// * [None] - If the asset is not supported by the contract.
+ ///
+ /// # Examples
+ ///
+ /// ```sway
+ /// use standards::src6::SRC6;
+ ///
+ /// fn foo(
+ /// contract_id: ContractId,
+ /// underlying_asset: AssetId,
+ /// vault_sub_id: SubId
+ /// ) {
+ /// let contract_abi = abi(SRC6, contract_id.bits());
+ /// let max_withdrawable: u64 = contract_abi.max_withdrawable(underlying_asset, vault_sub_id).unwrap();
+ /// assert(max_withdrawable != 0);
+ /// }
+ /// ```
#[storage(read)]
fn max_withdrawable(underlying_asset: AssetId, vault_sub_id: SubId) -> Option;
}
diff --git a/standards/src/src7.sw b/standards/src/src7.sw
index e8a0dcc..8b0289d 100644
--- a/standards/src/src7.sw
+++ b/standards/src/src7.sw
@@ -88,7 +88,7 @@ impl SetMetadataEvent {
///
/// * `asset`: [AssetId] - The asset for which metadata is set.
/// * `metadata`: [Option] - The Metadata that is set.
- /// * `ket`: [String] - The key used for the metadata.
+ /// * `key`: [String] - The key used for the metadata.
/// * `sender`: [Identity] - The caller that set the metadata.
///
/// # Returns
diff --git a/standards/src/standards.sw b/standards/src/standards.sw
index 0fea34b..67698b1 100644
--- a/standards/src/standards.sw
+++ b/standards/src/standards.sw
@@ -8,4 +8,5 @@ pub mod src10;
pub mod src11;
pub mod src12;
pub mod src14;
+pub mod src15;
pub mod src20;