cosmwasm_std/testing/
mock.rs

1use crate::prelude::*;
2use crate::HashFunction;
3use crate::{Addr, CanonicalAddr, Timestamp};
4use alloc::collections::BTreeMap;
5#[cfg(feature = "cosmwasm_1_3")]
6use alloc::collections::BTreeSet;
7use bech32::primitives::decode::CheckedHrpstring;
8use bech32::{encode, Bech32, Hrp};
9use core::marker::PhantomData;
10#[cfg(feature = "cosmwasm_1_3")]
11use core::ops::Bound;
12use rand_core::OsRng;
13use serde::de::DeserializeOwned;
14#[cfg(any(feature = "stargate", feature = "ibc2"))]
15use serde::Serialize;
16use sha2::{Digest, Sha256};
17
18use crate::coin::Coin;
19use crate::deps::OwnedDeps;
20#[cfg(feature = "stargate")]
21use crate::ibc::{
22    IbcAcknowledgement, IbcChannel, IbcChannelCloseMsg, IbcChannelConnectMsg, IbcChannelOpenMsg,
23    IbcEndpoint, IbcOrder, IbcPacket, IbcPacketAckMsg, IbcPacketReceiveMsg, IbcPacketTimeoutMsg,
24    IbcTimeoutBlock,
25};
26#[cfg(feature = "ibc2")]
27use crate::ibc2::{
28    Ibc2PacketAckMsg, Ibc2PacketReceiveMsg, Ibc2PacketSendMsg, Ibc2PacketTimeoutMsg, Ibc2Payload,
29};
30#[cfg(feature = "cosmwasm_1_1")]
31use crate::query::SupplyResponse;
32#[cfg(feature = "staking")]
33use crate::query::{
34    AllDelegationsResponse, AllValidatorsResponse, BondedDenomResponse, DelegationResponse,
35    FullDelegation, StakingQuery, Validator, ValidatorResponse,
36};
37use crate::query::{BalanceResponse, BankQuery, CustomQuery, QueryRequest, WasmQuery};
38#[cfg(feature = "cosmwasm_1_3")]
39use crate::query::{DelegatorWithdrawAddressResponse, DistributionQuery};
40use crate::results::{ContractResult, Empty, SystemResult};
41use crate::traits::{Api, Querier, QuerierResult};
42use crate::types::{BlockInfo, ContractInfo, Env, TransactionInfo};
43use crate::{from_json, to_json_binary, Binary, Uint256};
44#[cfg(feature = "cosmwasm_1_3")]
45use crate::{
46    query::{AllDenomMetadataResponse, DecCoin, DenomMetadataResponse},
47    PageRequest,
48};
49use crate::{Attribute, DenomMetadata};
50#[cfg(feature = "stargate")]
51use crate::{ChannelResponse, IbcQuery, PortIdResponse};
52#[cfg(feature = "cosmwasm_1_4")]
53use crate::{Decimal256, DelegationRewardsResponse, DelegatorValidatorsResponse};
54use crate::{RecoverPubkeyError, StdError, StdResult, SystemError, VerificationError};
55
56use super::MockStorage;
57
58pub const MOCK_CONTRACT_ADDR: &str =
59    "cosmwasm1jpev2csrppg792t22rn8z8uew8h3sjcpglcd0qv9g8gj8ky922tscp8avs";
60
61/// Creates all external requirements that can be injected for unit tests.
62///
63/// See also [`mock_dependencies_with_balance`] and [`mock_dependencies_with_balances`]
64/// if you want to start with some initial balances.
65pub fn mock_dependencies() -> OwnedDeps<MockStorage, MockApi, MockQuerier, Empty> {
66    OwnedDeps {
67        storage: MockStorage::default(),
68        api: MockApi::default(),
69        querier: MockQuerier::default(),
70        custom_query_type: PhantomData,
71    }
72}
73
74/// Creates all external requirements that can be injected for unit tests.
75///
76/// It sets the given balance for the contract itself, nothing else.
77pub fn mock_dependencies_with_balance(
78    contract_balance: &[Coin],
79) -> OwnedDeps<MockStorage, MockApi, MockQuerier, Empty> {
80    mock_dependencies_with_balances(&[(MOCK_CONTRACT_ADDR, contract_balance)])
81}
82
83/// Initializes the querier along with the mock_dependencies.
84/// Sets all balances provided (you must explicitly set contract balance if desired).
85pub fn mock_dependencies_with_balances(
86    balances: &[(&str, &[Coin])],
87) -> OwnedDeps<MockStorage, MockApi, MockQuerier> {
88    OwnedDeps {
89        storage: MockStorage::default(),
90        api: MockApi::default(),
91        querier: MockQuerier::new(balances),
92        custom_query_type: PhantomData,
93    }
94}
95
96/// Default prefix used when creating Bech32 encoded address.
97const BECH32_PREFIX: &str = "cosmwasm";
98
99// MockApi zero pads all human addresses to make them fit the canonical_length
100// it trims off zeros for the reverse operation.
101// not really smart, but allows us to see a difference (and consistent length for canonical addresses)
102#[derive(Copy, Clone)]
103pub struct MockApi {
104    /// Prefix used for creating addresses in Bech32 encoding.
105    bech32_prefix: &'static str,
106}
107
108impl Default for MockApi {
109    fn default() -> Self {
110        MockApi {
111            bech32_prefix: BECH32_PREFIX,
112        }
113    }
114}
115
116impl Api for MockApi {
117    fn addr_validate(&self, input: &str) -> StdResult<Addr> {
118        let canonical = self.addr_canonicalize(input)?;
119        let normalized = self.addr_humanize(&canonical)?;
120        if input != normalized.as_str() {
121            return Err(StdError::generic_err(
122                "Invalid input: address not normalized",
123            ));
124        }
125        Ok(Addr::unchecked(input))
126    }
127
128    fn addr_canonicalize(&self, input: &str) -> StdResult<CanonicalAddr> {
129        let hrp_str = CheckedHrpstring::new::<Bech32>(input)
130            .map_err(|_| StdError::generic_err("Error decoding bech32"))?;
131
132        if !hrp_str
133            .hrp()
134            .as_bytes()
135            .eq_ignore_ascii_case(self.bech32_prefix.as_bytes())
136        {
137            return Err(StdError::generic_err("Wrong bech32 prefix"));
138        }
139
140        let bytes: Vec<u8> = hrp_str.byte_iter().collect();
141        validate_length(&bytes)?;
142        Ok(bytes.into())
143    }
144
145    fn addr_humanize(&self, canonical: &CanonicalAddr) -> StdResult<Addr> {
146        validate_length(canonical.as_ref())?;
147
148        let prefix = Hrp::parse(self.bech32_prefix)
149            .map_err(|_| StdError::generic_err("Invalid bech32 prefix"))?;
150        encode::<Bech32>(prefix, canonical.as_slice())
151            .map(Addr::unchecked)
152            .map_err(|_| StdError::generic_err("Bech32 encoding error"))
153    }
154
155    fn bls12_381_aggregate_g1(&self, g1s: &[u8]) -> Result<[u8; 48], VerificationError> {
156        cosmwasm_crypto::bls12_381_aggregate_g1(g1s).map_err(Into::into)
157    }
158
159    fn bls12_381_aggregate_g2(&self, g2s: &[u8]) -> Result<[u8; 96], VerificationError> {
160        cosmwasm_crypto::bls12_381_aggregate_g2(g2s).map_err(Into::into)
161    }
162
163    fn bls12_381_pairing_equality(
164        &self,
165        ps: &[u8],
166        qs: &[u8],
167        r: &[u8],
168        s: &[u8],
169    ) -> Result<bool, VerificationError> {
170        cosmwasm_crypto::bls12_381_pairing_equality(ps, qs, r, s).map_err(Into::into)
171    }
172
173    fn bls12_381_hash_to_g1(
174        &self,
175        hash_function: HashFunction,
176        msg: &[u8],
177        dst: &[u8],
178    ) -> Result<[u8; 48], VerificationError> {
179        Ok(cosmwasm_crypto::bls12_381_hash_to_g1(
180            hash_function.into(),
181            msg,
182            dst,
183        ))
184    }
185
186    fn bls12_381_hash_to_g2(
187        &self,
188        hash_function: HashFunction,
189        msg: &[u8],
190        dst: &[u8],
191    ) -> Result<[u8; 96], VerificationError> {
192        Ok(cosmwasm_crypto::bls12_381_hash_to_g2(
193            hash_function.into(),
194            msg,
195            dst,
196        ))
197    }
198
199    fn secp256k1_verify(
200        &self,
201        message_hash: &[u8],
202        signature: &[u8],
203        public_key: &[u8],
204    ) -> Result<bool, VerificationError> {
205        Ok(cosmwasm_crypto::secp256k1_verify(
206            message_hash,
207            signature,
208            public_key,
209        )?)
210    }
211
212    fn secp256k1_recover_pubkey(
213        &self,
214        message_hash: &[u8],
215        signature: &[u8],
216        recovery_param: u8,
217    ) -> Result<Vec<u8>, RecoverPubkeyError> {
218        let pubkey =
219            cosmwasm_crypto::secp256k1_recover_pubkey(message_hash, signature, recovery_param)?;
220        Ok(pubkey.to_vec())
221    }
222
223    fn secp256r1_verify(
224        &self,
225        message_hash: &[u8],
226        signature: &[u8],
227        public_key: &[u8],
228    ) -> Result<bool, VerificationError> {
229        Ok(cosmwasm_crypto::secp256r1_verify(
230            message_hash,
231            signature,
232            public_key,
233        )?)
234    }
235
236    fn secp256r1_recover_pubkey(
237        &self,
238        message_hash: &[u8],
239        signature: &[u8],
240        recovery_param: u8,
241    ) -> Result<Vec<u8>, RecoverPubkeyError> {
242        let pubkey =
243            cosmwasm_crypto::secp256r1_recover_pubkey(message_hash, signature, recovery_param)?;
244        Ok(pubkey.to_vec())
245    }
246
247    fn ed25519_verify(
248        &self,
249        message: &[u8],
250        signature: &[u8],
251        public_key: &[u8],
252    ) -> Result<bool, VerificationError> {
253        Ok(cosmwasm_crypto::ed25519_verify(
254            message, signature, public_key,
255        )?)
256    }
257
258    fn ed25519_batch_verify(
259        &self,
260        messages: &[&[u8]],
261        signatures: &[&[u8]],
262        public_keys: &[&[u8]],
263    ) -> Result<bool, VerificationError> {
264        Ok(cosmwasm_crypto::ed25519_batch_verify(
265            &mut OsRng,
266            messages,
267            signatures,
268            public_keys,
269        )?)
270    }
271
272    fn debug(&self, #[allow(unused)] message: &str) {
273        println!("{message}");
274    }
275}
276
277impl MockApi {
278    /// Returns [MockApi] with Bech32 prefix set to provided value.
279    ///
280    /// Bech32 prefix must not be empty.
281    ///
282    /// # Example
283    ///
284    /// ```
285    /// # use cosmwasm_std::Addr;
286    /// # use cosmwasm_std::testing::MockApi;
287    /// #
288    /// let mock_api = MockApi::default().with_prefix("juno");
289    /// let addr = mock_api.addr_make("creator");
290    ///
291    /// assert_eq!(addr.to_string(), "juno1h34lmpywh4upnjdg90cjf4j70aee6z8qqfspugamjp42e4q28kqsksmtyp");
292    /// ```
293    pub fn with_prefix(mut self, prefix: &'static str) -> Self {
294        self.bech32_prefix = prefix;
295        self
296    }
297
298    /// Returns an address built from provided input string.
299    ///
300    /// # Example
301    ///
302    /// ```
303    /// # use cosmwasm_std::Addr;
304    /// # use cosmwasm_std::testing::MockApi;
305    /// #
306    /// let mock_api = MockApi::default();
307    /// let addr = mock_api.addr_make("creator");
308    ///
309    /// assert_eq!(addr.to_string(), "cosmwasm1h34lmpywh4upnjdg90cjf4j70aee6z8qqfspugamjp42e4q28kqs8s7vcp");
310    /// ```
311    ///
312    /// # Panics
313    ///
314    /// This function panics when generating a valid address is not possible,
315    /// especially when Bech32 prefix set in function [with_prefix](Self::with_prefix) is empty.
316    ///
317    pub fn addr_make(&self, input: &str) -> Addr {
318        let digest = Sha256::digest(input);
319
320        let prefix = match Hrp::parse(self.bech32_prefix) {
321            Ok(prefix) => prefix,
322            Err(reason) => panic!("Generating address failed with reason: {reason}"),
323        };
324
325        match encode::<Bech32>(prefix, &digest) {
326            Ok(address) => Addr::unchecked(address),
327            Err(reason) => panic!("Generating address failed with reason: {reason}"),
328        }
329    }
330}
331
332/// Does basic validation of the number of bytes in a canonical address
333fn validate_length(bytes: &[u8]) -> StdResult<()> {
334    match bytes.len() {
335        1..=255 => Ok(()),
336        _ => Err(StdError::generic_err("Invalid canonical address length")),
337    }
338}
339
340/// Returns a default environment with height, time, chain_id, and contract address.
341/// You can submit as is to most contracts, or modify height/time if you want to
342/// test for expiration.
343///
344/// This is intended for use in test code only.
345///
346/// The contract address uses the same bech32 prefix as [`MockApi`](crate::testing::MockApi). While
347/// this is good for the majority of users, you might need to create your `Env`s
348/// differently if you need a valid address using a different prefix.
349///
350/// ## Examples
351///
352/// Create an env:
353///
354/// ```
355/// # use cosmwasm_std::{Addr, Binary, BlockInfo, ContractInfo, Env, Timestamp, TransactionInfo};
356/// use cosmwasm_std::testing::mock_env;
357///
358/// let env = mock_env();
359/// assert_eq!(env, Env {
360///     block: BlockInfo {
361///         height: 12_345,
362///         time: Timestamp::from_nanos(1_571_797_419_879_305_533),
363///         chain_id: "cosmos-testnet-14002".to_string(),
364///     },
365///     transaction: Some(TransactionInfo::new(3, Binary::from_hex("E5469DACEC17CEF8A260FD37675ED87E7FB6A2B5AD95193C51308006C7E494B3").unwrap())),
366///     contract: ContractInfo {
367///         address: Addr::unchecked("cosmwasm1jpev2csrppg792t22rn8z8uew8h3sjcpglcd0qv9g8gj8ky922tscp8avs"),
368///     },
369/// });
370/// ```
371///
372/// Mutate and reuse environment:
373///
374/// ```
375/// # use cosmwasm_std::{Addr, BlockInfo, ContractInfo, Env, Timestamp, TransactionInfo};
376/// use cosmwasm_std::testing::mock_env;
377///
378/// let env1 = mock_env();
379///
380/// // First test with `env1`
381///
382/// let mut env2 = env1.clone();
383/// env2.block.height += 1;
384/// env2.block.time = env1.block.time.plus_seconds(6);
385///
386/// // `env2` is one block and 6 seconds later
387///
388/// let mut env3 = env2.clone();
389/// env3.block.height += 1;
390/// env3.block.time = env2.block.time.plus_nanos(5_500_000_000);
391///
392/// // `env3` is one block and 5.5 seconds later
393/// ```
394pub fn mock_env() -> Env {
395    let mut envs = Envs::new(BECH32_PREFIX);
396    envs.make()
397}
398
399/// A factory type that stores chain information such as bech32 prefix and can make mock `Env`s from there.
400///
401/// It increments height for each mock call and block time by 5 seconds but is otherwise dumb.
402///
403/// In contrast to using `mock_env`, the bech32 prefix must always be specified.
404///
405/// ## Examples
406///
407/// Typical usage
408///
409/// ```
410/// # use cosmwasm_std::Timestamp;
411/// use cosmwasm_std::testing::Envs;
412///
413/// let mut envs = Envs::new("food");
414///
415/// let env = envs.make();
416/// assert_eq!(env.contract.address.as_str(), "food1jpev2csrppg792t22rn8z8uew8h3sjcpglcd0qv9g8gj8ky922ts74yrjj");
417/// assert_eq!(env.block.height, 12_345);
418/// assert_eq!(env.block.time, Timestamp::from_nanos(1_571_797_419_879_305_533));
419///
420/// let env = envs.make();
421/// assert_eq!(env.contract.address.as_str(), "food1jpev2csrppg792t22rn8z8uew8h3sjcpglcd0qv9g8gj8ky922ts74yrjj");
422/// assert_eq!(env.block.height, 12_346);
423/// assert_eq!(env.block.time, Timestamp::from_nanos(1_571_797_424_879_305_533));
424///
425/// let env = envs.make();
426/// assert_eq!(env.contract.address.as_str(), "food1jpev2csrppg792t22rn8z8uew8h3sjcpglcd0qv9g8gj8ky922ts74yrjj");
427/// assert_eq!(env.block.height, 12_347);
428/// assert_eq!(env.block.time, Timestamp::from_nanos(1_571_797_429_879_305_533));
429/// ```
430///
431/// Or use with iterator
432///
433/// ```
434/// # use cosmwasm_std::Timestamp;
435/// use cosmwasm_std::testing::Envs;
436///
437/// let mut envs = Envs::new("food");
438///
439/// for (index, env) in envs.take(100).enumerate() {
440///     assert_eq!(env.contract.address.as_str(), "food1jpev2csrppg792t22rn8z8uew8h3sjcpglcd0qv9g8gj8ky922ts74yrjj");
441///     assert_eq!(env.block.height, 12_345 + index as u64);
442///     assert_eq!(env.block.time, Timestamp::from_nanos(1_571_797_419_879_305_533).plus_seconds((index*5) as u64));
443/// }
444/// ```
445pub struct Envs {
446    chain_id: String,
447    contract_address: Addr,
448    /// The number of nanoseconds between two consecutive blocks
449    block_time: u64,
450    last_height: u64,
451    last_time: Timestamp,
452}
453
454/// Options to create an `Envs` instance.
455///
456/// ## Examples
457///
458/// Must be constructed with the help of `Default` since new options might be added later.
459///
460/// ```
461/// # use cosmwasm_std::Timestamp;
462/// use cosmwasm_std::testing::{Envs, EnvsOptions};
463///
464/// let mut options = EnvsOptions::default();
465/// options.chain_id = "megachain".to_string();
466/// options.bech32_prefix = "mega";
467/// let mut envs = Envs::with_options(options);
468///
469/// let env = envs.make();
470/// assert_eq!(env.block.chain_id, "megachain");
471/// assert_eq!(env.contract.address.as_str(), "mega1jpev2csrppg792t22rn8z8uew8h3sjcpglcd0qv9g8gj8ky922ts7vnj8h");
472/// ```
473#[derive(Clone, Debug)]
474#[non_exhaustive]
475pub struct EnvsOptions {
476    pub bech32_prefix: &'static str, /* static due to MockApi's Copy requirement. No better idea for now. */
477    pub block_time: u64,
478    // The height before the first `make` call
479    pub initial_height: u64,
480    // The block time before the first `make` call
481    pub initial_time: Timestamp,
482    pub chain_id: String,
483}
484
485impl Default for EnvsOptions {
486    fn default() -> Self {
487        EnvsOptions {
488            bech32_prefix: BECH32_PREFIX,
489            block_time: 5_000_000_000, // 5s
490            initial_height: 12_344,
491            initial_time: Timestamp::from_nanos(1_571_797_419_879_305_533).minus_seconds(5),
492            chain_id: "cosmos-testnet-14002".to_string(),
493        }
494    }
495}
496
497impl Envs {
498    pub fn new(bech32_prefix: &'static str) -> Self {
499        Self::with_options(EnvsOptions {
500            bech32_prefix,
501            ..Default::default()
502        })
503    }
504
505    pub fn with_options(options: EnvsOptions) -> Self {
506        let api = MockApi::default().with_prefix(options.bech32_prefix);
507        Envs {
508            chain_id: options.chain_id,
509            // Default values here for compatibility with old `mock_env` function. They could be changed to anything else if there is a good reason.
510            contract_address: api.addr_make("cosmos2contract"),
511            block_time: options.block_time,
512            last_height: options.initial_height,
513            last_time: options.initial_time,
514        }
515    }
516
517    pub fn make(&mut self) -> Env {
518        self.checked_make().unwrap()
519    }
520
521    fn checked_make(&mut self) -> Option<Env> {
522        let height = self.last_height.checked_add(1)?;
523        let time = Timestamp::from_nanos(self.last_time.nanos().checked_add(self.block_time)?);
524
525        self.last_height = height;
526        self.last_time = time;
527
528        Some(Env {
529            block: BlockInfo {
530                height,
531                time,
532                chain_id: self.chain_id.clone(),
533            },
534            transaction: Some(TransactionInfo::new(
535                3,
536                Binary::from_hex(
537                    "E5469DACEC17CEF8A260FD37675ED87E7FB6A2B5AD95193C51308006C7E494B3",
538                )
539                .unwrap(),
540            )),
541            contract: ContractInfo {
542                address: self.contract_address.clone(),
543            },
544        })
545    }
546}
547
548impl Default for Envs {
549    fn default() -> Self {
550        Envs::with_options(EnvsOptions::default())
551    }
552}
553
554// The iterator implementation ends in case of overflows to avoid panics.
555// Using this is recommended for very long running test suites.
556impl Iterator for Envs {
557    type Item = Env;
558
559    fn next(&mut self) -> Option<Self::Item> {
560        self.checked_make()
561    }
562}
563
564/// Creates an IbcChannel for testing. You set a few key parameters for handshaking,
565/// If you want to set more, use this as a default and mutate other fields
566#[cfg(feature = "stargate")]
567pub fn mock_ibc_channel(my_channel_id: &str, order: IbcOrder, version: &str) -> IbcChannel {
568    IbcChannel {
569        endpoint: IbcEndpoint {
570            port_id: "my_port".to_string(),
571            channel_id: my_channel_id.to_string(),
572        },
573        counterparty_endpoint: IbcEndpoint {
574            port_id: "their_port".to_string(),
575            channel_id: "channel-7".to_string(),
576        },
577        order,
578        version: version.to_string(),
579        connection_id: "connection-2".to_string(),
580    }
581}
582
583/// Creates a IbcChannelOpenMsg::OpenInit for testing ibc_channel_open.
584#[cfg(feature = "stargate")]
585pub fn mock_ibc_channel_open_init(
586    my_channel_id: &str,
587    order: IbcOrder,
588    version: &str,
589) -> IbcChannelOpenMsg {
590    IbcChannelOpenMsg::new_init(mock_ibc_channel(my_channel_id, order, version))
591}
592
593/// Creates a IbcChannelOpenMsg::OpenTry for testing ibc_channel_open.
594#[cfg(feature = "stargate")]
595pub fn mock_ibc_channel_open_try(
596    my_channel_id: &str,
597    order: IbcOrder,
598    version: &str,
599) -> IbcChannelOpenMsg {
600    IbcChannelOpenMsg::new_try(mock_ibc_channel(my_channel_id, order, version), version)
601}
602
603/// Creates a IbcChannelConnectMsg::ConnectAck for testing ibc_channel_connect.
604#[cfg(feature = "stargate")]
605pub fn mock_ibc_channel_connect_ack(
606    my_channel_id: &str,
607    order: IbcOrder,
608    version: &str,
609) -> IbcChannelConnectMsg {
610    IbcChannelConnectMsg::new_ack(mock_ibc_channel(my_channel_id, order, version), version)
611}
612
613/// Creates a IbcChannelConnectMsg::ConnectConfirm for testing ibc_channel_connect.
614#[cfg(feature = "stargate")]
615pub fn mock_ibc_channel_connect_confirm(
616    my_channel_id: &str,
617    order: IbcOrder,
618    version: &str,
619) -> IbcChannelConnectMsg {
620    IbcChannelConnectMsg::new_confirm(mock_ibc_channel(my_channel_id, order, version))
621}
622
623/// Creates a IbcChannelCloseMsg::CloseInit for testing ibc_channel_close.
624#[cfg(feature = "stargate")]
625pub fn mock_ibc_channel_close_init(
626    my_channel_id: &str,
627    order: IbcOrder,
628    version: &str,
629) -> IbcChannelCloseMsg {
630    IbcChannelCloseMsg::new_init(mock_ibc_channel(my_channel_id, order, version))
631}
632
633/// Creates a IbcChannelCloseMsg::CloseConfirm for testing ibc_channel_close.
634#[cfg(feature = "stargate")]
635pub fn mock_ibc_channel_close_confirm(
636    my_channel_id: &str,
637    order: IbcOrder,
638    version: &str,
639) -> IbcChannelCloseMsg {
640    IbcChannelCloseMsg::new_confirm(mock_ibc_channel(my_channel_id, order, version))
641}
642
643/// Creates a IbcPacketReceiveMsg for testing ibc_packet_receive. You set a few key parameters that are
644/// often parsed. If you want to set more, use this as a default and mutate other fields
645#[cfg(feature = "stargate")]
646pub fn mock_ibc_packet_recv(
647    my_channel_id: &str,
648    data: &impl Serialize,
649) -> StdResult<IbcPacketReceiveMsg> {
650    Ok(IbcPacketReceiveMsg::new(
651        IbcPacket {
652            data: to_json_binary(data)?,
653            src: IbcEndpoint {
654                port_id: "their-port".to_string(),
655                channel_id: "channel-1234".to_string(),
656            },
657            dest: IbcEndpoint {
658                port_id: "our-port".to_string(),
659                channel_id: my_channel_id.into(),
660            },
661            sequence: 27,
662            timeout: IbcTimeoutBlock {
663                revision: 1,
664                height: 12345678,
665            }
666            .into(),
667        },
668        Addr::unchecked("relayer"),
669    ))
670}
671
672/// Creates a Ibc2PacketAckMsg for testing ibc2_packet_ack. You set a few key parameters that are
673/// often parsed. If you want to set more, use this as a default and mutate other fields
674#[cfg(feature = "ibc2")]
675pub fn mock_ibc2_packet_ack(data: &impl Serialize) -> StdResult<Ibc2PacketAckMsg> {
676    Ok(Ibc2PacketAckMsg::new(
677        "source_id23".to_string(),
678        "channel_id23".to_string(),
679        Ibc2Payload {
680            source_port: "wasm2srcport".to_string(),
681            destination_port: "wasm2destport".to_string(),
682            version: "v2".to_string(),
683            encoding: "json".to_string(),
684            value: to_json_binary(data)?,
685        },
686        Binary::new(vec![]),
687        Addr::unchecked("relayer"),
688    ))
689}
690
691/// Creates a IbcPacketReceiveMsg for testing ibc_packet_receive. You set a few key parameters that are
692/// often parsed. If you want to set more, use this as a default and mutate other fields
693#[cfg(feature = "ibc2")]
694pub fn mock_ibc2_packet_recv(data: &impl Serialize) -> StdResult<Ibc2PacketReceiveMsg> {
695    Ok(Ibc2PacketReceiveMsg::new(
696        Ibc2Payload {
697            source_port: "wasm2srcport".to_string(),
698            destination_port: "wasm2destport".to_string(),
699            version: "v2".to_string(),
700            encoding: "json".to_string(),
701            value: to_json_binary(data)?,
702        },
703        Addr::unchecked("relayer"),
704        "channel_id23".to_string(),
705        42,
706    ))
707}
708
709/// Creates a Ibc2PacketTimeoutMsg for testing ibc2_packet_timeout.
710#[cfg(feature = "ibc2")]
711pub fn mock_ibc2_packet_timeout(data: &impl Serialize) -> StdResult<Ibc2PacketTimeoutMsg> {
712    let payload = Ibc2Payload {
713        source_port: "wasm2srcport".to_string(),
714        destination_port: "wasm2destport".to_string(),
715        version: "v2".to_string(),
716        encoding: "json".to_string(),
717        value: to_json_binary(data)?,
718    };
719    Ok(Ibc2PacketTimeoutMsg::new(
720        payload,
721        "source_client".to_string(),
722        "destination_client".to_string(),
723        1,
724        Addr::unchecked("relayer"),
725    ))
726}
727
728/// Creates a Ibc2PacketTimeoutMsg for testing ibc2_packet_timeout.
729#[cfg(feature = "ibc2")]
730pub fn mock_ibc2_packet_send(data: &impl Serialize) -> StdResult<Ibc2PacketSendMsg> {
731    let payload = Ibc2Payload {
732        source_port: "wasm2srcport".to_string(),
733        destination_port: "wasm2destport".to_string(),
734        version: "v2".to_string(),
735        encoding: "json".to_string(),
736        value: to_json_binary(data)?,
737    };
738    Ok(Ibc2PacketSendMsg::new(
739        payload,
740        "source_client".to_string(),
741        "destination_client".to_string(),
742        1,
743        Addr::unchecked("signer_contract"),
744    ))
745}
746
747/// Creates a IbcPacket for testing ibc_packet_{ack,timeout}. You set a few key parameters that are
748/// often parsed. If you want to set more, use this as a default and mutate other fields.
749/// The difference from mock_ibc_packet_recv is if `my_channel_id` is src or dest.
750#[cfg(feature = "stargate")]
751fn mock_ibc_packet(my_channel_id: &str, data: &impl Serialize) -> StdResult<IbcPacket> {
752    Ok(IbcPacket {
753        data: to_json_binary(data)?,
754        src: IbcEndpoint {
755            port_id: "their-port".to_string(),
756            channel_id: my_channel_id.into(),
757        },
758        dest: IbcEndpoint {
759            port_id: "our-port".to_string(),
760            channel_id: "channel-1234".to_string(),
761        },
762        sequence: 29,
763        timeout: IbcTimeoutBlock {
764            revision: 1,
765            height: 432332552,
766        }
767        .into(),
768    })
769}
770
771/// Creates a IbcPacketAckMsg for testing ibc_packet_ack. You set a few key parameters that are
772/// often parsed. If you want to set more, use this as a default and mutate other fields.
773/// The difference from mock_ibc_packet_recv is if `my_channel_id` is src or dest.
774#[cfg(feature = "stargate")]
775pub fn mock_ibc_packet_ack(
776    my_channel_id: &str,
777    data: &impl Serialize,
778    ack: IbcAcknowledgement,
779) -> StdResult<IbcPacketAckMsg> {
780    let packet = mock_ibc_packet(my_channel_id, data)?;
781
782    Ok(IbcPacketAckMsg::new(
783        ack,
784        packet,
785        Addr::unchecked("relayer"),
786    ))
787}
788
789/// Creates a IbcPacketTimeoutMsg for testing ibc_packet_timeout. You set a few key parameters that are
790/// often parsed. If you want to set more, use this as a default and mutate other fields.
791/// The difference from mock_ibc_packet_recv is if `my_channel_id` is src or dest.
792#[cfg(feature = "stargate")]
793pub fn mock_ibc_packet_timeout(
794    my_channel_id: &str,
795    data: &impl Serialize,
796) -> StdResult<IbcPacketTimeoutMsg> {
797    let packet = mock_ibc_packet(my_channel_id, data)?;
798    Ok(IbcPacketTimeoutMsg::new(packet, Addr::unchecked("relayer")))
799}
800
801/// The same type as cosmwasm-std's QuerierResult, but easier to reuse in
802/// cosmwasm-vm. It might diverge from QuerierResult at some point.
803pub type MockQuerierCustomHandlerResult = SystemResult<ContractResult<Binary>>;
804
805/// MockQuerier holds an immutable table of bank balances
806/// and configurable handlers for Wasm queries and custom queries.
807pub struct MockQuerier<C: DeserializeOwned = Empty> {
808    pub bank: BankQuerier,
809    #[cfg(feature = "staking")]
810    pub staking: StakingQuerier,
811    #[cfg(feature = "cosmwasm_1_3")]
812    pub distribution: DistributionQuerier,
813    wasm: WasmQuerier,
814    #[cfg(feature = "stargate")]
815    pub ibc: IbcQuerier,
816    /// A handler to handle custom queries. This is set to a dummy handler that
817    /// always errors by default. Update it via `with_custom_handler`.
818    ///
819    /// Use box to avoid the need of another generic type
820    custom_handler: Box<dyn for<'a> Fn(&'a C) -> MockQuerierCustomHandlerResult>,
821}
822
823impl<C: DeserializeOwned> MockQuerier<C> {
824    pub fn new(balances: &[(&str, &[Coin])]) -> Self {
825        MockQuerier {
826            bank: BankQuerier::new(balances),
827            #[cfg(feature = "cosmwasm_1_3")]
828            distribution: DistributionQuerier::default(),
829            #[cfg(feature = "staking")]
830            staking: StakingQuerier::default(),
831            wasm: WasmQuerier::default(),
832            #[cfg(feature = "stargate")]
833            ibc: IbcQuerier::default(),
834            // strange argument notation suggested as a workaround here: https://github.com/rust-lang/rust/issues/41078#issuecomment-294296365
835            custom_handler: Box::from(|_: &_| -> MockQuerierCustomHandlerResult {
836                SystemResult::Err(SystemError::UnsupportedRequest {
837                    kind: "custom".to_string(),
838                })
839            }),
840        }
841    }
842
843    pub fn update_wasm<WH>(&mut self, handler: WH)
844    where
845        WH: Fn(&WasmQuery) -> QuerierResult + 'static,
846    {
847        self.wasm.update_handler(handler)
848    }
849
850    pub fn with_custom_handler<CH>(mut self, handler: CH) -> Self
851    where
852        CH: Fn(&C) -> MockQuerierCustomHandlerResult + 'static,
853    {
854        self.custom_handler = Box::from(handler);
855        self
856    }
857}
858
859impl Default for MockQuerier {
860    fn default() -> Self {
861        MockQuerier::new(&[])
862    }
863}
864
865impl<C: CustomQuery + DeserializeOwned> Querier for MockQuerier<C> {
866    fn raw_query(&self, bin_request: &[u8]) -> QuerierResult {
867        let request: QueryRequest<C> = match from_json(bin_request) {
868            Ok(v) => v,
869            Err(e) => {
870                return SystemResult::Err(SystemError::InvalidRequest {
871                    error: format!("Parsing query request: {e}"),
872                    request: bin_request.into(),
873                })
874            }
875        };
876        self.handle_query(&request)
877    }
878}
879
880impl<C: CustomQuery + DeserializeOwned> MockQuerier<C> {
881    pub fn handle_query(&self, request: &QueryRequest<C>) -> QuerierResult {
882        match &request {
883            QueryRequest::Bank(bank_query) => self.bank.query(bank_query),
884            QueryRequest::Custom(custom_query) => (*self.custom_handler)(custom_query),
885            #[cfg(feature = "staking")]
886            QueryRequest::Staking(staking_query) => self.staking.query(staking_query),
887            #[cfg(feature = "cosmwasm_1_3")]
888            QueryRequest::Distribution(distribution_query) => {
889                self.distribution.query(distribution_query)
890            }
891            QueryRequest::Wasm(msg) => self.wasm.query(msg),
892            #[cfg(feature = "stargate")]
893            #[allow(deprecated)]
894            QueryRequest::Stargate { .. } => SystemResult::Err(SystemError::UnsupportedRequest {
895                kind: "Stargate".to_string(),
896            }),
897            #[cfg(feature = "cosmwasm_2_0")]
898            QueryRequest::Grpc(_) => SystemResult::Err(SystemError::UnsupportedRequest {
899                kind: "GRPC".to_string(),
900            }),
901            #[cfg(feature = "stargate")]
902            QueryRequest::Ibc(msg) => self.ibc.query(msg),
903        }
904    }
905}
906
907struct WasmQuerier {
908    /// A handler to handle Wasm queries. This is set to a dummy handler that
909    /// always errors by default. Update it via `with_custom_handler`.
910    ///
911    /// Use box to avoid the need of generic type.
912    handler: Box<dyn for<'a> Fn(&'a WasmQuery) -> QuerierResult>,
913}
914
915impl WasmQuerier {
916    fn new(handler: Box<dyn for<'a> Fn(&'a WasmQuery) -> QuerierResult>) -> Self {
917        Self { handler }
918    }
919
920    fn update_handler<WH>(&mut self, handler: WH)
921    where
922        WH: Fn(&WasmQuery) -> QuerierResult + 'static,
923    {
924        self.handler = Box::from(handler)
925    }
926
927    fn query(&self, request: &WasmQuery) -> QuerierResult {
928        (*self.handler)(request)
929    }
930}
931
932impl Default for WasmQuerier {
933    fn default() -> Self {
934        let handler = Box::from(|request: &WasmQuery| -> QuerierResult {
935            let err = match request {
936                WasmQuery::Smart { contract_addr, .. } => SystemError::NoSuchContract {
937                    addr: contract_addr.clone(),
938                },
939                WasmQuery::Raw { contract_addr, .. } => SystemError::NoSuchContract {
940                    addr: contract_addr.clone(),
941                },
942                WasmQuery::ContractInfo { contract_addr, .. } => SystemError::NoSuchContract {
943                    addr: contract_addr.clone(),
944                },
945                #[cfg(feature = "cosmwasm_1_2")]
946                WasmQuery::CodeInfo { code_id, .. } => {
947                    SystemError::NoSuchCode { code_id: *code_id }
948                }
949                #[cfg(all(feature = "cosmwasm_3_0", feature = "iterator"))]
950                WasmQuery::RawRange { contract_addr, .. } => SystemError::NoSuchContract {
951                    addr: contract_addr.clone(),
952                },
953            };
954            SystemResult::Err(err)
955        });
956        Self::new(handler)
957    }
958}
959
960#[derive(Clone, Default)]
961pub struct BankQuerier {
962    #[allow(dead_code)]
963    /// BTreeMap<denom, amount>
964    supplies: BTreeMap<String, Uint256>,
965    /// A map from address to balance. The address is the String conversion of `Addr`,
966    /// i.e. the bech32 encoded address.
967    balances: BTreeMap<String, Vec<Coin>>,
968    /// Vec<Metadata>
969    denom_metadata: BTreeMap<Vec<u8>, DenomMetadata>,
970}
971
972impl BankQuerier {
973    pub fn new(balances: &[(&str, &[Coin])]) -> Self {
974        let balances: BTreeMap<_, _> = balances
975            .iter()
976            .map(|(address, balance)| (address.to_string(), balance.to_vec()))
977            .collect();
978
979        BankQuerier {
980            supplies: Self::calculate_supplies(&balances),
981            balances,
982            denom_metadata: BTreeMap::new(),
983        }
984    }
985
986    /// set a new balance for the given address and return the old balance
987    pub fn update_balance(
988        &mut self,
989        addr: impl Into<String>,
990        balance: Vec<Coin>,
991    ) -> Option<Vec<Coin>> {
992        let result = self.balances.insert(addr.into(), balance);
993        self.supplies = Self::calculate_supplies(&self.balances);
994
995        result
996    }
997
998    pub fn set_denom_metadata(&mut self, denom_metadata: &[DenomMetadata]) {
999        self.denom_metadata = denom_metadata
1000            .iter()
1001            .map(|d| (d.base.as_bytes().to_vec(), d.clone()))
1002            .collect();
1003    }
1004
1005    fn calculate_supplies(balances: &BTreeMap<String, Vec<Coin>>) -> BTreeMap<String, Uint256> {
1006        let mut supplies = BTreeMap::new();
1007
1008        let all_coins = balances.iter().flat_map(|(_, coins)| coins);
1009
1010        for coin in all_coins {
1011            *supplies
1012                .entry(coin.denom.clone())
1013                .or_insert_with(Uint256::zero) += coin.amount;
1014        }
1015
1016        supplies
1017    }
1018
1019    pub fn query(&self, request: &BankQuery) -> QuerierResult {
1020        let contract_result: ContractResult<Binary> = match request {
1021            #[cfg(feature = "cosmwasm_1_1")]
1022            BankQuery::Supply { denom } => {
1023                let amount = self
1024                    .supplies
1025                    .get(denom)
1026                    .cloned()
1027                    .unwrap_or_else(Uint256::zero);
1028                let bank_res = SupplyResponse {
1029                    amount: Coin {
1030                        amount,
1031                        denom: denom.to_string(),
1032                    },
1033                };
1034                to_json_binary(&bank_res).into()
1035            }
1036            BankQuery::Balance { address, denom } => {
1037                // proper error on not found, serialize result on found
1038                let amount = self
1039                    .balances
1040                    .get(address)
1041                    .and_then(|v| v.iter().find(|c| &c.denom == denom).map(|c| c.amount))
1042                    .unwrap_or_default();
1043                let bank_res = BalanceResponse {
1044                    amount: Coin {
1045                        amount,
1046                        denom: denom.to_string(),
1047                    },
1048                };
1049                to_json_binary(&bank_res).into()
1050            }
1051            #[cfg(feature = "cosmwasm_1_3")]
1052            BankQuery::DenomMetadata { denom } => {
1053                let denom_metadata = self.denom_metadata.get(denom.as_bytes());
1054                match denom_metadata {
1055                    Some(m) => {
1056                        let metadata_res = DenomMetadataResponse {
1057                            metadata: m.clone(),
1058                        };
1059                        to_json_binary(&metadata_res).into()
1060                    }
1061                    None => return SystemResult::Err(SystemError::Unknown {}),
1062                }
1063            }
1064            #[cfg(feature = "cosmwasm_1_3")]
1065            BankQuery::AllDenomMetadata { pagination } => {
1066                let default_pagination = PageRequest {
1067                    key: None,
1068                    limit: 100,
1069                    reverse: false,
1070                };
1071                let pagination = pagination.as_ref().unwrap_or(&default_pagination);
1072
1073                // range of all denoms after the given key (or until the key for reverse)
1074                let range = match (pagination.reverse, &pagination.key) {
1075                    (_, None) => (Bound::Unbounded, Bound::Unbounded),
1076                    (true, Some(key)) => (Bound::Unbounded, Bound::Included(key.as_slice())),
1077                    (false, Some(key)) => (Bound::Included(key.as_slice()), Bound::Unbounded),
1078                };
1079                let iter = self.denom_metadata.range::<[u8], _>(range);
1080                // using dynamic dispatch here to reduce code duplication and since this is only testing code
1081                let iter: Box<dyn Iterator<Item = _>> = if pagination.reverse {
1082                    Box::new(iter.rev())
1083                } else {
1084                    Box::new(iter)
1085                };
1086
1087                let mut metadata: Vec<_> = iter
1088                    // take the requested amount + 1 to get the next key
1089                    .take((pagination.limit.saturating_add(1)) as usize)
1090                    .map(|(_, m)| m.clone())
1091                    .collect();
1092
1093                // if we took more than requested, remove the last element (the next key),
1094                // otherwise this is the last batch
1095                let next_key = if metadata.len() > pagination.limit as usize {
1096                    metadata.pop().map(|m| Binary::from(m.base.as_bytes()))
1097                } else {
1098                    None
1099                };
1100
1101                let metadata_res = AllDenomMetadataResponse { metadata, next_key };
1102                to_json_binary(&metadata_res).into()
1103            }
1104        };
1105        // system result is always ok in the mock implementation
1106        SystemResult::Ok(contract_result)
1107    }
1108}
1109
1110#[cfg(feature = "stargate")]
1111#[derive(Clone, Default)]
1112pub struct IbcQuerier {
1113    port_id: String,
1114    channels: Vec<IbcChannel>,
1115}
1116
1117#[cfg(feature = "stargate")]
1118impl IbcQuerier {
1119    /// Create a mock querier where:
1120    /// - port_id is the port the "contract" is bound to
1121    /// - channels are a list of ibc channels
1122    pub fn new(port_id: &str, channels: &[IbcChannel]) -> Self {
1123        IbcQuerier {
1124            port_id: port_id.to_string(),
1125            channels: channels.to_vec(),
1126        }
1127    }
1128
1129    /// Update the querier's configuration
1130    pub fn update(&mut self, port_id: impl Into<String>, channels: &[IbcChannel]) {
1131        self.port_id = port_id.into();
1132        self.channels = channels.to_vec();
1133    }
1134
1135    pub fn query(&self, request: &IbcQuery) -> QuerierResult {
1136        let contract_result: ContractResult<Binary> = match request {
1137            IbcQuery::Channel {
1138                channel_id,
1139                port_id,
1140            } => {
1141                let channel = self
1142                    .channels
1143                    .iter()
1144                    .find(|c| match port_id {
1145                        Some(p) => c.endpoint.channel_id.eq(channel_id) && c.endpoint.port_id.eq(p),
1146                        None => {
1147                            c.endpoint.channel_id.eq(channel_id)
1148                                && c.endpoint.port_id == self.port_id
1149                        }
1150                    })
1151                    .cloned();
1152                let res = ChannelResponse { channel };
1153                to_json_binary(&res).into()
1154            }
1155            IbcQuery::PortId {} => {
1156                let res = PortIdResponse {
1157                    port_id: self.port_id.clone(),
1158                };
1159                to_json_binary(&res).into()
1160            }
1161        };
1162        // system result is always ok in the mock implementation
1163        SystemResult::Ok(contract_result)
1164    }
1165}
1166
1167#[cfg(feature = "staking")]
1168#[derive(Clone, Default)]
1169pub struct StakingQuerier {
1170    denom: String,
1171    validators: Vec<Validator>,
1172    delegations: Vec<FullDelegation>,
1173}
1174
1175#[cfg(feature = "staking")]
1176impl StakingQuerier {
1177    pub fn new(denom: &str, validators: &[Validator], delegations: &[FullDelegation]) -> Self {
1178        StakingQuerier {
1179            denom: denom.to_string(),
1180            validators: validators.to_vec(),
1181            delegations: delegations.to_vec(),
1182        }
1183    }
1184
1185    /// Update the querier's configuration
1186    pub fn update(
1187        &mut self,
1188        denom: impl Into<String>,
1189        validators: &[Validator],
1190        delegations: &[FullDelegation],
1191    ) {
1192        self.denom = denom.into();
1193        self.validators = validators.to_vec();
1194        self.delegations = delegations.to_vec();
1195    }
1196
1197    pub fn query(&self, request: &StakingQuery) -> QuerierResult {
1198        let contract_result: ContractResult<Binary> = match request {
1199            StakingQuery::BondedDenom {} => {
1200                let res = BondedDenomResponse {
1201                    denom: self.denom.clone(),
1202                };
1203                to_json_binary(&res).into()
1204            }
1205            StakingQuery::AllValidators {} => {
1206                let res = AllValidatorsResponse {
1207                    validators: self.validators.clone(),
1208                };
1209                to_json_binary(&res).into()
1210            }
1211            StakingQuery::Validator { address } => {
1212                let validator: Option<Validator> = self
1213                    .validators
1214                    .iter()
1215                    .find(|validator| validator.address == *address)
1216                    .cloned();
1217                let res = ValidatorResponse { validator };
1218                to_json_binary(&res).into()
1219            }
1220            StakingQuery::AllDelegations { delegator } => {
1221                let delegations: Vec<_> = self
1222                    .delegations
1223                    .iter()
1224                    .filter(|d| d.delegator.as_str() == delegator)
1225                    .cloned()
1226                    .map(|d| d.into())
1227                    .collect();
1228                let res = AllDelegationsResponse { delegations };
1229                to_json_binary(&res).into()
1230            }
1231            StakingQuery::Delegation {
1232                delegator,
1233                validator,
1234            } => {
1235                let delegation = self
1236                    .delegations
1237                    .iter()
1238                    .find(|d| d.delegator.as_str() == delegator && d.validator == *validator);
1239                let res = DelegationResponse {
1240                    delegation: delegation.cloned(),
1241                };
1242                to_json_binary(&res).into()
1243            }
1244        };
1245        // system result is always ok in the mock implementation
1246        SystemResult::Ok(contract_result)
1247    }
1248}
1249
1250#[cfg(feature = "cosmwasm_1_3")]
1251#[derive(Clone, Default)]
1252pub struct DistributionQuerier {
1253    withdraw_addresses: BTreeMap<String, String>,
1254    /// Mock of accumulated rewards, indexed first by delegator and then validator address.
1255    rewards: BTreeMap<String, BTreeMap<String, Vec<DecCoin>>>,
1256    /// Mock of validators that a delegator has bonded to.
1257    validators: BTreeMap<String, BTreeSet<String>>,
1258}
1259
1260#[cfg(feature = "cosmwasm_1_3")]
1261impl DistributionQuerier {
1262    pub fn new<T>(withdraw_addresses: T) -> Self
1263    where
1264        T: IntoIterator<Item = (String, String)>,
1265    {
1266        DistributionQuerier {
1267            withdraw_addresses: withdraw_addresses.into_iter().collect(),
1268            ..Default::default()
1269        }
1270    }
1271
1272    pub fn set_withdraw_address(
1273        &mut self,
1274        delegator_address: impl Into<String>,
1275        withdraw_address: impl Into<String>,
1276    ) {
1277        self.withdraw_addresses
1278            .insert(delegator_address.into(), withdraw_address.into());
1279    }
1280
1281    /// Sets multiple withdraw addresses.
1282    ///
1283    /// This allows passing multiple tuples of `(delegator_address, withdraw_address)`.
1284    /// It does not overwrite existing entries.
1285    pub fn set_withdraw_addresses(
1286        &mut self,
1287        withdraw_addresses: impl IntoIterator<Item = (impl Into<String>, impl Into<String>)>,
1288    ) {
1289        for (d, w) in withdraw_addresses {
1290            self.set_withdraw_address(d, w);
1291        }
1292    }
1293
1294    pub fn clear_withdraw_addresses(&mut self) {
1295        self.withdraw_addresses.clear();
1296    }
1297
1298    /// Sets accumulated rewards for a given validator and delegator pair.
1299    pub fn set_rewards(
1300        &mut self,
1301        validator: impl Into<String>,
1302        delegator: impl Into<String>,
1303        rewards: Vec<DecCoin>,
1304    ) {
1305        self.rewards
1306            .entry(delegator.into())
1307            .or_default()
1308            .insert(validator.into(), rewards);
1309    }
1310
1311    /// Sets the validators a given delegator has bonded to.
1312    pub fn set_validators(
1313        &mut self,
1314        delegator: impl Into<String>,
1315        validators: impl IntoIterator<Item = impl Into<String>>,
1316    ) {
1317        self.validators.insert(
1318            delegator.into(),
1319            validators.into_iter().map(Into::into).collect(),
1320        );
1321    }
1322
1323    pub fn query(&self, request: &DistributionQuery) -> QuerierResult {
1324        let contract_result: ContractResult<Binary> = match request {
1325            DistributionQuery::DelegatorWithdrawAddress { delegator_address } => {
1326                let res = DelegatorWithdrawAddressResponse {
1327                    withdraw_address: Addr::unchecked(
1328                        self.withdraw_addresses
1329                            .get(delegator_address)
1330                            .unwrap_or(delegator_address),
1331                    ),
1332                };
1333                to_json_binary(&res).into()
1334            }
1335            #[cfg(feature = "cosmwasm_1_4")]
1336            DistributionQuery::DelegationRewards {
1337                delegator_address,
1338                validator_address,
1339            } => {
1340                let res = DelegationRewardsResponse {
1341                    rewards: self
1342                        .rewards
1343                        .get(delegator_address)
1344                        .and_then(|v| v.get(validator_address))
1345                        .cloned()
1346                        .unwrap_or_default(),
1347                };
1348                to_json_binary(&res).into()
1349            }
1350            #[cfg(feature = "cosmwasm_1_4")]
1351            DistributionQuery::DelegationTotalRewards { delegator_address } => {
1352                let validator_rewards = self
1353                    .validator_rewards(delegator_address)
1354                    .unwrap_or_default();
1355                let res = crate::DelegationTotalRewardsResponse {
1356                    total: validator_rewards
1357                        .iter()
1358                        .fold(BTreeMap::<&str, DecCoin>::new(), |mut acc, rewards| {
1359                            for coin in &rewards.reward {
1360                                acc.entry(&coin.denom)
1361                                    .or_insert_with(|| DecCoin {
1362                                        denom: coin.denom.clone(),
1363                                        amount: Decimal256::zero(),
1364                                    })
1365                                    .amount += coin.amount;
1366                            }
1367
1368                            acc
1369                        })
1370                        .into_values()
1371                        .collect(),
1372                    rewards: validator_rewards,
1373                };
1374                to_json_binary(&res).into()
1375            }
1376            #[cfg(feature = "cosmwasm_1_4")]
1377            DistributionQuery::DelegatorValidators { delegator_address } => {
1378                let res = DelegatorValidatorsResponse {
1379                    validators: self
1380                        .validators
1381                        .get(delegator_address)
1382                        .map(|set| set.iter().cloned().collect())
1383                        .unwrap_or_default(),
1384                };
1385                to_json_binary(&res).into()
1386            }
1387        };
1388        // system result is always ok in the mock implementation
1389        SystemResult::Ok(contract_result)
1390    }
1391
1392    /// Helper method to get all rewards for a given delegator.
1393    #[cfg(feature = "cosmwasm_1_4")]
1394    fn validator_rewards(&self, delegator_address: &str) -> Option<Vec<crate::DelegatorReward>> {
1395        let validator_rewards = self.rewards.get(delegator_address)?;
1396
1397        Some(
1398            validator_rewards
1399                .iter()
1400                .map(|(validator, rewards)| crate::DelegatorReward {
1401                    validator_address: validator.clone(),
1402                    reward: rewards.clone(),
1403                })
1404                .collect(),
1405        )
1406    }
1407}
1408
1409/// Only for test code. This bypasses assertions in new, allowing us to create _*
1410/// Attributes to simulate responses from the blockchain
1411pub fn mock_wasmd_attr(key: impl Into<String>, value: impl Into<String>) -> Attribute {
1412    Attribute {
1413        key: key.into(),
1414        value: value.into(),
1415    }
1416}
1417
1418#[cfg(test)]
1419mod tests {
1420    use super::*;
1421    #[allow(unused)]
1422    use crate::coins;
1423    #[cfg(feature = "cosmwasm_1_3")]
1424    use crate::DenomUnit;
1425    use crate::{coin, instantiate2_address, ContractInfoResponse, HexBinary, Response, Storage};
1426    #[cfg(feature = "staking")]
1427    use crate::{Decimal, Delegation};
1428    use base64::{engine::general_purpose, Engine};
1429    use cosmwasm_core::BLS12_381_G1_GENERATOR;
1430    use hex_literal::hex;
1431    use serde::Deserialize;
1432
1433    const SECP256K1_MSG_HASH_HEX: &str =
1434        "5ae8317d34d1e595e3fa7247db80c0af4320cce1116de187f8f7e2e099c0d8d0";
1435    const SECP256K1_SIG_HEX: &str = "207082eb2c3dfa0b454e0906051270ba4074ac93760ba9e7110cd9471475111151eb0dbbc9920e72146fb564f99d039802bf6ef2561446eb126ef364d21ee9c4";
1436    const SECP256K1_PUBKEY_HEX: &str = "04051c1ee2190ecfb174bfe4f90763f2b4ff7517b70a2aec1876ebcfd644c4633fb03f3cfbd94b1f376e34592d9d41ccaf640bb751b00a1fadeb0c01157769eb73";
1437
1438    const SECP256R1_MSG_HASH_HEX: &str =
1439        "5eb28029ebf3c7025ff2fc2f6de6f62aecf6a72139e1cba5f20d11bbef036a7f";
1440    const SECP256R1_SIG_HEX: &str = "e67a9717ccf96841489d6541f4f6adb12d17b59a6bef847b6183b8fcf16a32eb9ae6ba6d637706849a6a9fc388cf0232d85c26ea0d1fe7437adb48de58364333";
1441    const SECP256R1_PUBKEY_HEX: &str = "0468229b48c2fe19d3db034e4c15077eb7471a66031f28a980821873915298ba76303e8ee3742a893f78b810991da697083dd8f11128c47651c27a56740a80c24c";
1442
1443    const ED25519_MSG_HEX: &str = "72";
1444    const ED25519_SIG_HEX: &str = "92a009a9f0d4cab8720e820b5f642540a2b27b5416503f8fb3762223ebdb69da085ac1e43e15996e458f3613d0f11d8c387b2eaeb4302aeeb00d291612bb0c00";
1445    const ED25519_PUBKEY_HEX: &str =
1446        "3d4017c3e843895a92b70aa74d1b7ebc9c982ccf2ec4968cc0cd55f12af4660c";
1447
1448    // See https://github.com/drand/kyber-bls12381/issues/22 and
1449    // https://github.com/drand/drand/pull/1249
1450    const DOMAIN_HASH_TO_G2: &[u8] = b"BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_NUL_";
1451
1452    /// Public key League of Entropy Mainnet (curl -sS https://drand.cloudflare.com/info)
1453    const PK_LEO_MAINNET: [u8; 48] = hex!("868f005eb8e6e4ca0a47c8a77ceaa5309a47978a7c71bc5cce96366b5d7a569937c529eeda66c7293784a9402801af31");
1454
1455    const ETH_BLOCK_HEADER: &[u8] =
1456        include_bytes!("../../../crypto/testdata/eth-headers/1699693797.394876721s.json");
1457
1458    #[test]
1459    fn mock_env_works() {
1460        let env = mock_env();
1461        assert_eq!(
1462            env,
1463            Env {
1464                block: BlockInfo {
1465                    height: 12345,
1466                    time: Timestamp::from_nanos(1571797419879305533),
1467                    chain_id: "cosmos-testnet-14002".to_string()
1468                },
1469                transaction: Some(TransactionInfo::new(
1470                    3,
1471                    Binary::from_hex(
1472                        "E5469DACEC17CEF8A260FD37675ED87E7FB6A2B5AD95193C51308006C7E494B3"
1473                    )
1474                    .unwrap(),
1475                )),
1476                contract: ContractInfo {
1477                    address: Addr::unchecked(MOCK_CONTRACT_ADDR)
1478                }
1479            }
1480        )
1481    }
1482
1483    #[test]
1484    fn envs_works() {
1485        let mut envs = Envs::new("food");
1486
1487        let env = envs.make();
1488        assert_eq!(
1489            env.contract.address.as_str(),
1490            "food1jpev2csrppg792t22rn8z8uew8h3sjcpglcd0qv9g8gj8ky922ts74yrjj"
1491        );
1492        assert_eq!(env.block.height, 12_345);
1493        assert_eq!(
1494            env.block.time,
1495            Timestamp::from_nanos(1_571_797_419_879_305_533)
1496        );
1497
1498        let env = envs.make();
1499        assert_eq!(
1500            env.contract.address.as_str(),
1501            "food1jpev2csrppg792t22rn8z8uew8h3sjcpglcd0qv9g8gj8ky922ts74yrjj"
1502        );
1503        assert_eq!(env.block.height, 12_346);
1504        assert_eq!(
1505            env.block.time,
1506            Timestamp::from_nanos(1_571_797_424_879_305_533)
1507        );
1508
1509        let env = envs.make();
1510        assert_eq!(
1511            env.contract.address.as_str(),
1512            "food1jpev2csrppg792t22rn8z8uew8h3sjcpglcd0qv9g8gj8ky922ts74yrjj"
1513        );
1514        assert_eq!(env.block.height, 12_347);
1515        assert_eq!(
1516            env.block.time,
1517            Timestamp::from_nanos(1_571_797_429_879_305_533)
1518        );
1519    }
1520
1521    #[test]
1522    fn envs_implements_iterator() {
1523        let envs = Envs::new("food");
1524
1525        let result: Vec<_> = envs.into_iter().take(5).collect();
1526
1527        assert_eq!(
1528            result[0].contract.address.as_str(),
1529            "food1jpev2csrppg792t22rn8z8uew8h3sjcpglcd0qv9g8gj8ky922ts74yrjj"
1530        );
1531        assert_eq!(result[0].block.height, 12_345);
1532        assert_eq!(
1533            result[0].block.time,
1534            Timestamp::from_nanos(1_571_797_419_879_305_533)
1535        );
1536
1537        assert_eq!(
1538            result[4].contract.address.as_str(),
1539            "food1jpev2csrppg792t22rn8z8uew8h3sjcpglcd0qv9g8gj8ky922ts74yrjj"
1540        );
1541        assert_eq!(result[4].block.height, 12_349);
1542        assert_eq!(
1543            result[4].block.time,
1544            Timestamp::from_nanos(1_571_797_439_879_305_533)
1545        );
1546
1547        // Get a millions envs through iterator
1548        let mut envs = Envs::new("yo");
1549        let first = envs.next().unwrap();
1550        let last = envs.take(1_000_000).last().unwrap();
1551        assert_eq!(first.block.height, 12_345);
1552        assert_eq!(last.block.height, 1_012_345);
1553        assert_eq!(
1554            last.block.time,
1555            first.block.time.plus_seconds(1_000_000 * 5)
1556        );
1557    }
1558
1559    #[test]
1560    fn addr_validate_works() {
1561        // default prefix is 'cosmwasm'
1562        let api = MockApi::default();
1563
1564        // valid
1565        let humanized = "cosmwasm1h34lmpywh4upnjdg90cjf4j70aee6z8qqfspugamjp42e4q28kqs8s7vcp";
1566        let addr = api.addr_validate(humanized).unwrap();
1567        assert_eq!(addr.as_str(), humanized);
1568
1569        // invalid: too short
1570        api.addr_validate("").unwrap_err();
1571        // invalid: not normalized
1572        api.addr_validate("Foobar123").unwrap_err();
1573        api.addr_validate("FOOBAR123").unwrap_err();
1574    }
1575
1576    #[test]
1577    fn addr_canonicalize_works() {
1578        let api = MockApi::default();
1579
1580        api.addr_canonicalize(
1581            "cosmwasm1h34lmpywh4upnjdg90cjf4j70aee6z8qqfspugamjp42e4q28kqs8s7vcp",
1582        )
1583        .unwrap();
1584
1585        // is case insensitive
1586        let data1 = api
1587            .addr_canonicalize(
1588                "cosmwasm1h34lmpywh4upnjdg90cjf4j70aee6z8qqfspugamjp42e4q28kqs8s7vcp",
1589            )
1590            .unwrap();
1591        let data2 = api
1592            .addr_canonicalize(
1593                "COSMWASM1H34LMPYWH4UPNJDG90CJF4J70AEE6Z8QQFSPUGAMJP42E4Q28KQS8S7VCP",
1594            )
1595            .unwrap();
1596        assert_eq!(data1, data2);
1597    }
1598
1599    #[test]
1600    fn canonicalize_and_humanize_restores_original() {
1601        // create api with 'cosmwasm' prefix
1602        let api = MockApi::default();
1603
1604        // normalizes input
1605        let original =
1606            String::from("COSMWASM1H34LMPYWH4UPNJDG90CJF4J70AEE6Z8QQFSPUGAMJP42E4Q28KQS8S7VCP");
1607        let canonical = api.addr_canonicalize(&original).unwrap();
1608        let recovered = api.addr_humanize(&canonical).unwrap();
1609        assert_eq!(
1610            recovered.as_str(),
1611            "cosmwasm1h34lmpywh4upnjdg90cjf4j70aee6z8qqfspugamjp42e4q28kqs8s7vcp"
1612        );
1613
1614        // create api with 'juno' prefix
1615        let api = MockApi::default().with_prefix("juno");
1616
1617        // long input (Juno contract address)
1618        let original =
1619            String::from("juno1v82su97skv6ucfqvuvswe0t5fph7pfsrtraxf0x33d8ylj5qnrysdvkc95");
1620        let canonical = api.addr_canonicalize(&original).unwrap();
1621        let recovered = api.addr_humanize(&canonical).unwrap();
1622        assert_eq!(recovered.as_str(), original);
1623    }
1624
1625    #[test]
1626    fn addr_canonicalize_short_input() {
1627        let api = MockApi::default();
1628
1629        // empty address should fail
1630        let empty = "cosmwasm1pj90vm";
1631        assert!(api
1632            .addr_canonicalize(empty)
1633            .unwrap_err()
1634            .to_string()
1635            .contains("Invalid canonical address length"));
1636
1637        // one byte address should work
1638        let human = "cosmwasm1qqvk2mde";
1639        assert_eq!(api.addr_canonicalize(human).unwrap().as_ref(), [0u8]);
1640    }
1641
1642    #[test]
1643    fn addr_canonicalize_long_input() {
1644        let api = MockApi::default();
1645        let human =
1646            "cosmwasm1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqehqqkz";
1647        let err = api.addr_canonicalize(human).unwrap_err();
1648        assert!(err.to_string().contains("Invalid canonical address length"));
1649    }
1650
1651    #[test]
1652    fn addr_humanize_input_length() {
1653        let api = MockApi::default();
1654        let input = CanonicalAddr::from(vec![]);
1655        assert_eq!(
1656            api.addr_humanize(&input).unwrap_err(),
1657            StdError::generic_err("Invalid canonical address length")
1658        );
1659    }
1660
1661    #[test]
1662    fn bls12_381_aggregate_g1_works() {
1663        #[derive(serde::Deserialize)]
1664        struct EthHeader {
1665            public_keys: Vec<String>,
1666            aggregate_pubkey: String,
1667        }
1668
1669        let api = MockApi::default();
1670        let header: EthHeader = serde_json::from_slice(ETH_BLOCK_HEADER).unwrap();
1671        let expected = general_purpose::STANDARD
1672            .decode(header.aggregate_pubkey)
1673            .unwrap();
1674
1675        let pubkeys: Vec<u8> = header
1676            .public_keys
1677            .into_iter()
1678            .flat_map(|key| general_purpose::STANDARD.decode(key).unwrap())
1679            .collect();
1680        let sum = api.bls12_381_aggregate_g1(&pubkeys).unwrap();
1681
1682        assert_eq!(expected, sum);
1683    }
1684
1685    #[test]
1686    fn bls12_381_aggregate_g2_works() {
1687        let api = MockApi::default();
1688
1689        let points: Vec<u8> = [
1690            hex!("b6ed936746e01f8ecf281f020953fbf1f01debd5657c4a383940b020b26507f6076334f91e2366c96e9ab279fb5158090352ea1c5b0c9274504f4f0e7053af24802e51e4568d164fe986834f41e55c8e850ce1f98458c0cfc9ab380b55285a55"),
1691            hex!("b23c46be3a001c63ca711f87a005c200cc550b9429d5f4eb38d74322144f1b63926da3388979e5321012fb1a0526bcd100b5ef5fe72628ce4cd5e904aeaa3279527843fae5ca9ca675f4f51ed8f83bbf7155da9ecc9663100a885d5dc6df96d9"),
1692            hex!("948a7cb99f76d616c2c564ce9bf4a519f1bea6b0a624a02276443c245854219fabb8d4ce061d255af5330b078d5380681751aa7053da2c98bae898edc218c75f07e24d8802a17cd1f6833b71e58f5eb5b94208b4d0bb3848cecb075ea21be115"),
1693        ]
1694        .into_iter()
1695        .flatten()
1696        .collect();
1697
1698        let expected = hex!("9683b3e6701f9a4b706709577963110043af78a5b41991b998475a3d3fd62abf35ce03b33908418efc95a058494a8ae504354b9f626231f6b3f3c849dfdeaf5017c4780e2aee1850ceaf4b4d9ce70971a3d2cfcd97b7e5ecf6759f8da5f76d31");
1699        let sum = api.bls12_381_aggregate_g2(&points).unwrap();
1700
1701        assert_eq!(sum, expected);
1702    }
1703
1704    #[test]
1705    fn bls12_381_pairing_equality_works() {
1706        let api = MockApi::default();
1707
1708        let dst = b"BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_POP_";
1709        let ps = hex!("a491d1b0ecd9bb917989f0e74f0dea0422eac4a873e5e2644f368dffb9a6e20fd6e10c1b77654d067c0618f6e5a7f79ab301803f8b5ac4a1133581fc676dfedc60d891dd5fa99028805e5ea5b08d3491af75d0707adab3b70c6a6a580217bf81b53d21a4cfd562c469cc81514d4ce5a6b577d8403d32a394dc265dd190b47fa9f829fdd7963afdf972e5e77854051f6f");
1710        let qs: Vec<u8> = [
1711            hex!("0000000000000000000000000000000000000000000000000000000000000000"),
1712            hex!("5656565656565656565656565656565656565656565656565656565656565656"),
1713            hex!("abababababababababababababababababababababababababababababababab"),
1714        ]
1715        .into_iter()
1716        .flat_map(|msg| {
1717            api.bls12_381_hash_to_g2(HashFunction::Sha256, &msg, dst)
1718                .unwrap()
1719        })
1720        .collect();
1721        let s = hex!("9104e74b9dfd3ad502f25d6a5ef57db0ed7d9a0e00f3500586d8ce44231212542fcfaf87840539b398bf07626705cf1105d246ca1062c6c2e1a53029a0f790ed5e3cb1f52f8234dc5144c45fc847c0cd37a92d68e7c5ba7c648a8a339f171244");
1722
1723        let is_valid = api
1724            .bls12_381_pairing_equality(&ps, &qs, &BLS12_381_G1_GENERATOR, &s)
1725            .unwrap();
1726        assert!(is_valid);
1727    }
1728
1729    #[test]
1730    fn bls12_381_hash_to_g1_works() {
1731        // See: <https://datatracker.ietf.org/doc/rfc9380/>; Section J.9.1
1732
1733        let api = MockApi::default();
1734        let msg = b"abc";
1735        let dst = b"QUUX-V01-CS02-with-BLS12381G1_XMD:SHA-256_SSWU_RO_";
1736
1737        let hashed_point = api
1738            .bls12_381_hash_to_g1(HashFunction::Sha256, msg, dst)
1739            .unwrap();
1740        let mut serialized_expected_compressed = hex!("03567bc5ef9c690c2ab2ecdf6a96ef1c139cc0b2f284dca0a9a7943388a49a3aee664ba5379a7655d3c68900be2f6903");
1741        // Set the compression tag
1742        serialized_expected_compressed[0] |= 0b1000_0000;
1743
1744        assert_eq!(hashed_point, serialized_expected_compressed);
1745    }
1746
1747    #[test]
1748    fn bls12_381_hash_to_g2_works() {
1749        let api = MockApi::default();
1750        let msg = b"abc";
1751        let dst = b"QUUX-V01-CS02-with-BLS12381G2_XMD:SHA-256_SSWU_RO_";
1752
1753        let hashed_point = api
1754            .bls12_381_hash_to_g2(HashFunction::Sha256, msg, dst)
1755            .unwrap();
1756        let mut serialized_expected_compressed = hex!("139cddbccdc5e91b9623efd38c49f81a6f83f175e80b06fc374de9eb4b41dfe4ca3a230ed250fbe3a2acf73a41177fd802c2d18e033b960562aae3cab37a27ce00d80ccd5ba4b7fe0e7a210245129dbec7780ccc7954725f4168aff2787776e6");
1757        // Set the compression tag
1758        serialized_expected_compressed[0] |= 0b1000_0000;
1759
1760        assert_eq!(hashed_point, serialized_expected_compressed);
1761    }
1762
1763    #[test]
1764    fn bls12_318_pairing_equality_works() {
1765        fn build_bls_message(round: u64, previous_signature: &[u8]) -> Vec<u8> {
1766            Sha256::new()
1767                .chain_update(previous_signature)
1768                .chain_update(round.to_be_bytes())
1769                .finalize()
1770                .to_vec()
1771        }
1772
1773        let api = MockApi::default();
1774
1775        let previous_signature = hex::decode("a609e19a03c2fcc559e8dae14900aaefe517cb55c840f6e69bc8e4f66c8d18e8a609685d9917efbfb0c37f058c2de88f13d297c7e19e0ab24813079efe57a182554ff054c7638153f9b26a60e7111f71a0ff63d9571704905d3ca6df0b031747").unwrap();
1776        let signature = hex::decode("82f5d3d2de4db19d40a6980e8aa37842a0e55d1df06bd68bddc8d60002e8e959eb9cfa368b3c1b77d18f02a54fe047b80f0989315f83b12a74fd8679c4f12aae86eaf6ab5690b34f1fddd50ee3cc6f6cdf59e95526d5a5d82aaa84fa6f181e42").unwrap();
1777        let round: u64 = 72785;
1778
1779        let msg = build_bls_message(round, &previous_signature);
1780        let msg_point = api
1781            .bls12_381_hash_to_g2(HashFunction::Sha256, &msg, DOMAIN_HASH_TO_G2)
1782            .unwrap();
1783
1784        let is_valid = api
1785            .bls12_381_pairing_equality(
1786                &BLS12_381_G1_GENERATOR,
1787                &signature,
1788                &PK_LEO_MAINNET,
1789                &msg_point,
1790            )
1791            .unwrap();
1792
1793        assert!(is_valid);
1794    }
1795
1796    // Basic "works" test. Exhaustive tests on VM's side (packages/vm/src/imports.rs)
1797    #[test]
1798    fn secp256k1_verify_works() {
1799        let api = MockApi::default();
1800
1801        let hash = hex::decode(SECP256K1_MSG_HASH_HEX).unwrap();
1802        let signature = hex::decode(SECP256K1_SIG_HEX).unwrap();
1803        let public_key = hex::decode(SECP256K1_PUBKEY_HEX).unwrap();
1804
1805        assert!(api
1806            .secp256k1_verify(&hash, &signature, &public_key)
1807            .unwrap());
1808    }
1809
1810    // Basic "fails" test. Exhaustive tests on VM's side (packages/vm/src/imports.rs)
1811    #[test]
1812    fn secp256k1_verify_fails() {
1813        let api = MockApi::default();
1814
1815        let mut hash = hex::decode(SECP256K1_MSG_HASH_HEX).unwrap();
1816        // alter hash
1817        hash[0] ^= 0x01;
1818        let signature = hex::decode(SECP256K1_SIG_HEX).unwrap();
1819        let public_key = hex::decode(SECP256K1_PUBKEY_HEX).unwrap();
1820
1821        assert!(!api
1822            .secp256k1_verify(&hash, &signature, &public_key)
1823            .unwrap());
1824    }
1825
1826    // Basic "errors" test. Exhaustive tests on VM's side (packages/vm/src/imports.rs)
1827    #[test]
1828    fn secp256k1_verify_errs() {
1829        let api = MockApi::default();
1830
1831        let hash = hex::decode(SECP256K1_MSG_HASH_HEX).unwrap();
1832        let signature = hex::decode(SECP256K1_SIG_HEX).unwrap();
1833        let public_key = vec![];
1834
1835        let res = api.secp256k1_verify(&hash, &signature, &public_key);
1836        assert_eq!(res.unwrap_err(), VerificationError::InvalidPubkeyFormat);
1837    }
1838
1839    #[test]
1840    fn secp256k1_recover_pubkey_works() {
1841        let api = MockApi::default();
1842
1843        // https://gist.github.com/webmaster128/130b628d83621a33579751846699ed15
1844        let hash = hex!("5ae8317d34d1e595e3fa7247db80c0af4320cce1116de187f8f7e2e099c0d8d0");
1845        let signature = hex!("45c0b7f8c09a9e1f1cea0c25785594427b6bf8f9f878a8af0b1abbb48e16d0920d8becd0c220f67c51217eecfd7184ef0732481c843857e6bc7fc095c4f6b788");
1846        let recovery_param = 1;
1847        let expected = hex!("044a071e8a6e10aada2b8cf39fa3b5fb3400b04e99ea8ae64ceea1a977dbeaf5d5f8c8fbd10b71ab14cd561f7df8eb6da50f8a8d81ba564342244d26d1d4211595");
1848
1849        let pubkey = api
1850            .secp256k1_recover_pubkey(&hash, &signature, recovery_param)
1851            .unwrap();
1852        assert_eq!(pubkey, expected);
1853    }
1854
1855    #[test]
1856    fn secp256k1_recover_pubkey_fails_for_wrong_recovery_param() {
1857        let api = MockApi::default();
1858
1859        // https://gist.github.com/webmaster128/130b628d83621a33579751846699ed15
1860        let hash = hex!("5ae8317d34d1e595e3fa7247db80c0af4320cce1116de187f8f7e2e099c0d8d0");
1861        let signature = hex!("45c0b7f8c09a9e1f1cea0c25785594427b6bf8f9f878a8af0b1abbb48e16d0920d8becd0c220f67c51217eecfd7184ef0732481c843857e6bc7fc095c4f6b788");
1862        let _recovery_param = 1;
1863        let expected = hex!("044a071e8a6e10aada2b8cf39fa3b5fb3400b04e99ea8ae64ceea1a977dbeaf5d5f8c8fbd10b71ab14cd561f7df8eb6da50f8a8d81ba564342244d26d1d4211595");
1864
1865        // Wrong recovery param leads to different pubkey
1866        let pubkey = api.secp256k1_recover_pubkey(&hash, &signature, 0).unwrap();
1867        assert_eq!(pubkey.len(), 65);
1868        assert_ne!(pubkey, expected);
1869
1870        // Invalid recovery param leads to error
1871        let result = api.secp256k1_recover_pubkey(&hash, &signature, 42);
1872        match result.unwrap_err() {
1873            RecoverPubkeyError::InvalidRecoveryParam => {}
1874            err => panic!("Unexpected error: {err:?}"),
1875        }
1876    }
1877
1878    #[test]
1879    fn secp256k1_recover_pubkey_fails_for_wrong_hash() {
1880        let api = MockApi::default();
1881
1882        // https://gist.github.com/webmaster128/130b628d83621a33579751846699ed15
1883        let hash = hex!("5ae8317d34d1e595e3fa7247db80c0af4320cce1116de187f8f7e2e099c0d8d0");
1884        let signature = hex!("45c0b7f8c09a9e1f1cea0c25785594427b6bf8f9f878a8af0b1abbb48e16d0920d8becd0c220f67c51217eecfd7184ef0732481c843857e6bc7fc095c4f6b788");
1885        let recovery_param = 1;
1886        let expected = hex!("044a071e8a6e10aada2b8cf39fa3b5fb3400b04e99ea8ae64ceea1a977dbeaf5d5f8c8fbd10b71ab14cd561f7df8eb6da50f8a8d81ba564342244d26d1d4211595");
1887
1888        // Wrong hash
1889        let mut corrupted_hash = hash;
1890        corrupted_hash[0] ^= 0x01;
1891        let pubkey = api
1892            .secp256k1_recover_pubkey(&corrupted_hash, &signature, recovery_param)
1893            .unwrap();
1894        assert_eq!(pubkey.len(), 65);
1895        assert_ne!(pubkey, expected);
1896
1897        // Malformed hash
1898        let mut malformed_hash = hash.to_vec();
1899        malformed_hash.push(0x8a);
1900        let result = api.secp256k1_recover_pubkey(&malformed_hash, &signature, recovery_param);
1901        match result.unwrap_err() {
1902            RecoverPubkeyError::InvalidHashFormat => {}
1903            err => panic!("Unexpected error: {err:?}"),
1904        }
1905    }
1906
1907    // Basic "works" test. Exhaustive tests on VM's side (packages/vm/src/imports.rs)
1908    #[test]
1909    fn secp256r1_verify_works() {
1910        let api = MockApi::default();
1911
1912        let hash = hex::decode(SECP256R1_MSG_HASH_HEX).unwrap();
1913        let signature = hex::decode(SECP256R1_SIG_HEX).unwrap();
1914        let public_key = hex::decode(SECP256R1_PUBKEY_HEX).unwrap();
1915
1916        assert!(api
1917            .secp256r1_verify(&hash, &signature, &public_key)
1918            .unwrap());
1919    }
1920
1921    // Basic "fails" test. Exhaustive tests on VM's side (packages/vm/src/imports.rs)
1922    #[test]
1923    fn secp256r1_verify_fails() {
1924        let api = MockApi::default();
1925
1926        let mut hash = hex::decode(SECP256R1_MSG_HASH_HEX).unwrap();
1927        // alter hash
1928        hash[0] ^= 0x01;
1929        let signature = hex::decode(SECP256R1_SIG_HEX).unwrap();
1930        let public_key = hex::decode(SECP256R1_PUBKEY_HEX).unwrap();
1931
1932        assert!(!api
1933            .secp256r1_verify(&hash, &signature, &public_key)
1934            .unwrap());
1935    }
1936
1937    // Basic "errors" test. Exhaustive tests on VM's side (packages/vm/src/imports.rs)
1938    #[test]
1939    fn secp256r1_verify_errs() {
1940        let api = MockApi::default();
1941
1942        let hash = hex::decode(SECP256R1_MSG_HASH_HEX).unwrap();
1943        let signature = hex::decode(SECP256R1_SIG_HEX).unwrap();
1944        let public_key = vec![];
1945
1946        let res = api.secp256r1_verify(&hash, &signature, &public_key);
1947        assert_eq!(res.unwrap_err(), VerificationError::InvalidPubkeyFormat);
1948    }
1949
1950    #[test]
1951    fn secp256r1_recover_pubkey_works() {
1952        let api = MockApi::default();
1953
1954        let hash = hex!("17b03f9f00f6692ccdde485fc63c4530751ef35da6f71336610944b0894fcfb8");
1955        let signature = hex!("9886ae46c1415c3bc959e82b760ad760aab66885a84e620aa339fdf102465c422bf3a80bc04faa35ebecc0f4864ac02d349f6f126e0f988501b8d3075409a26c");
1956        let recovery_param = 0;
1957        let expected = hex!("0451f99d2d52d4a6e734484a018b7ca2f895c2929b6754a3a03224d07ae61166ce4737da963c6ef7247fb88d19f9b0c667cac7fe12837fdab88c66f10d3c14cad1");
1958
1959        let pubkey = api
1960            .secp256r1_recover_pubkey(&hash, &signature, recovery_param)
1961            .unwrap();
1962        assert_eq!(pubkey, expected);
1963    }
1964
1965    #[test]
1966    fn secp256r1_recover_pubkey_fails_for_wrong_recovery_param() {
1967        let api = MockApi::default();
1968
1969        let hash = hex!("17b03f9f00f6692ccdde485fc63c4530751ef35da6f71336610944b0894fcfb8");
1970        let signature = hex!("9886ae46c1415c3bc959e82b760ad760aab66885a84e620aa339fdf102465c422bf3a80bc04faa35ebecc0f4864ac02d349f6f126e0f988501b8d3075409a26c");
1971        let expected = hex!("0451f99d2d52d4a6e734484a018b7ca2f895c2929b6754a3a03224d07ae61166ce4737da963c6ef7247fb88d19f9b0c667cac7fe12837fdab88c66f10d3c14cad1");
1972
1973        // Wrong recovery param leads to different pubkey
1974        let pubkey = api.secp256r1_recover_pubkey(&hash, &signature, 1).unwrap();
1975        assert_eq!(pubkey.len(), 65);
1976        assert_ne!(pubkey, expected);
1977
1978        // Invalid recovery param leads to error
1979        let result = api.secp256r1_recover_pubkey(&hash, &signature, 42);
1980        match result.unwrap_err() {
1981            RecoverPubkeyError::InvalidRecoveryParam => {}
1982            err => panic!("Unexpected error: {err:?}"),
1983        }
1984    }
1985
1986    #[test]
1987    fn secp256r1_recover_pubkey_fails_for_wrong_hash() {
1988        let api = MockApi::default();
1989
1990        let hash = hex!("17b03f9f00f6692ccdde485fc63c4530751ef35da6f71336610944b0894fcfb8");
1991        let signature = hex!("9886ae46c1415c3bc959e82b760ad760aab66885a84e620aa339fdf102465c422bf3a80bc04faa35ebecc0f4864ac02d349f6f126e0f988501b8d3075409a26c");
1992        let recovery_param = 0;
1993        let expected = hex!("0451f99d2d52d4a6e734484a018b7ca2f895c2929b6754a3a03224d07ae61166ce4737da963c6ef7247fb88d19f9b0c667cac7fe12837fdab88c66f10d3c14cad1");
1994
1995        // Wrong hash
1996        let mut corrupted_hash = hash;
1997        corrupted_hash[0] ^= 0x01;
1998        let pubkey = api
1999            .secp256r1_recover_pubkey(&corrupted_hash, &signature, recovery_param)
2000            .unwrap();
2001        assert_eq!(pubkey.len(), 65);
2002        assert_ne!(pubkey, expected);
2003
2004        // Malformed hash
2005        let mut malformed_hash = hash.to_vec();
2006        malformed_hash.push(0x8a);
2007        let result = api.secp256r1_recover_pubkey(&malformed_hash, &signature, recovery_param);
2008        match result.unwrap_err() {
2009            RecoverPubkeyError::InvalidHashFormat => {}
2010            err => panic!("Unexpected error: {err:?}"),
2011        }
2012    }
2013
2014    // Basic "works" test. Exhaustive tests on VM's side (packages/vm/src/imports.rs)
2015    #[test]
2016    fn ed25519_verify_works() {
2017        let api = MockApi::default();
2018
2019        let msg = hex::decode(ED25519_MSG_HEX).unwrap();
2020        let signature = hex::decode(ED25519_SIG_HEX).unwrap();
2021        let public_key = hex::decode(ED25519_PUBKEY_HEX).unwrap();
2022
2023        assert!(api.ed25519_verify(&msg, &signature, &public_key).unwrap());
2024    }
2025
2026    // Basic "fails" test. Exhaustive tests on VM's side (packages/vm/src/imports.rs)
2027    #[test]
2028    fn ed25519_verify_fails() {
2029        let api = MockApi::default();
2030
2031        let mut msg = hex::decode(ED25519_MSG_HEX).unwrap();
2032        // alter msg
2033        msg[0] ^= 0x01;
2034        let signature = hex::decode(ED25519_SIG_HEX).unwrap();
2035        let public_key = hex::decode(ED25519_PUBKEY_HEX).unwrap();
2036
2037        assert!(!api.ed25519_verify(&msg, &signature, &public_key).unwrap());
2038    }
2039
2040    // Basic "errors" test. Exhaustive tests on VM's side (packages/vm/src/imports.rs)
2041    #[test]
2042    fn ed25519_verify_errs() {
2043        let api = MockApi::default();
2044
2045        let msg = hex::decode(ED25519_MSG_HEX).unwrap();
2046        let signature = hex::decode(ED25519_SIG_HEX).unwrap();
2047        let public_key = vec![];
2048
2049        let res = api.ed25519_verify(&msg, &signature, &public_key);
2050        assert_eq!(res.unwrap_err(), VerificationError::InvalidPubkeyFormat);
2051    }
2052
2053    // Basic "works" test.
2054    #[test]
2055    fn ed25519_batch_verify_works() {
2056        let api = MockApi::default();
2057
2058        let msg = hex::decode(ED25519_MSG_HEX).unwrap();
2059        let signature = hex::decode(ED25519_SIG_HEX).unwrap();
2060        let public_key = hex::decode(ED25519_PUBKEY_HEX).unwrap();
2061
2062        let msgs: Vec<&[u8]> = vec![&msg];
2063        let signatures: Vec<&[u8]> = vec![&signature];
2064        let public_keys: Vec<&[u8]> = vec![&public_key];
2065
2066        assert!(api
2067            .ed25519_batch_verify(&msgs, &signatures, &public_keys)
2068            .unwrap());
2069    }
2070
2071    // Basic "fails" test.
2072    #[test]
2073    fn ed25519_batch_verify_fails() {
2074        let api = MockApi::default();
2075
2076        let mut msg = hex::decode(ED25519_MSG_HEX).unwrap();
2077        // alter msg
2078        msg[0] ^= 0x01;
2079        let signature = hex::decode(ED25519_SIG_HEX).unwrap();
2080        let public_key = hex::decode(ED25519_PUBKEY_HEX).unwrap();
2081
2082        let msgs: Vec<&[u8]> = vec![&msg];
2083        let signatures: Vec<&[u8]> = vec![&signature];
2084        let public_keys: Vec<&[u8]> = vec![&public_key];
2085
2086        assert!(!api
2087            .ed25519_batch_verify(&msgs, &signatures, &public_keys)
2088            .unwrap());
2089    }
2090
2091    // Basic "errors" test.
2092    #[test]
2093    fn ed25519_batch_verify_errs() {
2094        let api = MockApi::default();
2095
2096        let msg = hex::decode(ED25519_MSG_HEX).unwrap();
2097        let signature = hex::decode(ED25519_SIG_HEX).unwrap();
2098        let public_key: Vec<u8> = vec![0u8; 0];
2099
2100        let msgs: Vec<&[u8]> = vec![msg.as_slice()];
2101        let signatures: Vec<&[u8]> = vec![signature.as_slice()];
2102        let public_keys: Vec<&[u8]> = vec![&public_key];
2103
2104        let res = api.ed25519_batch_verify(&msgs, &signatures, &public_keys);
2105        assert_eq!(res.unwrap_err(), VerificationError::InvalidPubkeyFormat);
2106    }
2107
2108    #[cfg(feature = "cosmwasm_1_1")]
2109    #[test]
2110    fn bank_querier_supply() {
2111        let addr1 = String::from("foo");
2112        let balance1 = vec![coin(123, "ELF"), coin(777, "FLY")];
2113
2114        let addr2 = String::from("bar");
2115        let balance2 = coins(321, "ELF");
2116
2117        let bank = BankQuerier::new(&[(&addr1, &balance1), (&addr2, &balance2)]);
2118
2119        let elf = bank
2120            .query(&BankQuery::Supply {
2121                denom: "ELF".to_string(),
2122            })
2123            .unwrap()
2124            .unwrap();
2125        let res: SupplyResponse = from_json(elf).unwrap();
2126        assert_eq!(res.amount, coin(444, "ELF"));
2127
2128        let fly = bank
2129            .query(&BankQuery::Supply {
2130                denom: "FLY".to_string(),
2131            })
2132            .unwrap()
2133            .unwrap();
2134        let res: SupplyResponse = from_json(fly).unwrap();
2135        assert_eq!(res.amount, coin(777, "FLY"));
2136
2137        // if a denom does not exist, should return zero amount, instead of throwing an error
2138        let atom = bank
2139            .query(&BankQuery::Supply {
2140                denom: "ATOM".to_string(),
2141            })
2142            .unwrap()
2143            .unwrap();
2144        let res: SupplyResponse = from_json(atom).unwrap();
2145        assert_eq!(res.amount, coin(0, "ATOM"));
2146    }
2147
2148    #[test]
2149    fn bank_querier_one_balance() {
2150        let addr = String::from("foobar");
2151        let balance = vec![coin(123, "ELF"), coin(777, "FLY")];
2152        let bank = BankQuerier::new(&[(&addr, &balance)]);
2153
2154        // one match
2155        let fly = bank
2156            .query(&BankQuery::Balance {
2157                address: addr.clone(),
2158                denom: "FLY".to_string(),
2159            })
2160            .unwrap()
2161            .unwrap();
2162        let res: BalanceResponse = from_json(fly).unwrap();
2163        assert_eq!(res.amount, coin(777, "FLY"));
2164
2165        // missing denom
2166        let miss = bank
2167            .query(&BankQuery::Balance {
2168                address: addr,
2169                denom: "MISS".to_string(),
2170            })
2171            .unwrap()
2172            .unwrap();
2173        let res: BalanceResponse = from_json(miss).unwrap();
2174        assert_eq!(res.amount, coin(0, "MISS"));
2175    }
2176
2177    #[test]
2178    #[allow(deprecated)]
2179    fn bank_querier_missing_account() {
2180        let addr = String::from("foobar");
2181        let balance = vec![coin(123, "ELF"), coin(777, "FLY")];
2182        let bank = BankQuerier::new(&[(&addr, &balance)]);
2183
2184        // any denom on balances on empty account is empty coin
2185        let miss = bank
2186            .query(&BankQuery::Balance {
2187                address: String::from("elsewhere"),
2188                denom: "ELF".to_string(),
2189            })
2190            .unwrap()
2191            .unwrap();
2192        let res: BalanceResponse = from_json(miss).unwrap();
2193        assert_eq!(res.amount, coin(0, "ELF"));
2194    }
2195
2196    #[cfg(feature = "cosmwasm_1_3")]
2197    #[test]
2198    fn bank_querier_metadata_works() {
2199        let mut bank = BankQuerier::new(&[]);
2200        bank.set_denom_metadata(
2201            &(0..100)
2202                .map(|i| DenomMetadata {
2203                    symbol: format!("FOO{i}"),
2204                    name: "Foo".to_string(),
2205                    description: "Foo coin".to_string(),
2206                    denom_units: vec![DenomUnit {
2207                        denom: "ufoo".to_string(),
2208                        exponent: 8,
2209                        aliases: vec!["microfoo".to_string(), "foobar".to_string()],
2210                    }],
2211                    display: "FOO".to_string(),
2212                    base: format!("ufoo{i}"),
2213                    uri: "https://foo.bar".to_string(),
2214                    uri_hash: "foo".to_string(),
2215                })
2216                .collect::<Vec<_>>(),
2217        );
2218
2219        // querying first 10 should work
2220        let res = bank
2221            .query(&BankQuery::AllDenomMetadata {
2222                pagination: Some(PageRequest {
2223                    key: None,
2224                    limit: 10,
2225                    reverse: false,
2226                }),
2227            })
2228            .unwrap()
2229            .unwrap();
2230        let res: AllDenomMetadataResponse = from_json(res).unwrap();
2231        assert_eq!(res.metadata.len(), 10);
2232        assert!(res.next_key.is_some());
2233
2234        // querying next 10 should also work
2235        let res2 = bank
2236            .query(&BankQuery::AllDenomMetadata {
2237                pagination: Some(PageRequest {
2238                    key: res.next_key,
2239                    limit: 10,
2240                    reverse: false,
2241                }),
2242            })
2243            .unwrap()
2244            .unwrap();
2245        let res2: AllDenomMetadataResponse = from_json(res2).unwrap();
2246        assert_eq!(res2.metadata.len(), 10);
2247        assert_ne!(res.metadata.last(), res2.metadata.first());
2248        // should have no overlap
2249        for m in res.metadata {
2250            assert!(!res2.metadata.contains(&m));
2251        }
2252
2253        // querying all 100 should work
2254        let res = bank
2255            .query(&BankQuery::AllDenomMetadata {
2256                pagination: Some(PageRequest {
2257                    key: None,
2258                    limit: 100,
2259                    reverse: true,
2260                }),
2261            })
2262            .unwrap()
2263            .unwrap();
2264        let res: AllDenomMetadataResponse = from_json(res).unwrap();
2265        assert_eq!(res.metadata.len(), 100);
2266        assert!(res.next_key.is_none(), "no more data should be available");
2267        assert_eq!(res.metadata[0].symbol, "FOO99", "should have been reversed");
2268
2269        let more_res = bank
2270            .query(&BankQuery::AllDenomMetadata {
2271                pagination: Some(PageRequest {
2272                    key: res.next_key,
2273                    limit: u32::MAX,
2274                    reverse: true,
2275                }),
2276            })
2277            .unwrap()
2278            .unwrap();
2279        let more_res: AllDenomMetadataResponse = from_json(more_res).unwrap();
2280        assert_eq!(
2281            more_res.metadata, res.metadata,
2282            "should be same as previous query"
2283        );
2284    }
2285
2286    #[cfg(feature = "cosmwasm_1_3")]
2287    #[test]
2288    fn distribution_querier_delegator_withdraw_address() {
2289        let mut distribution = DistributionQuerier::default();
2290        distribution.set_withdraw_address("addr0", "withdraw0");
2291
2292        let query = DistributionQuery::DelegatorWithdrawAddress {
2293            delegator_address: "addr0".to_string(),
2294        };
2295
2296        let res = distribution.query(&query).unwrap().unwrap();
2297        let res: DelegatorWithdrawAddressResponse = from_json(res).unwrap();
2298        assert_eq!(res.withdraw_address.as_str(), "withdraw0");
2299
2300        let query = DistributionQuery::DelegatorWithdrawAddress {
2301            delegator_address: "addr1".to_string(),
2302        };
2303
2304        let res = distribution.query(&query).unwrap().unwrap();
2305        let res: DelegatorWithdrawAddressResponse = from_json(res).unwrap();
2306        assert_eq!(res.withdraw_address.as_str(), "addr1");
2307    }
2308
2309    #[cfg(feature = "cosmwasm_1_4")]
2310    #[test]
2311    fn distribution_querier_delegator_validators() {
2312        let mut distribution = DistributionQuerier::default();
2313        distribution.set_validators("addr0", ["valoper1", "valoper2"]);
2314
2315        let query = DistributionQuery::DelegatorValidators {
2316            delegator_address: "addr0".to_string(),
2317        };
2318
2319        let res = distribution.query(&query).unwrap().unwrap();
2320        let res: DelegatorValidatorsResponse = from_json(res).unwrap();
2321        assert_eq!(res.validators, ["valoper1", "valoper2"]);
2322
2323        let query = DistributionQuery::DelegatorValidators {
2324            delegator_address: "addr1".to_string(),
2325        };
2326
2327        let res = distribution.query(&query).unwrap().unwrap();
2328        let res: DelegatorValidatorsResponse = from_json(res).unwrap();
2329        assert_eq!(res.validators, ([] as [String; 0]));
2330    }
2331
2332    #[cfg(feature = "cosmwasm_1_4")]
2333    #[test]
2334    fn distribution_querier_delegation_rewards() {
2335        use crate::{Decimal256, DelegationTotalRewardsResponse, DelegatorReward};
2336
2337        let mut distribution = DistributionQuerier::default();
2338        let valoper0_rewards = vec![
2339            DecCoin::new(Decimal256::from_atomics(1234u128, 0).unwrap(), "uatom"),
2340            DecCoin::new(Decimal256::from_atomics(56781234u128, 4).unwrap(), "utest"),
2341        ];
2342        distribution.set_rewards("valoper0", "addr0", valoper0_rewards.clone());
2343
2344        // both exist / are set
2345        let query = DistributionQuery::DelegationRewards {
2346            delegator_address: "addr0".to_string(),
2347            validator_address: "valoper0".to_string(),
2348        };
2349        let res = distribution.query(&query).unwrap().unwrap();
2350        let res: DelegationRewardsResponse = from_json(res).unwrap();
2351        assert_eq!(res.rewards, valoper0_rewards);
2352
2353        // delegator does not exist
2354        let query = DistributionQuery::DelegationRewards {
2355            delegator_address: "nonexistent".to_string(),
2356            validator_address: "valoper0".to_string(),
2357        };
2358        let res = distribution.query(&query).unwrap().unwrap();
2359        let res: DelegationRewardsResponse = from_json(res).unwrap();
2360        assert_eq!(res.rewards.len(), 0);
2361
2362        // validator does not exist
2363        let query = DistributionQuery::DelegationRewards {
2364            delegator_address: "addr0".to_string(),
2365            validator_address: "valopernonexistent".to_string(),
2366        };
2367        let res = distribution.query(&query).unwrap().unwrap();
2368        let res: DelegationRewardsResponse = from_json(res).unwrap();
2369        assert_eq!(res.rewards.len(), 0);
2370
2371        // add one more validator
2372        let valoper1_rewards = vec![DecCoin::new(Decimal256::one(), "uatom")];
2373        distribution.set_rewards("valoper1", "addr0", valoper1_rewards.clone());
2374
2375        // total rewards
2376        let query = DistributionQuery::DelegationTotalRewards {
2377            delegator_address: "addr0".to_string(),
2378        };
2379        let res = distribution.query(&query).unwrap().unwrap();
2380        let res: DelegationTotalRewardsResponse = from_json(res).unwrap();
2381        assert_eq!(
2382            res.rewards,
2383            vec![
2384                DelegatorReward {
2385                    validator_address: "valoper0".into(),
2386                    reward: valoper0_rewards
2387                },
2388                DelegatorReward {
2389                    validator_address: "valoper1".into(),
2390                    reward: valoper1_rewards
2391                },
2392            ]
2393        );
2394        assert_eq!(
2395            res.total,
2396            [
2397                DecCoin::new(
2398                    Decimal256::from_atomics(1234u128, 0).unwrap() + Decimal256::one(),
2399                    "uatom"
2400                ),
2401                // total for utest should still be the same
2402                DecCoin::new(Decimal256::from_atomics(56781234u128, 4).unwrap(), "utest")
2403            ]
2404        );
2405    }
2406
2407    #[cfg(feature = "stargate")]
2408    #[test]
2409    fn ibc_querier_channel_existing() {
2410        let chan1 = mock_ibc_channel("channel-0", IbcOrder::Ordered, "ibc");
2411        let chan2 = mock_ibc_channel("channel-1", IbcOrder::Ordered, "ibc");
2412
2413        let ibc = IbcQuerier::new("myport", &[chan1.clone(), chan2]);
2414
2415        // query existing
2416        let query = &IbcQuery::Channel {
2417            channel_id: "channel-0".to_string(),
2418            port_id: Some("my_port".to_string()),
2419        };
2420        let raw = ibc.query(query).unwrap().unwrap();
2421        let chan: ChannelResponse = from_json(raw).unwrap();
2422        assert_eq!(chan.channel, Some(chan1));
2423    }
2424
2425    #[cfg(feature = "stargate")]
2426    #[test]
2427    fn ibc_querier_channel_existing_no_port() {
2428        let chan1 = IbcChannel {
2429            endpoint: IbcEndpoint {
2430                port_id: "myport".to_string(),
2431                channel_id: "channel-0".to_string(),
2432            },
2433            counterparty_endpoint: IbcEndpoint {
2434                port_id: "their_port".to_string(),
2435                channel_id: "channel-7".to_string(),
2436            },
2437            order: IbcOrder::Ordered,
2438            version: "ibc".to_string(),
2439            connection_id: "connection-2".to_string(),
2440        };
2441        let chan2 = mock_ibc_channel("channel-1", IbcOrder::Ordered, "ibc");
2442
2443        let ibc = IbcQuerier::new("myport", &[chan1.clone(), chan2]);
2444
2445        // query existing
2446        let query = &IbcQuery::Channel {
2447            channel_id: "channel-0".to_string(),
2448            port_id: Some("myport".to_string()),
2449        };
2450        let raw = ibc.query(query).unwrap().unwrap();
2451        let chan: ChannelResponse = from_json(raw).unwrap();
2452        assert_eq!(chan.channel, Some(chan1));
2453    }
2454
2455    #[cfg(feature = "stargate")]
2456    #[test]
2457    fn ibc_querier_channel_none() {
2458        let chan1 = mock_ibc_channel("channel-0", IbcOrder::Ordered, "ibc");
2459        let chan2 = mock_ibc_channel("channel-1", IbcOrder::Ordered, "ibc");
2460
2461        let ibc = IbcQuerier::new("myport", &[chan1, chan2]);
2462
2463        // query non-existing
2464        let query = &IbcQuery::Channel {
2465            channel_id: "channel-0".to_string(),
2466            port_id: None,
2467        };
2468        let raw = ibc.query(query).unwrap().unwrap();
2469        let chan: ChannelResponse = from_json(raw).unwrap();
2470        assert_eq!(chan.channel, None);
2471    }
2472
2473    #[cfg(feature = "stargate")]
2474    #[test]
2475    fn ibc_querier_port() {
2476        let chan1 = mock_ibc_channel("channel-0", IbcOrder::Ordered, "ibc");
2477
2478        let ibc = IbcQuerier::new("myport", &[chan1]);
2479
2480        // query channels matching "myport" (should be none)
2481        let query = &IbcQuery::PortId {};
2482        let raw = ibc.query(query).unwrap().unwrap();
2483        let res: PortIdResponse = from_json(raw).unwrap();
2484        assert_eq!(res.port_id, "myport");
2485    }
2486
2487    #[cfg(feature = "staking")]
2488    #[test]
2489    fn staking_querier_all_validators() {
2490        let val1 = Validator {
2491            address: String::from("validator-one"),
2492            commission: Decimal::percent(1),
2493            max_commission: Decimal::percent(3),
2494            max_change_rate: Decimal::percent(1),
2495        };
2496        let val2 = Validator {
2497            address: String::from("validator-two"),
2498            commission: Decimal::permille(15),
2499            max_commission: Decimal::permille(40),
2500            max_change_rate: Decimal::permille(5),
2501        };
2502
2503        let staking = StakingQuerier::new("ustake", &[val1.clone(), val2.clone()], &[]);
2504
2505        // one match
2506        let raw = staking
2507            .query(&StakingQuery::AllValidators {})
2508            .unwrap()
2509            .unwrap();
2510        let vals: AllValidatorsResponse = from_json(raw).unwrap();
2511        assert_eq!(vals.validators, vec![val1, val2]);
2512    }
2513
2514    #[cfg(feature = "staking")]
2515    #[test]
2516    fn staking_querier_validator() {
2517        let address1 = String::from("validator-one");
2518        let address2 = String::from("validator-two");
2519        let address_non_existent = String::from("wannabe-validator");
2520
2521        let val1 = Validator {
2522            address: address1.clone(),
2523            commission: Decimal::percent(1),
2524            max_commission: Decimal::percent(3),
2525            max_change_rate: Decimal::percent(1),
2526        };
2527        let val2 = Validator {
2528            address: address2.clone(),
2529            commission: Decimal::permille(15),
2530            max_commission: Decimal::permille(40),
2531            max_change_rate: Decimal::permille(5),
2532        };
2533
2534        let staking = StakingQuerier::new("ustake", &[val1.clone(), val2.clone()], &[]);
2535
2536        // query 1
2537        let raw = staking
2538            .query(&StakingQuery::Validator { address: address1 })
2539            .unwrap()
2540            .unwrap();
2541        let res: ValidatorResponse = from_json(raw).unwrap();
2542        assert_eq!(res.validator, Some(val1));
2543
2544        // query 2
2545        let raw = staking
2546            .query(&StakingQuery::Validator { address: address2 })
2547            .unwrap()
2548            .unwrap();
2549        let res: ValidatorResponse = from_json(raw).unwrap();
2550        assert_eq!(res.validator, Some(val2));
2551
2552        // query non-existent
2553        let raw = staking
2554            .query(&StakingQuery::Validator {
2555                address: address_non_existent,
2556            })
2557            .unwrap()
2558            .unwrap();
2559        let res: ValidatorResponse = from_json(raw).unwrap();
2560        assert_eq!(res.validator, None);
2561    }
2562
2563    #[cfg(feature = "staking")]
2564    // gets delegators from query or panic
2565    fn get_all_delegators(
2566        staking: &StakingQuerier,
2567        delegator: impl Into<String>,
2568    ) -> Vec<Delegation> {
2569        let raw = staking
2570            .query(&StakingQuery::AllDelegations {
2571                delegator: delegator.into(),
2572            })
2573            .unwrap()
2574            .unwrap();
2575        let dels: AllDelegationsResponse = from_json(raw).unwrap();
2576        dels.delegations
2577    }
2578
2579    #[cfg(feature = "staking")]
2580    // gets full delegators from query or panic
2581    fn get_delegator(
2582        staking: &StakingQuerier,
2583        delegator: impl Into<String>,
2584        validator: impl Into<String>,
2585    ) -> Option<FullDelegation> {
2586        let raw = staking
2587            .query(&StakingQuery::Delegation {
2588                delegator: delegator.into(),
2589                validator: validator.into(),
2590            })
2591            .unwrap()
2592            .unwrap();
2593        let dels: DelegationResponse = from_json(raw).unwrap();
2594        dels.delegation
2595    }
2596
2597    #[cfg(feature = "staking")]
2598    #[test]
2599    fn staking_querier_delegations() {
2600        let val1 = String::from("validator-one");
2601        let val2 = String::from("validator-two");
2602
2603        let user_a = Addr::unchecked("investor");
2604        let user_b = Addr::unchecked("speculator");
2605        let user_c = Addr::unchecked("hodler");
2606
2607        // we need multiple validators per delegator, so the queries provide different results
2608        let del1a = FullDelegation {
2609            delegator: user_a.clone(),
2610            validator: val1.clone(),
2611            amount: coin(100, "ustake"),
2612            can_redelegate: coin(100, "ustake"),
2613            accumulated_rewards: coins(5, "ustake"),
2614        };
2615        let del2a = FullDelegation {
2616            delegator: user_a.clone(),
2617            validator: val2.clone(),
2618            amount: coin(500, "ustake"),
2619            can_redelegate: coin(500, "ustake"),
2620            accumulated_rewards: coins(20, "ustake"),
2621        };
2622
2623        // note we cannot have multiple delegations on one validator, they are collapsed into one
2624        let del1b = FullDelegation {
2625            delegator: user_b.clone(),
2626            validator: val1.clone(),
2627            amount: coin(500, "ustake"),
2628            can_redelegate: coin(0, "ustake"),
2629            accumulated_rewards: coins(0, "ustake"),
2630        };
2631
2632        // and another one on val2
2633        let del2c = FullDelegation {
2634            delegator: user_c.clone(),
2635            validator: val2.clone(),
2636            amount: coin(8888, "ustake"),
2637            can_redelegate: coin(4567, "ustake"),
2638            accumulated_rewards: coins(900, "ustake"),
2639        };
2640
2641        let staking = StakingQuerier::new(
2642            "ustake",
2643            &[],
2644            &[del1a.clone(), del1b.clone(), del2a.clone(), del2c.clone()],
2645        );
2646
2647        // get all for user a
2648        let dels = get_all_delegators(&staking, user_a.clone());
2649        assert_eq!(dels, vec![del1a.clone().into(), del2a.clone().into()]);
2650
2651        // get all for user b
2652        let dels = get_all_delegators(&staking, user_b.clone());
2653        assert_eq!(dels, vec![del1b.clone().into()]);
2654
2655        // get all for user c
2656        let dels = get_all_delegators(&staking, user_c.clone());
2657        assert_eq!(dels, vec![del2c.clone().into()]);
2658
2659        // for user with no delegations...
2660        let dels = get_all_delegators(&staking, String::from("no one"));
2661        assert_eq!(dels, vec![]);
2662
2663        // filter a by validator (1 and 1)
2664        let dels = get_delegator(&staking, user_a.clone(), val1.clone());
2665        assert_eq!(dels, Some(del1a));
2666        let dels = get_delegator(&staking, user_a, val2.clone());
2667        assert_eq!(dels, Some(del2a));
2668
2669        // filter b by validator (2 and 0)
2670        let dels = get_delegator(&staking, user_b.clone(), val1.clone());
2671        assert_eq!(dels, Some(del1b));
2672        let dels = get_delegator(&staking, user_b, val2.clone());
2673        assert_eq!(dels, None);
2674
2675        // filter c by validator (0 and 1)
2676        let dels = get_delegator(&staking, user_c.clone(), val1);
2677        assert_eq!(dels, None);
2678        let dels = get_delegator(&staking, user_c, val2);
2679        assert_eq!(dels, Some(del2c));
2680    }
2681
2682    #[test]
2683    fn wasm_querier_works() {
2684        let mut querier = WasmQuerier::default();
2685
2686        let any_addr = "foo".to_string();
2687
2688        // By default, querier errors for WasmQuery::Raw
2689        let system_err = querier
2690            .query(&WasmQuery::Raw {
2691                contract_addr: any_addr.clone(),
2692                key: b"the key".into(),
2693            })
2694            .unwrap_err();
2695        match system_err {
2696            SystemError::NoSuchContract { addr } => assert_eq!(addr, any_addr),
2697            err => panic!("Unexpected error: {err:?}"),
2698        }
2699
2700        // By default, querier errors for WasmQuery::Smart
2701        let system_err = querier
2702            .query(&WasmQuery::Smart {
2703                contract_addr: any_addr.clone(),
2704                msg: b"{}".into(),
2705            })
2706            .unwrap_err();
2707        match system_err {
2708            SystemError::NoSuchContract { addr } => assert_eq!(addr, any_addr),
2709            err => panic!("Unexpected error: {err:?}"),
2710        }
2711
2712        // By default, querier errors for WasmQuery::ContractInfo
2713        let system_err = querier
2714            .query(&WasmQuery::ContractInfo {
2715                contract_addr: any_addr.clone(),
2716            })
2717            .unwrap_err();
2718        match system_err {
2719            SystemError::NoSuchContract { addr } => assert_eq!(addr, any_addr),
2720            err => panic!("Unexpected error: {err:?}"),
2721        }
2722
2723        #[cfg(feature = "cosmwasm_1_2")]
2724        {
2725            // By default, querier errors for WasmQuery::CodeInfo
2726            let system_err = querier
2727                .query(&WasmQuery::CodeInfo { code_id: 4 })
2728                .unwrap_err();
2729            match system_err {
2730                SystemError::NoSuchCode { code_id } => assert_eq!(code_id, 4),
2731                err => panic!("Unexpected error: {err:?}"),
2732            }
2733        }
2734
2735        #[cfg(all(feature = "cosmwasm_3_0", feature = "iterator"))]
2736        {
2737            // By default, querier errors for WasmQuery::RawRange
2738            let system_err = querier
2739                .query(&WasmQuery::RawRange {
2740                    contract_addr: any_addr.clone(),
2741                    start: None,
2742                    end: None,
2743                    limit: 10,
2744                    order: crate::Order::Ascending,
2745                })
2746                .unwrap_err();
2747            match system_err {
2748                SystemError::NoSuchContract { addr } => assert_eq!(addr, any_addr),
2749                err => panic!("Unexpected error: {err:?}"),
2750            }
2751        }
2752
2753        querier.update_handler(|request| {
2754            let api = MockApi::default();
2755            let contract1 = api.addr_make("contract1");
2756            let mut storage1 = MockStorage::new();
2757            storage1.set(b"the key", b"the value");
2758
2759            match request {
2760                WasmQuery::Raw { contract_addr, key } => {
2761                    let Ok(addr) = api.addr_validate(contract_addr) else {
2762                        return SystemResult::Err(SystemError::NoSuchContract {
2763                            addr: contract_addr.clone(),
2764                        });
2765                    };
2766                    if addr == contract1 {
2767                        if let Some(value) = storage1.get(key) {
2768                            SystemResult::Ok(ContractResult::Ok(Binary::new(value)))
2769                        } else {
2770                            SystemResult::Ok(ContractResult::Ok(Binary::default()))
2771                        }
2772                    } else {
2773                        SystemResult::Err(SystemError::NoSuchContract {
2774                            addr: contract_addr.clone(),
2775                        })
2776                    }
2777                }
2778                WasmQuery::Smart { contract_addr, msg } => {
2779                    let Ok(addr) = api.addr_validate(contract_addr) else {
2780                        return SystemResult::Err(SystemError::NoSuchContract {
2781                            addr: contract_addr.clone(),
2782                        });
2783                    };
2784                    if addr == contract1 {
2785                        #[derive(Deserialize)]
2786                        struct MyMsg {}
2787                        let _msg: MyMsg = match from_json(msg) {
2788                            Ok(msg) => msg,
2789                            Err(err) => {
2790                                return SystemResult::Ok(ContractResult::Err(err.to_string()))
2791                            }
2792                        };
2793                        let response: Response = Response::new().set_data(b"good");
2794                        SystemResult::Ok(ContractResult::Ok(to_json_binary(&response).unwrap()))
2795                    } else {
2796                        SystemResult::Err(SystemError::NoSuchContract {
2797                            addr: contract_addr.clone(),
2798                        })
2799                    }
2800                }
2801                WasmQuery::ContractInfo { contract_addr } => {
2802                    let Ok(addr) = api.addr_validate(contract_addr) else {
2803                        return SystemResult::Err(SystemError::NoSuchContract {
2804                            addr: contract_addr.clone(),
2805                        });
2806                    };
2807                    if addr == contract1 {
2808                        let response = ContractInfoResponse {
2809                            code_id: 4,
2810                            creator: Addr::unchecked("lalala"),
2811                            admin: None,
2812                            pinned: false,
2813                            ibc_port: None,
2814                            ibc2_port: None,
2815                        };
2816                        SystemResult::Ok(ContractResult::Ok(to_json_binary(&response).unwrap()))
2817                    } else {
2818                        SystemResult::Err(SystemError::NoSuchContract {
2819                            addr: contract_addr.clone(),
2820                        })
2821                    }
2822                }
2823                #[cfg(feature = "cosmwasm_1_2")]
2824                WasmQuery::CodeInfo { code_id } => {
2825                    use crate::{Checksum, CodeInfoResponse};
2826                    let code_id = *code_id;
2827                    if code_id == 4 {
2828                        let response = CodeInfoResponse {
2829                            code_id,
2830                            creator: Addr::unchecked("lalala"),
2831                            checksum: Checksum::from_hex(
2832                                "84cf20810fd429caf58898c3210fcb71759a27becddae08dbde8668ea2f4725d",
2833                            )
2834                            .unwrap(),
2835                        };
2836                        SystemResult::Ok(ContractResult::Ok(to_json_binary(&response).unwrap()))
2837                    } else {
2838                        SystemResult::Err(SystemError::NoSuchCode { code_id })
2839                    }
2840                }
2841                #[cfg(all(feature = "cosmwasm_3_0", feature = "iterator"))]
2842                WasmQuery::RawRange {
2843                    contract_addr,
2844                    start,
2845                    end,
2846                    limit,
2847                    order,
2848                } => {
2849                    let Ok(addr) = api.addr_validate(contract_addr) else {
2850                        return SystemResult::Err(SystemError::NoSuchContract {
2851                            addr: contract_addr.clone(),
2852                        });
2853                    };
2854                    if addr == contract1 {
2855                        let mut data: Vec<_> = storage1
2856                            .range(
2857                                start.as_ref().map(Binary::as_slice),
2858                                end.as_ref().map(Binary::as_slice),
2859                                *order,
2860                            )
2861                            .take(*limit as usize + 1) // take one more entry than limit
2862                            .map(|(key, value)| (Binary::new(key), Binary::new(value)))
2863                            .collect();
2864
2865                        // if we have more than limit, there are more entries to fetch
2866                        let next_key = if data.len() > *limit as usize {
2867                            data.pop().map(|(key, _)| key)
2868                        } else {
2869                            None
2870                        };
2871                        let raw_range_response = crate::RawRangeResponse { data, next_key };
2872
2873                        SystemResult::Ok(ContractResult::Ok(
2874                            to_json_binary(&raw_range_response).unwrap(),
2875                        ))
2876                    } else {
2877                        SystemResult::Err(SystemError::NoSuchContract {
2878                            addr: contract_addr.clone(),
2879                        })
2880                    }
2881                }
2882            }
2883        });
2884
2885        let contract_addr = MockApi::default().addr_make("contract1");
2886
2887        // WasmQuery::Raw
2888        let result = querier.query(&WasmQuery::Raw {
2889            contract_addr: contract_addr.clone().into(),
2890            key: b"the key".into(),
2891        });
2892
2893        match result {
2894            SystemResult::Ok(ContractResult::Ok(value)) => assert_eq!(value, b"the value" as &[u8]),
2895            res => panic!("Unexpected result: {res:?}"),
2896        }
2897        let result = querier.query(&WasmQuery::Raw {
2898            contract_addr: contract_addr.clone().into(),
2899            key: b"other key".into(),
2900        });
2901        match result {
2902            SystemResult::Ok(ContractResult::Ok(value)) => assert_eq!(value, b"" as &[u8]),
2903            res => panic!("Unexpected result: {res:?}"),
2904        }
2905
2906        // WasmQuery::Smart
2907        let result = querier.query(&WasmQuery::Smart {
2908            contract_addr: contract_addr.clone().into(),
2909            msg: b"{}".into(),
2910        });
2911        match result {
2912            SystemResult::Ok(ContractResult::Ok(value)) => assert_eq!(
2913                value,
2914                br#"{"messages":[],"attributes":[],"events":[],"data":"Z29vZA=="}"# as &[u8]
2915            ),
2916            res => panic!("Unexpected result: {res:?}"),
2917        }
2918        let result = querier.query(&WasmQuery::Smart {
2919            contract_addr: contract_addr.clone().into(),
2920            msg: b"a broken request".into(),
2921        });
2922        match result {
2923            SystemResult::Ok(ContractResult::Err(err)) => {
2924                assert_eq!(err, "Error parsing into type cosmwasm_std::testing::mock::tests::wasm_querier_works::{{closure}}::MyMsg: expected value at line 1 column 1")
2925            }
2926            res => panic!("Unexpected result: {res:?}"),
2927        }
2928
2929        // WasmQuery::ContractInfo
2930        let result = querier.query(&WasmQuery::ContractInfo {
2931            contract_addr: contract_addr.clone().into(),
2932        });
2933        match result {
2934            SystemResult::Ok(ContractResult::Ok(value)) => assert_eq!(
2935                value,
2936                br#"{"code_id":4,"creator":"lalala","admin":null,"pinned":false,"ibc_port":null,"ibc2_port":null}"#
2937                    as &[u8]
2938            ),
2939            res => panic!("Unexpected result: {res:?}"),
2940        }
2941
2942        // WasmQuery::CodeInfo
2943        #[cfg(feature = "cosmwasm_1_2")]
2944        {
2945            let result = querier.query(&WasmQuery::CodeInfo { code_id: 4 });
2946            match result {
2947                SystemResult::Ok(ContractResult::Ok(value)) => assert_eq!(
2948                    value,
2949                    br#"{"code_id":4,"creator":"lalala","checksum":"84cf20810fd429caf58898c3210fcb71759a27becddae08dbde8668ea2f4725d"}"#
2950                ),
2951                res => panic!("Unexpected result: {res:?}"),
2952            }
2953        }
2954
2955        #[cfg(all(feature = "cosmwasm_3_0", feature = "iterator"))]
2956        {
2957            let result = querier.query(&WasmQuery::RawRange {
2958                contract_addr: contract_addr.clone().into(),
2959                start: Some(Binary::from(b"the key")),
2960                end: Some(Binary::from(b"the keyasdf")),
2961                limit: 10,
2962                order: crate::Order::Ascending,
2963            });
2964            match result {
2965                SystemResult::Ok(ContractResult::Ok(value)) => assert_eq!(
2966                    value.as_slice(),
2967                    br#"{"data":[["dGhlIGtleQ==","dGhlIHZhbHVl"]],"next_key":null}"#
2968                ),
2969                res => panic!("Unexpected result: {res:?}"),
2970            }
2971        }
2972    }
2973
2974    #[test]
2975    fn making_an_address_works() {
2976        let mock_api = MockApi::default();
2977
2978        assert_eq!(
2979            mock_api.addr_make("creator").to_string(),
2980            "cosmwasm1h34lmpywh4upnjdg90cjf4j70aee6z8qqfspugamjp42e4q28kqs8s7vcp",
2981        );
2982
2983        assert_eq!(
2984            mock_api.addr_make("").to_string(),
2985            "cosmwasm1uwcvgs5clswpfxhm7nyfjmaeysn6us0yvjdexn9yjkv3k7zjhp2sly4xh9",
2986        );
2987
2988        let mock_api = MockApi::default().with_prefix("juno");
2989        assert_eq!(
2990            mock_api.addr_make("creator").to_string(),
2991            "juno1h34lmpywh4upnjdg90cjf4j70aee6z8qqfspugamjp42e4q28kqsksmtyp",
2992        );
2993    }
2994
2995    #[test]
2996    fn colon_in_prefix_is_valid() {
2997        let mock_api = MockApi::default().with_prefix("did:com:");
2998        let addr = mock_api
2999            .addr_validate("did:com:1jkf0kmeyefvyzpwf56m7sne2000ay53r6upttu")
3000            .unwrap();
3001
3002        assert_eq!(
3003            addr.as_str(),
3004            "did:com:1jkf0kmeyefvyzpwf56m7sne2000ay53r6upttu"
3005        );
3006    }
3007
3008    #[test]
3009    #[should_panic(
3010        expected = "Generating address failed with reason: hrp is empty, must have at least 1 character"
3011    )]
3012    fn making_an_address_with_empty_prefix_should_panic() {
3013        MockApi::default().with_prefix("").addr_make("creator");
3014    }
3015
3016    #[test]
3017    #[cfg(feature = "cosmwasm_1_3")]
3018    fn distribution_querier_new_works() {
3019        let addresses = [
3020            ("addr0000".to_string(), "addr0001".to_string()),
3021            ("addr0002".to_string(), "addr0001".to_string()),
3022        ];
3023        let btree_map = BTreeMap::from(addresses.clone());
3024
3025        // should still work with HashMap
3026        let hashmap = std::collections::HashMap::from(addresses.clone());
3027        let querier = DistributionQuerier::new(hashmap);
3028        assert_eq!(querier.withdraw_addresses, btree_map);
3029
3030        // should work with BTreeMap
3031        let querier = DistributionQuerier::new(btree_map.clone());
3032        assert_eq!(querier.withdraw_addresses, btree_map);
3033
3034        // should work with array
3035        let querier = DistributionQuerier::new(addresses);
3036        assert_eq!(querier.withdraw_addresses, btree_map);
3037    }
3038
3039    #[test]
3040    fn instantiate2_address_can_be_humanized() {
3041        let mock_api = MockApi::default();
3042
3043        let contract_addr = mock_api
3044            .addr_canonicalize(mock_api.addr_make("contract").as_str())
3045            .unwrap();
3046        let checksum =
3047            HexBinary::from_hex("9af782a3a1bcbcd22dbb6a45c751551d9af782a3a1bcbcd22dbb6a45c751551d")
3048                .unwrap();
3049        let salt = b"instance 1231";
3050        let canonical_addr = instantiate2_address(&checksum, &contract_addr, salt).unwrap();
3051        // we are not interested in the exact humanization, just that it works
3052        mock_api.addr_humanize(&canonical_addr).unwrap();
3053    }
3054}