From 63e9d6d2df9b91ee079fc5aea661d4834daab5a7 Mon Sep 17 00:00:00 2001 From: Nikhil Suri Date: Fri, 24 Mar 2023 21:24:18 +0000 Subject: [PATCH] std: Add BankQuery::AllDenomMetadata gated by cosmwasm_1_3 feature flag --- .circleci/config.yml | 10 +++++----- CHANGELOG.md | 6 ++++++ MIGRATING.md | 4 ++-- docs/CAPABILITIES-BUILT-IN.md | 2 ++ docs/USING_COSMWASM_STD.md | 1 + packages/check/src/main.rs | 3 ++- packages/std/Cargo.toml | 3 +++ packages/std/src/exports.rs | 4 ++++ packages/std/src/lib.rs | 2 ++ packages/std/src/metadata.rs | 23 +++++++++++++++++++++++ packages/std/src/query/bank.rs | 19 +++++++++++++++++++ packages/std/src/query/mod.rs | 2 ++ packages/std/src/testing/mock.rs | 18 +++++++++++++++++- packages/std/src/traits.rs | 11 +++++++++++ packages/vm/src/testing/instance.rs | 3 ++- 15 files changed, 101 insertions(+), 10 deletions(-) create mode 100644 packages/std/src/metadata.rs diff --git a/.circleci/config.yml b/.circleci/config.yml index 166f2be8be..e30d6b67a4 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -362,15 +362,15 @@ jobs: - run: name: Build library for native target (all features) working_directory: ~/project/packages/std - command: cargo build --locked --features abort,iterator,staking,stargate,cosmwasm_1_2 + command: cargo build --locked --features abort,iterator,staking,stargate,cosmwasm_1_3 - run: name: Build library for wasm target (all features) working_directory: ~/project/packages/std - command: cargo wasm --locked --features abort,iterator,staking,stargate,cosmwasm_1_2 + command: cargo wasm --locked --features abort,iterator,staking,stargate,cosmwasm_1_3 - run: name: Run unit tests (all features) working_directory: ~/project/packages/std - command: cargo test --locked --features abort,iterator,staking,stargate,cosmwasm_1_2 + command: cargo test --locked --features abort,iterator,staking,stargate,cosmwasm_1_3 - save_cache: paths: - /usr/local/cargo/registry @@ -913,7 +913,7 @@ jobs: - run: name: Clippy linting on std (all feature flags) working_directory: ~/project/packages/std - command: cargo clippy --all-targets --features abort,iterator,staking,stargate,cosmwasm_1_2 -- -D warnings + command: cargo clippy --all-targets --features abort,iterator,staking,stargate,cosmwasm_1_3 -- -D warnings - run: name: Clippy linting on storage (no feature flags) working_directory: ~/project/packages/storage @@ -990,7 +990,7 @@ jobs: CRYPTO=" cargo tarpaulin --skip-clean --out Xml --output-dir reports/crypto --packages cosmwasm-crypto" DERIVE=" cargo tarpaulin --skip-clean --out Xml --output-dir reports/derive --packages cosmwasm-derive" SCHEMA=" cargo tarpaulin --skip-clean --out Xml --output-dir reports/schema --packages cosmwasm-schema" - STD=" cargo tarpaulin --skip-clean --out Xml --output-dir reports/std --packages cosmwasm-std --features abort,iterator,staking,stargate,cosmwasm_1_2" + STD=" cargo tarpaulin --skip-clean --out Xml --output-dir reports/std --packages cosmwasm-std --features abort,iterator,staking,stargate,cosmwasm_1_3" STORAGE="cargo tarpaulin --skip-clean --out Xml --output-dir reports/storage --packages cosmwasm-storage" docker run --security-opt seccomp=unconfined -v "${PWD}:/volume" xd009642/tarpaulin:0.21.0 \ sh -c "$CRYPTO && $DERIVE && $SCHEMA && $STD && $STORAGE" diff --git a/CHANGELOG.md b/CHANGELOG.md index c889600c51..96ee315cc2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,12 @@ and this project adheres to ## [Unreleased] +- cosmwasm-std: Implement `BankQuery::AllDenomMetadata` to allow querying all + the denom metadata. In order to use this query in a contract, the + `cosmwasm_1_3` feature needs to be enabled for the `cosmwasm_std` dependency. + This makes the contract incompatible with chains running anything lower than + CosmWasm `1.3.0`. + ## [1.2.3] - 2023-03-22 - cosmwasm-vm: Use saturating increments for `Stats` fields to ensure we don't diff --git a/MIGRATING.md b/MIGRATING.md index 0000f999fc..c65a29de5c 100644 --- a/MIGRATING.md +++ b/MIGRATING.md @@ -28,8 +28,8 @@ major releases of `cosmwasm`. Note that you can also view the +cosmwasm-std = { version = "1.1.0", features = ["stargate", "cosmwasm_1_2"] } ``` - Please note that `cosmwasm_1_2` implies `cosmwasm_1_1`, so there is no need to - set both. + Please note that `cosmwasm_1_2` implies `cosmwasm_1_1`, and `cosmwasm_1_3` + implies `cosmwasm_1_2`, and so on, so there is no need to set multiple. - If you use mixed type multiplication between `Uint{64,128,256}` and `Decimal{,256}`, check out diff --git a/docs/CAPABILITIES-BUILT-IN.md b/docs/CAPABILITIES-BUILT-IN.md index 8fdd679fe1..190c9f825d 100644 --- a/docs/CAPABILITIES-BUILT-IN.md +++ b/docs/CAPABILITIES-BUILT-IN.md @@ -15,3 +15,5 @@ might define others. CosmWasm `1.1.0` or higher support this. - `cosmwasm_1_2` enables the `GovMsg::VoteWeighted` and `WasmMsg::Instantiate2` messages. Only chains running CosmWasm `1.2.0` or higher support this. +- `cosmwasm_1_3` enables the `BankQuery::AllDenomMetadata` query. Only chains + running CosmWasm `1.3.0` or higher support this. diff --git a/docs/USING_COSMWASM_STD.md b/docs/USING_COSMWASM_STD.md index 45841e908b..2519b9b8a5 100644 --- a/docs/USING_COSMWASM_STD.md +++ b/docs/USING_COSMWASM_STD.md @@ -44,6 +44,7 @@ The libarary comes with the following features: | baktraces | | Add backtraces to errors (for unit testing) | | cosmwasm_1_1 | | Features that require CosmWasm 1.1+ on the chain | | cosmwasm_1_2 | | Features that require CosmWasm 1.2+ on the chain | +| cosmwasm_1_3 | | Features that require CosmWasm 1.3+ on the chain | ## The cosmwasm-std dependency for contract developers diff --git a/packages/check/src/main.rs b/packages/check/src/main.rs index c1f7da1784..f3efc4355c 100644 --- a/packages/check/src/main.rs +++ b/packages/check/src/main.rs @@ -10,7 +10,8 @@ use colored::Colorize; use cosmwasm_vm::capabilities_from_csv; use cosmwasm_vm::internals::{check_wasm, compile}; -const DEFAULT_AVAILABLE_CAPABILITIES: &str = "iterator,staking,stargate,cosmwasm_1_1,cosmwasm_1_2"; +const DEFAULT_AVAILABLE_CAPABILITIES: &str = + "iterator,staking,stargate,cosmwasm_1_1,cosmwasm_1_2,cosmwasm_1_3"; pub fn main() { let matches = App::new("Contract checking") diff --git a/packages/std/Cargo.toml b/packages/std/Cargo.toml index 06d7686e41..dcf1abe3b0 100644 --- a/packages/std/Cargo.toml +++ b/packages/std/Cargo.toml @@ -39,6 +39,9 @@ cosmwasm_1_1 = [] # This feature makes `GovMsg::VoteWeighted` available for the contract to call, but requires # the host blockchain to run CosmWasm `1.2.0` or higher. cosmwasm_1_2 = ["cosmwasm_1_1"] +# This feature makes `BankQuery::DenomMetadata` available for the contract to call, but requires +# the host blockchain to run CosmWasm `1.3.0` or higher. +cosmwasm_1_3 = ["cosmwasm_1_2"] [dependencies] base64 = "0.13.0" diff --git a/packages/std/src/exports.rs b/packages/std/src/exports.rs index 5b4b30925c..27c46768dc 100644 --- a/packages/std/src/exports.rs +++ b/packages/std/src/exports.rs @@ -49,6 +49,10 @@ extern "C" fn requires_cosmwasm_1_1() -> () {} #[no_mangle] extern "C" fn requires_cosmwasm_1_2() -> () {} +#[cfg(feature = "cosmwasm_1_3")] +#[no_mangle] +extern "C" fn requires_cosmwasm_1_3() -> () {} + /// interface_version_* exports mark which Wasm VM interface level this contract is compiled for. /// They can be checked by cosmwasm_vm. /// Update this whenever the Wasm VM interface breaks. diff --git a/packages/std/src/lib.rs b/packages/std/src/lib.rs index 34a01301f5..6cc2fc08ff 100644 --- a/packages/std/src/lib.rs +++ b/packages/std/src/lib.rs @@ -16,6 +16,7 @@ mod import_helpers; #[cfg(feature = "iterator")] mod iterator; mod math; +mod metadata; mod never; mod panic; mod query; @@ -50,6 +51,7 @@ pub use crate::math::{ Decimal, Decimal256, Decimal256RangeExceeded, DecimalRangeExceeded, Fraction, Isqrt, Uint128, Uint256, Uint512, Uint64, }; +pub use crate::metadata::{DenomMetadata, DenomUnit}; pub use crate::never::Never; #[cfg(feature = "cosmwasm_1_2")] pub use crate::query::CodeInfoResponse; diff --git a/packages/std/src/metadata.rs b/packages/std/src/metadata.rs new file mode 100644 index 0000000000..d3400a49a5 --- /dev/null +++ b/packages/std/src/metadata.rs @@ -0,0 +1,23 @@ +use schemars::JsonSchema; +use serde::{Deserialize, Serialize}; + +use crate::math::Uint128; + +#[derive(Serialize, Deserialize, Clone, Default, Debug, PartialEq, Eq, JsonSchema)] +pub struct DenomMetadata { + pub description: String, + pub denom_units: Vec, + pub base: String, + pub display: String, + pub name: String, + pub symbol: String, + pub uri: String, + pub uri_hash: String, +} + +#[derive(Serialize, Deserialize, Clone, Default, Debug, PartialEq, Eq, JsonSchema)] +pub struct DenomUnit { + pub denom: String, + pub exponent: Uint128, + pub aliases: Vec, +} diff --git a/packages/std/src/query/bank.rs b/packages/std/src/query/bank.rs index b3a43e11d5..222fc86e17 100644 --- a/packages/std/src/query/bank.rs +++ b/packages/std/src/query/bank.rs @@ -3,6 +3,9 @@ use serde::{Deserialize, Serialize}; use crate::Coin; +#[cfg(feature = "cosmwasm_1_3")] +use crate::DenomMetadata; + use super::query_response::QueryResponseType; #[non_exhaustive] @@ -21,6 +24,10 @@ pub enum BankQuery { /// Note that this may be much more expensive than Balance and should be avoided if possible. /// Return value is AllBalanceResponse. AllBalances { address: String }, + /// This calls into the native bank module for querying metadata for all bank tokens. + /// Return value is AllDenomMetadataResponse + #[cfg(feature = "cosmwasm_1_3")] + AllDenomMetadata {}, } #[cfg(feature = "cosmwasm_1_1")] @@ -54,3 +61,15 @@ pub struct AllBalanceResponse { } impl QueryResponseType for AllBalanceResponse {} + +#[cfg(feature = "cosmwasm_1_3")] +#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, Eq, JsonSchema)] +#[serde(rename_all = "snake_case")] +#[non_exhaustive] +pub struct AllDenomMetadataResponse { + /// Always returns metadata for all token denoms on the base chain. + pub metadata: Vec, +} + +#[cfg(feature = "cosmwasm_1_3")] +impl QueryResponseType for AllDenomMetadataResponse {} diff --git a/packages/std/src/query/mod.rs b/packages/std/src/query/mod.rs index 50061df091..e79417bc99 100644 --- a/packages/std/src/query/mod.rs +++ b/packages/std/src/query/mod.rs @@ -11,6 +11,8 @@ mod query_response; mod staking; mod wasm; +#[cfg(feature = "cosmwasm_1_3")] +pub use bank::AllDenomMetadataResponse; #[cfg(feature = "cosmwasm_1_1")] pub use bank::SupplyResponse; pub use bank::{AllBalanceResponse, BalanceResponse, BankQuery}; diff --git a/packages/std/src/testing/mock.rs b/packages/std/src/testing/mock.rs index d219236578..c8bcf67f00 100644 --- a/packages/std/src/testing/mock.rs +++ b/packages/std/src/testing/mock.rs @@ -16,6 +16,8 @@ use crate::ibc::{ IbcTimeoutBlock, }; use crate::math::Uint128; +#[cfg(feature = "cosmwasm_1_3")] +use crate::query::AllDenomMetadataResponse; #[cfg(feature = "cosmwasm_1_1")] use crate::query::SupplyResponse; use crate::query::{ @@ -32,7 +34,7 @@ use crate::storage::MemoryStorage; use crate::timestamp::Timestamp; use crate::traits::{Api, Querier, QuerierResult}; use crate::types::{BlockInfo, ContractInfo, Env, MessageInfo, TransactionInfo}; -use crate::Attribute; +use crate::{Attribute, DenomMetadata}; #[cfg(feature = "stargate")] use crate::{ChannelResponse, IbcQuery, ListChannelsResponse, PortIdResponse}; @@ -599,6 +601,8 @@ pub struct BankQuerier { supplies: HashMap, /// HashMap balances: HashMap>, + /// Vec + denom_metadata: Vec, } impl BankQuerier { @@ -611,6 +615,7 @@ impl BankQuerier { BankQuerier { supplies: Self::calculate_supplies(&balances), balances, + denom_metadata: Vec::new(), } } @@ -625,6 +630,10 @@ impl BankQuerier { result } + pub fn set_denom_metadata(&mut self, denom_metadata: &[DenomMetadata]) { + self.denom_metadata = denom_metadata.to_vec(); + } + fn calculate_supplies(balances: &HashMap>) -> HashMap { let mut supplies = HashMap::new(); @@ -678,6 +687,13 @@ impl BankQuerier { }; to_binary(&bank_res).into() } + #[cfg(feature = "cosmwasm_1_3")] + BankQuery::AllDenomMetadata {} => { + let metadata_res = AllDenomMetadataResponse { + metadata: self.denom_metadata.clone(), + }; + to_binary(&metadata_res).into() + } }; // system result is always ok in the mock implementation SystemResult::Ok(contract_result) diff --git a/packages/std/src/traits.rs b/packages/std/src/traits.rs index e3ba067b6e..79db30f6f5 100644 --- a/packages/std/src/traits.rs +++ b/packages/std/src/traits.rs @@ -8,6 +8,8 @@ use crate::coin::Coin; use crate::errors::{RecoverPubkeyError, StdError, StdResult, VerificationError}; #[cfg(feature = "iterator")] use crate::iterator::{Order, Record}; +#[cfg(feature = "cosmwasm_1_3")] +use crate::query::AllDenomMetadataResponse; #[cfg(feature = "cosmwasm_1_2")] use crate::query::CodeInfoResponse; #[cfg(feature = "cosmwasm_1_1")] @@ -23,6 +25,8 @@ use crate::query::{ use crate::results::{ContractResult, Empty, SystemResult}; use crate::serde::{from_binary, to_binary, to_vec}; use crate::ContractInfoResponse; +#[cfg(feature = "cosmwasm_1_3")] +use crate::DenomMetadata; /// Storage provides read and write access to a persistent storage. /// If you only want to provide read access, provide `&Storage` @@ -239,6 +243,13 @@ impl<'a, C: CustomQuery> QuerierWrapper<'a, C> { Ok(res.amount) } + #[cfg(feature = "cosmwasm_1_3")] + pub fn query_all_denom_metadata(&self) -> StdResult> { + let request = BankQuery::AllDenomMetadata {}.into(); + let res: AllDenomMetadataResponse = self.query(&request)?; + Ok(res.metadata) + } + // this queries another wasm contract. You should know a priori the proper types for T and U // (response and request) based on the contract API pub fn query_wasm_smart( diff --git a/packages/vm/src/testing/instance.rs b/packages/vm/src/testing/instance.rs index 14b85cf7c9..6a4f11a37f 100644 --- a/packages/vm/src/testing/instance.rs +++ b/packages/vm/src/testing/instance.rs @@ -98,7 +98,8 @@ pub struct MockInstanceOptions<'a> { impl MockInstanceOptions<'_> { fn default_capabilities() -> HashSet { #[allow(unused_mut)] - let mut out = capabilities_from_csv("iterator,staking,cosmwasm_1_1,cosmwasm_1_2"); + let mut out = + capabilities_from_csv("iterator,staking,cosmwasm_1_1,cosmwasm_1_2,cosmwasm_1_3"); #[cfg(feature = "stargate")] out.insert("stargate".to_string()); out