secret_cosmwasm_std/testing/
mock.rs

1use serde::de::DeserializeOwned;
2#[cfg(feature = "stargate")]
3use serde::Serialize;
4use std::collections::HashMap;
5use std::marker::PhantomData;
6
7use crate::addresses::{Addr, CanonicalAddr};
8use crate::binary::Binary;
9use crate::coin::Coin;
10use crate::deps::OwnedDeps;
11use crate::errors::{
12    RecoverPubkeyError, SigningError, StdError, StdResult, SystemError, VerificationError,
13};
14#[cfg(feature = "stargate")]
15use crate::ibc::{
16    IbcAcknowledgement, IbcChannel, IbcChannelCloseMsg, IbcChannelConnectMsg, IbcChannelOpenMsg,
17    IbcEndpoint, IbcOrder, IbcPacket, IbcPacketAckMsg, IbcPacketReceiveMsg, IbcPacketTimeoutMsg,
18    IbcTimeoutBlock,
19};
20use crate::math::Uint128;
21#[cfg(feature = "cosmwasm_1_1")]
22use crate::query::SupplyResponse;
23use crate::query::{
24    AllBalanceResponse, BalanceResponse, BankQuery, CustomQuery, QueryRequest, WasmQuery,
25};
26#[cfg(feature = "staking")]
27use crate::query::{
28    AllDelegationsResponse, AllValidatorsResponse, BondedDenomResponse, DelegationResponse,
29    FullDelegation, StakingQuery, Validator, ValidatorResponse,
30};
31use crate::results::{ContractResult, Empty, SystemResult};
32use crate::serde::{from_slice, to_binary};
33use crate::storage::MemoryStorage;
34use crate::timestamp::Timestamp;
35use crate::traits::{Api, Querier, QuerierResult};
36use crate::types::{BlockInfo, ContractInfo, Env, MessageInfo, TransactionInfo};
37use crate::Attribute;
38
39pub const MOCK_CONTRACT_ADDR: &str = "cosmos2contract";
40
41/// Creates all external requirements that can be injected for unit tests.
42///
43/// See also [`mock_dependencies_with_balance`] and [`mock_dependencies_with_balances`]
44/// if you want to start with some initial balances.
45pub fn mock_dependencies() -> OwnedDeps<MockStorage, MockApi, MockQuerier, Empty> {
46    OwnedDeps {
47        storage: MockStorage::default(),
48        api: MockApi::default(),
49        querier: MockQuerier::default(),
50        custom_query_type: PhantomData,
51    }
52}
53
54/// Creates all external requirements that can be injected for unit tests.
55///
56/// It sets the given balance for the contract itself, nothing else.
57pub fn mock_dependencies_with_balance(
58    contract_balance: &[Coin],
59) -> OwnedDeps<MockStorage, MockApi, MockQuerier, Empty> {
60    mock_dependencies_with_balances(&[(MOCK_CONTRACT_ADDR, contract_balance)])
61}
62
63/// Initializes the querier along with the mock_dependencies.
64/// Sets all balances provided (you must explicitly set contract balance if desired).
65pub fn mock_dependencies_with_balances(
66    balances: &[(&str, &[Coin])],
67) -> OwnedDeps<MockStorage, MockApi, MockQuerier> {
68    OwnedDeps {
69        storage: MockStorage::default(),
70        api: MockApi::default(),
71        querier: MockQuerier::new(balances),
72        custom_query_type: PhantomData,
73    }
74}
75
76// Use MemoryStorage implementation (which is valid in non-testcode)
77// We can later make simplifications here if needed
78pub type MockStorage = MemoryStorage;
79
80/// Length of canonical addresses created with this API. Contracts should not make any assumtions
81/// what this value is.
82/// The value here must be restorable with `SHUFFLES_ENCODE` + `SHUFFLES_DECODE` in-shuffles.
83const CANONICAL_LENGTH: usize = 54;
84
85const SHUFFLES_ENCODE: usize = 18;
86const SHUFFLES_DECODE: usize = 2;
87
88// MockPrecompiles zero pads all human addresses to make them fit the canonical_length
89// it trims off zeros for the reverse operation.
90// not really smart, but allows us to see a difference (and consistent length for canonical adddresses)
91#[derive(Copy, Clone)]
92pub struct MockApi {
93    /// Length of canonical addresses created with this API. Contracts should not make any assumtions
94    /// what this value is.
95    canonical_length: usize,
96}
97
98impl Default for MockApi {
99    fn default() -> Self {
100        MockApi {
101            canonical_length: CANONICAL_LENGTH,
102        }
103    }
104}
105
106impl Api for MockApi {
107    fn addr_validate(&self, input: &str) -> StdResult<Addr> {
108        let canonical = self.addr_canonicalize(input)?;
109        let normalized = self.addr_humanize(&canonical)?;
110        if input != normalized {
111            return Err(StdError::generic_err(
112                "Invalid input: address not normalized",
113            ));
114        }
115
116        Ok(Addr::unchecked(input))
117    }
118
119    fn addr_canonicalize(&self, input: &str) -> StdResult<CanonicalAddr> {
120        // Dummy input validation. This is more sophisticated for formats like bech32, where format and checksum are validated.
121        if input.len() < 3 {
122            return Err(StdError::generic_err(
123                "Invalid input: human address too short",
124            ));
125        }
126        if input.len() > self.canonical_length {
127            return Err(StdError::generic_err(
128                "Invalid input: human address too long",
129            ));
130        }
131
132        // mimicks formats like hex or bech32 where different casings are valid for one address
133        let normalized = input.to_lowercase();
134
135        let mut out = Vec::from(normalized);
136
137        // pad to canonical length with NULL bytes
138        out.resize(self.canonical_length, 0x00);
139        // content-dependent rotate followed by shuffle to destroy
140        // the most obvious structure (https://github.com/CosmWasm/cosmwasm/issues/552)
141        let rotate_by = digit_sum(&out) % self.canonical_length;
142        out.rotate_left(rotate_by);
143        for _ in 0..SHUFFLES_ENCODE {
144            out = riffle_shuffle(&out);
145        }
146        Ok(out.into())
147    }
148
149    fn addr_humanize(&self, canonical: &CanonicalAddr) -> StdResult<Addr> {
150        if canonical.len() != self.canonical_length {
151            return Err(StdError::generic_err(
152                "Invalid input: canonical address length not correct",
153            ));
154        }
155
156        let mut tmp: Vec<u8> = canonical.clone().into();
157        // Shuffle two more times which restored the original value (24 elements are back to original after 20 rounds)
158        for _ in 0..SHUFFLES_DECODE {
159            tmp = riffle_shuffle(&tmp);
160        }
161        // Rotate back
162        let rotate_by = digit_sum(&tmp) % self.canonical_length;
163        tmp.rotate_right(rotate_by);
164        // Remove NULL bytes (i.e. the padding)
165        let trimmed = tmp.into_iter().filter(|&x| x != 0x00).collect();
166        // decode UTF-8 bytes into string
167        let human = String::from_utf8(trimmed)?;
168        Ok(Addr::unchecked(human))
169    }
170
171    fn secp256k1_verify(
172        &self,
173        message_hash: &[u8],
174        signature: &[u8],
175        public_key: &[u8],
176    ) -> Result<bool, VerificationError> {
177        Ok(secret_cosmwasm_crypto::secp256k1_verify(
178            message_hash,
179            signature,
180            public_key,
181        )?)
182    }
183
184    fn secp256k1_recover_pubkey(
185        &self,
186        message_hash: &[u8],
187        signature: &[u8],
188        recovery_param: u8,
189    ) -> Result<Vec<u8>, RecoverPubkeyError> {
190        let pubkey =
191            secret_cosmwasm_crypto::secp256k1_recover_pubkey(message_hash, signature, recovery_param)?;
192        Ok(pubkey.to_vec())
193    }
194
195    fn ed25519_verify(
196        &self,
197        message: &[u8],
198        signature: &[u8],
199        public_key: &[u8],
200    ) -> Result<bool, VerificationError> {
201        Ok(secret_cosmwasm_crypto::ed25519_verify(
202            message, signature, public_key,
203        )?)
204    }
205
206    fn ed25519_batch_verify(
207        &self,
208        messages: &[&[u8]],
209        signatures: &[&[u8]],
210        public_keys: &[&[u8]],
211    ) -> Result<bool, VerificationError> {
212        Ok(secret_cosmwasm_crypto::ed25519_batch_verify(
213            messages,
214            signatures,
215            public_keys,
216        )?)
217    }
218
219    fn debug(&self, message: &str) {
220        println!("{}", message);
221    }
222
223    fn secp256k1_sign(&self, message: &[u8], private_key: &[u8]) -> Result<Vec<u8>, SigningError> {
224        Ok(secret_cosmwasm_crypto::secp256k1_sign(message, private_key)?)
225    }
226
227    fn ed25519_sign(&self, message: &[u8], private_key: &[u8]) -> Result<Vec<u8>, SigningError> {
228        Ok(secret_cosmwasm_crypto::ed25519_sign(message, private_key)?)
229    }
230
231    fn check_gas(&self) -> StdResult<u64> {
232        Ok(0)
233    }
234
235    fn gas_evaporate(&self, _evaporate: u32) -> StdResult<()> {
236        Ok(())
237    }
238}
239
240/// Returns a default enviroment with height, time, chain_id, and contract address
241/// You can submit as is to most contracts, or modify height/time if you want to
242/// test for expiration.
243///
244/// This is intended for use in test code only.
245pub fn mock_env() -> Env {
246    Env {
247        block: BlockInfo {
248            height: 12_345,
249            time: Timestamp::from_nanos(1_571_797_419_879_305_533),
250            chain_id: "cosmos-testnet-14002".to_string(),
251            #[cfg(feature = "random")]
252            random: Some(
253                Binary::from_base64("wLsKdf/sYqvSMI0G0aWRjob25mrIB0VQVjTjDXnDafk=").unwrap(),
254            ),
255        },
256        transaction: Some(TransactionInfo { index: 3, hash: "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855".to_string() }),
257        contract: ContractInfo {
258            address: Addr::unchecked(MOCK_CONTRACT_ADDR),
259            code_hash: "".to_string(),
260        },
261    }
262}
263
264/// Just set sender and funds for the message.
265/// This is intended for use in test code only.
266pub fn mock_info(sender: &str, funds: &[Coin]) -> MessageInfo {
267    MessageInfo {
268        sender: Addr::unchecked(sender),
269        funds: funds.to_vec(),
270    }
271}
272
273/// Creates an IbcChannel for testing. You set a few key parameters for handshaking,
274/// If you want to set more, use this as a default and mutate other fields
275#[cfg(feature = "stargate")]
276pub fn mock_ibc_channel(my_channel_id: &str, order: IbcOrder, version: &str) -> IbcChannel {
277    IbcChannel {
278        endpoint: IbcEndpoint {
279            port_id: "my_port".to_string(),
280            channel_id: my_channel_id.to_string(),
281        },
282        counterparty_endpoint: IbcEndpoint {
283            port_id: "their_port".to_string(),
284            channel_id: "channel-7".to_string(),
285        },
286        order,
287        version: version.to_string(),
288        connection_id: "connection-2".to_string(),
289    }
290}
291
292/// Creates a IbcChannelOpenMsg::OpenInit for testing ibc_channel_open.
293#[cfg(feature = "stargate")]
294pub fn mock_ibc_channel_open_init(
295    my_channel_id: &str,
296    order: IbcOrder,
297    version: &str,
298) -> IbcChannelOpenMsg {
299    IbcChannelOpenMsg::new_init(mock_ibc_channel(my_channel_id, order, version))
300}
301
302/// Creates a IbcChannelOpenMsg::OpenTry for testing ibc_channel_open.
303#[cfg(feature = "stargate")]
304pub fn mock_ibc_channel_open_try(
305    my_channel_id: &str,
306    order: IbcOrder,
307    version: &str,
308) -> IbcChannelOpenMsg {
309    IbcChannelOpenMsg::new_try(mock_ibc_channel(my_channel_id, order, version), version)
310}
311
312/// Creates a IbcChannelConnectMsg::ConnectAck for testing ibc_channel_connect.
313#[cfg(feature = "stargate")]
314pub fn mock_ibc_channel_connect_ack(
315    my_channel_id: &str,
316    order: IbcOrder,
317    version: &str,
318) -> IbcChannelConnectMsg {
319    IbcChannelConnectMsg::new_ack(mock_ibc_channel(my_channel_id, order, version), version)
320}
321
322/// Creates a IbcChannelConnectMsg::ConnectConfirm for testing ibc_channel_connect.
323#[cfg(feature = "stargate")]
324pub fn mock_ibc_channel_connect_confirm(
325    my_channel_id: &str,
326    order: IbcOrder,
327    version: &str,
328) -> IbcChannelConnectMsg {
329    IbcChannelConnectMsg::new_confirm(mock_ibc_channel(my_channel_id, order, version))
330}
331
332/// Creates a IbcChannelCloseMsg::CloseInit for testing ibc_channel_close.
333#[cfg(feature = "stargate")]
334pub fn mock_ibc_channel_close_init(
335    my_channel_id: &str,
336    order: IbcOrder,
337    version: &str,
338) -> IbcChannelCloseMsg {
339    IbcChannelCloseMsg::new_init(mock_ibc_channel(my_channel_id, order, version))
340}
341
342/// Creates a IbcChannelCloseMsg::CloseConfirm for testing ibc_channel_close.
343#[cfg(feature = "stargate")]
344pub fn mock_ibc_channel_close_confirm(
345    my_channel_id: &str,
346    order: IbcOrder,
347    version: &str,
348) -> IbcChannelCloseMsg {
349    IbcChannelCloseMsg::new_confirm(mock_ibc_channel(my_channel_id, order, version))
350}
351
352/// Creates a IbcPacketReceiveMsg for testing ibc_packet_receive. You set a few key parameters that are
353/// often parsed. If you want to set more, use this as a default and mutate other fields
354#[cfg(feature = "stargate")]
355pub fn mock_ibc_packet_recv(
356    my_channel_id: &str,
357    data: &impl Serialize,
358) -> StdResult<IbcPacketReceiveMsg> {
359    Ok(IbcPacketReceiveMsg::new(
360        IbcPacket {
361            data: to_binary(data)?,
362            src: IbcEndpoint {
363                port_id: "their-port".to_string(),
364                channel_id: "channel-1234".to_string(),
365            },
366            dest: IbcEndpoint {
367                port_id: "our-port".to_string(),
368                channel_id: my_channel_id.into(),
369            },
370            sequence: 27,
371            timeout: IbcTimeoutBlock {
372                revision: 1,
373                height: 12345678,
374            }
375            .into(),
376        },
377        #[cfg(feature = "ibc3")]
378        Addr::unchecked("relayer"),
379    ))
380}
381
382/// Creates a IbcPacket for testing ibc_packet_{ack,timeout}. You set a few key parameters that are
383/// often parsed. If you want to set more, use this as a default and mutate other fields.
384/// The difference from mock_ibc_packet_recv is if `my_channel_id` is src or dest.
385#[cfg(feature = "stargate")]
386fn mock_ibc_packet(my_channel_id: &str, data: &impl Serialize) -> StdResult<IbcPacket> {
387    Ok(IbcPacket {
388        data: to_binary(data)?,
389        src: IbcEndpoint {
390            port_id: "their-port".to_string(),
391            channel_id: my_channel_id.into(),
392        },
393        dest: IbcEndpoint {
394            port_id: "our-port".to_string(),
395            channel_id: "channel-1234".to_string(),
396        },
397        sequence: 29,
398        timeout: IbcTimeoutBlock {
399            revision: 1,
400            height: 432332552,
401        }
402        .into(),
403    })
404}
405
406/// Creates a IbcPacketAckMsg for testing ibc_packet_ack. You set a few key parameters that are
407/// often parsed. If you want to set more, use this as a default and mutate other fields.
408/// The difference from mock_ibc_packet_recv is if `my_channel_id` is src or dest.
409#[cfg(feature = "stargate")]
410pub fn mock_ibc_packet_ack(
411    my_channel_id: &str,
412    data: &impl Serialize,
413    ack: IbcAcknowledgement,
414) -> StdResult<IbcPacketAckMsg> {
415    let packet = mock_ibc_packet(my_channel_id, data)?;
416
417    Ok(IbcPacketAckMsg::new(
418        ack,
419        packet,
420        #[cfg(feature = "ibc3")]
421        Addr::unchecked("relayer"),
422    ))
423}
424
425/// Creates a IbcPacketTimeoutMsg for testing ibc_packet_timeout. You set a few key parameters that are
426/// often parsed. If you want to set more, use this as a default and mutate other fields.
427/// The difference from mock_ibc_packet_recv is if `my_channel_id` is src or dest./
428#[cfg(feature = "stargate")]
429pub fn mock_ibc_packet_timeout(
430    my_channel_id: &str,
431    data: &impl Serialize,
432) -> StdResult<IbcPacketTimeoutMsg> {
433    let packet = mock_ibc_packet(my_channel_id, data)?;
434    Ok(IbcPacketTimeoutMsg::new(
435        packet,
436        #[cfg(feature = "ibc3")]
437        Addr::unchecked("relayer"),
438    ))
439}
440
441/// The same type as cosmwasm-std's QuerierResult, but easier to reuse in
442/// cosmwasm-vm. It might diverge from QuerierResult at some point.
443pub type MockQuerierCustomHandlerResult = SystemResult<ContractResult<Binary>>;
444
445/// MockQuerier holds an immutable table of bank balances
446/// and configurable handlers for Wasm queries and custom queries.
447pub struct MockQuerier<C: DeserializeOwned = Empty> {
448    bank: BankQuerier,
449    #[cfg(feature = "staking")]
450    staking: StakingQuerier,
451    wasm: WasmQuerier,
452    /// A handler to handle custom queries. This is set to a dummy handler that
453    /// always errors by default. Update it via `with_custom_handler`.
454    ///
455    /// Use box to avoid the need of another generic type
456    custom_handler: Box<dyn for<'a> Fn(&'a C) -> MockQuerierCustomHandlerResult>,
457}
458
459impl<C: DeserializeOwned> MockQuerier<C> {
460    pub fn new(balances: &[(&str, &[Coin])]) -> Self {
461        MockQuerier {
462            bank: BankQuerier::new(balances),
463            #[cfg(feature = "staking")]
464            staking: StakingQuerier::default(),
465            wasm: WasmQuerier::default(),
466            // strange argument notation suggested as a workaround here: https://github.com/rust-lang/rust/issues/41078#issuecomment-294296365
467            custom_handler: Box::from(|_: &_| -> MockQuerierCustomHandlerResult {
468                SystemResult::Err(SystemError::UnsupportedRequest {
469                    kind: "custom".to_string(),
470                })
471            }),
472        }
473    }
474
475    // set a new balance for the given address and return the old balance
476    pub fn update_balance(
477        &mut self,
478        addr: impl Into<String>,
479        balance: Vec<Coin>,
480    ) -> Option<Vec<Coin>> {
481        self.bank.update_balance(addr, balance)
482    }
483
484    #[cfg(feature = "staking")]
485    pub fn update_staking(
486        &mut self,
487        denom: &str,
488        validators: &[crate::query::Validator],
489        delegations: &[crate::query::FullDelegation],
490    ) {
491        self.staking = StakingQuerier::new(denom, validators, delegations);
492    }
493
494    pub fn update_wasm<WH: 'static>(&mut self, handler: WH)
495    where
496        WH: Fn(&WasmQuery) -> QuerierResult,
497    {
498        self.wasm.update_handler(handler)
499    }
500
501    pub fn with_custom_handler<CH: 'static>(mut self, handler: CH) -> Self
502    where
503        CH: Fn(&C) -> MockQuerierCustomHandlerResult,
504    {
505        self.custom_handler = Box::from(handler);
506        self
507    }
508}
509
510impl Default for MockQuerier {
511    fn default() -> Self {
512        MockQuerier::new(&[])
513    }
514}
515
516impl<C: CustomQuery + DeserializeOwned> Querier for MockQuerier<C> {
517    fn raw_query(&self, bin_request: &[u8]) -> QuerierResult {
518        let request: QueryRequest<C> = match from_slice(bin_request) {
519            Ok(v) => v,
520            Err(e) => {
521                return SystemResult::Err(SystemError::InvalidRequest {
522                    error: format!("Parsing query request: {}", e),
523                    request: bin_request.into(),
524                })
525            }
526        };
527        self.handle_query(&request)
528    }
529}
530
531impl<C: CustomQuery + DeserializeOwned> MockQuerier<C> {
532    pub fn handle_query(&self, request: &QueryRequest<C>) -> QuerierResult {
533        match &request {
534            QueryRequest::Bank(bank_query) => self.bank.query(bank_query),
535            QueryRequest::Custom(custom_query) => (*self.custom_handler)(custom_query),
536            #[cfg(feature = "staking")]
537            QueryRequest::Staking(staking_query) => self.staking.query(staking_query),
538            QueryRequest::Wasm(msg) => self.wasm.query(msg),
539            #[cfg(feature = "stargate")]
540            QueryRequest::Stargate { .. } => SystemResult::Err(SystemError::UnsupportedRequest {
541                kind: "Stargate".to_string(),
542            }),
543            #[cfg(feature = "stargate")]
544            QueryRequest::Ibc(_) => SystemResult::Err(SystemError::UnsupportedRequest {
545                kind: "Ibc".to_string(),
546            }),
547        }
548    }
549}
550
551struct WasmQuerier {
552    /// A handler to handle Wasm queries. This is set to a dummy handler that
553    /// always errors by default. Update it via `with_custom_handler`.
554    ///
555    /// Use box to avoid the need of generic type.
556    handler: Box<dyn for<'a> Fn(&'a WasmQuery) -> QuerierResult>,
557}
558
559impl WasmQuerier {
560    fn new(handler: Box<dyn for<'a> Fn(&'a WasmQuery) -> QuerierResult>) -> Self {
561        Self { handler }
562    }
563
564    fn update_handler<WH: 'static>(&mut self, handler: WH)
565    where
566        WH: Fn(&WasmQuery) -> QuerierResult,
567    {
568        self.handler = Box::from(handler)
569    }
570
571    fn query(&self, request: &WasmQuery) -> QuerierResult {
572        (*self.handler)(request)
573    }
574}
575
576impl Default for WasmQuerier {
577    fn default() -> Self {
578        let handler = Box::from(|request: &WasmQuery| -> QuerierResult {
579            let addr = match request {
580                WasmQuery::Smart { contract_addr, .. } => contract_addr,
581                WasmQuery::ContractInfo { contract_addr, .. } => contract_addr,
582                WasmQuery::Raw { .. } => {
583                    return SystemResult::Err(SystemError::InvalidRequest {
584                        error: "raw queries are unsupported".to_string(),
585                        request: Default::default(),
586                    })
587                }
588            }
589            .clone();
590            SystemResult::Err(SystemError::NoSuchContract { addr })
591        });
592        Self::new(handler)
593    }
594}
595
596#[derive(Clone, Default)]
597pub struct BankQuerier {
598    #[allow(dead_code)]
599    /// HashMap<denom, amount>
600    supplies: HashMap<String, Uint128>,
601    /// HashMap<address, coins>
602    balances: HashMap<String, Vec<Coin>>,
603}
604
605impl BankQuerier {
606    pub fn new(balances: &[(&str, &[Coin])]) -> Self {
607        let balances: HashMap<_, _> = balances
608            .iter()
609            .map(|(s, c)| (s.to_string(), c.to_vec()))
610            .collect();
611
612        BankQuerier {
613            supplies: Self::calculate_supplies(&balances),
614            balances,
615        }
616    }
617
618    pub fn update_balance(
619        &mut self,
620        addr: impl Into<String>,
621        balance: Vec<Coin>,
622    ) -> Option<Vec<Coin>> {
623        let result = self.balances.insert(addr.into(), balance);
624        self.supplies = Self::calculate_supplies(&self.balances);
625
626        result
627    }
628
629    fn calculate_supplies(balances: &HashMap<String, Vec<Coin>>) -> HashMap<String, Uint128> {
630        let mut supplies = HashMap::new();
631
632        let all_coins = balances.iter().flat_map(|(_, coins)| coins);
633
634        for coin in all_coins {
635            *supplies
636                .entry(coin.denom.clone())
637                .or_insert_with(Uint128::zero) += coin.amount;
638        }
639
640        supplies
641    }
642
643    pub fn query(&self, request: &BankQuery) -> QuerierResult {
644        let contract_result: ContractResult<Binary> = match request {
645            #[cfg(feature = "cosmwasm_1_1")]
646            BankQuery::Supply { denom } => {
647                let amount = self
648                    .supplies
649                    .get(denom)
650                    .cloned()
651                    .unwrap_or_else(Uint128::zero);
652                let bank_res = SupplyResponse {
653                    amount: Coin {
654                        amount,
655                        denom: denom.to_string(),
656                    },
657                };
658                to_binary(&bank_res).into()
659            }
660            BankQuery::Balance { address, denom } => {
661                // proper error on not found, serialize result on found
662                let amount = self
663                    .balances
664                    .get(address)
665                    .and_then(|v| v.iter().find(|c| &c.denom == denom).map(|c| c.amount))
666                    .unwrap_or_default();
667                let bank_res = BalanceResponse {
668                    amount: Coin {
669                        amount,
670                        denom: denom.to_string(),
671                    },
672                };
673                to_binary(&bank_res).into()
674            }
675            BankQuery::AllBalances { address } => {
676                // proper error on not found, serialize result on found
677                let bank_res = AllBalanceResponse {
678                    amount: self.balances.get(address).cloned().unwrap_or_default(),
679                };
680                to_binary(&bank_res).into()
681            }
682        };
683        // system result is always ok in the mock implementation
684        SystemResult::Ok(contract_result)
685    }
686}
687
688#[cfg(feature = "staking")]
689#[derive(Clone, Default)]
690pub struct StakingQuerier {
691    denom: String,
692    validators: Vec<Validator>,
693    delegations: Vec<FullDelegation>,
694}
695
696#[cfg(feature = "staking")]
697impl StakingQuerier {
698    pub fn new(denom: &str, validators: &[Validator], delegations: &[FullDelegation]) -> Self {
699        StakingQuerier {
700            denom: denom.to_string(),
701            validators: validators.to_vec(),
702            delegations: delegations.to_vec(),
703        }
704    }
705
706    pub fn query(&self, request: &StakingQuery) -> QuerierResult {
707        let contract_result: ContractResult<Binary> = match request {
708            StakingQuery::BondedDenom {} => {
709                let res = BondedDenomResponse {
710                    denom: self.denom.clone(),
711                };
712                to_binary(&res).into()
713            }
714            StakingQuery::AllValidators {} => {
715                let res = AllValidatorsResponse {
716                    validators: self.validators.clone(),
717                };
718                to_binary(&res).into()
719            }
720            StakingQuery::Validator { address } => {
721                let validator: Option<Validator> = self
722                    .validators
723                    .iter()
724                    .find(|validator| validator.address == *address)
725                    .cloned();
726                let res = ValidatorResponse { validator };
727                to_binary(&res).into()
728            }
729            StakingQuery::AllDelegations { delegator } => {
730                let delegations: Vec<_> = self
731                    .delegations
732                    .iter()
733                    .filter(|d| d.delegator.as_str() == delegator)
734                    .cloned()
735                    .map(|d| d.into())
736                    .collect();
737                let res = AllDelegationsResponse { delegations };
738                to_binary(&res).into()
739            }
740            StakingQuery::Delegation {
741                delegator,
742                validator,
743            } => {
744                let delegation = self
745                    .delegations
746                    .iter()
747                    .find(|d| d.delegator.as_str() == delegator && d.validator == *validator);
748                let res = DelegationResponse {
749                    delegation: delegation.cloned(),
750                };
751                to_binary(&res).into()
752            }
753        };
754        // system result is always ok in the mock implementation
755        SystemResult::Ok(contract_result)
756    }
757}
758
759/// Performs a perfect shuffle (in shuffle)
760///
761/// https://en.wikipedia.org/wiki/Riffle_shuffle_permutation#Perfect_shuffles
762/// https://en.wikipedia.org/wiki/In_shuffle
763///
764/// The number of shuffles required to restore the original order are listed in
765/// https://oeis.org/A002326, e.g.:
766///
767/// ```ignore
768/// 2: 2
769/// 4: 4
770/// 6: 3
771/// 8: 6
772/// 10: 10
773/// 12: 12
774/// 14: 4
775/// 16: 8
776/// 18: 18
777/// 20: 6
778/// 22: 11
779/// 24: 20
780/// 26: 18
781/// 28: 28
782/// 30: 5
783/// 32: 10
784/// 34: 12
785/// 36: 36
786/// 38: 12
787/// 40: 20
788/// 42: 14
789/// 44: 12
790/// 46: 23
791/// 48: 21
792/// 50: 8
793/// 52: 52
794/// 54: 20
795/// 56: 18
796/// 58: 58
797/// 60: 60
798/// 62: 6
799/// 64: 12
800/// 66: 66
801/// 68: 22
802/// 70: 35
803/// 72: 9
804/// 74: 20
805/// ```
806pub fn riffle_shuffle<T: Clone>(input: &[T]) -> Vec<T> {
807    assert!(
808        input.len() % 2 == 0,
809        "Method only defined for even number of elements"
810    );
811    let mid = input.len() / 2;
812    let (left, right) = input.split_at(mid);
813    let mut out = Vec::<T>::with_capacity(input.len());
814    for i in 0..mid {
815        out.push(right[i].clone());
816        out.push(left[i].clone());
817    }
818    out
819}
820
821pub fn digit_sum(input: &[u8]) -> usize {
822    input.iter().fold(0, |sum, val| sum + (*val as usize))
823}
824
825/// Only for test code. This bypasses assertions in new, allowing us to create _*
826/// Attributes to simulate responses from the blockchain
827pub fn mock_wasmd_attr(key: impl Into<String>, value: impl Into<String>) -> Attribute {
828    Attribute {
829        key: key.into(),
830        value: value.into(),
831        encrypted: true,
832    }
833}
834
835#[cfg(test)]
836mod tests {
837    use super::*;
838    use crate::{coin, coins, from_binary, to_binary, ContractInfoResponse, Response};
839    #[cfg(feature = "staking")]
840    use crate::{Decimal, Delegation};
841    use hex_literal::hex;
842    use serde::Deserialize;
843
844    const SECP256K1_MSG_HASH_HEX: &str =
845        "5ae8317d34d1e595e3fa7247db80c0af4320cce1116de187f8f7e2e099c0d8d0";
846    const SECP256K1_SIG_HEX: &str = "207082eb2c3dfa0b454e0906051270ba4074ac93760ba9e7110cd9471475111151eb0dbbc9920e72146fb564f99d039802bf6ef2561446eb126ef364d21ee9c4";
847    const SECP256K1_PUBKEY_HEX: &str = "04051c1ee2190ecfb174bfe4f90763f2b4ff7517b70a2aec1876ebcfd644c4633fb03f3cfbd94b1f376e34592d9d41ccaf640bb751b00a1fadeb0c01157769eb73";
848
849    const ED25519_MSG_HEX: &str = "72";
850    const ED25519_SIG_HEX: &str = "92a009a9f0d4cab8720e820b5f642540a2b27b5416503f8fb3762223ebdb69da085ac1e43e15996e458f3613d0f11d8c387b2eaeb4302aeeb00d291612bb0c00";
851    const ED25519_PUBKEY_HEX: &str =
852        "3d4017c3e843895a92b70aa74d1b7ebc9c982ccf2ec4968cc0cd55f12af4660c";
853
854    #[test]
855    fn mock_info_works() {
856        let info = mock_info("my name", &coins(100, "atom"));
857        assert_eq!(
858            info,
859            MessageInfo {
860                sender: Addr::unchecked("my name"),
861                funds: vec![Coin {
862                    amount: 100u128.into(),
863                    denom: "atom".into(),
864                }]
865            }
866        );
867    }
868
869    #[test]
870    fn addr_validate_works() {
871        let api = MockApi::default();
872
873        // valid
874        let addr = api.addr_validate("foobar123").unwrap();
875        assert_eq!(addr, "foobar123");
876
877        // invalid: too short
878        api.addr_validate("").unwrap_err();
879        // invalid: not normalized
880        api.addr_validate("Foobar123").unwrap_err();
881        api.addr_validate("FOOBAR123").unwrap_err();
882    }
883
884    #[test]
885    fn addr_canonicalize_works() {
886        let api = MockApi::default();
887
888        api.addr_canonicalize("foobar123").unwrap();
889
890        // is case insensitive
891        let data1 = api.addr_canonicalize("foo123").unwrap();
892        let data2 = api.addr_canonicalize("FOO123").unwrap();
893        assert_eq!(data1, data2);
894    }
895
896    #[test]
897    fn canonicalize_and_humanize_restores_original() {
898        let api = MockApi::default();
899
900        // simple
901        let original = String::from("shorty");
902        let canonical = api.addr_canonicalize(&original).unwrap();
903        let recovered = api.addr_humanize(&canonical).unwrap();
904        assert_eq!(recovered, original);
905
906        // normalizes input
907        let original = String::from("CosmWasmChef");
908        let canonical = api.addr_canonicalize(&original).unwrap();
909        let recovered = api.addr_humanize(&canonical).unwrap();
910        assert_eq!(recovered, "cosmwasmchef");
911    }
912
913    #[test]
914    #[should_panic(expected = "address too short")]
915    fn addr_canonicalize_min_input_length() {
916        let api = MockApi::default();
917        let human = String::from("1");
918        let _ = api.addr_canonicalize(&human).unwrap();
919    }
920
921    #[test]
922    #[should_panic(expected = "address too long")]
923    fn addr_canonicalize_max_input_length() {
924        let api = MockApi::default();
925        let human =
926            String::from("some-extremely-long-address-not-supported-by-this-api-longer-than-54");
927        let _ = api.addr_canonicalize(&human).unwrap();
928    }
929
930    #[test]
931    #[should_panic(expected = "length not correct")]
932    fn addr_humanize_input_length() {
933        let api = MockApi::default();
934        let input = CanonicalAddr::from(vec![61; 11]);
935        api.addr_humanize(&input).unwrap();
936    }
937
938    // Basic "works" test. Exhaustive tests on VM's side (packages/vm/src/imports.rs)
939    #[test]
940    fn secp256k1_verify_works() {
941        let api = MockApi::default();
942
943        let hash = hex::decode(SECP256K1_MSG_HASH_HEX).unwrap();
944        let signature = hex::decode(SECP256K1_SIG_HEX).unwrap();
945        let public_key = hex::decode(SECP256K1_PUBKEY_HEX).unwrap();
946
947        assert!(api
948            .secp256k1_verify(&hash, &signature, &public_key)
949            .unwrap());
950    }
951
952    // Basic "fails" test. Exhaustive tests on VM's side (packages/vm/src/imports.rs)
953    #[test]
954    fn secp256k1_verify_fails() {
955        let api = MockApi::default();
956
957        let mut hash = hex::decode(SECP256K1_MSG_HASH_HEX).unwrap();
958        // alter hash
959        hash[0] ^= 0x01;
960        let signature = hex::decode(SECP256K1_SIG_HEX).unwrap();
961        let public_key = hex::decode(SECP256K1_PUBKEY_HEX).unwrap();
962
963        assert!(!api
964            .secp256k1_verify(&hash, &signature, &public_key)
965            .unwrap());
966    }
967
968    // Basic "errors" test. Exhaustive tests on VM's side (packages/vm/src/imports.rs)
969    #[test]
970    fn secp256k1_verify_errs() {
971        let api = MockApi::default();
972
973        let hash = hex::decode(SECP256K1_MSG_HASH_HEX).unwrap();
974        let signature = hex::decode(SECP256K1_SIG_HEX).unwrap();
975        let public_key = vec![];
976
977        let res = api.secp256k1_verify(&hash, &signature, &public_key);
978        assert_eq!(res.unwrap_err(), VerificationError::InvalidPubkeyFormat);
979    }
980
981    #[test]
982    fn secp256k1_recover_pubkey_works() {
983        let api = MockApi::default();
984
985        // https://gist.github.com/webmaster128/130b628d83621a33579751846699ed15
986        let hash = hex!("5ae8317d34d1e595e3fa7247db80c0af4320cce1116de187f8f7e2e099c0d8d0");
987        let signature = hex!("45c0b7f8c09a9e1f1cea0c25785594427b6bf8f9f878a8af0b1abbb48e16d0920d8becd0c220f67c51217eecfd7184ef0732481c843857e6bc7fc095c4f6b788");
988        let recovery_param = 1;
989        let expected = hex!("044a071e8a6e10aada2b8cf39fa3b5fb3400b04e99ea8ae64ceea1a977dbeaf5d5f8c8fbd10b71ab14cd561f7df8eb6da50f8a8d81ba564342244d26d1d4211595");
990
991        let pubkey = api
992            .secp256k1_recover_pubkey(&hash, &signature, recovery_param)
993            .unwrap();
994        assert_eq!(pubkey, expected);
995    }
996
997    #[test]
998    fn secp256k1_recover_pubkey_fails_for_wrong_recovery_param() {
999        let api = MockApi::default();
1000
1001        // https://gist.github.com/webmaster128/130b628d83621a33579751846699ed15
1002        let hash = hex!("5ae8317d34d1e595e3fa7247db80c0af4320cce1116de187f8f7e2e099c0d8d0");
1003        let signature = hex!("45c0b7f8c09a9e1f1cea0c25785594427b6bf8f9f878a8af0b1abbb48e16d0920d8becd0c220f67c51217eecfd7184ef0732481c843857e6bc7fc095c4f6b788");
1004        let _recovery_param = 1;
1005        let expected = hex!("044a071e8a6e10aada2b8cf39fa3b5fb3400b04e99ea8ae64ceea1a977dbeaf5d5f8c8fbd10b71ab14cd561f7df8eb6da50f8a8d81ba564342244d26d1d4211595");
1006
1007        // Wrong recovery param leads to different pubkey
1008        let pubkey = api.secp256k1_recover_pubkey(&hash, &signature, 0).unwrap();
1009        assert_eq!(pubkey.len(), 65);
1010        assert_ne!(pubkey, expected);
1011
1012        // Invalid recovery param leads to error
1013        let result = api.secp256k1_recover_pubkey(&hash, &signature, 42);
1014        match result.unwrap_err() {
1015            RecoverPubkeyError::InvalidRecoveryParam => {}
1016            err => panic!("Unexpected error: {:?}", err),
1017        }
1018    }
1019
1020    #[test]
1021    fn secp256k1_recover_pubkey_fails_for_wrong_hash() {
1022        let api = MockApi::default();
1023
1024        // https://gist.github.com/webmaster128/130b628d83621a33579751846699ed15
1025        let hash = hex!("5ae8317d34d1e595e3fa7247db80c0af4320cce1116de187f8f7e2e099c0d8d0");
1026        let signature = hex!("45c0b7f8c09a9e1f1cea0c25785594427b6bf8f9f878a8af0b1abbb48e16d0920d8becd0c220f67c51217eecfd7184ef0732481c843857e6bc7fc095c4f6b788");
1027        let recovery_param = 1;
1028        let expected = hex!("044a071e8a6e10aada2b8cf39fa3b5fb3400b04e99ea8ae64ceea1a977dbeaf5d5f8c8fbd10b71ab14cd561f7df8eb6da50f8a8d81ba564342244d26d1d4211595");
1029
1030        // Wrong hash
1031        let mut corrupted_hash = hash;
1032        corrupted_hash[0] ^= 0x01;
1033        let pubkey = api
1034            .secp256k1_recover_pubkey(&corrupted_hash, &signature, recovery_param)
1035            .unwrap();
1036        assert_eq!(pubkey.len(), 65);
1037        assert_ne!(pubkey, expected);
1038
1039        // Malformed hash
1040        let mut malformed_hash = hash.to_vec();
1041        malformed_hash.push(0x8a);
1042        let result = api.secp256k1_recover_pubkey(&malformed_hash, &signature, recovery_param);
1043        match result.unwrap_err() {
1044            RecoverPubkeyError::InvalidHashFormat => {}
1045            err => panic!("Unexpected error: {:?}", err),
1046        }
1047    }
1048
1049    // Basic "works" test. Exhaustive tests on VM's side (packages/vm/src/imports.rs)
1050    #[test]
1051    fn ed25519_verify_works() {
1052        let api = MockApi::default();
1053
1054        let msg = hex::decode(ED25519_MSG_HEX).unwrap();
1055        let signature = hex::decode(ED25519_SIG_HEX).unwrap();
1056        let public_key = hex::decode(ED25519_PUBKEY_HEX).unwrap();
1057
1058        assert!(api.ed25519_verify(&msg, &signature, &public_key).unwrap());
1059    }
1060
1061    // Basic "fails" test. Exhaustive tests on VM's side (packages/vm/src/imports.rs)
1062    #[test]
1063    fn ed25519_verify_fails() {
1064        let api = MockApi::default();
1065
1066        let mut msg = hex::decode(ED25519_MSG_HEX).unwrap();
1067        // alter msg
1068        msg[0] ^= 0x01;
1069        let signature = hex::decode(ED25519_SIG_HEX).unwrap();
1070        let public_key = hex::decode(ED25519_PUBKEY_HEX).unwrap();
1071
1072        assert!(!api.ed25519_verify(&msg, &signature, &public_key).unwrap());
1073    }
1074
1075    // Basic "errors" test. Exhaustive tests on VM's side (packages/vm/src/imports.rs)
1076    #[test]
1077    fn ed25519_verify_errs() {
1078        let api = MockApi::default();
1079
1080        let msg = hex::decode(ED25519_MSG_HEX).unwrap();
1081        let signature = hex::decode(ED25519_SIG_HEX).unwrap();
1082        let public_key = vec![];
1083
1084        let res = api.ed25519_verify(&msg, &signature, &public_key);
1085        assert_eq!(res.unwrap_err(), VerificationError::InvalidPubkeyFormat);
1086    }
1087
1088    // Basic "works" test.
1089    #[test]
1090    fn ed25519_batch_verify_works() {
1091        let api = MockApi::default();
1092
1093        let msg = hex::decode(ED25519_MSG_HEX).unwrap();
1094        let signature = hex::decode(ED25519_SIG_HEX).unwrap();
1095        let public_key = hex::decode(ED25519_PUBKEY_HEX).unwrap();
1096
1097        let msgs: Vec<&[u8]> = vec![&msg];
1098        let signatures: Vec<&[u8]> = vec![&signature];
1099        let public_keys: Vec<&[u8]> = vec![&public_key];
1100
1101        assert!(api
1102            .ed25519_batch_verify(&msgs, &signatures, &public_keys)
1103            .unwrap());
1104    }
1105
1106    // Basic "fails" test.
1107    #[test]
1108    fn ed25519_batch_verify_fails() {
1109        let api = MockApi::default();
1110
1111        let mut msg = hex::decode(ED25519_MSG_HEX).unwrap();
1112        // alter msg
1113        msg[0] ^= 0x01;
1114        let signature = hex::decode(ED25519_SIG_HEX).unwrap();
1115        let public_key = hex::decode(ED25519_PUBKEY_HEX).unwrap();
1116
1117        let msgs: Vec<&[u8]> = vec![&msg];
1118        let signatures: Vec<&[u8]> = vec![&signature];
1119        let public_keys: Vec<&[u8]> = vec![&public_key];
1120
1121        assert!(!api
1122            .ed25519_batch_verify(&msgs, &signatures, &public_keys)
1123            .unwrap());
1124    }
1125
1126    // Basic "errors" test.
1127    #[test]
1128    fn ed25519_batch_verify_errs() {
1129        let api = MockApi::default();
1130
1131        let msg = hex::decode(ED25519_MSG_HEX).unwrap();
1132        let signature = hex::decode(ED25519_SIG_HEX).unwrap();
1133        let public_key: Vec<u8> = vec![0u8; 0];
1134
1135        let msgs: Vec<&[u8]> = vec![msg.as_slice()];
1136        let signatures: Vec<&[u8]> = vec![signature.as_slice()];
1137        let public_keys: Vec<&[u8]> = vec![&public_key];
1138
1139        let res = api.ed25519_batch_verify(&msgs, &signatures, &public_keys);
1140        assert_eq!(res.unwrap_err(), VerificationError::InvalidPubkeyFormat);
1141    }
1142
1143    #[cfg(feature = "cosmwasm_1_1")]
1144    #[test]
1145    fn bank_querier_supply() {
1146        let addr1 = String::from("foo");
1147        let balance1 = vec![coin(123, "ELF"), coin(777, "FLY")];
1148
1149        let addr2 = String::from("bar");
1150        let balance2 = coins(321, "ELF");
1151
1152        let bank = BankQuerier::new(&[(&addr1, &balance1), (&addr2, &balance2)]);
1153
1154        let elf = bank
1155            .query(&BankQuery::Supply {
1156                denom: "ELF".to_string(),
1157            })
1158            .unwrap()
1159            .unwrap();
1160        let res: SupplyResponse = from_binary(&elf).unwrap();
1161        assert_eq!(res.amount, coin(444, "ELF"));
1162
1163        let fly = bank
1164            .query(&BankQuery::Supply {
1165                denom: "FLY".to_string(),
1166            })
1167            .unwrap()
1168            .unwrap();
1169        let res: SupplyResponse = from_binary(&fly).unwrap();
1170        assert_eq!(res.amount, coin(777, "FLY"));
1171
1172        // if a denom does not exist, should return zero amount, instead of throwing an error
1173        let atom = bank
1174            .query(&BankQuery::Supply {
1175                denom: "ATOM".to_string(),
1176            })
1177            .unwrap()
1178            .unwrap();
1179        let res: SupplyResponse = from_binary(&atom).unwrap();
1180        assert_eq!(res.amount, coin(0, "ATOM"));
1181    }
1182
1183    #[test]
1184    fn bank_querier_all_balances() {
1185        let addr = String::from("foobar");
1186        let balance = vec![coin(123, "ELF"), coin(777, "FLY")];
1187        let bank = BankQuerier::new(&[(&addr, &balance)]);
1188
1189        let all = bank
1190            .query(&BankQuery::AllBalances { address: addr })
1191            .unwrap()
1192            .unwrap();
1193        let res: AllBalanceResponse = from_binary(&all).unwrap();
1194        assert_eq!(&res.amount, &balance);
1195    }
1196
1197    #[test]
1198    fn bank_querier_one_balance() {
1199        let addr = String::from("foobar");
1200        let balance = vec![coin(123, "ELF"), coin(777, "FLY")];
1201        let bank = BankQuerier::new(&[(&addr, &balance)]);
1202
1203        // one match
1204        let fly = bank
1205            .query(&BankQuery::Balance {
1206                address: addr.clone(),
1207                denom: "FLY".to_string(),
1208            })
1209            .unwrap()
1210            .unwrap();
1211        let res: BalanceResponse = from_binary(&fly).unwrap();
1212        assert_eq!(res.amount, coin(777, "FLY"));
1213
1214        // missing denom
1215        let miss = bank
1216            .query(&BankQuery::Balance {
1217                address: addr,
1218                denom: "MISS".to_string(),
1219            })
1220            .unwrap()
1221            .unwrap();
1222        let res: BalanceResponse = from_binary(&miss).unwrap();
1223        assert_eq!(res.amount, coin(0, "MISS"));
1224    }
1225
1226    #[test]
1227    fn bank_querier_missing_account() {
1228        let addr = String::from("foobar");
1229        let balance = vec![coin(123, "ELF"), coin(777, "FLY")];
1230        let bank = BankQuerier::new(&[(&addr, &balance)]);
1231
1232        // all balances on empty account is empty vec
1233        let all = bank
1234            .query(&BankQuery::AllBalances {
1235                address: String::from("elsewhere"),
1236            })
1237            .unwrap()
1238            .unwrap();
1239        let res: AllBalanceResponse = from_binary(&all).unwrap();
1240        assert_eq!(res.amount, vec![]);
1241
1242        // any denom on balances on empty account is empty coin
1243        let miss = bank
1244            .query(&BankQuery::Balance {
1245                address: String::from("elsewhere"),
1246                denom: "ELF".to_string(),
1247            })
1248            .unwrap()
1249            .unwrap();
1250        let res: BalanceResponse = from_binary(&miss).unwrap();
1251        assert_eq!(res.amount, coin(0, "ELF"));
1252    }
1253
1254    #[cfg(feature = "staking")]
1255    #[test]
1256    fn staking_querier_all_validators() {
1257        let val1 = Validator {
1258            address: String::from("validator-one"),
1259            commission: Decimal::percent(1),
1260            max_commission: Decimal::percent(3),
1261            max_change_rate: Decimal::percent(1),
1262        };
1263        let val2 = Validator {
1264            address: String::from("validator-two"),
1265            commission: Decimal::permille(15),
1266            max_commission: Decimal::permille(40),
1267            max_change_rate: Decimal::permille(5),
1268        };
1269
1270        let staking = StakingQuerier::new("ustake", &[val1.clone(), val2.clone()], &[]);
1271
1272        // one match
1273        let raw = staking
1274            .query(&StakingQuery::AllValidators {})
1275            .unwrap()
1276            .unwrap();
1277        let vals: AllValidatorsResponse = from_binary(&raw).unwrap();
1278        assert_eq!(vals.validators, vec![val1, val2]);
1279    }
1280
1281    #[cfg(feature = "staking")]
1282    #[test]
1283    fn staking_querier_validator() {
1284        let address1 = String::from("validator-one");
1285        let address2 = String::from("validator-two");
1286        let address_non_existent = String::from("wannabe-validator");
1287
1288        let val1 = Validator {
1289            address: address1.clone(),
1290            commission: Decimal::percent(1),
1291            max_commission: Decimal::percent(3),
1292            max_change_rate: Decimal::percent(1),
1293        };
1294        let val2 = Validator {
1295            address: address2.clone(),
1296            commission: Decimal::permille(15),
1297            max_commission: Decimal::permille(40),
1298            max_change_rate: Decimal::permille(5),
1299        };
1300
1301        let staking = StakingQuerier::new("ustake", &[val1.clone(), val2.clone()], &[]);
1302
1303        // query 1
1304        let raw = staking
1305            .query(&StakingQuery::Validator { address: address1 })
1306            .unwrap()
1307            .unwrap();
1308        let res: ValidatorResponse = from_binary(&raw).unwrap();
1309        assert_eq!(res.validator, Some(val1));
1310
1311        // query 2
1312        let raw = staking
1313            .query(&StakingQuery::Validator { address: address2 })
1314            .unwrap()
1315            .unwrap();
1316        let res: ValidatorResponse = from_binary(&raw).unwrap();
1317        assert_eq!(res.validator, Some(val2));
1318
1319        // query non-existent
1320        let raw = staking
1321            .query(&StakingQuery::Validator {
1322                address: address_non_existent,
1323            })
1324            .unwrap()
1325            .unwrap();
1326        let res: ValidatorResponse = from_binary(&raw).unwrap();
1327        assert_eq!(res.validator, None);
1328    }
1329
1330    #[cfg(feature = "staking")]
1331    // gets delegators from query or panic
1332    fn get_all_delegators(
1333        staking: &StakingQuerier,
1334        delegator: impl Into<String>,
1335    ) -> Vec<Delegation> {
1336        let raw = staking
1337            .query(&StakingQuery::AllDelegations {
1338                delegator: delegator.into(),
1339            })
1340            .unwrap()
1341            .unwrap();
1342        let dels: AllDelegationsResponse = from_binary(&raw).unwrap();
1343        dels.delegations
1344    }
1345
1346    #[cfg(feature = "staking")]
1347    // gets full delegators from query or panic
1348    fn get_delegator(
1349        staking: &StakingQuerier,
1350        delegator: impl Into<String>,
1351        validator: impl Into<String>,
1352    ) -> Option<FullDelegation> {
1353        let raw = staking
1354            .query(&StakingQuery::Delegation {
1355                delegator: delegator.into(),
1356                validator: validator.into(),
1357            })
1358            .unwrap()
1359            .unwrap();
1360        let dels: DelegationResponse = from_binary(&raw).unwrap();
1361        dels.delegation
1362    }
1363
1364    #[cfg(feature = "staking")]
1365    #[test]
1366    fn staking_querier_delegations() {
1367        let val1 = String::from("validator-one");
1368        let val2 = String::from("validator-two");
1369
1370        let user_a = Addr::unchecked("investor");
1371        let user_b = Addr::unchecked("speculator");
1372        let user_c = Addr::unchecked("hodler");
1373
1374        // we need multiple validators per delegator, so the queries provide different results
1375        let del1a = FullDelegation {
1376            delegator: user_a.clone(),
1377            validator: val1.clone(),
1378            amount: coin(100, "ustake"),
1379            can_redelegate: coin(100, "ustake"),
1380            accumulated_rewards: coins(5, "ustake"),
1381        };
1382        let del2a = FullDelegation {
1383            delegator: user_a.clone(),
1384            validator: val2.clone(),
1385            amount: coin(500, "ustake"),
1386            can_redelegate: coin(500, "ustake"),
1387            accumulated_rewards: coins(20, "ustake"),
1388        };
1389
1390        // note we cannot have multiple delegations on one validator, they are collapsed into one
1391        let del1b = FullDelegation {
1392            delegator: user_b.clone(),
1393            validator: val1.clone(),
1394            amount: coin(500, "ustake"),
1395            can_redelegate: coin(0, "ustake"),
1396            accumulated_rewards: coins(0, "ustake"),
1397        };
1398
1399        // and another one on val2
1400        let del2c = FullDelegation {
1401            delegator: user_c.clone(),
1402            validator: val2.clone(),
1403            amount: coin(8888, "ustake"),
1404            can_redelegate: coin(4567, "ustake"),
1405            accumulated_rewards: coins(900, "ustake"),
1406        };
1407
1408        let staking = StakingQuerier::new(
1409            "ustake",
1410            &[],
1411            &[del1a.clone(), del1b.clone(), del2a.clone(), del2c.clone()],
1412        );
1413
1414        // get all for user a
1415        let dels = get_all_delegators(&staking, user_a.clone());
1416        assert_eq!(dels, vec![del1a.clone().into(), del2a.clone().into()]);
1417
1418        // get all for user b
1419        let dels = get_all_delegators(&staking, user_b.clone());
1420        assert_eq!(dels, vec![del1b.clone().into()]);
1421
1422        // get all for user c
1423        let dels = get_all_delegators(&staking, user_c.clone());
1424        assert_eq!(dels, vec![del2c.clone().into()]);
1425
1426        // for user with no delegations...
1427        let dels = get_all_delegators(&staking, String::from("no one"));
1428        assert_eq!(dels, vec![]);
1429
1430        // filter a by validator (1 and 1)
1431        let dels = get_delegator(&staking, user_a.clone(), val1.clone());
1432        assert_eq!(dels, Some(del1a));
1433        let dels = get_delegator(&staking, user_a, val2.clone());
1434        assert_eq!(dels, Some(del2a));
1435
1436        // filter b by validator (2 and 0)
1437        let dels = get_delegator(&staking, user_b.clone(), val1.clone());
1438        assert_eq!(dels, Some(del1b));
1439        let dels = get_delegator(&staking, user_b, val2.clone());
1440        assert_eq!(dels, None);
1441
1442        // filter c by validator (0 and 1)
1443        let dels = get_delegator(&staking, user_c.clone(), val1);
1444        assert_eq!(dels, None);
1445        let dels = get_delegator(&staking, user_c, val2);
1446        assert_eq!(dels, Some(del2c));
1447    }
1448
1449    #[test]
1450    fn wasm_querier_works() {
1451        let mut querier = WasmQuerier::default();
1452
1453        let any_addr = "foo".to_string();
1454        let any_code_hash = "goo".to_string();
1455
1456        // Query WasmQuery::Smart
1457        let system_err = querier
1458            .query(&WasmQuery::Smart {
1459                contract_addr: any_addr.clone(),
1460                code_hash: any_code_hash.clone(),
1461                msg: b"{}".into(),
1462            })
1463            .unwrap_err();
1464        match system_err {
1465            SystemError::NoSuchContract { addr } => assert_eq!(addr, any_addr),
1466            err => panic!("Unexpected error: {:?}", err),
1467        }
1468
1469        // Query WasmQuery::ContractInfo
1470        let system_err = querier
1471            .query(&WasmQuery::ContractInfo {
1472                contract_addr: any_addr.clone(),
1473            })
1474            .unwrap_err();
1475        match system_err {
1476            SystemError::NoSuchContract { addr } => assert_eq!(addr, any_addr),
1477            err => panic!("Unexpected error: {:?}", err),
1478        }
1479
1480        querier.update_handler(|request| {
1481            let constract1 = Addr::unchecked("contract1");
1482            let mut storage1 = HashMap::<Binary, Binary>::default();
1483            storage1.insert(b"the key".into(), b"the value".into());
1484
1485            match request {
1486                WasmQuery::Smart {
1487                    contract_addr, msg, ..
1488                } => {
1489                    if *contract_addr == constract1 {
1490                        #[derive(Deserialize)]
1491                        struct MyMsg {}
1492                        let _msg: MyMsg = match from_binary(msg) {
1493                            Ok(msg) => msg,
1494                            Err(err) => {
1495                                return SystemResult::Ok(ContractResult::Err(err.to_string()))
1496                            }
1497                        };
1498                        let response: Response = Response::new().set_data(b"good");
1499                        SystemResult::Ok(ContractResult::Ok(to_binary(&response).unwrap()))
1500                    } else {
1501                        SystemResult::Err(SystemError::NoSuchContract {
1502                            addr: contract_addr.clone(),
1503                        })
1504                    }
1505                }
1506                WasmQuery::ContractInfo { contract_addr } => {
1507                    if *contract_addr == constract1 {
1508                        let response = ContractInfoResponse {
1509                            code_id: 4,
1510                            creator: "lalala".into(),
1511                            pinned: false,
1512                            ibc_port: None,
1513                        };
1514                        SystemResult::Ok(ContractResult::Ok(to_binary(&response).unwrap()))
1515                    } else {
1516                        SystemResult::Err(SystemError::NoSuchContract {
1517                            addr: contract_addr.clone(),
1518                        })
1519                    }
1520                }
1521                _ => {
1522                    panic!("Raw queries are unsupported")
1523                }
1524            }
1525        });
1526
1527        // WasmQuery::Smart
1528        let result = querier.query(&WasmQuery::Smart {
1529            contract_addr: "contract1".into(),
1530            code_hash: "code_hash1".into(),
1531            msg: b"{}".into(),
1532        });
1533        match result {
1534            SystemResult::Ok(ContractResult::Ok(value)) => assert_eq!(
1535                value,
1536                br#"{"messages":[],"attributes":[],"events":[],"data":"Z29vZA=="}"# as &[u8]
1537            ),
1538            res => panic!("Unexpected result: {:?}", res),
1539        }
1540        let result = querier.query(&WasmQuery::Smart {
1541            contract_addr: "contract1".into(),
1542            code_hash: "code_hash1".into(),
1543            msg: b"a broken request".into(),
1544        });
1545        match result {
1546            SystemResult::Ok(ContractResult::Err(err)) => {
1547                assert_eq!(err, "Error parsing into type secret_cosmwasm_std::testing::mock::tests::wasm_querier_works::{{closure}}::MyMsg: Invalid type")
1548            }
1549            res => panic!("Unexpected result: {:?}", res),
1550        }
1551
1552        // WasmQuery::ContractInfo
1553        let result = querier.query(&WasmQuery::ContractInfo {
1554            contract_addr: "contract1".into(),
1555        });
1556        match result {
1557            SystemResult::Ok(ContractResult::Ok(value)) => assert_eq!(
1558                value,
1559                br#"{"code_id":4,"creator":"lalala","pinned":false,"ibc_port":null}"# as &[u8]
1560            ),
1561            res => panic!("Unexpected result: {:?}", res),
1562        }
1563    }
1564
1565    #[test]
1566    fn riffle_shuffle_works() {
1567        // Example from https://en.wikipedia.org/wiki/In_shuffle
1568        let start = [0xA, 0x2, 0x3, 0x4, 0x5, 0x6];
1569        let round1 = riffle_shuffle(&start);
1570        assert_eq!(round1, [0x4, 0xA, 0x5, 0x2, 0x6, 0x3]);
1571        let round2 = riffle_shuffle(&round1);
1572        assert_eq!(round2, [0x2, 0x4, 0x6, 0xA, 0x3, 0x5]);
1573        let round3 = riffle_shuffle(&round2);
1574        assert_eq!(round3, start);
1575
1576        // For 14 elements, the original order is restored after 4 executions
1577        // See https://en.wikipedia.org/wiki/In_shuffle#Mathematics and https://oeis.org/A002326
1578        let original = [12, 33, 76, 576, 0, 44, 1, 14, 78, 99, 871212, -7, 2, -1];
1579        let mut result = Vec::from(original);
1580        for _ in 0..4 {
1581            result = riffle_shuffle(&result);
1582        }
1583        assert_eq!(result, original);
1584
1585        // For 24 elements, the original order is restored after 20 executions
1586        let original = [
1587            7, 4, 2, 4656, 23, 45, 23, 1, 12, 76, 576, 0, 12, 1, 14, 78, 99, 12, 1212, 444, 31,
1588            111, 424, 34,
1589        ];
1590        let mut result = Vec::from(original);
1591        for _ in 0..20 {
1592            result = riffle_shuffle(&result);
1593        }
1594        assert_eq!(result, original);
1595    }
1596
1597    #[test]
1598    fn digit_sum_works() {
1599        assert_eq!(digit_sum(&[]), 0);
1600        assert_eq!(digit_sum(&[0]), 0);
1601        assert_eq!(digit_sum(&[0, 0]), 0);
1602        assert_eq!(digit_sum(&[0, 0, 0]), 0);
1603
1604        assert_eq!(digit_sum(&[1, 0, 0]), 1);
1605        assert_eq!(digit_sum(&[0, 1, 0]), 1);
1606        assert_eq!(digit_sum(&[0, 0, 1]), 1);
1607
1608        assert_eq!(digit_sum(&[1, 2, 3]), 6);
1609
1610        assert_eq!(digit_sum(&[255, 1]), 256);
1611    }
1612}