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