From ca3b76434cf5e26d33992245985260ca9e5f6259 Mon Sep 17 00:00:00 2001 From: ThienLK1 Date: Tue, 8 Nov 2022 15:32:44 +0700 Subject: [PATCH 01/23] add supported interface --- .../cw2-supported-interface/.cargo/config | 3 + packages/cw2-supported-interface/Cargo.toml | 16 +++ packages/cw2-supported-interface/README.md | 58 ++++++++ packages/cw2-supported-interface/src/lib.rs | 136 ++++++++++++++++++ 4 files changed, 213 insertions(+) create mode 100644 packages/cw2-supported-interface/.cargo/config create mode 100644 packages/cw2-supported-interface/Cargo.toml create mode 100644 packages/cw2-supported-interface/README.md create mode 100644 packages/cw2-supported-interface/src/lib.rs diff --git a/packages/cw2-supported-interface/.cargo/config b/packages/cw2-supported-interface/.cargo/config new file mode 100644 index 000000000..e82e5693f --- /dev/null +++ b/packages/cw2-supported-interface/.cargo/config @@ -0,0 +1,3 @@ +[alias] +wasm = "build --release --target wasm32-unknown-unknown" +wasm-debug = "build --target wasm32-unknown-unknown" diff --git a/packages/cw2-supported-interface/Cargo.toml b/packages/cw2-supported-interface/Cargo.toml new file mode 100644 index 000000000..25c737941 --- /dev/null +++ b/packages/cw2-supported-interface/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "cw2-supported-interface" +version = "1.0.0" +authors = ["ThienLK1@aura-nw"] +edition = "2021" +description = "Definition and types for the CosmWasm-2 interface" +license = "Apache-2.0" +repository = "https://github.com/CosmWasm/cw-plus" +homepage = "https://cosmwasm.com" + +[dependencies] +cosmwasm-schema = "1.0.0" +cosmwasm-std = { version = "1.0.0", default-features = false } +cw-storage-plus = "0.16.0" +schemars = "0.8.1" +serde = { version = "1.0.0", default-features = false, features = ["derive"] } diff --git a/packages/cw2-supported-interface/README.md b/packages/cw2-supported-interface/README.md new file mode 100644 index 000000000..b80c599a2 --- /dev/null +++ b/packages/cw2-supported-interface/README.md @@ -0,0 +1,58 @@ +# CW2 Spec: Contract Info + +Most of the CW* specs are focused on the *public interfaces* +of the contract. The APIs used for `ExecuteMsg` or `QueryMsg`. +However, when we wish to migrate or inspect smart contract info, +we need some form of smart contract information embedded on state. + +This is where CW2 comes in. It specifies a special Item to +be stored on disk by all contracts on `instantiate`. + +`ContractInfo` must be stored under the `"contract_info"` key which translates +to `"636F6E74726163745F696E666F"` in hex format. +Since the state is well defined, we do not need to support any "smart queries". +We do provide a helper to construct a "raw query" to read the ContractInfo +of any CW2-compliant contract. + +You can query using: +```shell +wasmd query wasm contract-state raw [contract_addr] 636F6E74726163745F696E666F --node $RPC +``` + +When the `migrate` function is called, then the new contract +can read that data andsee if this is an expected contract we can +migrate from. And also contain extra version information if we +support multiple migrate paths. + +### Data structures + +**Required** + +All CW2-compliant contracts must store the following data: + +* key: `contract_info` +* data: Json-serialized `ContractVersion` + +```rust +pub struct ContractVersion { + /// contract is a globally unique identifier for the contract. + /// it should build off standard namespacing for whichever language it is in, + /// and prefix it with the registry we use. + /// For rust we prefix with `crates.io:`, to give us eg. `crates.io:cw20-base` + pub contract: String, + /// version is any string that this implementation knows. It may be simple counter "1", "2". + /// or semantic version on release tags "v0.7.0", or some custom feature flag list. + /// the only code that needs to understand the version parsing is code that knows how to + /// migrate from the given contract (and is tied to it's implementation somehow) + pub version: String, +} +``` + +Thus, an serialized example may looks like: + +```json +{ + "contract": "crates.io:cw20-base", + "version": "v0.1.0" +} +``` diff --git a/packages/cw2-supported-interface/src/lib.rs b/packages/cw2-supported-interface/src/lib.rs new file mode 100644 index 000000000..a4e95aecc --- /dev/null +++ b/packages/cw2-supported-interface/src/lib.rs @@ -0,0 +1,136 @@ +/*! +Most of the CW* specs are focused on the *public interfaces* +of the contract. The APIs used for `ExecuteMsg` or `QueryMsg`. +However, when we wish to migrate or inspect smart contract info, +we need some form of smart contract information embedded on state. + +This is where CW2 comes in. It specifies a special Item to +be stored on disk by all contracts on `instantiate`. + +`ContractInfo` must be stored under the `"contract_info"` key which translates +to `"636F6E74726163745F696E666F"` in hex format. +Since the state is well defined, we do not need to support any "smart queries". +We do provide a helper to construct a "raw query" to read the ContractInfo +of any CW2-compliant contract. + +For more information on this specification, please check out the +[README](https://github.com/CosmWasm/cw-plus/blob/main/packages/cw2/README.md). +*/ + +use cosmwasm_schema::cw_serde; +use cosmwasm_std::{CustomQuery, QuerierWrapper, QueryRequest, StdResult, Storage, WasmQuery}; +use cw_storage_plus::Item; + +pub const CONTRACT: Item = Item::new("contract_info"); + +#[cw_serde] +pub struct ContractVersion { + /// contract is the crate name of the implementing contract, eg. `crate:cw20-base` + /// we will use other prefixes for other languages, and their standard global namespacing + pub contract: String, + /// version is any string that this implementation knows. It may be simple counter "1", "2". + /// or semantic version on release tags "v0.7.0", or some custom feature flag list. + /// the only code that needs to understand the version parsing is code that knows how to + /// migrate from the given contract (and is tied to it's implementation somehow) + pub version: String, + /// supported_interface is an optional parameter returning a vector of string represents interfaces + /// that the contract support The string value is the interface crate names in Rust crate Registry. + /// This parameter is inspired by the EIP-165 from Ethereum. + /// Each string value should follow a common standard such as : + /// e.g ["crates.io:cw721","crates.io:cw2"] + /// NOTE: this is just a hint for the caller to adapt on how to interact with this contract. + /// There is no guarantee that the contract actually implement these interfaces. + pub supported_interface: Option>, +} + +/// get_contract_version can be use in migrate to read the previous version of this contract +pub fn get_contract_version(store: &dyn Storage) -> StdResult { + CONTRACT.load(store) +} + +/// set_contract_version should be used in instantiate to store the original version, and after a successful +/// migrate to update it +pub fn set_contract_version, U: Into>( + store: &mut dyn Storage, + name: T, + version: U, + supported_interface: Option>, +) -> StdResult<()> { + let val = ContractVersion { + contract: name.into(), + version: version.into(), + supported_interface: supported_interface.into(), + }; + CONTRACT.save(store, &val) +} + +/// This will make a raw_query to another contract to determine the current version it +/// claims to be. This should not be trusted, but could be used as a quick filter +/// if the other contract exists and claims to be a cw20-base contract for example. +/// (Note: you usually want to require *interfaces* not *implementations* of the +/// contracts you compose with, so be careful of overuse) +pub fn query_contract_info( + querier: &QuerierWrapper, + contract_addr: T, +) -> StdResult +where + T: Into, + CQ: CustomQuery, +{ + let req = QueryRequest::Wasm(WasmQuery::Raw { + contract_addr: contract_addr.into(), + key: CONTRACT.as_slice().into(), + }); + querier.query(&req) +} + +#[cfg(test)] +mod tests { + use super::*; + use cosmwasm_std::testing::MockStorage; + use std::vec::Vec; + + #[test] + fn get_and_set_work() { + let mut store = MockStorage::new(); + + // error if not set + assert!(get_contract_version(&store).is_err()); + + // set and get + let contract_name = "crate:cw20-base"; + let contract_version = "0.2.0"; + set_contract_version(&mut store, contract_name, contract_version, None).unwrap(); + + let loaded = get_contract_version(&store).unwrap(); + let expected = ContractVersion { + contract: contract_name.to_string(), + version: contract_version.to_string(), + supported_interface: None, + }; + assert_eq!(expected, loaded); + + // set and get with supported_interface + let contract_name = "crate:cw20-base"; + let contract_version = "0.2.0"; + let supported_interface = Some(Vec::from([ + "crates.io:cw2".to_string(), + "crates.io:cw721".to_string(), + ])); + set_contract_version( + &mut store, + contract_name, + contract_version, + supported_interface.clone(), + ) + .unwrap(); + + let loaded = get_contract_version(&store).unwrap(); + let expected = ContractVersion { + contract: contract_name.to_string(), + version: contract_version.to_string(), + supported_interface: supported_interface.clone(), + }; + assert_eq!(expected, loaded); + } +} From cce9ca8d80cd3cda56fbe2d939bd445752a9e0dd Mon Sep 17 00:00:00 2001 From: ThienLK1 Date: Tue, 8 Nov 2022 15:44:42 +0700 Subject: [PATCH 02/23] update readme --- packages/cw2-supported-interface/README.md | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/packages/cw2-supported-interface/README.md b/packages/cw2-supported-interface/README.md index b80c599a2..1012f81c5 100644 --- a/packages/cw2-supported-interface/README.md +++ b/packages/cw2-supported-interface/README.md @@ -45,6 +45,14 @@ pub struct ContractVersion { /// the only code that needs to understand the version parsing is code that knows how to /// migrate from the given contract (and is tied to it's implementation somehow) pub version: String, + /// supported_interface is an optional parameter returning a vector of string represents interfaces + /// that the contract support The string value is the interface crate names in Rust crate Registry. + /// This parameter is inspired by the EIP-165 from Ethereum. + /// Each string value should follow a common standard such as : + /// e.g ["crates.io:cw721","crates.io:cw2"] + /// NOTE: this is just a hint for the caller to adapt on how to interact with this contract. + /// There is no guarantee that the contract actually implement these interfaces. + pub supported_interface: Option>, } ``` @@ -53,6 +61,7 @@ Thus, an serialized example may looks like: ```json { "contract": "crates.io:cw20-base", - "version": "v0.1.0" + "version": "v0.1.0", + "supported_interface": ["crates.io:cw721","crates.io:cw2"] } ``` From 8ba749c396a414b259b2736a50c4b75babd9d39f Mon Sep 17 00:00:00 2001 From: ThienLK1 Date: Tue, 8 Nov 2022 15:56:08 +0700 Subject: [PATCH 03/23] add cargo.lock --- Cargo.lock | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/Cargo.lock b/Cargo.lock index d1cc452a8..b1f47c19f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -330,6 +330,17 @@ dependencies = [ "serde", ] +[[package]] +name = "cw2-supported-interface" +version = "1.0.0" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cw-storage-plus", + "schemars", + "serde", +] + [[package]] name = "cw20" version = "1.0.1" From 55d2aca64a2cb80d246c563abbfdaf050192f4fa Mon Sep 17 00:00:00 2001 From: ThienLK1 Date: Tue, 8 Nov 2022 17:17:06 +0700 Subject: [PATCH 04/23] fix lint --- packages/cw2-supported-interface/src/lib.rs | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/packages/cw2-supported-interface/src/lib.rs b/packages/cw2-supported-interface/src/lib.rs index a4e95aecc..bce5efd95 100644 --- a/packages/cw2-supported-interface/src/lib.rs +++ b/packages/cw2-supported-interface/src/lib.rs @@ -59,7 +59,7 @@ pub fn set_contract_version, U: Into>( let val = ContractVersion { contract: name.into(), version: version.into(), - supported_interface: supported_interface.into(), + supported_interface, }; CONTRACT.save(store, &val) } @@ -88,7 +88,6 @@ where mod tests { use super::*; use cosmwasm_std::testing::MockStorage; - use std::vec::Vec; #[test] fn get_and_set_work() { @@ -113,23 +112,18 @@ mod tests { // set and get with supported_interface let contract_name = "crate:cw20-base"; let contract_version = "0.2.0"; - let supported_interface = Some(Vec::from([ + let supported_interface: Option> = Some(Vec::from([ "crates.io:cw2".to_string(), "crates.io:cw721".to_string(), ])); - set_contract_version( - &mut store, - contract_name, - contract_version, - supported_interface.clone(), - ) - .unwrap(); + let v_ref = &supported_interface; + set_contract_version(&mut store, contract_name, contract_version, v_ref.clone()).unwrap(); let loaded = get_contract_version(&store).unwrap(); let expected = ContractVersion { contract: contract_name.to_string(), version: contract_version.to_string(), - supported_interface: supported_interface.clone(), + supported_interface: v_ref.clone(), }; assert_eq!(expected, loaded); } From 3d0f227b566dc779fb86911170e3d5b4cc3b5a0a Mon Sep 17 00:00:00 2001 From: ThienLK1 Date: Thu, 10 Nov 2022 14:05:23 +0700 Subject: [PATCH 05/23] add cw22 --- Cargo.lock | 22 +-- packages/cw2-supported-interface/src/lib.rs | 130 ------------------ .../.cargo/config | 0 .../Cargo.toml | 2 +- .../README.md | 20 +-- packages/cw22/src/lib.rs | 82 +++++++++++ 6 files changed, 98 insertions(+), 158 deletions(-) delete mode 100644 packages/cw2-supported-interface/src/lib.rs rename packages/{cw2-supported-interface => cw22}/.cargo/config (100%) rename packages/{cw2-supported-interface => cw22}/Cargo.toml (93%) rename packages/{cw2-supported-interface => cw22}/README.md (67%) create mode 100644 packages/cw22/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index b1f47c19f..9c3ee791e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -330,17 +330,6 @@ dependencies = [ "serde", ] -[[package]] -name = "cw2-supported-interface" -version = "1.0.0" -dependencies = [ - "cosmwasm-schema", - "cosmwasm-std", - "cw-storage-plus", - "schemars", - "serde", -] - [[package]] name = "cw20" version = "1.0.1" @@ -386,6 +375,17 @@ dependencies = [ "thiserror", ] +[[package]] +name = "cw22" +version = "1.0.0" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cw-storage-plus", + "schemars", + "serde", +] + [[package]] name = "cw3" version = "1.0.1" diff --git a/packages/cw2-supported-interface/src/lib.rs b/packages/cw2-supported-interface/src/lib.rs deleted file mode 100644 index bce5efd95..000000000 --- a/packages/cw2-supported-interface/src/lib.rs +++ /dev/null @@ -1,130 +0,0 @@ -/*! -Most of the CW* specs are focused on the *public interfaces* -of the contract. The APIs used for `ExecuteMsg` or `QueryMsg`. -However, when we wish to migrate or inspect smart contract info, -we need some form of smart contract information embedded on state. - -This is where CW2 comes in. It specifies a special Item to -be stored on disk by all contracts on `instantiate`. - -`ContractInfo` must be stored under the `"contract_info"` key which translates -to `"636F6E74726163745F696E666F"` in hex format. -Since the state is well defined, we do not need to support any "smart queries". -We do provide a helper to construct a "raw query" to read the ContractInfo -of any CW2-compliant contract. - -For more information on this specification, please check out the -[README](https://github.com/CosmWasm/cw-plus/blob/main/packages/cw2/README.md). -*/ - -use cosmwasm_schema::cw_serde; -use cosmwasm_std::{CustomQuery, QuerierWrapper, QueryRequest, StdResult, Storage, WasmQuery}; -use cw_storage_plus::Item; - -pub const CONTRACT: Item = Item::new("contract_info"); - -#[cw_serde] -pub struct ContractVersion { - /// contract is the crate name of the implementing contract, eg. `crate:cw20-base` - /// we will use other prefixes for other languages, and their standard global namespacing - pub contract: String, - /// version is any string that this implementation knows. It may be simple counter "1", "2". - /// or semantic version on release tags "v0.7.0", or some custom feature flag list. - /// the only code that needs to understand the version parsing is code that knows how to - /// migrate from the given contract (and is tied to it's implementation somehow) - pub version: String, - /// supported_interface is an optional parameter returning a vector of string represents interfaces - /// that the contract support The string value is the interface crate names in Rust crate Registry. - /// This parameter is inspired by the EIP-165 from Ethereum. - /// Each string value should follow a common standard such as : - /// e.g ["crates.io:cw721","crates.io:cw2"] - /// NOTE: this is just a hint for the caller to adapt on how to interact with this contract. - /// There is no guarantee that the contract actually implement these interfaces. - pub supported_interface: Option>, -} - -/// get_contract_version can be use in migrate to read the previous version of this contract -pub fn get_contract_version(store: &dyn Storage) -> StdResult { - CONTRACT.load(store) -} - -/// set_contract_version should be used in instantiate to store the original version, and after a successful -/// migrate to update it -pub fn set_contract_version, U: Into>( - store: &mut dyn Storage, - name: T, - version: U, - supported_interface: Option>, -) -> StdResult<()> { - let val = ContractVersion { - contract: name.into(), - version: version.into(), - supported_interface, - }; - CONTRACT.save(store, &val) -} - -/// This will make a raw_query to another contract to determine the current version it -/// claims to be. This should not be trusted, but could be used as a quick filter -/// if the other contract exists and claims to be a cw20-base contract for example. -/// (Note: you usually want to require *interfaces* not *implementations* of the -/// contracts you compose with, so be careful of overuse) -pub fn query_contract_info( - querier: &QuerierWrapper, - contract_addr: T, -) -> StdResult -where - T: Into, - CQ: CustomQuery, -{ - let req = QueryRequest::Wasm(WasmQuery::Raw { - contract_addr: contract_addr.into(), - key: CONTRACT.as_slice().into(), - }); - querier.query(&req) -} - -#[cfg(test)] -mod tests { - use super::*; - use cosmwasm_std::testing::MockStorage; - - #[test] - fn get_and_set_work() { - let mut store = MockStorage::new(); - - // error if not set - assert!(get_contract_version(&store).is_err()); - - // set and get - let contract_name = "crate:cw20-base"; - let contract_version = "0.2.0"; - set_contract_version(&mut store, contract_name, contract_version, None).unwrap(); - - let loaded = get_contract_version(&store).unwrap(); - let expected = ContractVersion { - contract: contract_name.to_string(), - version: contract_version.to_string(), - supported_interface: None, - }; - assert_eq!(expected, loaded); - - // set and get with supported_interface - let contract_name = "crate:cw20-base"; - let contract_version = "0.2.0"; - let supported_interface: Option> = Some(Vec::from([ - "crates.io:cw2".to_string(), - "crates.io:cw721".to_string(), - ])); - let v_ref = &supported_interface; - set_contract_version(&mut store, contract_name, contract_version, v_ref.clone()).unwrap(); - - let loaded = get_contract_version(&store).unwrap(); - let expected = ContractVersion { - contract: contract_name.to_string(), - version: contract_version.to_string(), - supported_interface: v_ref.clone(), - }; - assert_eq!(expected, loaded); - } -} diff --git a/packages/cw2-supported-interface/.cargo/config b/packages/cw22/.cargo/config similarity index 100% rename from packages/cw2-supported-interface/.cargo/config rename to packages/cw22/.cargo/config diff --git a/packages/cw2-supported-interface/Cargo.toml b/packages/cw22/Cargo.toml similarity index 93% rename from packages/cw2-supported-interface/Cargo.toml rename to packages/cw22/Cargo.toml index 25c737941..c84e48dc7 100644 --- a/packages/cw2-supported-interface/Cargo.toml +++ b/packages/cw22/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "cw2-supported-interface" +name = "cw22" version = "1.0.0" authors = ["ThienLK1@aura-nw"] edition = "2021" diff --git a/packages/cw2-supported-interface/README.md b/packages/cw22/README.md similarity index 67% rename from packages/cw2-supported-interface/README.md rename to packages/cw22/README.md index 1012f81c5..9f888722d 100644 --- a/packages/cw2-supported-interface/README.md +++ b/packages/cw22/README.md @@ -30,21 +30,11 @@ support multiple migrate paths. All CW2-compliant contracts must store the following data: -* key: `contract_info` -* data: Json-serialized `ContractVersion` +* key: `contract_supported_interface` +* data: Json-serialized `ContractSupportedInterface` ```rust -pub struct ContractVersion { - /// contract is a globally unique identifier for the contract. - /// it should build off standard namespacing for whichever language it is in, - /// and prefix it with the registry we use. - /// For rust we prefix with `crates.io:`, to give us eg. `crates.io:cw20-base` - pub contract: String, - /// version is any string that this implementation knows. It may be simple counter "1", "2". - /// or semantic version on release tags "v0.7.0", or some custom feature flag list. - /// the only code that needs to understand the version parsing is code that knows how to - /// migrate from the given contract (and is tied to it's implementation somehow) - pub version: String, +pub struct ContractSupportedInterface { /// supported_interface is an optional parameter returning a vector of string represents interfaces /// that the contract support The string value is the interface crate names in Rust crate Registry. /// This parameter is inspired by the EIP-165 from Ethereum. @@ -52,7 +42,7 @@ pub struct ContractVersion { /// e.g ["crates.io:cw721","crates.io:cw2"] /// NOTE: this is just a hint for the caller to adapt on how to interact with this contract. /// There is no guarantee that the contract actually implement these interfaces. - pub supported_interface: Option>, + pub supported_interface: Vec, } ``` @@ -60,8 +50,6 @@ Thus, an serialized example may looks like: ```json { - "contract": "crates.io:cw20-base", - "version": "v0.1.0", "supported_interface": ["crates.io:cw721","crates.io:cw2"] } ``` diff --git a/packages/cw22/src/lib.rs b/packages/cw22/src/lib.rs new file mode 100644 index 000000000..ffd54106d --- /dev/null +++ b/packages/cw22/src/lib.rs @@ -0,0 +1,82 @@ +/*! +Most of the CW* specs are focused on the *public interfaces* +of the contract. The APIs used for `ExecuteMsg` or `QueryMsg`. +However, when we wish to migrate or inspect smart contract info, +we need some form of smart contract information embedded on state. + +This is where CW2 comes in. It specifies a special Item to +be stored on disk by all contracts on `instantiate`. + +`ContractInfo` must be stored under the `"contract_info"` key which translates +to `"636F6E74726163745F696E666F"` in hex format. +Since the state is well defined, we do not need to support any "smart queries". +We do provide a helper to construct a "raw query" to read the ContractInfo +of any CW2-compliant contract. + +For more information on this specification, please check out the +[README](https://github.com/CosmWasm/cw-plus/blob/main/packages/cw22/README.md). +*/ + +use cosmwasm_schema::cw_serde; +use cosmwasm_std::{StdResult, Storage}; +use cw_storage_plus::Item; + +pub const CONTRACT: Item = Item::new("contract_supported_interface"); + +#[cw_serde] +pub struct ContractSupportedInterface { + /// supported_interface is an optional parameter returning a vector of string represents interfaces + /// that the contract support The string value is the interface crate names in Rust crate Registry. + /// This parameter is inspired by the EIP-165 from Ethereum. + /// Each string value should follow a common standard such as : + /// e.g ["crates.io:cw22","crates.io:cw2"] + /// NOTE: this is just a hint for the caller to adapt on how to interact with this contract. + /// There is no guarantee that the contract actually implement these interfaces. + pub supported_interface: Vec, +} + +/// get_contract_version can be use in migrate to read the previous version of this contract +pub fn get_contract_supported_interface( + store: &dyn Storage, +) -> StdResult { + CONTRACT.load(store) +} + +/// set_contract_version should be used in instantiate to store the original version, and after a successful +/// migrate to update it +pub fn set_contract_supported_interface( + store: &mut dyn Storage, + supported_interface: Vec, +) -> StdResult<()> { + let val = ContractSupportedInterface { + supported_interface, + }; + CONTRACT.save(store, &val) +} + +#[cfg(test)] +mod tests { + use super::*; + use cosmwasm_std::testing::MockStorage; + + #[test] + fn get_and_set_work() { + let mut store = MockStorage::new(); + + // error if not set + assert!(get_contract_supported_interface(&store).is_err()); + + // set and get with supported_interface + let supported_interface: Vec = + Vec::from(["crates.io:cw2".to_string(), "crates.io:cw22".to_string()]); + + let v_ref = &supported_interface; + set_contract_supported_interface(&mut store, v_ref.clone()).unwrap(); + + let loaded = get_contract_supported_interface(&store).unwrap(); + let expected = ContractSupportedInterface { + supported_interface: v_ref.clone(), + }; + assert_eq!(expected, loaded); + } +} From 5b4275dc6c6271f8478281fee0ff819228546a55 Mon Sep 17 00:00:00 2001 From: ThienLK1 Date: Thu, 10 Nov 2022 14:53:18 +0700 Subject: [PATCH 06/23] update README.md --- packages/cw22/README.md | 30 ++++++------------------------ packages/cw22/src/lib.rs | 15 ++------------- 2 files changed, 8 insertions(+), 37 deletions(-) diff --git a/packages/cw22/README.md b/packages/cw22/README.md index 9f888722d..47afbd5e2 100644 --- a/packages/cw22/README.md +++ b/packages/cw22/README.md @@ -1,34 +1,16 @@ -# CW2 Spec: Contract Info +# CW22 Spec: Contract Info -Most of the CW* specs are focused on the *public interfaces* -of the contract. The APIs used for `ExecuteMsg` or `QueryMsg`. -However, when we wish to migrate or inspect smart contract info, -we need some form of smart contract information embedded on state. +The standard used to declare which interface contract implements +This standard is inspired by the EIP-165 from Ethereum. -This is where CW2 comes in. It specifies a special Item to -be stored on disk by all contracts on `instantiate`. - -`ContractInfo` must be stored under the `"contract_info"` key which translates -to `"636F6E74726163745F696E666F"` in hex format. -Since the state is well defined, we do not need to support any "smart queries". -We do provide a helper to construct a "raw query" to read the ContractInfo -of any CW2-compliant contract. - -You can query using: -```shell -wasmd query wasm contract-state raw [contract_addr] 636F6E74726163745F696E666F --node $RPC -``` - -When the `migrate` function is called, then the new contract -can read that data andsee if this is an expected contract we can -migrate from. And also contain extra version information if we -support multiple migrate paths. +For more information on this specification, please check out the +[README](https://github.com/CosmWasm/cw-plus/blob/main/packages/cw22/README.md). ### Data structures **Required** -All CW2-compliant contracts must store the following data: +All CW22-compliant contracts must store the following data: * key: `contract_supported_interface` * data: Json-serialized `ContractSupportedInterface` diff --git a/packages/cw22/src/lib.rs b/packages/cw22/src/lib.rs index ffd54106d..14b86a37d 100644 --- a/packages/cw22/src/lib.rs +++ b/packages/cw22/src/lib.rs @@ -1,17 +1,6 @@ /*! -Most of the CW* specs are focused on the *public interfaces* -of the contract. The APIs used for `ExecuteMsg` or `QueryMsg`. -However, when we wish to migrate or inspect smart contract info, -we need some form of smart contract information embedded on state. - -This is where CW2 comes in. It specifies a special Item to -be stored on disk by all contracts on `instantiate`. - -`ContractInfo` must be stored under the `"contract_info"` key which translates -to `"636F6E74726163745F696E666F"` in hex format. -Since the state is well defined, we do not need to support any "smart queries". -We do provide a helper to construct a "raw query" to read the ContractInfo -of any CW2-compliant contract. +The standard used to declare which interface contract implements +This standard is inspired by the EIP-165 from Ethereum. For more information on this specification, please check out the [README](https://github.com/CosmWasm/cw-plus/blob/main/packages/cw22/README.md). From a868481f7cc36c3eb0690bed2a08e2a24e836904 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thi=E1=BB=87n?= <42140277+ThienLK1@users.noreply.github.com> Date: Thu, 10 Nov 2022 15:05:37 +0700 Subject: [PATCH 07/23] Update README.md --- packages/cw22/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/cw22/README.md b/packages/cw22/README.md index 47afbd5e2..61a304b6e 100644 --- a/packages/cw22/README.md +++ b/packages/cw22/README.md @@ -1,6 +1,6 @@ # CW22 Spec: Contract Info -The standard used to declare which interface contract implements +The standard used to declare which interface contract implements. This standard is inspired by the EIP-165 from Ethereum. For more information on this specification, please check out the From 719ff728281a8e95ef54362fbb97f4518c63cfeb Mon Sep 17 00:00:00 2001 From: ThienLK1 Date: Fri, 18 Nov 2022 15:20:43 +0700 Subject: [PATCH 08/23] add cw22 - define version of supported interface --- Cargo.lock | 11 --- packages/cw22/Cargo.toml | 3 + packages/cw22/src/error.rs | 14 ++++ packages/cw22/src/lib.rs | 150 ++++++++++++++++++++++++++++++------- packages/cw22/src/query.rs | 10 +++ 5 files changed, 151 insertions(+), 37 deletions(-) create mode 100644 packages/cw22/src/error.rs create mode 100644 packages/cw22/src/query.rs diff --git a/Cargo.lock b/Cargo.lock index 9c3ee791e..d1cc452a8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -375,17 +375,6 @@ dependencies = [ "thiserror", ] -[[package]] -name = "cw22" -version = "1.0.0" -dependencies = [ - "cosmwasm-schema", - "cosmwasm-std", - "cw-storage-plus", - "schemars", - "serde", -] - [[package]] name = "cw3" version = "1.0.1" diff --git a/packages/cw22/Cargo.toml b/packages/cw22/Cargo.toml index c84e48dc7..261bcc149 100644 --- a/packages/cw22/Cargo.toml +++ b/packages/cw22/Cargo.toml @@ -14,3 +14,6 @@ cosmwasm-std = { version = "1.0.0", default-features = false } cw-storage-plus = "0.16.0" schemars = "0.8.1" serde = { version = "1.0.0", default-features = false, features = ["derive"] } +thiserror = { version = "1.0.23" } +version-compare = "0.1" +semver = "1.0.14" diff --git a/packages/cw22/src/error.rs b/packages/cw22/src/error.rs new file mode 100644 index 000000000..9df4de571 --- /dev/null +++ b/packages/cw22/src/error.rs @@ -0,0 +1,14 @@ +use cosmwasm_std::StdError; +use thiserror::Error; + +#[derive(Error, Debug, PartialEq)] +pub enum ContractError { + #[error("{0}")] + Std(#[from] StdError), + + #[error("Supported Interface must be more than zero")] + SupportedInterfaceMustBeMoreThanZero {}, + + #[error("Contract does not support this interface")] + ContractDoesNotSupportThisInterface {}, +} diff --git a/packages/cw22/src/lib.rs b/packages/cw22/src/lib.rs index 14b86a37d..426903aa4 100644 --- a/packages/cw22/src/lib.rs +++ b/packages/cw22/src/lib.rs @@ -4,13 +4,19 @@ This standard is inspired by the EIP-165 from Ethereum. For more information on this specification, please check out the [README](https://github.com/CosmWasm/cw-plus/blob/main/packages/cw22/README.md). -*/ + */ +mod error; +mod query; + +use crate::error::ContractError; use cosmwasm_schema::cw_serde; use cosmwasm_std::{StdResult, Storage}; -use cw_storage_plus::Item; +use cw_storage_plus::Map; +use query::VersionResponse; +use semver::{Version, VersionReq}; -pub const CONTRACT: Item = Item::new("contract_supported_interface"); +pub const SUPPORTED_INTERFACES: Map = Map::new("supported_interfaces"); #[cw_serde] pub struct ContractSupportedInterface { @@ -18,29 +24,67 @@ pub struct ContractSupportedInterface { /// that the contract support The string value is the interface crate names in Rust crate Registry. /// This parameter is inspired by the EIP-165 from Ethereum. /// Each string value should follow a common standard such as : - /// e.g ["crates.io:cw22","crates.io:cw2"] + /// e.g "crates.io:cw2" /// NOTE: this is just a hint for the caller to adapt on how to interact with this contract. /// There is no guarantee that the contract actually implement these interfaces. - pub supported_interface: Vec, + pub supported_interface: String, + /// semantic version on release tags. + /// e.g "v0.16.0" + pub version: String, +} + +/// set_contract_supported_interface should be used in instantiate to store the original version +pub fn set_contract_supported_interface( + store: &mut dyn Storage, + mut supported_interfaces: Vec, +) -> Result<(), ContractError> { + while let Some(supported_interface) = supported_interfaces.pop() { + let id = supported_interface.supported_interface; + let version = supported_interface.version; + SUPPORTED_INTERFACES.save(store, id, &version)?; + } + Ok(()) } -/// get_contract_version can be use in migrate to read the previous version of this contract -pub fn get_contract_supported_interface( +/// query_supported_interface_version show if contract supports interface and which version +pub fn query_supported_interface_version( store: &dyn Storage, + interface: String, ) -> StdResult { - CONTRACT.load(store) + let version = SUPPORTED_INTERFACES + .may_load(store, interface.clone())? + .unwrap_or_default(); + let res = ContractSupportedInterface { + supported_interface: interface, + version, + }; + Ok(res) } -/// set_contract_version should be used in instantiate to store the original version, and after a successful -/// migrate to update it -pub fn set_contract_supported_interface( - store: &mut dyn Storage, - supported_interface: Vec, -) -> StdResult<()> { - let val = ContractSupportedInterface { - supported_interface, - }; - CONTRACT.save(store, &val) +/// query_supported_interface show if contract supports interface with specified version +/// query example">=1.2.3, <1.8.0" +pub fn query_supported_interface( + store: &dyn Storage, + interface: String, + query: String, +) -> StdResult { + let req = VersionReq::parse(&query).unwrap(); + let supported_version_rs = SUPPORTED_INTERFACES + .may_load(store, interface)? + .unwrap_or_default(); + let supported_version = Version::parse(&supported_version_rs); + match supported_version { + Ok(ver) => Ok(VersionResponse { + version_require: query, + supported_version: supported_version_rs, + result: req.matches(&ver), + }), + Err(_) => Ok(VersionResponse { + version_require: query, + supported_version: supported_version_rs, + result: false, + }), + } } #[cfg(test)] @@ -52,20 +96,74 @@ mod tests { fn get_and_set_work() { let mut store = MockStorage::new(); - // error if not set - assert!(get_contract_supported_interface(&store).is_err()); + let interface = "crates.io:cw2"; + let interface2 = "crates.io:cw22"; + let contract_interface = ContractSupportedInterface { + supported_interface: String::from(interface), + version: String::from("0.16.0"), + }; + let contract_interface2 = ContractSupportedInterface { + supported_interface: String::from(interface2), + version: String::from("0.1.0"), + }; // set and get with supported_interface - let supported_interface: Vec = - Vec::from(["crates.io:cw2".to_string(), "crates.io:cw22".to_string()]); + let supported_interface: Vec = + Vec::from([contract_interface, contract_interface2]); + + set_contract_supported_interface(&mut store, supported_interface).unwrap(); - let v_ref = &supported_interface; - set_contract_supported_interface(&mut store, v_ref.clone()).unwrap(); + // get version of not supported interface + let loaded = + query_supported_interface_version(&store, "crates.io:cw721".to_string()).unwrap(); + let expected = ContractSupportedInterface { + supported_interface: "crates.io:cw721".to_string(), + version: "".to_string(), + }; + assert_eq!(expected, loaded); - let loaded = get_contract_supported_interface(&store).unwrap(); + // get version of supported interface + let loaded = + query_supported_interface_version(&store, "crates.io:cw2".to_string()).unwrap(); let expected = ContractSupportedInterface { - supported_interface: v_ref.clone(), + supported_interface: "crates.io:cw2".to_string(), + version: "0.16.0".to_string(), }; assert_eq!(expected, loaded); + + // check specified version of not supported interface + let version_req = ">=0.1.0".to_string(); + let result = + query_supported_interface(&store, "crates.io:cw721".to_string(), version_req.clone()) + .unwrap(); + let expected = VersionResponse { + version_require: version_req, + supported_version: "".to_string(), + result: false, + }; + assert_eq!(expected, result); + + // check specified version of supported interface + let version_req = ">=1.2.3, <1.8.0".to_string(); + let result = + query_supported_interface(&store, "crates.io:cw2".to_string(), version_req.clone()) + .unwrap(); + let expected = VersionResponse { + version_require: version_req, + supported_version: "0.16.0".to_string(), + result: false, + }; + assert_eq!(expected, result); + + let version_req = ">=0.1.0".to_string(); + let result = + query_supported_interface(&store, "crates.io:cw2".to_string(), version_req.clone()) + .unwrap(); + let expected = VersionResponse { + version_require: version_req, + supported_version: "0.16.0".to_string(), + result: true, + }; + assert_eq!(expected, result); } } diff --git a/packages/cw22/src/query.rs b/packages/cw22/src/query.rs new file mode 100644 index 000000000..61e264233 --- /dev/null +++ b/packages/cw22/src/query.rs @@ -0,0 +1,10 @@ +// use cosmwasm_schema::cw_serde; +// use cosmwasm_std::{Uint128}; + +// #[cw_serde] +#[derive(Debug, PartialEq)] +pub struct VersionResponse { + pub version_require: String, + pub supported_version: String, + pub result: bool, +} From c774fb8b9a9375a360716a5a05411a8ed44a0e46 Mon Sep 17 00:00:00 2001 From: ThienLK1 Date: Fri, 18 Nov 2022 15:24:44 +0700 Subject: [PATCH 09/23] add cw22 - define version of supported interface --- packages/cw22/src/error.rs | 14 -------------- packages/cw22/src/lib.rs | 5 ++--- 2 files changed, 2 insertions(+), 17 deletions(-) delete mode 100644 packages/cw22/src/error.rs diff --git a/packages/cw22/src/error.rs b/packages/cw22/src/error.rs deleted file mode 100644 index 9df4de571..000000000 --- a/packages/cw22/src/error.rs +++ /dev/null @@ -1,14 +0,0 @@ -use cosmwasm_std::StdError; -use thiserror::Error; - -#[derive(Error, Debug, PartialEq)] -pub enum ContractError { - #[error("{0}")] - Std(#[from] StdError), - - #[error("Supported Interface must be more than zero")] - SupportedInterfaceMustBeMoreThanZero {}, - - #[error("Contract does not support this interface")] - ContractDoesNotSupportThisInterface {}, -} diff --git a/packages/cw22/src/lib.rs b/packages/cw22/src/lib.rs index 426903aa4..d8cffe1cd 100644 --- a/packages/cw22/src/lib.rs +++ b/packages/cw22/src/lib.rs @@ -6,11 +6,10 @@ For more information on this specification, please check out the [README](https://github.com/CosmWasm/cw-plus/blob/main/packages/cw22/README.md). */ -mod error; mod query; -use crate::error::ContractError; use cosmwasm_schema::cw_serde; +use cosmwasm_std::StdError; use cosmwasm_std::{StdResult, Storage}; use cw_storage_plus::Map; use query::VersionResponse; @@ -37,7 +36,7 @@ pub struct ContractSupportedInterface { pub fn set_contract_supported_interface( store: &mut dyn Storage, mut supported_interfaces: Vec, -) -> Result<(), ContractError> { +) -> Result<(), StdError> { while let Some(supported_interface) = supported_interfaces.pop() { let id = supported_interface.supported_interface; let version = supported_interface.version; From 80697a1eea65df5c8dc619d5c3824e6b2427b46f Mon Sep 17 00:00:00 2001 From: ThienLK1 Date: Fri, 18 Nov 2022 15:42:12 +0700 Subject: [PATCH 10/23] fix lint --- packages/cw22/src/query.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/packages/cw22/src/query.rs b/packages/cw22/src/query.rs index 61e264233..2fb6e3c09 100644 --- a/packages/cw22/src/query.rs +++ b/packages/cw22/src/query.rs @@ -1,8 +1,6 @@ -// use cosmwasm_schema::cw_serde; -// use cosmwasm_std::{Uint128}; +use cosmwasm_schema::cw_serde; -// #[cw_serde] -#[derive(Debug, PartialEq)] +#[cw_serde] pub struct VersionResponse { pub version_require: String, pub supported_version: String, From c3f5a4170b6bbae400a15de1abe6d54db313cb28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thi=E1=BB=87n?= <42140277+ThienLK1@users.noreply.github.com> Date: Tue, 22 Nov 2022 10:23:17 +0700 Subject: [PATCH 11/23] Updated config.yml --- .circleci/config.yml | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index 1e434e445..1a3caf0c6 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -21,6 +21,7 @@ workflows: - package_cw3 - package_cw4 - package_cw20 + - package_cw22 - lint - wasm-build - coverage @@ -419,6 +420,34 @@ jobs: - target key: cargocache-v2-cw20:1.64.0-{{ checksum "~/project/Cargo.lock" }} + package_cw22: + docker: + - image: rust:1.64.0 + working_directory: ~/project/packages/cw22 + steps: + - checkout: + path: ~/project + - run: + name: Version information + command: rustc --version; cargo --version; rustup --version; rustup target list --installed + - restore_cache: + keys: + - cargocache-v2-cw22:1.64.0-{{ checksum "~/project/Cargo.lock" }} + - run: + name: Build library for native target + command: cargo build --locked + - run: + name: Run unit tests + command: cargo test --locked + - run: + name: Build and run schema generator + command: cargo schema --locked + - save_cache: + paths: + - /usr/local/cargo/registry + - target + key: cargocache-v2-cw22:1.64.0-{{ checksum "~/project/Cargo.lock" }} + package_cw1155: docker: - image: rust:1.64.0 From e42a428a80358c430bc4facc4cfcfd50ee90204b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thi=E1=BB=87n?= <42140277+ThienLK1@users.noreply.github.com> Date: Tue, 22 Nov 2022 10:27:27 +0700 Subject: [PATCH 12/23] Updated config.yml --- .circleci/config.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 1a3caf0c6..300e4b8a8 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -439,9 +439,6 @@ jobs: - run: name: Run unit tests command: cargo test --locked - - run: - name: Build and run schema generator - command: cargo schema --locked - save_cache: paths: - /usr/local/cargo/registry From c072201f51afea336b9b455a58c32a46bdd09dea Mon Sep 17 00:00:00 2001 From: ThienLK1 Date: Tue, 22 Nov 2022 10:33:21 +0700 Subject: [PATCH 13/23] remove unused dependencies --- packages/cw22/Cargo.toml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/cw22/Cargo.toml b/packages/cw22/Cargo.toml index 261bcc149..01b4e2f38 100644 --- a/packages/cw22/Cargo.toml +++ b/packages/cw22/Cargo.toml @@ -3,7 +3,7 @@ name = "cw22" version = "1.0.0" authors = ["ThienLK1@aura-nw"] edition = "2021" -description = "Definition and types for the CosmWasm-2 interface" +description = "Definition and types for the CosmWasm-22 interface" license = "Apache-2.0" repository = "https://github.com/CosmWasm/cw-plus" homepage = "https://cosmwasm.com" @@ -14,6 +14,4 @@ cosmwasm-std = { version = "1.0.0", default-features = false } cw-storage-plus = "0.16.0" schemars = "0.8.1" serde = { version = "1.0.0", default-features = false, features = ["derive"] } -thiserror = { version = "1.0.23" } -version-compare = "0.1" semver = "1.0.14" From af031e3b595c73d1b5f971bdc15655cdc2e262c2 Mon Sep 17 00:00:00 2001 From: eledra89 Date: Mon, 28 Nov 2022 17:10:44 +0700 Subject: [PATCH 14/23] Add comments --- packages/cw22/src/lib.rs | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/packages/cw22/src/lib.rs b/packages/cw22/src/lib.rs index d8cffe1cd..4512080da 100644 --- a/packages/cw22/src/lib.rs +++ b/packages/cw22/src/lib.rs @@ -1,9 +1,15 @@ /*! -The standard used to declare which interface contract implements -This standard is inspired by the EIP-165 from Ethereum. +CW22 defines a way for a contract to declare which interfaces do the contract implement +This standard is inspired by the EIP-165 from Ethereum. Originally it was proposed to +be merged into CW2: Contract Info, then it is splitted to a separated cargo to keep CW2 +being backward compatible. -For more information on this specification, please check out the -[README](https://github.com/CosmWasm/cw-plus/blob/main/packages/cw22/README.md). +Each supported interface contains a string value pointing to the corresponding cargo package +and a specific release of the package. There is also a function to check whether the contract +support a specific version of an interface or not. + +The version string for each interface follows Semantic Versioning standard. More info is in: +https://docs.rs/semver/latest/semver/ */ mod query; @@ -27,12 +33,13 @@ pub struct ContractSupportedInterface { /// NOTE: this is just a hint for the caller to adapt on how to interact with this contract. /// There is no guarantee that the contract actually implement these interfaces. pub supported_interface: String, - /// semantic version on release tags. - /// e.g "v0.16.0" + /// semantic version on release tags of the interface package following SemVer guideline. + /// e.g "0.16.0" pub version: String, } -/// set_contract_supported_interface should be used in instantiate to store the original version +/// set_contract_supported_interface should be used in instantiate to store the original version +/// of supported interfaces. It should also be used after every migration. pub fn set_contract_supported_interface( store: &mut dyn Storage, mut supported_interfaces: Vec, @@ -45,7 +52,7 @@ pub fn set_contract_supported_interface( Ok(()) } -/// query_supported_interface_version show if contract supports interface and which version +/// query_supported_interface_version show the version of an interface supported by the contract pub fn query_supported_interface_version( store: &dyn Storage, interface: String, @@ -60,7 +67,7 @@ pub fn query_supported_interface_version( Ok(res) } -/// query_supported_interface show if contract supports interface with specified version +/// query_supported_interface show if contract supports an interface with version following SemVer query /// query example">=1.2.3, <1.8.0" pub fn query_supported_interface( store: &dyn Storage, From 67a913c57aab53fcfabd77855f28b650a205784f Mon Sep 17 00:00:00 2001 From: eledra89 Date: Mon, 28 Nov 2022 17:19:20 +0700 Subject: [PATCH 15/23] Fix lint --- packages/cw22/src/lib.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/cw22/src/lib.rs b/packages/cw22/src/lib.rs index 4512080da..bccda4540 100644 --- a/packages/cw22/src/lib.rs +++ b/packages/cw22/src/lib.rs @@ -1,16 +1,16 @@ /*! CW22 defines a way for a contract to declare which interfaces do the contract implement -This standard is inspired by the EIP-165 from Ethereum. Originally it was proposed to +This standard is inspired by the EIP-165 from Ethereum. Originally it was proposed to be merged into CW2: Contract Info, then it is splitted to a separated cargo to keep CW2 -being backward compatible. +being backward compatible. -Each supported interface contains a string value pointing to the corresponding cargo package +Each supported interface contains a string value pointing to the corresponding cargo package and a specific release of the package. There is also a function to check whether the contract support a specific version of an interface or not. The version string for each interface follows Semantic Versioning standard. More info is in: https://docs.rs/semver/latest/semver/ - */ +*/ mod query; @@ -38,7 +38,7 @@ pub struct ContractSupportedInterface { pub version: String, } -/// set_contract_supported_interface should be used in instantiate to store the original version +/// set_contract_supported_interface should be used in instantiate to store the original version /// of supported interfaces. It should also be used after every migration. pub fn set_contract_supported_interface( store: &mut dyn Storage, From 99ee3211f3640880f426e3c0575e0fe38336de75 Mon Sep 17 00:00:00 2001 From: ThienLK1 Date: Fri, 2 Dec 2022 14:17:55 +0700 Subject: [PATCH 16/23] add minimum_version & require_version --- packages/cw22/Cargo.toml | 1 + packages/cw22/README.md | 29 ++--- packages/cw22/src/error.rs | 11 ++ packages/cw22/src/lib.rs | 224 ++++++++++++++++++++----------------- packages/cw22/src/query.rs | 8 -- 5 files changed, 146 insertions(+), 127 deletions(-) create mode 100644 packages/cw22/src/error.rs delete mode 100644 packages/cw22/src/query.rs diff --git a/packages/cw22/Cargo.toml b/packages/cw22/Cargo.toml index 01b4e2f38..6e3857050 100644 --- a/packages/cw22/Cargo.toml +++ b/packages/cw22/Cargo.toml @@ -15,3 +15,4 @@ cw-storage-plus = "0.16.0" schemars = "0.8.1" serde = { version = "1.0.0", default-features = false, features = ["derive"] } semver = "1.0.14" +thiserror = { version = "1.0.23" } diff --git a/packages/cw22/README.md b/packages/cw22/README.md index 61a304b6e..2edb8248b 100644 --- a/packages/cw22/README.md +++ b/packages/cw22/README.md @@ -1,6 +1,6 @@ # CW22 Spec: Contract Info -The standard used to declare which interface contract implements. +The standard used to declare which interface contract implements. This standard is inspired by the EIP-165 from Ethereum. For more information on this specification, please check out the @@ -17,21 +17,16 @@ All CW22-compliant contracts must store the following data: ```rust pub struct ContractSupportedInterface { - /// supported_interface is an optional parameter returning a vector of string represents interfaces - /// that the contract support The string value is the interface crate names in Rust crate Registry. - /// This parameter is inspired by the EIP-165 from Ethereum. - /// Each string value should follow a common standard such as : - /// e.g ["crates.io:cw721","crates.io:cw2"] - /// NOTE: this is just a hint for the caller to adapt on how to interact with this contract. - /// There is no guarantee that the contract actually implement these interfaces. - pub supported_interface: Vec, -} -``` - -Thus, an serialized example may looks like: - -```json -{ - "supported_interface": ["crates.io:cw721","crates.io:cw2"] + /// supported_interface is an optional parameter returning a vector of string represents interfaces + /// that the contract support The string value is the interface crate names in Rust crate Registry. + /// This parameter is inspired by the EIP-165 from Ethereum. + /// Each string value should follow a common standard such as : + /// e.g "crates.io:cw2" + /// NOTE: this is just a hint for the caller to adapt on how to interact with this contract. + /// There is no guarantee that the contract actually implement these interfaces. + pub supported_interface: String, + /// semantic version on release tags of the interface package following SemVer guideline. + /// e.g "0.16.0" + pub version: String, } ``` diff --git a/packages/cw22/src/error.rs b/packages/cw22/src/error.rs new file mode 100644 index 000000000..7bfb9a0c0 --- /dev/null +++ b/packages/cw22/src/error.rs @@ -0,0 +1,11 @@ +use cosmwasm_std::StdError; +use thiserror::Error; + +#[derive(Error, Debug, PartialEq)] +pub enum ContractError { + #[error("{0}")] + Std(#[from] StdError), + + #[error("Version's format is invalid")] + InvalidVersionFormat {}, +} diff --git a/packages/cw22/src/lib.rs b/packages/cw22/src/lib.rs index bccda4540..08625c658 100644 --- a/packages/cw22/src/lib.rs +++ b/packages/cw22/src/lib.rs @@ -10,18 +10,16 @@ support a specific version of an interface or not. The version string for each interface follows Semantic Versioning standard. More info is in: https://docs.rs/semver/latest/semver/ -*/ - -mod query; + */ +mod error; +use crate::error::ContractError; use cosmwasm_schema::cw_serde; -use cosmwasm_std::StdError; use cosmwasm_std::{StdResult, Storage}; use cw_storage_plus::Map; -use query::VersionResponse; use semver::{Version, VersionReq}; -pub const SUPPORTED_INTERFACES: Map = Map::new("supported_interfaces"); +pub const SUPPORTED_INTERFACES: Map<&str, String> = Map::new("supported_interfaces"); #[cw_serde] pub struct ContractSupportedInterface { @@ -42,12 +40,18 @@ pub struct ContractSupportedInterface { /// of supported interfaces. It should also be used after every migration. pub fn set_contract_supported_interface( store: &mut dyn Storage, - mut supported_interfaces: Vec, -) -> Result<(), StdError> { - while let Some(supported_interface) = supported_interfaces.pop() { - let id = supported_interface.supported_interface; - let version = supported_interface.version; - SUPPORTED_INTERFACES.save(store, id, &version)?; + supported_interfaces: &[ContractSupportedInterface], +) -> Result<(), ContractError> { + for item in supported_interfaces { + let ver = Version::parse(&item.version); + match ver { + Ok(_) => { + SUPPORTED_INTERFACES.save(store, &item.supported_interface, &item.version)?; + } + Err(_) => { + return Err(ContractError::InvalidVersionFormat {}); + } + } } Ok(()) } @@ -55,42 +59,50 @@ pub fn set_contract_supported_interface( /// query_supported_interface_version show the version of an interface supported by the contract pub fn query_supported_interface_version( store: &dyn Storage, - interface: String, -) -> StdResult { - let version = SUPPORTED_INTERFACES - .may_load(store, interface.clone())? - .unwrap_or_default(); - let res = ContractSupportedInterface { - supported_interface: interface, - version, + interface: &str, +) -> StdResult> { + let version = SUPPORTED_INTERFACES.may_load(store, interface)?; + Ok(version) +} + +pub fn minimum_version(version: &str, required: &str) -> bool { + let mut req_str = ">=".to_owned(); + req_str.push_str(required); + let req = VersionReq::parse(req_str.as_str()); + let req = match req { + Ok(r) => r, + Err(_) => { + return false; + } }; - Ok(res) + let ver = Version::parse(version); + let ver = match ver { + Ok(v) => v, + Err(_) => { + return false; + } + }; + req.matches(&ver) } /// query_supported_interface show if contract supports an interface with version following SemVer query /// query example">=1.2.3, <1.8.0" -pub fn query_supported_interface( - store: &dyn Storage, - interface: String, - query: String, -) -> StdResult { - let req = VersionReq::parse(&query).unwrap(); - let supported_version_rs = SUPPORTED_INTERFACES - .may_load(store, interface)? - .unwrap_or_default(); - let supported_version = Version::parse(&supported_version_rs); - match supported_version { - Ok(ver) => Ok(VersionResponse { - version_require: query, - supported_version: supported_version_rs, - result: req.matches(&ver), - }), - Err(_) => Ok(VersionResponse { - version_require: query, - supported_version: supported_version_rs, - result: false, - }), - } +pub fn require_version(version: &str, request: &str) -> bool { + let req = VersionReq::parse(request); + let req = match req { + Ok(r) => r, + Err(_) => { + return false; + } + }; + let ver = Version::parse(version); + let ver = match ver { + Ok(v) => v, + Err(_) => { + return false; + } + }; + req.matches(&ver) } #[cfg(test)] @@ -102,74 +114,82 @@ mod tests { fn get_and_set_work() { let mut store = MockStorage::new(); - let interface = "crates.io:cw2"; - let interface2 = "crates.io:cw22"; - let contract_interface = ContractSupportedInterface { - supported_interface: String::from(interface), - version: String::from("0.16.0"), - }; + let interface2 = "crates.io:cw2"; + let interface22 = "crates.io:cw22"; + let interface721 = "crates.io:cw721"; let contract_interface2 = ContractSupportedInterface { supported_interface: String::from(interface2), + version: String::from("0.16.0"), + }; + let contract_interface22 = ContractSupportedInterface { + supported_interface: String::from(interface22), version: String::from("0.1.0"), }; + let contract_interface721 = ContractSupportedInterface { + supported_interface: String::from(interface22), + version: String::from("v0.1.0"), + }; - // set and get with supported_interface - let supported_interface: Vec = - Vec::from([contract_interface, contract_interface2]); + // set supported_interface error + let supported_interface = &[contract_interface721]; - set_contract_supported_interface(&mut store, supported_interface).unwrap(); + let rs_error = + set_contract_supported_interface(&mut store, supported_interface).unwrap_err(); + let expected = ContractError::InvalidVersionFormat {}; + assert_eq!(expected, rs_error); + // set supported_interface + let supported_interface = &[contract_interface2, contract_interface22]; + + set_contract_supported_interface(&mut store, supported_interface).unwrap(); // get version of not supported interface - let loaded = - query_supported_interface_version(&store, "crates.io:cw721".to_string()).unwrap(); - let expected = ContractSupportedInterface { - supported_interface: "crates.io:cw721".to_string(), - version: "".to_string(), - }; - assert_eq!(expected, loaded); + let loaded = query_supported_interface_version(&store, interface721).unwrap(); + assert_eq!(None, loaded); // get version of supported interface - let loaded = - query_supported_interface_version(&store, "crates.io:cw2".to_string()).unwrap(); - let expected = ContractSupportedInterface { - supported_interface: "crates.io:cw2".to_string(), - version: "0.16.0".to_string(), - }; - assert_eq!(expected, loaded); - - // check specified version of not supported interface - let version_req = ">=0.1.0".to_string(); - let result = - query_supported_interface(&store, "crates.io:cw721".to_string(), version_req.clone()) - .unwrap(); - let expected = VersionResponse { - version_require: version_req, - supported_version: "".to_string(), - result: false, - }; - assert_eq!(expected, result); - - // check specified version of supported interface - let version_req = ">=1.2.3, <1.8.0".to_string(); - let result = - query_supported_interface(&store, "crates.io:cw2".to_string(), version_req.clone()) - .unwrap(); - let expected = VersionResponse { - version_require: version_req, - supported_version: "0.16.0".to_string(), - result: false, - }; - assert_eq!(expected, result); - - let version_req = ">=0.1.0".to_string(); - let result = - query_supported_interface(&store, "crates.io:cw2".to_string(), version_req.clone()) - .unwrap(); - let expected = VersionResponse { - version_require: version_req, - supported_version: "0.16.0".to_string(), - result: true, - }; - assert_eq!(expected, result); + let loaded = query_supported_interface_version(&store, interface2).unwrap(); + let expected = String::from("0.16.0"); + assert_eq!(Some(expected), loaded); + + // check request version + let version_req = ">=0.1.0"; + let result = require_version("0.16.0", version_req); + assert!(result); + + // check request version + let version_req = ">=0.16.0"; + let result = require_version("0.1.0", version_req); + assert!(!result); + + // check request version + let version_req = ">=1.2.3, <1.8.0"; + let result = require_version("0.16.0", version_req); + assert!(!result); + + // check request version - version format invalid + let version_req = ">=0.2.3"; + let result = require_version("v0.16.0", version_req); + assert!(!result); + + // check require version - require version invalid + let version_req = "!=0.2.3"; + let result = require_version("0.16.0", version_req); + assert!(!result); + + // check minimum version + let result = minimum_version("0.16.0", "0.2.3"); + assert!(result); + + // check minimum version + let result = minimum_version("0.2.0", "0.2.3"); + assert!(!result); + + // check minimum version - version format error + let result = minimum_version("v0.16.0", "0.2.3"); + assert!(!result); + + // check minimum version - require version format error + let result = minimum_version("0.16.0", "v0.2.3"); + assert!(!result); } } diff --git a/packages/cw22/src/query.rs b/packages/cw22/src/query.rs deleted file mode 100644 index 2fb6e3c09..000000000 --- a/packages/cw22/src/query.rs +++ /dev/null @@ -1,8 +0,0 @@ -use cosmwasm_schema::cw_serde; - -#[cw_serde] -pub struct VersionResponse { - pub version_require: String, - pub supported_version: String, - pub result: bool, -} From a07ac76a4cc6a900ab5885f2924ba5801e0111a8 Mon Sep 17 00:00:00 2001 From: ThienLK1 Date: Fri, 2 Dec 2022 15:29:19 +0700 Subject: [PATCH 17/23] add minimum_version & require_version --- packages/cw22/Cargo.toml | 2 +- packages/cw22/README.md | 26 ++++++++++++++++++++++++-- packages/cw22/src/error.rs | 11 ----------- packages/cw22/src/lib.rs | 11 ++++------- 4 files changed, 29 insertions(+), 21 deletions(-) delete mode 100644 packages/cw22/src/error.rs diff --git a/packages/cw22/Cargo.toml b/packages/cw22/Cargo.toml index 6e3857050..7393dd8a9 100644 --- a/packages/cw22/Cargo.toml +++ b/packages/cw22/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cw22" -version = "1.0.0" +version = "0.1.0" authors = ["ThienLK1@aura-nw"] edition = "2021" description = "Definition and types for the CosmWasm-22 interface" diff --git a/packages/cw22/README.md b/packages/cw22/README.md index 2edb8248b..1da8458d0 100644 --- a/packages/cw22/README.md +++ b/packages/cw22/README.md @@ -1,7 +1,7 @@ # CW22 Spec: Contract Info -The standard used to declare which interface contract implements. -This standard is inspired by the EIP-165 from Ethereum. +The standard used to declare which interface contract implements. This standard is inspired by the EIP-165 from +Ethereum. For more information on this specification, please check out the [README](https://github.com/CosmWasm/cw-plus/blob/main/packages/cw22/README.md). @@ -30,3 +30,25 @@ pub struct ContractSupportedInterface { pub version: String, } ``` + +Below is an example used in cw20 contract, where we declare to implement cw20 interface with version 0.16.0 at +instantiate: + +```rust +use cw22::{set_contract_supported_interface, ContractSupportedInterface}; + +pub fn instantiate( + mut deps: DepsMut, + _env: Env, + _info: MessageInfo, + msg: InstantiateMsg, +) -> Result { + ///... + let supported_interface = ContractSupportedInterface { + supported_interface: String::from("crates.io:cw20"), + version: String::from("0.16.0"), + }; + set_contract_supported_interface(deps.storage, &[supported_interface])?; + ///... +} +``` diff --git a/packages/cw22/src/error.rs b/packages/cw22/src/error.rs deleted file mode 100644 index 7bfb9a0c0..000000000 --- a/packages/cw22/src/error.rs +++ /dev/null @@ -1,11 +0,0 @@ -use cosmwasm_std::StdError; -use thiserror::Error; - -#[derive(Error, Debug, PartialEq)] -pub enum ContractError { - #[error("{0}")] - Std(#[from] StdError), - - #[error("Version's format is invalid")] - InvalidVersionFormat {}, -} diff --git a/packages/cw22/src/lib.rs b/packages/cw22/src/lib.rs index 08625c658..f78a9b3ad 100644 --- a/packages/cw22/src/lib.rs +++ b/packages/cw22/src/lib.rs @@ -11,11 +11,8 @@ support a specific version of an interface or not. The version string for each interface follows Semantic Versioning standard. More info is in: https://docs.rs/semver/latest/semver/ */ -mod error; - -use crate::error::ContractError; use cosmwasm_schema::cw_serde; -use cosmwasm_std::{StdResult, Storage}; +use cosmwasm_std::{StdError, StdResult, Storage}; use cw_storage_plus::Map; use semver::{Version, VersionReq}; @@ -41,7 +38,7 @@ pub struct ContractSupportedInterface { pub fn set_contract_supported_interface( store: &mut dyn Storage, supported_interfaces: &[ContractSupportedInterface], -) -> Result<(), ContractError> { +) -> StdResult<()> { for item in supported_interfaces { let ver = Version::parse(&item.version); match ver { @@ -49,7 +46,7 @@ pub fn set_contract_supported_interface( SUPPORTED_INTERFACES.save(store, &item.supported_interface, &item.version)?; } Err(_) => { - return Err(ContractError::InvalidVersionFormat {}); + return Err(StdError::generic_err("Version's format is invalid")); } } } @@ -135,7 +132,7 @@ mod tests { let rs_error = set_contract_supported_interface(&mut store, supported_interface).unwrap_err(); - let expected = ContractError::InvalidVersionFormat {}; + let expected = StdError::generic_err("Version's format is invalid"); assert_eq!(expected, rs_error); // set supported_interface From df1f0c6c9911d4b09607271ac0f09e84b793e124 Mon Sep 17 00:00:00 2001 From: ThienLK1 Date: Fri, 2 Dec 2022 15:45:09 +0700 Subject: [PATCH 18/23] remove unused lib --- Cargo.lock | 1 - packages/cw22/Cargo.toml | 1 - 2 files changed, 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d1cc452a8..8c59d81e5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -372,7 +372,6 @@ dependencies = [ "schemars", "semver", "serde", - "thiserror", ] [[package]] diff --git a/packages/cw22/Cargo.toml b/packages/cw22/Cargo.toml index 7393dd8a9..1ecaca7de 100644 --- a/packages/cw22/Cargo.toml +++ b/packages/cw22/Cargo.toml @@ -15,4 +15,3 @@ cw-storage-plus = "0.16.0" schemars = "0.8.1" serde = { version = "1.0.0", default-features = false, features = ["derive"] } semver = "1.0.14" -thiserror = { version = "1.0.23" } From c9e3508d486831a0a3c9d8ab90e5a33f858952e4 Mon Sep 17 00:00:00 2001 From: Vu Ngoc Quang Date: Wed, 7 Jun 2023 01:13:24 +0700 Subject: [PATCH 19/23] refactor minimum_version and require_version --- packages/cw22/src/lib.rs | 55 ++++++++++++---------------------------- 1 file changed, 16 insertions(+), 39 deletions(-) diff --git a/packages/cw22/src/lib.rs b/packages/cw22/src/lib.rs index f78a9b3ad..bf84b0517 100644 --- a/packages/cw22/src/lib.rs +++ b/packages/cw22/src/lib.rs @@ -63,43 +63,23 @@ pub fn query_supported_interface_version( } pub fn minimum_version(version: &str, required: &str) -> bool { - let mut req_str = ">=".to_owned(); - req_str.push_str(required); - let req = VersionReq::parse(req_str.as_str()); - let req = match req { - Ok(r) => r, - Err(_) => { - return false; + if let Ok(ver) = Version::parse(version) { + if let Ok(req) = VersionReq::parse(format!(">={}", required).as_str()) { + return req.matches(&ver); } - }; - let ver = Version::parse(version); - let ver = match ver { - Ok(v) => v, - Err(_) => { - return false; - } - }; - req.matches(&ver) + } + false } /// query_supported_interface show if contract supports an interface with version following SemVer query /// query example">=1.2.3, <1.8.0" pub fn require_version(version: &str, request: &str) -> bool { - let req = VersionReq::parse(request); - let req = match req { - Ok(r) => r, - Err(_) => { - return false; + if let Ok(ver) = Version::parse(version) { + if let Ok(req) = VersionReq::parse(request) { + return req.matches(&ver); } - }; - let ver = Version::parse(version); - let ver = match ver { - Ok(v) => v, - Err(_) => { - return false; - } - }; - req.matches(&ver) + } + false } #[cfg(test)] @@ -147,45 +127,42 @@ mod tests { let loaded = query_supported_interface_version(&store, interface2).unwrap(); let expected = String::from("0.16.0"); assert_eq!(Some(expected), loaded); + } - // check request version + #[test] + fn test_require_version() { let version_req = ">=0.1.0"; let result = require_version("0.16.0", version_req); assert!(result); - // check request version let version_req = ">=0.16.0"; let result = require_version("0.1.0", version_req); assert!(!result); - // check request version let version_req = ">=1.2.3, <1.8.0"; let result = require_version("0.16.0", version_req); assert!(!result); - // check request version - version format invalid let version_req = ">=0.2.3"; let result = require_version("v0.16.0", version_req); assert!(!result); - // check require version - require version invalid let version_req = "!=0.2.3"; let result = require_version("0.16.0", version_req); assert!(!result); + } - // check minimum version + #[test] + fn test_minimum_version() { let result = minimum_version("0.16.0", "0.2.3"); assert!(result); - // check minimum version let result = minimum_version("0.2.0", "0.2.3"); assert!(!result); - // check minimum version - version format error let result = minimum_version("v0.16.0", "0.2.3"); assert!(!result); - // check minimum version - require version format error let result = minimum_version("0.16.0", "v0.2.3"); assert!(!result); } From 43db6a09ac654f0916d28ee3f9298e64d73d92e8 Mon Sep 17 00:00:00 2001 From: Vu Ngoc Quang Date: Wed, 7 Jun 2023 14:04:36 +0700 Subject: [PATCH 20/23] update Cargo lock --- Cargo.lock | 13 +++++++++++++ packages/cw22/Cargo.toml | 8 ++++---- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8c59d81e5..4264598be 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -372,6 +372,19 @@ dependencies = [ "schemars", "semver", "serde", + "thiserror", +] + +[[package]] +name = "cw22" +version = "0.1.0" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cw-storage-plus", + "schemars", + "semver", + "serde", ] [[package]] diff --git a/packages/cw22/Cargo.toml b/packages/cw22/Cargo.toml index 1ecaca7de..80aed4e8d 100644 --- a/packages/cw22/Cargo.toml +++ b/packages/cw22/Cargo.toml @@ -9,9 +9,9 @@ repository = "https://github.com/CosmWasm/cw-plus" homepage = "https://cosmwasm.com" [dependencies] -cosmwasm-schema = "1.0.0" -cosmwasm-std = { version = "1.0.0", default-features = false } -cw-storage-plus = "0.16.0" +cosmwasm-schema = "1.1.0" +cosmwasm-std = { version = "1.1.0", default-features = false } +cw-storage-plus = "1.0.1" schemars = "0.8.1" -serde = { version = "1.0.0", default-features = false, features = ["derive"] } +serde = { version = "1.0.103", default-features = false, features = ["derive"] } semver = "1.0.14" From a6c6106d8db1cba228a007ff137ab96e75c15707 Mon Sep 17 00:00:00 2001 From: Vu Ngoc Quang Date: Thu, 8 Jun 2023 01:04:36 +0700 Subject: [PATCH 21/23] Use Cow instead of String --- packages/cw22/src/lib.rs | 56 +++++++++++++++++++--------------------- 1 file changed, 27 insertions(+), 29 deletions(-) diff --git a/packages/cw22/src/lib.rs b/packages/cw22/src/lib.rs index bf84b0517..7ca5f250c 100644 --- a/packages/cw22/src/lib.rs +++ b/packages/cw22/src/lib.rs @@ -1,36 +1,34 @@ -/*! -CW22 defines a way for a contract to declare which interfaces do the contract implement -This standard is inspired by the EIP-165 from Ethereum. Originally it was proposed to -be merged into CW2: Contract Info, then it is splitted to a separated cargo to keep CW2 -being backward compatible. - -Each supported interface contains a string value pointing to the corresponding cargo package -and a specific release of the package. There is also a function to check whether the contract -support a specific version of an interface or not. - -The version string for each interface follows Semantic Versioning standard. More info is in: -https://docs.rs/semver/latest/semver/ - */ +//! CW22 defines a way for a contract to declare which interfaces do the contract implement +//! This standard is inspired by the EIP-165 from Ethereum. Originally it was proposed to +//! be merged into CW2: Contract Info, then it is splitted to a separated cargo to keep CW2 +//! being backward compatible. + +//! Each supported interface contains a string value pointing to the corresponding cargo package +//! and a specific release of the package. There is also a function to check whether the contract +//! support a specific version of an interface or not. + +//! The version string for each interface follows Semantic Versioning standard. More info is in: +//! https://docs.rs/semver/latest/semver/ use cosmwasm_schema::cw_serde; use cosmwasm_std::{StdError, StdResult, Storage}; use cw_storage_plus::Map; use semver::{Version, VersionReq}; +use std::borrow::Cow; pub const SUPPORTED_INTERFACES: Map<&str, String> = Map::new("supported_interfaces"); #[cw_serde] -pub struct ContractSupportedInterface { - /// supported_interface is an optional parameter returning a vector of string represents interfaces - /// that the contract support The string value is the interface crate names in Rust crate Registry. - /// This parameter is inspired by the EIP-165 from Ethereum. - /// Each string value should follow a common standard such as : - /// e.g "crates.io:cw2" +pub struct ContractSupportedInterface<'a> { + /// supported_interface is the name of an interface that the contract support. + /// This is inspired by the EIP-165 from Ethereum. + /// Interface names should follow a common standard such as : in Rust crate registry. + /// e.g. "crates.io:cw2" /// NOTE: this is just a hint for the caller to adapt on how to interact with this contract. /// There is no guarantee that the contract actually implement these interfaces. - pub supported_interface: String, + pub supported_interface: Cow<'a, str>, /// semantic version on release tags of the interface package following SemVer guideline. - /// e.g "0.16.0" - pub version: String, + /// e.g. "0.16.0" + pub version: Cow<'a, str>, } /// set_contract_supported_interface should be used in instantiate to store the original version @@ -43,7 +41,7 @@ pub fn set_contract_supported_interface( let ver = Version::parse(&item.version); match ver { Ok(_) => { - SUPPORTED_INTERFACES.save(store, &item.supported_interface, &item.version)?; + SUPPORTED_INTERFACES.save(store, &item.supported_interface, &item.version.to_string())?; } Err(_) => { return Err(StdError::generic_err("Version's format is invalid")); @@ -95,16 +93,16 @@ mod tests { let interface22 = "crates.io:cw22"; let interface721 = "crates.io:cw721"; let contract_interface2 = ContractSupportedInterface { - supported_interface: String::from(interface2), - version: String::from("0.16.0"), + supported_interface: Cow::Borrowed(interface2), + version: Cow::from("0.16.0"), }; let contract_interface22 = ContractSupportedInterface { - supported_interface: String::from(interface22), - version: String::from("0.1.0"), + supported_interface: Cow::Borrowed(interface22), + version: Cow::from("0.1.0"), }; let contract_interface721 = ContractSupportedInterface { - supported_interface: String::from(interface22), - version: String::from("v0.1.0"), + supported_interface: Cow::Borrowed(interface22), + version: Cow::from("v0.1.0"), }; // set supported_interface error From 1353e5b24fbea47a693b14c10126914206c87c23 Mon Sep 17 00:00:00 2001 From: Vu Ngoc Quang Date: Thu, 8 Jun 2023 22:09:45 +0700 Subject: [PATCH 22/23] chore: cargo fmt --- packages/cw22/src/lib.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/cw22/src/lib.rs b/packages/cw22/src/lib.rs index 7ca5f250c..f79209413 100644 --- a/packages/cw22/src/lib.rs +++ b/packages/cw22/src/lib.rs @@ -19,7 +19,7 @@ pub const SUPPORTED_INTERFACES: Map<&str, String> = Map::new("supported_interfac #[cw_serde] pub struct ContractSupportedInterface<'a> { - /// supported_interface is the name of an interface that the contract support. + /// supported_interface is the name of an interface that the contract support. /// This is inspired by the EIP-165 from Ethereum. /// Interface names should follow a common standard such as : in Rust crate registry. /// e.g. "crates.io:cw2" @@ -41,7 +41,11 @@ pub fn set_contract_supported_interface( let ver = Version::parse(&item.version); match ver { Ok(_) => { - SUPPORTED_INTERFACES.save(store, &item.supported_interface, &item.version.to_string())?; + SUPPORTED_INTERFACES.save( + store, + &item.supported_interface, + &item.version.to_string(), + )?; } Err(_) => { return Err(StdError::generic_err("Version's format is invalid")); From fb37be3babe26e3ddfe05f04bc447c4970af4803 Mon Sep 17 00:00:00 2001 From: Vu Ngoc Quang Date: Sat, 10 Jun 2023 17:27:39 +0700 Subject: [PATCH 23/23] Update cw22 readme --- packages/cw22/README.md | 27 +++++++++++++-------------- packages/cw22/src/lib.rs | 2 +- 2 files changed, 14 insertions(+), 15 deletions(-) diff --git a/packages/cw22/README.md b/packages/cw22/README.md index 1da8458d0..6356ce69b 100644 --- a/packages/cw22/README.md +++ b/packages/cw22/README.md @@ -16,18 +16,17 @@ All CW22-compliant contracts must store the following data: * data: Json-serialized `ContractSupportedInterface` ```rust -pub struct ContractSupportedInterface { - /// supported_interface is an optional parameter returning a vector of string represents interfaces - /// that the contract support The string value is the interface crate names in Rust crate Registry. - /// This parameter is inspired by the EIP-165 from Ethereum. - /// Each string value should follow a common standard such as : - /// e.g "crates.io:cw2" - /// NOTE: this is just a hint for the caller to adapt on how to interact with this contract. - /// There is no guarantee that the contract actually implement these interfaces. - pub supported_interface: String, - /// semantic version on release tags of the interface package following SemVer guideline. - /// e.g "0.16.0" - pub version: String, +pub struct ContractSupportedInterface<'a> { + /// supported_interface is the name of an interface that the contract supports. + /// This is inspired by the EIP-165 from Ethereum. + /// Interface names should follow a common standard such as : in Rust crate registry. + /// e.g. "crates.io:cw2" + /// NOTE: this is just a hint for the caller to adapt on how to interact with this contract. + /// There is no guarantee that the contract actually implements the interface. + pub supported_interface: Cow<'a, str>, + /// Version on release tags of the interface package following [SemVer](https://semver.org/) guideline. + /// e.g. "0.16.0" + pub version: Cow<'a, str>, } ``` @@ -45,8 +44,8 @@ pub fn instantiate( ) -> Result { ///... let supported_interface = ContractSupportedInterface { - supported_interface: String::from("crates.io:cw20"), - version: String::from("0.16.0"), + supported_interface: "crates.io:cw20".into(), + version: "0.16.0".into(), }; set_contract_supported_interface(deps.storage, &[supported_interface])?; ///... diff --git a/packages/cw22/src/lib.rs b/packages/cw22/src/lib.rs index f79209413..f1fd477c1 100644 --- a/packages/cw22/src/lib.rs +++ b/packages/cw22/src/lib.rs @@ -102,7 +102,7 @@ mod tests { }; let contract_interface22 = ContractSupportedInterface { supported_interface: Cow::Borrowed(interface22), - version: Cow::from("0.1.0"), + version: "0.1.0".into(), }; let contract_interface721 = ContractSupportedInterface { supported_interface: Cow::Borrowed(interface22),