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            #[allow(deprecated)]
962            IbcQuery::FeeEnabledChannel { .. } => {
963                use crate::query::FeeEnabledChannelResponse;
964                // for now, we always return true
965                to_json_binary(&FeeEnabledChannelResponse::new(true)).into()
966            }
967        };
968        // system result is always ok in the mock implementation
969        SystemResult::Ok(contract_result)
970    }
971}
972
973#[cfg(feature = "staking")]
974#[derive(Clone, Default)]
975pub struct StakingQuerier {
976    denom: String,
977    validators: Vec<Validator>,
978    delegations: Vec<FullDelegation>,
979}
980
981#[cfg(feature = "staking")]
982impl StakingQuerier {
983    pub fn new(denom: &str, validators: &[Validator], delegations: &[FullDelegation]) -> Self {
984        StakingQuerier {
985            denom: denom.to_string(),
986            validators: validators.to_vec(),
987            delegations: delegations.to_vec(),
988        }
989    }
990
991    /// Update the querier's configuration
992    pub fn update(
993        &mut self,
994        denom: impl Into<String>,
995        validators: &[Validator],
996        delegations: &[FullDelegation],
997    ) {
998        self.denom = denom.into();
999        self.validators = validators.to_vec();
1000        self.delegations = delegations.to_vec();
1001    }
1002
1003    pub fn query(&self, request: &StakingQuery) -> QuerierResult {
1004        let contract_result: ContractResult<Binary> = match request {
1005            StakingQuery::BondedDenom {} => {
1006                let res = BondedDenomResponse {
1007                    denom: self.denom.clone(),
1008                };
1009                to_json_binary(&res).into()
1010            }
1011            StakingQuery::AllValidators {} => {
1012                let res = AllValidatorsResponse {
1013                    validators: self.validators.clone(),
1014                };
1015                to_json_binary(&res).into()
1016            }
1017            StakingQuery::Validator { address } => {
1018                let validator: Option<Validator> = self
1019                    .validators
1020                    .iter()
1021                    .find(|validator| validator.address == *address)
1022                    .cloned();
1023                let res = ValidatorResponse { validator };
1024                to_json_binary(&res).into()
1025            }
1026            StakingQuery::AllDelegations { delegator } => {
1027                let delegations: Vec<_> = self
1028                    .delegations
1029                    .iter()
1030                    .filter(|d| d.delegator.as_str() == delegator)
1031                    .cloned()
1032                    .map(|d| d.into())
1033                    .collect();
1034                let res = AllDelegationsResponse { delegations };
1035                to_json_binary(&res).into()
1036            }
1037            StakingQuery::Delegation {
1038                delegator,
1039                validator,
1040            } => {
1041                let delegation = self
1042                    .delegations
1043                    .iter()
1044                    .find(|d| d.delegator.as_str() == delegator && d.validator == *validator);
1045                let res = DelegationResponse {
1046                    delegation: delegation.cloned(),
1047                };
1048                to_json_binary(&res).into()
1049            }
1050        };
1051        // system result is always ok in the mock implementation
1052        SystemResult::Ok(contract_result)
1053    }
1054}
1055
1056#[cfg(feature = "cosmwasm_1_3")]
1057#[derive(Clone, Default)]
1058pub struct DistributionQuerier {
1059    withdraw_addresses: BTreeMap<String, String>,
1060    /// Mock of accumulated rewards, indexed first by delegator and then validator address.
1061    rewards: BTreeMap<String, BTreeMap<String, Vec<DecCoin>>>,
1062    /// Mock of validators that a delegator has bonded to.
1063    validators: BTreeMap<String, BTreeSet<String>>,
1064}
1065
1066#[cfg(feature = "cosmwasm_1_3")]
1067impl DistributionQuerier {
1068    pub fn new<T>(withdraw_addresses: T) -> Self
1069    where
1070        T: IntoIterator<Item = (String, String)>,
1071    {
1072        DistributionQuerier {
1073            withdraw_addresses: withdraw_addresses.into_iter().collect(),
1074            ..Default::default()
1075        }
1076    }
1077
1078    pub fn set_withdraw_address(
1079        &mut self,
1080        delegator_address: impl Into<String>,
1081        withdraw_address: impl Into<String>,
1082    ) {
1083        self.withdraw_addresses
1084            .insert(delegator_address.into(), withdraw_address.into());
1085    }
1086
1087    /// Sets multiple withdraw addresses.
1088    ///
1089    /// This allows passing multiple tuples of `(delegator_address, withdraw_address)`.
1090    /// It does not overwrite existing entries.
1091    pub fn set_withdraw_addresses(
1092        &mut self,
1093        withdraw_addresses: impl IntoIterator<Item = (impl Into<String>, impl Into<String>)>,
1094    ) {
1095        for (d, w) in withdraw_addresses {
1096            self.set_withdraw_address(d, w);
1097        }
1098    }
1099
1100    pub fn clear_withdraw_addresses(&mut self) {
1101        self.withdraw_addresses.clear();
1102    }
1103
1104    /// Sets accumulated rewards for a given validator and delegator pair.
1105    pub fn set_rewards(
1106        &mut self,
1107        validator: impl Into<String>,
1108        delegator: impl Into<String>,
1109        rewards: Vec<DecCoin>,
1110    ) {
1111        self.rewards
1112            .entry(delegator.into())
1113            .or_default()
1114            .insert(validator.into(), rewards);
1115    }
1116
1117    /// Sets the validators a given delegator has bonded to.
1118    pub fn set_validators(
1119        &mut self,
1120        delegator: impl Into<String>,
1121        validators: impl IntoIterator<Item = impl Into<String>>,
1122    ) {
1123        self.validators.insert(
1124            delegator.into(),
1125            validators.into_iter().map(Into::into).collect(),
1126        );
1127    }
1128
1129    pub fn query(&self, request: &DistributionQuery) -> QuerierResult {
1130        let contract_result: ContractResult<Binary> = match request {
1131            DistributionQuery::DelegatorWithdrawAddress { delegator_address } => {
1132                let res = DelegatorWithdrawAddressResponse {
1133                    withdraw_address: Addr::unchecked(
1134                        self.withdraw_addresses
1135                            .get(delegator_address)
1136                            .unwrap_or(delegator_address),
1137                    ),
1138                };
1139                to_json_binary(&res).into()
1140            }
1141            #[cfg(feature = "cosmwasm_1_4")]
1142            DistributionQuery::DelegationRewards {
1143                delegator_address,
1144                validator_address,
1145            } => {
1146                let res = DelegationRewardsResponse {
1147                    rewards: self
1148                        .rewards
1149                        .get(delegator_address)
1150                        .and_then(|v| v.get(validator_address))
1151                        .cloned()
1152                        .unwrap_or_default(),
1153                };
1154                to_json_binary(&res).into()
1155            }
1156            #[cfg(feature = "cosmwasm_1_4")]
1157            DistributionQuery::DelegationTotalRewards { delegator_address } => {
1158                let validator_rewards = self
1159                    .validator_rewards(delegator_address)
1160                    .unwrap_or_default();
1161                let res = crate::DelegationTotalRewardsResponse {
1162                    total: validator_rewards
1163                        .iter()
1164                        .fold(BTreeMap::<&str, DecCoin>::new(), |mut acc, rewards| {
1165                            for coin in &rewards.reward {
1166                                acc.entry(&coin.denom)
1167                                    .or_insert_with(|| DecCoin {
1168                                        denom: coin.denom.clone(),
1169                                        amount: Decimal256::zero(),
1170                                    })
1171                                    .amount += coin.amount;
1172                            }
1173
1174                            acc
1175                        })
1176                        .into_values()
1177                        .collect(),
1178                    rewards: validator_rewards,
1179                };
1180                to_json_binary(&res).into()
1181            }
1182            #[cfg(feature = "cosmwasm_1_4")]
1183            DistributionQuery::DelegatorValidators { delegator_address } => {
1184                let res = DelegatorValidatorsResponse {
1185                    validators: self
1186                        .validators
1187                        .get(delegator_address)
1188                        .map(|set| set.iter().cloned().collect())
1189                        .unwrap_or_default(),
1190                };
1191                to_json_binary(&res).into()
1192            }
1193        };
1194        // system result is always ok in the mock implementation
1195        SystemResult::Ok(contract_result)
1196    }
1197
1198    /// Helper method to get all rewards for a given delegator.
1199    #[cfg(feature = "cosmwasm_1_4")]
1200    fn validator_rewards(&self, delegator_address: &str) -> Option<Vec<crate::DelegatorReward>> {
1201        let validator_rewards = self.rewards.get(delegator_address)?;
1202
1203        Some(
1204            validator_rewards
1205                .iter()
1206                .map(|(validator, rewards)| crate::DelegatorReward {
1207                    validator_address: validator.clone(),
1208                    reward: rewards.clone(),
1209                })
1210                .collect(),
1211        )
1212    }
1213}
1214
1215/// Only for test code. This bypasses assertions in new, allowing us to create _*
1216/// Attributes to simulate responses from the blockchain
1217pub fn mock_wasmd_attr(key: impl Into<String>, value: impl Into<String>) -> Attribute {
1218    Attribute {
1219        key: key.into(),
1220        value: value.into(),
1221    }
1222}
1223
1224#[cfg(test)]
1225mod tests {
1226    use super::*;
1227    #[cfg(feature = "cosmwasm_1_3")]
1228    use crate::DenomUnit;
1229    use crate::{coin, coins, instantiate2_address, ContractInfoResponse, HexBinary, Response};
1230    #[cfg(feature = "staking")]
1231    use crate::{Decimal, Delegation};
1232    use base64::{engine::general_purpose, Engine};
1233    use cosmwasm_core::BLS12_381_G1_GENERATOR;
1234    use hex_literal::hex;
1235    use serde::Deserialize;
1236
1237    const SECP256K1_MSG_HASH_HEX: &str =
1238        "5ae8317d34d1e595e3fa7247db80c0af4320cce1116de187f8f7e2e099c0d8d0";
1239    const SECP256K1_SIG_HEX: &str = "207082eb2c3dfa0b454e0906051270ba4074ac93760ba9e7110cd9471475111151eb0dbbc9920e72146fb564f99d039802bf6ef2561446eb126ef364d21ee9c4";
1240    const SECP256K1_PUBKEY_HEX: &str = "04051c1ee2190ecfb174bfe4f90763f2b4ff7517b70a2aec1876ebcfd644c4633fb03f3cfbd94b1f376e34592d9d41ccaf640bb751b00a1fadeb0c01157769eb73";
1241
1242    const SECP256R1_MSG_HASH_HEX: &str =
1243        "5eb28029ebf3c7025ff2fc2f6de6f62aecf6a72139e1cba5f20d11bbef036a7f";
1244    const SECP256R1_SIG_HEX: &str = "e67a9717ccf96841489d6541f4f6adb12d17b59a6bef847b6183b8fcf16a32eb9ae6ba6d637706849a6a9fc388cf0232d85c26ea0d1fe7437adb48de58364333";
1245    const SECP256R1_PUBKEY_HEX: &str = "0468229b48c2fe19d3db034e4c15077eb7471a66031f28a980821873915298ba76303e8ee3742a893f78b810991da697083dd8f11128c47651c27a56740a80c24c";
1246
1247    const ED25519_MSG_HEX: &str = "72";
1248    const ED25519_SIG_HEX: &str = "92a009a9f0d4cab8720e820b5f642540a2b27b5416503f8fb3762223ebdb69da085ac1e43e15996e458f3613d0f11d8c387b2eaeb4302aeeb00d291612bb0c00";
1249    const ED25519_PUBKEY_HEX: &str =
1250        "3d4017c3e843895a92b70aa74d1b7ebc9c982ccf2ec4968cc0cd55f12af4660c";
1251
1252    // See https://github.com/drand/kyber-bls12381/issues/22 and
1253    // https://github.com/drand/drand/pull/1249
1254    const DOMAIN_HASH_TO_G2: &[u8] = b"BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_NUL_";
1255
1256    /// Public key League of Entropy Mainnet (curl -sS https://drand.cloudflare.com/info)
1257    const PK_LEO_MAINNET: [u8; 48] = hex!("868f005eb8e6e4ca0a47c8a77ceaa5309a47978a7c71bc5cce96366b5d7a569937c529eeda66c7293784a9402801af31");
1258
1259    const ETH_BLOCK_HEADER: &[u8] =
1260        include_bytes!("../../../crypto/testdata/eth-headers/1699693797.394876721s.json");
1261
1262    #[test]
1263    fn mock_env_matches_mock_contract_addr() {
1264        let contract_address = mock_env().contract.address;
1265        assert_eq!(contract_address, Addr::unchecked(MOCK_CONTRACT_ADDR));
1266    }
1267
1268    #[test]
1269    fn mock_info_works() {
1270        #[allow(deprecated)]
1271        let info = mock_info("my name", &coins(100, "atom"));
1272        assert_eq!(
1273            info,
1274            MessageInfo {
1275                sender: Addr::unchecked("my name"),
1276                funds: vec![Coin {
1277                    amount: 100u128.into(),
1278                    denom: "atom".into(),
1279                }]
1280            }
1281        );
1282    }
1283
1284    #[test]
1285    fn addr_validate_works() {
1286        // default prefix is 'cosmwasm'
1287        let api = MockApi::default();
1288
1289        // valid
1290        let humanized = "cosmwasm1h34lmpywh4upnjdg90cjf4j70aee6z8qqfspugamjp42e4q28kqs8s7vcp";
1291        let addr = api.addr_validate(humanized).unwrap();
1292        assert_eq!(addr.as_str(), humanized);
1293
1294        // invalid: too short
1295        api.addr_validate("").unwrap_err();
1296        // invalid: not normalized
1297        api.addr_validate("Foobar123").unwrap_err();
1298        api.addr_validate("FOOBAR123").unwrap_err();
1299    }
1300
1301    #[test]
1302    fn addr_canonicalize_works() {
1303        let api = MockApi::default();
1304
1305        api.addr_canonicalize(
1306            "cosmwasm1h34lmpywh4upnjdg90cjf4j70aee6z8qqfspugamjp42e4q28kqs8s7vcp",
1307        )
1308        .unwrap();
1309
1310        // is case insensitive
1311        let data1 = api
1312            .addr_canonicalize(
1313                "cosmwasm1h34lmpywh4upnjdg90cjf4j70aee6z8qqfspugamjp42e4q28kqs8s7vcp",
1314            )
1315            .unwrap();
1316        let data2 = api
1317            .addr_canonicalize(
1318                "COSMWASM1H34LMPYWH4UPNJDG90CJF4J70AEE6Z8QQFSPUGAMJP42E4Q28KQS8S7VCP",
1319            )
1320            .unwrap();
1321        assert_eq!(data1, data2);
1322    }
1323
1324    #[test]
1325    fn canonicalize_and_humanize_restores_original() {
1326        // create api with 'cosmwasm' prefix
1327        let api = MockApi::default();
1328
1329        // normalizes input
1330        let original =
1331            String::from("COSMWASM1H34LMPYWH4UPNJDG90CJF4J70AEE6Z8QQFSPUGAMJP42E4Q28KQS8S7VCP");
1332        let canonical = api.addr_canonicalize(&original).unwrap();
1333        let recovered = api.addr_humanize(&canonical).unwrap();
1334        assert_eq!(
1335            recovered.as_str(),
1336            "cosmwasm1h34lmpywh4upnjdg90cjf4j70aee6z8qqfspugamjp42e4q28kqs8s7vcp"
1337        );
1338
1339        // create api with 'juno' prefix
1340        let api = MockApi::default().with_prefix("juno");
1341
1342        // long input (Juno contract address)
1343        let original =
1344            String::from("juno1v82su97skv6ucfqvuvswe0t5fph7pfsrtraxf0x33d8ylj5qnrysdvkc95");
1345        let canonical = api.addr_canonicalize(&original).unwrap();
1346        let recovered = api.addr_humanize(&canonical).unwrap();
1347        assert_eq!(recovered.as_str(), original);
1348    }
1349
1350    #[test]
1351    fn addr_canonicalize_short_input() {
1352        let api = MockApi::default();
1353
1354        // empty address should fail
1355        let empty = "cosmwasm1pj90vm";
1356        assert!(api
1357            .addr_canonicalize(empty)
1358            .unwrap_err()
1359            .to_string()
1360            .contains("Invalid canonical address length"));
1361
1362        // one byte address should work
1363        let human = "cosmwasm1qqvk2mde";
1364        assert_eq!(api.addr_canonicalize(human).unwrap().as_ref(), [0u8]);
1365    }
1366
1367    #[test]
1368    fn addr_canonicalize_long_input() {
1369        let api = MockApi::default();
1370        let human =
1371            "cosmwasm1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqehqqkz";
1372        let err = api.addr_canonicalize(human).unwrap_err();
1373        assert!(err.to_string().contains("Invalid canonical address length"));
1374    }
1375
1376    #[test]
1377    fn addr_humanize_input_length() {
1378        let api = MockApi::default();
1379        let input = CanonicalAddr::from(vec![]);
1380        assert_eq!(
1381            api.addr_humanize(&input).unwrap_err(),
1382            StdError::generic_err("Invalid canonical address length")
1383        );
1384    }
1385
1386    #[test]
1387    fn bls12_381_aggregate_g1_works() {
1388        #[derive(serde::Deserialize)]
1389        struct EthHeader {
1390            public_keys: Vec<String>,
1391            aggregate_pubkey: String,
1392        }
1393
1394        let api = MockApi::default();
1395        let header: EthHeader = serde_json::from_slice(ETH_BLOCK_HEADER).unwrap();
1396        let expected = general_purpose::STANDARD
1397            .decode(header.aggregate_pubkey)
1398            .unwrap();
1399
1400        let pubkeys: Vec<u8> = header
1401            .public_keys
1402            .into_iter()
1403            .flat_map(|key| general_purpose::STANDARD.decode(key).unwrap())
1404            .collect();
1405        let sum = api.bls12_381_aggregate_g1(&pubkeys).unwrap();
1406
1407        assert_eq!(expected, sum);
1408    }
1409
1410    #[test]
1411    fn bls12_381_aggregate_g2_works() {
1412        let api = MockApi::default();
1413
1414        let points: Vec<u8> = [
1415            hex!("b6ed936746e01f8ecf281f020953fbf1f01debd5657c4a383940b020b26507f6076334f91e2366c96e9ab279fb5158090352ea1c5b0c9274504f4f0e7053af24802e51e4568d164fe986834f41e55c8e850ce1f98458c0cfc9ab380b55285a55"),
1416            hex!("b23c46be3a001c63ca711f87a005c200cc550b9429d5f4eb38d74322144f1b63926da3388979e5321012fb1a0526bcd100b5ef5fe72628ce4cd5e904aeaa3279527843fae5ca9ca675f4f51ed8f83bbf7155da9ecc9663100a885d5dc6df96d9"),
1417            hex!("948a7cb99f76d616c2c564ce9bf4a519f1bea6b0a624a02276443c245854219fabb8d4ce061d255af5330b078d5380681751aa7053da2c98bae898edc218c75f07e24d8802a17cd1f6833b71e58f5eb5b94208b4d0bb3848cecb075ea21be115"),
1418        ]
1419        .into_iter()
1420        .flatten()
1421        .collect();
1422
1423        let expected = hex!("9683b3e6701f9a4b706709577963110043af78a5b41991b998475a3d3fd62abf35ce03b33908418efc95a058494a8ae504354b9f626231f6b3f3c849dfdeaf5017c4780e2aee1850ceaf4b4d9ce70971a3d2cfcd97b7e5ecf6759f8da5f76d31");
1424        let sum = api.bls12_381_aggregate_g2(&points).unwrap();
1425
1426        assert_eq!(sum, expected);
1427    }
1428
1429    #[test]
1430    fn bls12_381_pairing_equality_works() {
1431        let api = MockApi::default();
1432
1433        let dst = b"BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_POP_";
1434        let ps = hex!("a491d1b0ecd9bb917989f0e74f0dea0422eac4a873e5e2644f368dffb9a6e20fd6e10c1b77654d067c0618f6e5a7f79ab301803f8b5ac4a1133581fc676dfedc60d891dd5fa99028805e5ea5b08d3491af75d0707adab3b70c6a6a580217bf81b53d21a4cfd562c469cc81514d4ce5a6b577d8403d32a394dc265dd190b47fa9f829fdd7963afdf972e5e77854051f6f");
1435        let qs: Vec<u8> = [
1436            hex!("0000000000000000000000000000000000000000000000000000000000000000"),
1437            hex!("5656565656565656565656565656565656565656565656565656565656565656"),
1438            hex!("abababababababababababababababababababababababababababababababab"),
1439        ]
1440        .into_iter()
1441        .flat_map(|msg| {
1442            api.bls12_381_hash_to_g2(HashFunction::Sha256, &msg, dst)
1443                .unwrap()
1444        })
1445        .collect();
1446        let s = hex!("9104e74b9dfd3ad502f25d6a5ef57db0ed7d9a0e00f3500586d8ce44231212542fcfaf87840539b398bf07626705cf1105d246ca1062c6c2e1a53029a0f790ed5e3cb1f52f8234dc5144c45fc847c0cd37a92d68e7c5ba7c648a8a339f171244");
1447
1448        let is_valid = api
1449            .bls12_381_pairing_equality(&ps, &qs, &BLS12_381_G1_GENERATOR, &s)
1450            .unwrap();
1451        assert!(is_valid);
1452    }
1453
1454    #[test]
1455    fn bls12_381_hash_to_g1_works() {
1456        // See: <https://datatracker.ietf.org/doc/rfc9380/>; Section J.9.1
1457
1458        let api = MockApi::default();
1459        let msg = b"abc";
1460        let dst = b"QUUX-V01-CS02-with-BLS12381G1_XMD:SHA-256_SSWU_RO_";
1461
1462        let hashed_point = api
1463            .bls12_381_hash_to_g1(HashFunction::Sha256, msg, dst)
1464            .unwrap();
1465        let mut serialized_expected_compressed = hex!("03567bc5ef9c690c2ab2ecdf6a96ef1c139cc0b2f284dca0a9a7943388a49a3aee664ba5379a7655d3c68900be2f6903");
1466        // Set the compression tag
1467        serialized_expected_compressed[0] |= 0b1000_0000;
1468
1469        assert_eq!(hashed_point, serialized_expected_compressed);
1470    }
1471
1472    #[test]
1473    fn bls12_381_hash_to_g2_works() {
1474        let api = MockApi::default();
1475        let msg = b"abc";
1476        let dst = b"QUUX-V01-CS02-with-BLS12381G2_XMD:SHA-256_SSWU_RO_";
1477
1478        let hashed_point = api
1479            .bls12_381_hash_to_g2(HashFunction::Sha256, msg, dst)
1480            .unwrap();
1481        let mut serialized_expected_compressed = hex!("139cddbccdc5e91b9623efd38c49f81a6f83f175e80b06fc374de9eb4b41dfe4ca3a230ed250fbe3a2acf73a41177fd802c2d18e033b960562aae3cab37a27ce00d80ccd5ba4b7fe0e7a210245129dbec7780ccc7954725f4168aff2787776e6");
1482        // Set the compression tag
1483        serialized_expected_compressed[0] |= 0b1000_0000;
1484
1485        assert_eq!(hashed_point, serialized_expected_compressed);
1486    }
1487
1488    #[test]
1489    fn bls12_318_pairing_equality_works() {
1490        fn build_bls_message(round: u64, previous_signature: &[u8]) -> Vec<u8> {
1491            Sha256::new()
1492                .chain_update(previous_signature)
1493                .chain_update(round.to_be_bytes())
1494                .finalize()
1495                .to_vec()
1496        }
1497
1498        let api = MockApi::default();
1499
1500        let previous_signature = hex::decode("a609e19a03c2fcc559e8dae14900aaefe517cb55c840f6e69bc8e4f66c8d18e8a609685d9917efbfb0c37f058c2de88f13d297c7e19e0ab24813079efe57a182554ff054c7638153f9b26a60e7111f71a0ff63d9571704905d3ca6df0b031747").unwrap();
1501        let signature = hex::decode("82f5d3d2de4db19d40a6980e8aa37842a0e55d1df06bd68bddc8d60002e8e959eb9cfa368b3c1b77d18f02a54fe047b80f0989315f83b12a74fd8679c4f12aae86eaf6ab5690b34f1fddd50ee3cc6f6cdf59e95526d5a5d82aaa84fa6f181e42").unwrap();
1502        let round: u64 = 72785;
1503
1504        let msg = build_bls_message(round, &previous_signature);
1505        let msg_point = api
1506            .bls12_381_hash_to_g2(HashFunction::Sha256, &msg, DOMAIN_HASH_TO_G2)
1507            .unwrap();
1508
1509        let is_valid = api
1510            .bls12_381_pairing_equality(
1511                &BLS12_381_G1_GENERATOR,
1512                &signature,
1513                &PK_LEO_MAINNET,
1514                &msg_point,
1515            )
1516            .unwrap();
1517
1518        assert!(is_valid);
1519    }
1520
1521    // Basic "works" test. Exhaustive tests on VM's side (packages/vm/src/imports.rs)
1522    #[test]
1523    fn secp256k1_verify_works() {
1524        let api = MockApi::default();
1525
1526        let hash = hex::decode(SECP256K1_MSG_HASH_HEX).unwrap();
1527        let signature = hex::decode(SECP256K1_SIG_HEX).unwrap();
1528        let public_key = hex::decode(SECP256K1_PUBKEY_HEX).unwrap();
1529
1530        assert!(api
1531            .secp256k1_verify(&hash, &signature, &public_key)
1532            .unwrap());
1533    }
1534
1535    // Basic "fails" test. Exhaustive tests on VM's side (packages/vm/src/imports.rs)
1536    #[test]
1537    fn secp256k1_verify_fails() {
1538        let api = MockApi::default();
1539
1540        let mut hash = hex::decode(SECP256K1_MSG_HASH_HEX).unwrap();
1541        // alter hash
1542        hash[0] ^= 0x01;
1543        let signature = hex::decode(SECP256K1_SIG_HEX).unwrap();
1544        let public_key = hex::decode(SECP256K1_PUBKEY_HEX).unwrap();
1545
1546        assert!(!api
1547            .secp256k1_verify(&hash, &signature, &public_key)
1548            .unwrap());
1549    }
1550
1551    // Basic "errors" test. Exhaustive tests on VM's side (packages/vm/src/imports.rs)
1552    #[test]
1553    fn secp256k1_verify_errs() {
1554        let api = MockApi::default();
1555
1556        let hash = hex::decode(SECP256K1_MSG_HASH_HEX).unwrap();
1557        let signature = hex::decode(SECP256K1_SIG_HEX).unwrap();
1558        let public_key = vec![];
1559
1560        let res = api.secp256k1_verify(&hash, &signature, &public_key);
1561        assert_eq!(res.unwrap_err(), VerificationError::InvalidPubkeyFormat);
1562    }
1563
1564    #[test]
1565    fn secp256k1_recover_pubkey_works() {
1566        let api = MockApi::default();
1567
1568        // https://gist.github.com/webmaster128/130b628d83621a33579751846699ed15
1569        let hash = hex!("5ae8317d34d1e595e3fa7247db80c0af4320cce1116de187f8f7e2e099c0d8d0");
1570        let signature = hex!("45c0b7f8c09a9e1f1cea0c25785594427b6bf8f9f878a8af0b1abbb48e16d0920d8becd0c220f67c51217eecfd7184ef0732481c843857e6bc7fc095c4f6b788");
1571        let recovery_param = 1;
1572        let expected = hex!("044a071e8a6e10aada2b8cf39fa3b5fb3400b04e99ea8ae64ceea1a977dbeaf5d5f8c8fbd10b71ab14cd561f7df8eb6da50f8a8d81ba564342244d26d1d4211595");
1573
1574        let pubkey = api
1575            .secp256k1_recover_pubkey(&hash, &signature, recovery_param)
1576            .unwrap();
1577        assert_eq!(pubkey, expected);
1578    }
1579
1580    #[test]
1581    fn secp256k1_recover_pubkey_fails_for_wrong_recovery_param() {
1582        let api = MockApi::default();
1583
1584        // https://gist.github.com/webmaster128/130b628d83621a33579751846699ed15
1585        let hash = hex!("5ae8317d34d1e595e3fa7247db80c0af4320cce1116de187f8f7e2e099c0d8d0");
1586        let signature = hex!("45c0b7f8c09a9e1f1cea0c25785594427b6bf8f9f878a8af0b1abbb48e16d0920d8becd0c220f67c51217eecfd7184ef0732481c843857e6bc7fc095c4f6b788");
1587        let _recovery_param = 1;
1588        let expected = hex!("044a071e8a6e10aada2b8cf39fa3b5fb3400b04e99ea8ae64ceea1a977dbeaf5d5f8c8fbd10b71ab14cd561f7df8eb6da50f8a8d81ba564342244d26d1d4211595");
1589
1590        // Wrong recovery param leads to different pubkey
1591        let pubkey = api.secp256k1_recover_pubkey(&hash, &signature, 0).unwrap();
1592        assert_eq!(pubkey.len(), 65);
1593        assert_ne!(pubkey, expected);
1594
1595        // Invalid recovery param leads to error
1596        let result = api.secp256k1_recover_pubkey(&hash, &signature, 42);
1597        match result.unwrap_err() {
1598            RecoverPubkeyError::InvalidRecoveryParam => {}
1599            err => panic!("Unexpected error: {err:?}"),
1600        }
1601    }
1602
1603    #[test]
1604    fn secp256k1_recover_pubkey_fails_for_wrong_hash() {
1605        let api = MockApi::default();
1606
1607        // https://gist.github.com/webmaster128/130b628d83621a33579751846699ed15
1608        let hash = hex!("5ae8317d34d1e595e3fa7247db80c0af4320cce1116de187f8f7e2e099c0d8d0");
1609        let signature = hex!("45c0b7f8c09a9e1f1cea0c25785594427b6bf8f9f878a8af0b1abbb48e16d0920d8becd0c220f67c51217eecfd7184ef0732481c843857e6bc7fc095c4f6b788");
1610        let recovery_param = 1;
1611        let expected = hex!("044a071e8a6e10aada2b8cf39fa3b5fb3400b04e99ea8ae64ceea1a977dbeaf5d5f8c8fbd10b71ab14cd561f7df8eb6da50f8a8d81ba564342244d26d1d4211595");
1612
1613        // Wrong hash
1614        let mut corrupted_hash = hash;
1615        corrupted_hash[0] ^= 0x01;
1616        let pubkey = api
1617            .secp256k1_recover_pubkey(&corrupted_hash, &signature, recovery_param)
1618            .unwrap();
1619        assert_eq!(pubkey.len(), 65);
1620        assert_ne!(pubkey, expected);
1621
1622        // Malformed hash
1623        let mut malformed_hash = hash.to_vec();
1624        malformed_hash.push(0x8a);
1625        let result = api.secp256k1_recover_pubkey(&malformed_hash, &signature, recovery_param);
1626        match result.unwrap_err() {
1627            RecoverPubkeyError::InvalidHashFormat => {}
1628            err => panic!("Unexpected error: {err:?}"),
1629        }
1630    }
1631
1632    // Basic "works" test. Exhaustive tests on VM's side (packages/vm/src/imports.rs)
1633    #[test]
1634    fn secp256r1_verify_works() {
1635        let api = MockApi::default();
1636
1637        let hash = hex::decode(SECP256R1_MSG_HASH_HEX).unwrap();
1638        let signature = hex::decode(SECP256R1_SIG_HEX).unwrap();
1639        let public_key = hex::decode(SECP256R1_PUBKEY_HEX).unwrap();
1640
1641        assert!(api
1642            .secp256r1_verify(&hash, &signature, &public_key)
1643            .unwrap());
1644    }
1645
1646    // Basic "fails" test. Exhaustive tests on VM's side (packages/vm/src/imports.rs)
1647    #[test]
1648    fn secp256r1_verify_fails() {
1649        let api = MockApi::default();
1650
1651        let mut hash = hex::decode(SECP256R1_MSG_HASH_HEX).unwrap();
1652        // alter hash
1653        hash[0] ^= 0x01;
1654        let signature = hex::decode(SECP256R1_SIG_HEX).unwrap();
1655        let public_key = hex::decode(SECP256R1_PUBKEY_HEX).unwrap();
1656
1657        assert!(!api
1658            .secp256r1_verify(&hash, &signature, &public_key)
1659            .unwrap());
1660    }
1661
1662    // Basic "errors" test. Exhaustive tests on VM's side (packages/vm/src/imports.rs)
1663    #[test]
1664    fn secp256r1_verify_errs() {
1665        let api = MockApi::default();
1666
1667        let hash = hex::decode(SECP256R1_MSG_HASH_HEX).unwrap();
1668        let signature = hex::decode(SECP256R1_SIG_HEX).unwrap();
1669        let public_key = vec![];
1670
1671        let res = api.secp256r1_verify(&hash, &signature, &public_key);
1672        assert_eq!(res.unwrap_err(), VerificationError::InvalidPubkeyFormat);
1673    }
1674
1675    #[test]
1676    fn secp256r1_recover_pubkey_works() {
1677        let api = MockApi::default();
1678
1679        let hash = hex!("17b03f9f00f6692ccdde485fc63c4530751ef35da6f71336610944b0894fcfb8");
1680        let signature = hex!("9886ae46c1415c3bc959e82b760ad760aab66885a84e620aa339fdf102465c422bf3a80bc04faa35ebecc0f4864ac02d349f6f126e0f988501b8d3075409a26c");
1681        let recovery_param = 0;
1682        let expected = hex!("0451f99d2d52d4a6e734484a018b7ca2f895c2929b6754a3a03224d07ae61166ce4737da963c6ef7247fb88d19f9b0c667cac7fe12837fdab88c66f10d3c14cad1");
1683
1684        let pubkey = api
1685            .secp256r1_recover_pubkey(&hash, &signature, recovery_param)
1686            .unwrap();
1687        assert_eq!(pubkey, expected);
1688    }
1689
1690    #[test]
1691    fn secp256r1_recover_pubkey_fails_for_wrong_recovery_param() {
1692        let api = MockApi::default();
1693
1694        let hash = hex!("17b03f9f00f6692ccdde485fc63c4530751ef35da6f71336610944b0894fcfb8");
1695        let signature = hex!("9886ae46c1415c3bc959e82b760ad760aab66885a84e620aa339fdf102465c422bf3a80bc04faa35ebecc0f4864ac02d349f6f126e0f988501b8d3075409a26c");
1696        let expected = hex!("0451f99d2d52d4a6e734484a018b7ca2f895c2929b6754a3a03224d07ae61166ce4737da963c6ef7247fb88d19f9b0c667cac7fe12837fdab88c66f10d3c14cad1");
1697
1698        // Wrong recovery param leads to different pubkey
1699        let pubkey = api.secp256r1_recover_pubkey(&hash, &signature, 1).unwrap();
1700        assert_eq!(pubkey.len(), 65);
1701        assert_ne!(pubkey, expected);
1702
1703        // Invalid recovery param leads to error
1704        let result = api.secp256r1_recover_pubkey(&hash, &signature, 42);
1705        match result.unwrap_err() {
1706            RecoverPubkeyError::InvalidRecoveryParam => {}
1707            err => panic!("Unexpected error: {err:?}"),
1708        }
1709    }
1710
1711    #[test]
1712    fn secp256r1_recover_pubkey_fails_for_wrong_hash() {
1713        let api = MockApi::default();
1714
1715        let hash = hex!("17b03f9f00f6692ccdde485fc63c4530751ef35da6f71336610944b0894fcfb8");
1716        let signature = hex!("9886ae46c1415c3bc959e82b760ad760aab66885a84e620aa339fdf102465c422bf3a80bc04faa35ebecc0f4864ac02d349f6f126e0f988501b8d3075409a26c");
1717        let recovery_param = 0;
1718        let expected = hex!("0451f99d2d52d4a6e734484a018b7ca2f895c2929b6754a3a03224d07ae61166ce4737da963c6ef7247fb88d19f9b0c667cac7fe12837fdab88c66f10d3c14cad1");
1719
1720        // Wrong hash
1721        let mut corrupted_hash = hash;
1722        corrupted_hash[0] ^= 0x01;
1723        let pubkey = api
1724            .secp256r1_recover_pubkey(&corrupted_hash, &signature, recovery_param)
1725            .unwrap();
1726        assert_eq!(pubkey.len(), 65);
1727        assert_ne!(pubkey, expected);
1728
1729        // Malformed hash
1730        let mut malformed_hash = hash.to_vec();
1731        malformed_hash.push(0x8a);
1732        let result = api.secp256r1_recover_pubkey(&malformed_hash, &signature, recovery_param);
1733        match result.unwrap_err() {
1734            RecoverPubkeyError::InvalidHashFormat => {}
1735            err => panic!("Unexpected error: {err:?}"),
1736        }
1737    }
1738
1739    // Basic "works" test. Exhaustive tests on VM's side (packages/vm/src/imports.rs)
1740    #[test]
1741    fn ed25519_verify_works() {
1742        let api = MockApi::default();
1743
1744        let msg = hex::decode(ED25519_MSG_HEX).unwrap();
1745        let signature = hex::decode(ED25519_SIG_HEX).unwrap();
1746        let public_key = hex::decode(ED25519_PUBKEY_HEX).unwrap();
1747
1748        assert!(api.ed25519_verify(&msg, &signature, &public_key).unwrap());
1749    }
1750
1751    // Basic "fails" test. Exhaustive tests on VM's side (packages/vm/src/imports.rs)
1752    #[test]
1753    fn ed25519_verify_fails() {
1754        let api = MockApi::default();
1755
1756        let mut msg = hex::decode(ED25519_MSG_HEX).unwrap();
1757        // alter msg
1758        msg[0] ^= 0x01;
1759        let signature = hex::decode(ED25519_SIG_HEX).unwrap();
1760        let public_key = hex::decode(ED25519_PUBKEY_HEX).unwrap();
1761
1762        assert!(!api.ed25519_verify(&msg, &signature, &public_key).unwrap());
1763    }
1764
1765    // Basic "errors" test. Exhaustive tests on VM's side (packages/vm/src/imports.rs)
1766    #[test]
1767    fn ed25519_verify_errs() {
1768        let api = MockApi::default();
1769
1770        let msg = hex::decode(ED25519_MSG_HEX).unwrap();
1771        let signature = hex::decode(ED25519_SIG_HEX).unwrap();
1772        let public_key = vec![];
1773
1774        let res = api.ed25519_verify(&msg, &signature, &public_key);
1775        assert_eq!(res.unwrap_err(), VerificationError::InvalidPubkeyFormat);
1776    }
1777
1778    // Basic "works" test.
1779    #[test]
1780    fn ed25519_batch_verify_works() {
1781        let api = MockApi::default();
1782
1783        let msg = hex::decode(ED25519_MSG_HEX).unwrap();
1784        let signature = hex::decode(ED25519_SIG_HEX).unwrap();
1785        let public_key = hex::decode(ED25519_PUBKEY_HEX).unwrap();
1786
1787        let msgs: Vec<&[u8]> = vec![&msg];
1788        let signatures: Vec<&[u8]> = vec![&signature];
1789        let public_keys: Vec<&[u8]> = vec![&public_key];
1790
1791        assert!(api
1792            .ed25519_batch_verify(&msgs, &signatures, &public_keys)
1793            .unwrap());
1794    }
1795
1796    // Basic "fails" test.
1797    #[test]
1798    fn ed25519_batch_verify_fails() {
1799        let api = MockApi::default();
1800
1801        let mut msg = hex::decode(ED25519_MSG_HEX).unwrap();
1802        // alter msg
1803        msg[0] ^= 0x01;
1804        let signature = hex::decode(ED25519_SIG_HEX).unwrap();
1805        let public_key = hex::decode(ED25519_PUBKEY_HEX).unwrap();
1806
1807        let msgs: Vec<&[u8]> = vec![&msg];
1808        let signatures: Vec<&[u8]> = vec![&signature];
1809        let public_keys: Vec<&[u8]> = vec![&public_key];
1810
1811        assert!(!api
1812            .ed25519_batch_verify(&msgs, &signatures, &public_keys)
1813            .unwrap());
1814    }
1815
1816    // Basic "errors" test.
1817    #[test]
1818    fn ed25519_batch_verify_errs() {
1819        let api = MockApi::default();
1820
1821        let msg = hex::decode(ED25519_MSG_HEX).unwrap();
1822        let signature = hex::decode(ED25519_SIG_HEX).unwrap();
1823        let public_key: Vec<u8> = vec![0u8; 0];
1824
1825        let msgs: Vec<&[u8]> = vec![msg.as_slice()];
1826        let signatures: Vec<&[u8]> = vec![signature.as_slice()];
1827        let public_keys: Vec<&[u8]> = vec![&public_key];
1828
1829        let res = api.ed25519_batch_verify(&msgs, &signatures, &public_keys);
1830        assert_eq!(res.unwrap_err(), VerificationError::InvalidPubkeyFormat);
1831    }
1832
1833    #[cfg(feature = "cosmwasm_1_1")]
1834    #[test]
1835    fn bank_querier_supply() {
1836        let addr1 = String::from("foo");
1837        let balance1 = vec![coin(123, "ELF"), coin(777, "FLY")];
1838
1839        let addr2 = String::from("bar");
1840        let balance2 = coins(321, "ELF");
1841
1842        let bank = BankQuerier::new(&[(&addr1, &balance1), (&addr2, &balance2)]);
1843
1844        let elf = bank
1845            .query(&BankQuery::Supply {
1846                denom: "ELF".to_string(),
1847            })
1848            .unwrap()
1849            .unwrap();
1850        let res: SupplyResponse = from_json(elf).unwrap();
1851        assert_eq!(res.amount, coin(444, "ELF"));
1852
1853        let fly = bank
1854            .query(&BankQuery::Supply {
1855                denom: "FLY".to_string(),
1856            })
1857            .unwrap()
1858            .unwrap();
1859        let res: SupplyResponse = from_json(fly).unwrap();
1860        assert_eq!(res.amount, coin(777, "FLY"));
1861
1862        // if a denom does not exist, should return zero amount, instead of throwing an error
1863        let atom = bank
1864            .query(&BankQuery::Supply {
1865                denom: "ATOM".to_string(),
1866            })
1867            .unwrap()
1868            .unwrap();
1869        let res: SupplyResponse = from_json(atom).unwrap();
1870        assert_eq!(res.amount, coin(0, "ATOM"));
1871    }
1872
1873    #[test]
1874    #[allow(deprecated)]
1875    fn bank_querier_all_balances() {
1876        let addr = String::from("foobar");
1877        let balance = vec![coin(123, "ELF"), coin(777, "FLY")];
1878        let bank = BankQuerier::new(&[(&addr, &balance)]);
1879
1880        let all = bank
1881            .query(&BankQuery::AllBalances { address: addr })
1882            .unwrap()
1883            .unwrap();
1884        let res: AllBalanceResponse = from_json(all).unwrap();
1885        assert_eq!(&res.amount, &balance);
1886    }
1887
1888    #[test]
1889    fn bank_querier_one_balance() {
1890        let addr = String::from("foobar");
1891        let balance = vec![coin(123, "ELF"), coin(777, "FLY")];
1892        let bank = BankQuerier::new(&[(&addr, &balance)]);
1893
1894        // one match
1895        let fly = bank
1896            .query(&BankQuery::Balance {
1897                address: addr.clone(),
1898                denom: "FLY".to_string(),
1899            })
1900            .unwrap()
1901            .unwrap();
1902        let res: BalanceResponse = from_json(fly).unwrap();
1903        assert_eq!(res.amount, coin(777, "FLY"));
1904
1905        // missing denom
1906        let miss = bank
1907            .query(&BankQuery::Balance {
1908                address: addr,
1909                denom: "MISS".to_string(),
1910            })
1911            .unwrap()
1912            .unwrap();
1913        let res: BalanceResponse = from_json(miss).unwrap();
1914        assert_eq!(res.amount, coin(0, "MISS"));
1915    }
1916
1917    #[test]
1918    #[allow(deprecated)]
1919    fn bank_querier_missing_account() {
1920        let addr = String::from("foobar");
1921        let balance = vec![coin(123, "ELF"), coin(777, "FLY")];
1922        let bank = BankQuerier::new(&[(&addr, &balance)]);
1923
1924        // all balances on empty account is empty vec
1925        let all = bank
1926            .query(&BankQuery::AllBalances {
1927                address: String::from("elsewhere"),
1928            })
1929            .unwrap()
1930            .unwrap();
1931        let res: AllBalanceResponse = from_json(all).unwrap();
1932        assert_eq!(res.amount, vec![]);
1933
1934        // any denom on balances on empty account is empty coin
1935        let miss = bank
1936            .query(&BankQuery::Balance {
1937                address: String::from("elsewhere"),
1938                denom: "ELF".to_string(),
1939            })
1940            .unwrap()
1941            .unwrap();
1942        let res: BalanceResponse = from_json(miss).unwrap();
1943        assert_eq!(res.amount, coin(0, "ELF"));
1944    }
1945
1946    #[cfg(feature = "cosmwasm_1_3")]
1947    #[test]
1948    fn bank_querier_metadata_works() {
1949        let mut bank = BankQuerier::new(&[]);
1950        bank.set_denom_metadata(
1951            &(0..100)
1952                .map(|i| DenomMetadata {
1953                    symbol: format!("FOO{i}"),
1954                    name: "Foo".to_string(),
1955                    description: "Foo coin".to_string(),
1956                    denom_units: vec![DenomUnit {
1957                        denom: "ufoo".to_string(),
1958                        exponent: 8,
1959                        aliases: vec!["microfoo".to_string(), "foobar".to_string()],
1960                    }],
1961                    display: "FOO".to_string(),
1962                    base: format!("ufoo{i}"),
1963                    uri: "https://foo.bar".to_string(),
1964                    uri_hash: "foo".to_string(),
1965                })
1966                .collect::<Vec<_>>(),
1967        );
1968
1969        // querying first 10 should work
1970        let res = bank
1971            .query(&BankQuery::AllDenomMetadata {
1972                pagination: Some(PageRequest {
1973                    key: None,
1974                    limit: 10,
1975                    reverse: false,
1976                }),
1977            })
1978            .unwrap()
1979            .unwrap();
1980        let res: AllDenomMetadataResponse = from_json(res).unwrap();
1981        assert_eq!(res.metadata.len(), 10);
1982        assert!(res.next_key.is_some());
1983
1984        // querying next 10 should also work
1985        let res2 = bank
1986            .query(&BankQuery::AllDenomMetadata {
1987                pagination: Some(PageRequest {
1988                    key: res.next_key,
1989                    limit: 10,
1990                    reverse: false,
1991                }),
1992            })
1993            .unwrap()
1994            .unwrap();
1995        let res2: AllDenomMetadataResponse = from_json(res2).unwrap();
1996        assert_eq!(res2.metadata.len(), 10);
1997        assert_ne!(res.metadata.last(), res2.metadata.first());
1998        // should have no overlap
1999        for m in res.metadata {
2000            assert!(!res2.metadata.contains(&m));
2001        }
2002
2003        // querying all 100 should work
2004        let res = bank
2005            .query(&BankQuery::AllDenomMetadata {
2006                pagination: Some(PageRequest {
2007                    key: None,
2008                    limit: 100,
2009                    reverse: true,
2010                }),
2011            })
2012            .unwrap()
2013            .unwrap();
2014        let res: AllDenomMetadataResponse = from_json(res).unwrap();
2015        assert_eq!(res.metadata.len(), 100);
2016        assert!(res.next_key.is_none(), "no more data should be available");
2017        assert_eq!(res.metadata[0].symbol, "FOO99", "should have been reversed");
2018
2019        let more_res = bank
2020            .query(&BankQuery::AllDenomMetadata {
2021                pagination: Some(PageRequest {
2022                    key: res.next_key,
2023                    limit: u32::MAX,
2024                    reverse: true,
2025                }),
2026            })
2027            .unwrap()
2028            .unwrap();
2029        let more_res: AllDenomMetadataResponse = from_json(more_res).unwrap();
2030        assert_eq!(
2031            more_res.metadata, res.metadata,
2032            "should be same as previous query"
2033        );
2034    }
2035
2036    #[cfg(feature = "cosmwasm_1_3")]
2037    #[test]
2038    fn distribution_querier_delegator_withdraw_address() {
2039        let mut distribution = DistributionQuerier::default();
2040        distribution.set_withdraw_address("addr0", "withdraw0");
2041
2042        let query = DistributionQuery::DelegatorWithdrawAddress {
2043            delegator_address: "addr0".to_string(),
2044        };
2045
2046        let res = distribution.query(&query).unwrap().unwrap();
2047        let res: DelegatorWithdrawAddressResponse = from_json(res).unwrap();
2048        assert_eq!(res.withdraw_address.as_str(), "withdraw0");
2049
2050        let query = DistributionQuery::DelegatorWithdrawAddress {
2051            delegator_address: "addr1".to_string(),
2052        };
2053
2054        let res = distribution.query(&query).unwrap().unwrap();
2055        let res: DelegatorWithdrawAddressResponse = from_json(res).unwrap();
2056        assert_eq!(res.withdraw_address.as_str(), "addr1");
2057    }
2058
2059    #[cfg(feature = "cosmwasm_1_4")]
2060    #[test]
2061    fn distribution_querier_delegator_validators() {
2062        let mut distribution = DistributionQuerier::default();
2063        distribution.set_validators("addr0", ["valoper1", "valoper2"]);
2064
2065        let query = DistributionQuery::DelegatorValidators {
2066            delegator_address: "addr0".to_string(),
2067        };
2068
2069        let res = distribution.query(&query).unwrap().unwrap();
2070        let res: DelegatorValidatorsResponse = from_json(res).unwrap();
2071        assert_eq!(res.validators, ["valoper1", "valoper2"]);
2072
2073        let query = DistributionQuery::DelegatorValidators {
2074            delegator_address: "addr1".to_string(),
2075        };
2076
2077        let res = distribution.query(&query).unwrap().unwrap();
2078        let res: DelegatorValidatorsResponse = from_json(res).unwrap();
2079        assert_eq!(res.validators, ([] as [String; 0]));
2080    }
2081
2082    #[cfg(feature = "cosmwasm_1_4")]
2083    #[test]
2084    fn distribution_querier_delegation_rewards() {
2085        use crate::{Decimal256, DelegationTotalRewardsResponse, DelegatorReward};
2086
2087        let mut distribution = DistributionQuerier::default();
2088        let valoper0_rewards = vec![
2089            DecCoin::new(Decimal256::from_atomics(1234u128, 0).unwrap(), "uatom"),
2090            DecCoin::new(Decimal256::from_atomics(56781234u128, 4).unwrap(), "utest"),
2091        ];
2092        distribution.set_rewards("valoper0", "addr0", valoper0_rewards.clone());
2093
2094        // both exist / are set
2095        let query = DistributionQuery::DelegationRewards {
2096            delegator_address: "addr0".to_string(),
2097            validator_address: "valoper0".to_string(),
2098        };
2099        let res = distribution.query(&query).unwrap().unwrap();
2100        let res: DelegationRewardsResponse = from_json(res).unwrap();
2101        assert_eq!(res.rewards, valoper0_rewards);
2102
2103        // delegator does not exist
2104        let query = DistributionQuery::DelegationRewards {
2105            delegator_address: "nonexistent".to_string(),
2106            validator_address: "valoper0".to_string(),
2107        };
2108        let res = distribution.query(&query).unwrap().unwrap();
2109        let res: DelegationRewardsResponse = from_json(res).unwrap();
2110        assert_eq!(res.rewards.len(), 0);
2111
2112        // validator does not exist
2113        let query = DistributionQuery::DelegationRewards {
2114            delegator_address: "addr0".to_string(),
2115            validator_address: "valopernonexistent".to_string(),
2116        };
2117        let res = distribution.query(&query).unwrap().unwrap();
2118        let res: DelegationRewardsResponse = from_json(res).unwrap();
2119        assert_eq!(res.rewards.len(), 0);
2120
2121        // add one more validator
2122        let valoper1_rewards = vec![DecCoin::new(Decimal256::one(), "uatom")];
2123        distribution.set_rewards("valoper1", "addr0", valoper1_rewards.clone());
2124
2125        // total rewards
2126        let query = DistributionQuery::DelegationTotalRewards {
2127            delegator_address: "addr0".to_string(),
2128        };
2129        let res = distribution.query(&query).unwrap().unwrap();
2130        let res: DelegationTotalRewardsResponse = from_json(res).unwrap();
2131        assert_eq!(
2132            res.rewards,
2133            vec![
2134                DelegatorReward {
2135                    validator_address: "valoper0".into(),
2136                    reward: valoper0_rewards
2137                },
2138                DelegatorReward {
2139                    validator_address: "valoper1".into(),
2140                    reward: valoper1_rewards
2141                },
2142            ]
2143        );
2144        assert_eq!(
2145            res.total,
2146            [
2147                DecCoin::new(
2148                    Decimal256::from_atomics(1234u128, 0).unwrap() + Decimal256::one(),
2149                    "uatom"
2150                ),
2151                // total for utest should still be the same
2152                DecCoin::new(Decimal256::from_atomics(56781234u128, 4).unwrap(), "utest")
2153            ]
2154        );
2155    }
2156
2157    #[cfg(feature = "stargate")]
2158    #[test]
2159    fn ibc_querier_channel_existing() {
2160        let chan1 = mock_ibc_channel("channel-0", IbcOrder::Ordered, "ibc");
2161        let chan2 = mock_ibc_channel("channel-1", IbcOrder::Ordered, "ibc");
2162
2163        let ibc = IbcQuerier::new("myport", &[chan1.clone(), chan2]);
2164
2165        // query existing
2166        let query = &IbcQuery::Channel {
2167            channel_id: "channel-0".to_string(),
2168            port_id: Some("my_port".to_string()),
2169        };
2170        let raw = ibc.query(query).unwrap().unwrap();
2171        let chan: ChannelResponse = from_json(raw).unwrap();
2172        assert_eq!(chan.channel, Some(chan1));
2173    }
2174
2175    #[cfg(feature = "stargate")]
2176    #[test]
2177    fn ibc_querier_channel_existing_no_port() {
2178        let chan1 = IbcChannel {
2179            endpoint: IbcEndpoint {
2180                port_id: "myport".to_string(),
2181                channel_id: "channel-0".to_string(),
2182            },
2183            counterparty_endpoint: IbcEndpoint {
2184                port_id: "their_port".to_string(),
2185                channel_id: "channel-7".to_string(),
2186            },
2187            order: IbcOrder::Ordered,
2188            version: "ibc".to_string(),
2189            connection_id: "connection-2".to_string(),
2190        };
2191        let chan2 = mock_ibc_channel("channel-1", IbcOrder::Ordered, "ibc");
2192
2193        let ibc = IbcQuerier::new("myport", &[chan1.clone(), chan2]);
2194
2195        // query existing
2196        let query = &IbcQuery::Channel {
2197            channel_id: "channel-0".to_string(),
2198            port_id: Some("myport".to_string()),
2199        };
2200        let raw = ibc.query(query).unwrap().unwrap();
2201        let chan: ChannelResponse = from_json(raw).unwrap();
2202        assert_eq!(chan.channel, Some(chan1));
2203    }
2204
2205    #[cfg(feature = "stargate")]
2206    #[test]
2207    fn ibc_querier_channel_none() {
2208        let chan1 = mock_ibc_channel("channel-0", IbcOrder::Ordered, "ibc");
2209        let chan2 = mock_ibc_channel("channel-1", IbcOrder::Ordered, "ibc");
2210
2211        let ibc = IbcQuerier::new("myport", &[chan1, chan2]);
2212
2213        // query non-existing
2214        let query = &IbcQuery::Channel {
2215            channel_id: "channel-0".to_string(),
2216            port_id: None,
2217        };
2218        let raw = ibc.query(query).unwrap().unwrap();
2219        let chan: ChannelResponse = from_json(raw).unwrap();
2220        assert_eq!(chan.channel, None);
2221    }
2222
2223    #[cfg(feature = "stargate")]
2224    #[test]
2225    #[allow(deprecated)]
2226    fn ibc_querier_channels_matching() {
2227        let chan1 = mock_ibc_channel("channel-0", IbcOrder::Ordered, "ibc");
2228        let chan2 = mock_ibc_channel("channel-1", IbcOrder::Ordered, "ibc");
2229
2230        let ibc = IbcQuerier::new("myport", &[chan1.clone(), chan2.clone()]);
2231
2232        // query channels matching "my_port" (should match both above)
2233        let query = &IbcQuery::ListChannels {
2234            port_id: Some("my_port".to_string()),
2235        };
2236        let raw = ibc.query(query).unwrap().unwrap();
2237        let res: ListChannelsResponse = from_json(raw).unwrap();
2238        assert_eq!(res.channels, vec![chan1, chan2]);
2239    }
2240
2241    #[cfg(feature = "stargate")]
2242    #[test]
2243    #[allow(deprecated)]
2244    fn ibc_querier_channels_no_matching() {
2245        let chan1 = mock_ibc_channel("channel-0", IbcOrder::Ordered, "ibc");
2246        let chan2 = mock_ibc_channel("channel-1", IbcOrder::Ordered, "ibc");
2247
2248        let ibc = IbcQuerier::new("myport", &[chan1, chan2]);
2249
2250        // query channels matching "myport" (should be none)
2251        let query = &IbcQuery::ListChannels { port_id: None };
2252        let raw = ibc.query(query).unwrap().unwrap();
2253        let res: ListChannelsResponse = from_json(raw).unwrap();
2254        assert_eq!(res.channels, vec![]);
2255    }
2256
2257    #[cfg(feature = "stargate")]
2258    #[test]
2259    fn ibc_querier_port() {
2260        let chan1 = mock_ibc_channel("channel-0", IbcOrder::Ordered, "ibc");
2261
2262        let ibc = IbcQuerier::new("myport", &[chan1]);
2263
2264        // query channels matching "myport" (should be none)
2265        let query = &IbcQuery::PortId {};
2266        let raw = ibc.query(query).unwrap().unwrap();
2267        let res: PortIdResponse = from_json(raw).unwrap();
2268        assert_eq!(res.port_id, "myport");
2269    }
2270
2271    #[cfg(feature = "staking")]
2272    #[test]
2273    fn staking_querier_all_validators() {
2274        let val1 = Validator {
2275            address: String::from("validator-one"),
2276            commission: Decimal::percent(1),
2277            max_commission: Decimal::percent(3),
2278            max_change_rate: Decimal::percent(1),
2279        };
2280        let val2 = Validator {
2281            address: String::from("validator-two"),
2282            commission: Decimal::permille(15),
2283            max_commission: Decimal::permille(40),
2284            max_change_rate: Decimal::permille(5),
2285        };
2286
2287        let staking = StakingQuerier::new("ustake", &[val1.clone(), val2.clone()], &[]);
2288
2289        // one match
2290        let raw = staking
2291            .query(&StakingQuery::AllValidators {})
2292            .unwrap()
2293            .unwrap();
2294        let vals: AllValidatorsResponse = from_json(raw).unwrap();
2295        assert_eq!(vals.validators, vec![val1, val2]);
2296    }
2297
2298    #[cfg(feature = "staking")]
2299    #[test]
2300    fn staking_querier_validator() {
2301        let address1 = String::from("validator-one");
2302        let address2 = String::from("validator-two");
2303        let address_non_existent = String::from("wannabe-validator");
2304
2305        let val1 = Validator {
2306            address: address1.clone(),
2307            commission: Decimal::percent(1),
2308            max_commission: Decimal::percent(3),
2309            max_change_rate: Decimal::percent(1),
2310        };
2311        let val2 = Validator {
2312            address: address2.clone(),
2313            commission: Decimal::permille(15),
2314            max_commission: Decimal::permille(40),
2315            max_change_rate: Decimal::permille(5),
2316        };
2317
2318        let staking = StakingQuerier::new("ustake", &[val1.clone(), val2.clone()], &[]);
2319
2320        // query 1
2321        let raw = staking
2322            .query(&StakingQuery::Validator { address: address1 })
2323            .unwrap()
2324            .unwrap();
2325        let res: ValidatorResponse = from_json(raw).unwrap();
2326        assert_eq!(res.validator, Some(val1));
2327
2328        // query 2
2329        let raw = staking
2330            .query(&StakingQuery::Validator { address: address2 })
2331            .unwrap()
2332            .unwrap();
2333        let res: ValidatorResponse = from_json(raw).unwrap();
2334        assert_eq!(res.validator, Some(val2));
2335
2336        // query non-existent
2337        let raw = staking
2338            .query(&StakingQuery::Validator {
2339                address: address_non_existent,
2340            })
2341            .unwrap()
2342            .unwrap();
2343        let res: ValidatorResponse = from_json(raw).unwrap();
2344        assert_eq!(res.validator, None);
2345    }
2346
2347    #[cfg(feature = "staking")]
2348    // gets delegators from query or panic
2349    fn get_all_delegators(
2350        staking: &StakingQuerier,
2351        delegator: impl Into<String>,
2352    ) -> Vec<Delegation> {
2353        let raw = staking
2354            .query(&StakingQuery::AllDelegations {
2355                delegator: delegator.into(),
2356            })
2357            .unwrap()
2358            .unwrap();
2359        let dels: AllDelegationsResponse = from_json(raw).unwrap();
2360        dels.delegations
2361    }
2362
2363    #[cfg(feature = "staking")]
2364    // gets full delegators from query or panic
2365    fn get_delegator(
2366        staking: &StakingQuerier,
2367        delegator: impl Into<String>,
2368        validator: impl Into<String>,
2369    ) -> Option<FullDelegation> {
2370        let raw = staking
2371            .query(&StakingQuery::Delegation {
2372                delegator: delegator.into(),
2373                validator: validator.into(),
2374            })
2375            .unwrap()
2376            .unwrap();
2377        let dels: DelegationResponse = from_json(raw).unwrap();
2378        dels.delegation
2379    }
2380
2381    #[cfg(feature = "staking")]
2382    #[test]
2383    fn staking_querier_delegations() {
2384        let val1 = String::from("validator-one");
2385        let val2 = String::from("validator-two");
2386
2387        let user_a = Addr::unchecked("investor");
2388        let user_b = Addr::unchecked("speculator");
2389        let user_c = Addr::unchecked("hodler");
2390
2391        // we need multiple validators per delegator, so the queries provide different results
2392        let del1a = FullDelegation {
2393            delegator: user_a.clone(),
2394            validator: val1.clone(),
2395            amount: coin(100, "ustake"),
2396            can_redelegate: coin(100, "ustake"),
2397            accumulated_rewards: coins(5, "ustake"),
2398        };
2399        let del2a = FullDelegation {
2400            delegator: user_a.clone(),
2401            validator: val2.clone(),
2402            amount: coin(500, "ustake"),
2403            can_redelegate: coin(500, "ustake"),
2404            accumulated_rewards: coins(20, "ustake"),
2405        };
2406
2407        // note we cannot have multiple delegations on one validator, they are collapsed into one
2408        let del1b = FullDelegation {
2409            delegator: user_b.clone(),
2410            validator: val1.clone(),
2411            amount: coin(500, "ustake"),
2412            can_redelegate: coin(0, "ustake"),
2413            accumulated_rewards: coins(0, "ustake"),
2414        };
2415
2416        // and another one on val2
2417        let del2c = FullDelegation {
2418            delegator: user_c.clone(),
2419            validator: val2.clone(),
2420            amount: coin(8888, "ustake"),
2421            can_redelegate: coin(4567, "ustake"),
2422            accumulated_rewards: coins(900, "ustake"),
2423        };
2424
2425        let staking = StakingQuerier::new(
2426            "ustake",
2427            &[],
2428            &[del1a.clone(), del1b.clone(), del2a.clone(), del2c.clone()],
2429        );
2430
2431        // get all for user a
2432        let dels = get_all_delegators(&staking, user_a.clone());
2433        assert_eq!(dels, vec![del1a.clone().into(), del2a.clone().into()]);
2434
2435        // get all for user b
2436        let dels = get_all_delegators(&staking, user_b.clone());
2437        assert_eq!(dels, vec![del1b.clone().into()]);
2438
2439        // get all for user c
2440        let dels = get_all_delegators(&staking, user_c.clone());
2441        assert_eq!(dels, vec![del2c.clone().into()]);
2442
2443        // for user with no delegations...
2444        let dels = get_all_delegators(&staking, String::from("no one"));
2445        assert_eq!(dels, vec![]);
2446
2447        // filter a by validator (1 and 1)
2448        let dels = get_delegator(&staking, user_a.clone(), val1.clone());
2449        assert_eq!(dels, Some(del1a));
2450        let dels = get_delegator(&staking, user_a, val2.clone());
2451        assert_eq!(dels, Some(del2a));
2452
2453        // filter b by validator (2 and 0)
2454        let dels = get_delegator(&staking, user_b.clone(), val1.clone());
2455        assert_eq!(dels, Some(del1b));
2456        let dels = get_delegator(&staking, user_b, val2.clone());
2457        assert_eq!(dels, None);
2458
2459        // filter c by validator (0 and 1)
2460        let dels = get_delegator(&staking, user_c.clone(), val1);
2461        assert_eq!(dels, None);
2462        let dels = get_delegator(&staking, user_c, val2);
2463        assert_eq!(dels, Some(del2c));
2464    }
2465
2466    #[test]
2467    fn wasm_querier_works() {
2468        let mut querier = WasmQuerier::default();
2469
2470        let any_addr = "foo".to_string();
2471
2472        // By default, querier errors for WasmQuery::Raw
2473        let system_err = querier
2474            .query(&WasmQuery::Raw {
2475                contract_addr: any_addr.clone(),
2476                key: b"the key".into(),
2477            })
2478            .unwrap_err();
2479        match system_err {
2480            SystemError::NoSuchContract { addr } => assert_eq!(addr, any_addr),
2481            err => panic!("Unexpected error: {err:?}"),
2482        }
2483
2484        // By default, querier errors for WasmQuery::Smart
2485        let system_err = querier
2486            .query(&WasmQuery::Smart {
2487                contract_addr: any_addr.clone(),
2488                msg: b"{}".into(),
2489            })
2490            .unwrap_err();
2491        match system_err {
2492            SystemError::NoSuchContract { addr } => assert_eq!(addr, any_addr),
2493            err => panic!("Unexpected error: {err:?}"),
2494        }
2495
2496        // By default, querier errors for WasmQuery::ContractInfo
2497        let system_err = querier
2498            .query(&WasmQuery::ContractInfo {
2499                contract_addr: any_addr.clone(),
2500            })
2501            .unwrap_err();
2502        match system_err {
2503            SystemError::NoSuchContract { addr } => assert_eq!(addr, any_addr),
2504            err => panic!("Unexpected error: {err:?}"),
2505        }
2506
2507        #[cfg(feature = "cosmwasm_1_2")]
2508        {
2509            // By default, querier errors for WasmQuery::CodeInfo
2510            let system_err = querier
2511                .query(&WasmQuery::CodeInfo { code_id: 4 })
2512                .unwrap_err();
2513            match system_err {
2514                SystemError::NoSuchCode { code_id } => assert_eq!(code_id, 4),
2515                err => panic!("Unexpected error: {err:?}"),
2516            }
2517        }
2518
2519        querier.update_handler(|request| {
2520            let api = MockApi::default();
2521            let contract1 = api.addr_make("contract1");
2522            let mut storage1 = BTreeMap::<Binary, Binary>::default();
2523            storage1.insert(b"the key".into(), b"the value".into());
2524
2525            match request {
2526                WasmQuery::Raw { contract_addr, key } => {
2527                    let Ok(addr) = api.addr_validate(contract_addr) else {
2528                        return SystemResult::Err(SystemError::NoSuchContract {
2529                            addr: contract_addr.clone(),
2530                        });
2531                    };
2532                    if addr == contract1 {
2533                        if let Some(value) = storage1.get(key) {
2534                            SystemResult::Ok(ContractResult::Ok(value.clone()))
2535                        } else {
2536                            SystemResult::Ok(ContractResult::Ok(Binary::default()))
2537                        }
2538                    } else {
2539                        SystemResult::Err(SystemError::NoSuchContract {
2540                            addr: contract_addr.clone(),
2541                        })
2542                    }
2543                }
2544                WasmQuery::Smart { contract_addr, msg } => {
2545                    let Ok(addr) = api.addr_validate(contract_addr) else {
2546                        return SystemResult::Err(SystemError::NoSuchContract {
2547                            addr: contract_addr.clone(),
2548                        });
2549                    };
2550                    if addr == contract1 {
2551                        #[derive(Deserialize)]
2552                        struct MyMsg {}
2553                        let _msg: MyMsg = match from_json(msg) {
2554                            Ok(msg) => msg,
2555                            Err(err) => {
2556                                return SystemResult::Ok(ContractResult::Err(err.to_string()))
2557                            }
2558                        };
2559                        let response: Response = Response::new().set_data(b"good");
2560                        SystemResult::Ok(ContractResult::Ok(to_json_binary(&response).unwrap()))
2561                    } else {
2562                        SystemResult::Err(SystemError::NoSuchContract {
2563                            addr: contract_addr.clone(),
2564                        })
2565                    }
2566                }
2567                WasmQuery::ContractInfo { contract_addr } => {
2568                    let Ok(addr) = api.addr_validate(contract_addr) else {
2569                        return SystemResult::Err(SystemError::NoSuchContract {
2570                            addr: contract_addr.clone(),
2571                        });
2572                    };
2573                    if addr == contract1 {
2574                        let response = ContractInfoResponse {
2575                            code_id: 4,
2576                            creator: Addr::unchecked("lalala"),
2577                            admin: None,
2578                            pinned: false,
2579                            ibc_port: None,
2580                        };
2581                        SystemResult::Ok(ContractResult::Ok(to_json_binary(&response).unwrap()))
2582                    } else {
2583                        SystemResult::Err(SystemError::NoSuchContract {
2584                            addr: contract_addr.clone(),
2585                        })
2586                    }
2587                }
2588                #[cfg(feature = "cosmwasm_1_2")]
2589                WasmQuery::CodeInfo { code_id } => {
2590                    use crate::{Checksum, CodeInfoResponse};
2591                    let code_id = *code_id;
2592                    if code_id == 4 {
2593                        let response = CodeInfoResponse {
2594                            code_id,
2595                            creator: Addr::unchecked("lalala"),
2596                            checksum: Checksum::from_hex(
2597                                "84cf20810fd429caf58898c3210fcb71759a27becddae08dbde8668ea2f4725d",
2598                            )
2599                            .unwrap(),
2600                        };
2601                        SystemResult::Ok(ContractResult::Ok(to_json_binary(&response).unwrap()))
2602                    } else {
2603                        SystemResult::Err(SystemError::NoSuchCode { code_id })
2604                    }
2605                }
2606            }
2607        });
2608
2609        let contract_addr = MockApi::default().addr_make("contract1");
2610
2611        // WasmQuery::Raw
2612        let result = querier.query(&WasmQuery::Raw {
2613            contract_addr: contract_addr.clone().into(),
2614            key: b"the key".into(),
2615        });
2616
2617        match result {
2618            SystemResult::Ok(ContractResult::Ok(value)) => assert_eq!(value, b"the value" as &[u8]),
2619            res => panic!("Unexpected result: {res:?}"),
2620        }
2621        let result = querier.query(&WasmQuery::Raw {
2622            contract_addr: contract_addr.clone().into(),
2623            key: b"other key".into(),
2624        });
2625        match result {
2626            SystemResult::Ok(ContractResult::Ok(value)) => assert_eq!(value, b"" as &[u8]),
2627            res => panic!("Unexpected result: {res:?}"),
2628        }
2629
2630        // WasmQuery::Smart
2631        let result = querier.query(&WasmQuery::Smart {
2632            contract_addr: contract_addr.clone().into(),
2633            msg: b"{}".into(),
2634        });
2635        match result {
2636            SystemResult::Ok(ContractResult::Ok(value)) => assert_eq!(
2637                value,
2638                br#"{"messages":[],"attributes":[],"events":[],"data":"Z29vZA=="}"# as &[u8]
2639            ),
2640            res => panic!("Unexpected result: {res:?}"),
2641        }
2642        let result = querier.query(&WasmQuery::Smart {
2643            contract_addr: contract_addr.clone().into(),
2644            msg: b"a broken request".into(),
2645        });
2646        match result {
2647            SystemResult::Ok(ContractResult::Err(err)) => {
2648                assert_eq!(err, "Error parsing into type cosmwasm_std::testing::mock::tests::wasm_querier_works::{{closure}}::MyMsg: Invalid type")
2649            }
2650            res => panic!("Unexpected result: {res:?}"),
2651        }
2652
2653        // WasmQuery::ContractInfo
2654        let result = querier.query(&WasmQuery::ContractInfo {
2655            contract_addr: contract_addr.into(),
2656        });
2657        match result {
2658            SystemResult::Ok(ContractResult::Ok(value)) => assert_eq!(
2659                value,
2660                br#"{"code_id":4,"creator":"lalala","admin":null,"pinned":false,"ibc_port":null}"#
2661                    as &[u8]
2662            ),
2663            res => panic!("Unexpected result: {res:?}"),
2664        }
2665
2666        // WasmQuery::CodeInfo
2667        #[cfg(feature = "cosmwasm_1_2")]
2668        {
2669            let result = querier.query(&WasmQuery::CodeInfo { code_id: 4 });
2670            match result {
2671                SystemResult::Ok(ContractResult::Ok(value)) => assert_eq!(
2672                    value,
2673                    br#"{"code_id":4,"creator":"lalala","checksum":"84cf20810fd429caf58898c3210fcb71759a27becddae08dbde8668ea2f4725d"}"#
2674                ),
2675                res => panic!("Unexpected result: {res:?}"),
2676            }
2677        }
2678    }
2679
2680    #[test]
2681    fn making_an_address_works() {
2682        let mock_api = MockApi::default();
2683
2684        assert_eq!(
2685            mock_api.addr_make("creator").to_string(),
2686            "cosmwasm1h34lmpywh4upnjdg90cjf4j70aee6z8qqfspugamjp42e4q28kqs8s7vcp",
2687        );
2688
2689        assert_eq!(
2690            mock_api.addr_make("").to_string(),
2691            "cosmwasm1uwcvgs5clswpfxhm7nyfjmaeysn6us0yvjdexn9yjkv3k7zjhp2sly4xh9",
2692        );
2693
2694        let mock_api = MockApi::default().with_prefix("juno");
2695        assert_eq!(
2696            mock_api.addr_make("creator").to_string(),
2697            "juno1h34lmpywh4upnjdg90cjf4j70aee6z8qqfspugamjp42e4q28kqsksmtyp",
2698        );
2699    }
2700
2701    #[test]
2702    fn colon_in_prefix_is_valid() {
2703        let mock_api = MockApi::default().with_prefix("did:com:");
2704        let addr = mock_api
2705            .addr_validate("did:com:1jkf0kmeyefvyzpwf56m7sne2000ay53r6upttu")
2706            .unwrap();
2707
2708        assert_eq!(
2709            addr.as_str(),
2710            "did:com:1jkf0kmeyefvyzpwf56m7sne2000ay53r6upttu"
2711        );
2712    }
2713
2714    #[test]
2715    #[should_panic(
2716        expected = "Generating address failed with reason: hrp is empty, must have at least 1 character"
2717    )]
2718    fn making_an_address_with_empty_prefix_should_panic() {
2719        MockApi::default().with_prefix("").addr_make("creator");
2720    }
2721
2722    #[test]
2723    #[cfg(feature = "cosmwasm_1_3")]
2724    fn distribution_querier_new_works() {
2725        let addresses = [
2726            ("addr0000".to_string(), "addr0001".to_string()),
2727            ("addr0002".to_string(), "addr0001".to_string()),
2728        ];
2729        let btree_map = BTreeMap::from(addresses.clone());
2730
2731        // should still work with HashMap
2732        let hashmap = std::collections::HashMap::from(addresses.clone());
2733        let querier = DistributionQuerier::new(hashmap);
2734        assert_eq!(querier.withdraw_addresses, btree_map);
2735
2736        // should work with BTreeMap
2737        let querier = DistributionQuerier::new(btree_map.clone());
2738        assert_eq!(querier.withdraw_addresses, btree_map);
2739
2740        // should work with array
2741        let querier = DistributionQuerier::new(addresses);
2742        assert_eq!(querier.withdraw_addresses, btree_map);
2743    }
2744
2745    #[test]
2746    fn instantiate2_address_can_be_humanized() {
2747        let mock_api = MockApi::default();
2748
2749        let contract_addr = mock_api
2750            .addr_canonicalize(mock_api.addr_make("contract").as_str())
2751            .unwrap();
2752        let checksum =
2753            HexBinary::from_hex("9af782a3a1bcbcd22dbb6a45c751551d9af782a3a1bcbcd22dbb6a45c751551d")
2754                .unwrap();
2755        let salt = b"instance 1231";
2756        let canonical_addr = instantiate2_address(&checksum, &contract_addr, salt).unwrap();
2757        // we are not interested in the exact humanization, just that it works
2758        mock_api.addr_humanize(&canonical_addr).unwrap();
2759    }
2760}