Skip to main content

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