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