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
41pub 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
54pub 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
63pub 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
76pub type MockStorage = MemoryStorage;
79
80const CANONICAL_LENGTH: usize = 54;
84
85const SHUFFLES_ENCODE: usize = 18;
86const SHUFFLES_DECODE: usize = 2;
87
88#[derive(Copy, Clone)]
92pub struct MockApi {
93 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 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 let normalized = input.to_lowercase();
134
135 let mut out = Vec::from(normalized);
136
137 out.resize(self.canonical_length, 0x00);
139 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 for _ in 0..SHUFFLES_DECODE {
159 tmp = riffle_shuffle(&tmp);
160 }
161 let rotate_by = digit_sum(&tmp) % self.canonical_length;
163 tmp.rotate_right(rotate_by);
164 let trimmed = tmp.into_iter().filter(|&x| x != 0x00).collect();
166 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
240pub 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
264pub fn mock_info(sender: &str, funds: &[Coin]) -> MessageInfo {
267 MessageInfo {
268 sender: Addr::unchecked(sender),
269 funds: funds.to_vec(),
270 }
271}
272
273#[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#[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#[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#[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#[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#[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#[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#[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#[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#[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#[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
441pub type MockQuerierCustomHandlerResult = SystemResult<ContractResult<Binary>>;
444
445pub struct MockQuerier<C: DeserializeOwned = Empty> {
448 bank: BankQuerier,
449 #[cfg(feature = "staking")]
450 staking: StakingQuerier,
451 wasm: WasmQuerier,
452 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 custom_handler: Box::from(|_: &_| -> MockQuerierCustomHandlerResult {
468 SystemResult::Err(SystemError::UnsupportedRequest {
469 kind: "custom".to_string(),
470 })
471 }),
472 }
473 }
474
475 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 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 supplies: HashMap<String, Uint128>,
601 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 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 let bank_res = AllBalanceResponse {
678 amount: self.balances.get(address).cloned().unwrap_or_default(),
679 };
680 to_binary(&bank_res).into()
681 }
682 };
683 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 SystemResult::Ok(contract_result)
756 }
757}
758
759pub 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
825pub 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 let addr = api.addr_validate("foobar123").unwrap();
875 assert_eq!(addr, "foobar123");
876
877 api.addr_validate("").unwrap_err();
879 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 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 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 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 #[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 #[test]
954 fn secp256k1_verify_fails() {
955 let api = MockApi::default();
956
957 let mut hash = hex::decode(SECP256K1_MSG_HASH_HEX).unwrap();
958 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 #[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 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 let hash = hex!("5ae8317d34d1e595e3fa7247db80c0af4320cce1116de187f8f7e2e099c0d8d0");
1003 let signature = hex!("45c0b7f8c09a9e1f1cea0c25785594427b6bf8f9f878a8af0b1abbb48e16d0920d8becd0c220f67c51217eecfd7184ef0732481c843857e6bc7fc095c4f6b788");
1004 let _recovery_param = 1;
1005 let expected = hex!("044a071e8a6e10aada2b8cf39fa3b5fb3400b04e99ea8ae64ceea1a977dbeaf5d5f8c8fbd10b71ab14cd561f7df8eb6da50f8a8d81ba564342244d26d1d4211595");
1006
1007 let pubkey = api.secp256k1_recover_pubkey(&hash, &signature, 0).unwrap();
1009 assert_eq!(pubkey.len(), 65);
1010 assert_ne!(pubkey, expected);
1011
1012 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 let hash = hex!("5ae8317d34d1e595e3fa7247db80c0af4320cce1116de187f8f7e2e099c0d8d0");
1026 let signature = hex!("45c0b7f8c09a9e1f1cea0c25785594427b6bf8f9f878a8af0b1abbb48e16d0920d8becd0c220f67c51217eecfd7184ef0732481c843857e6bc7fc095c4f6b788");
1027 let recovery_param = 1;
1028 let expected = hex!("044a071e8a6e10aada2b8cf39fa3b5fb3400b04e99ea8ae64ceea1a977dbeaf5d5f8c8fbd10b71ab14cd561f7df8eb6da50f8a8d81ba564342244d26d1d4211595");
1029
1030 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 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 #[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 #[test]
1063 fn ed25519_verify_fails() {
1064 let api = MockApi::default();
1065
1066 let mut msg = hex::decode(ED25519_MSG_HEX).unwrap();
1067 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 #[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 #[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 #[test]
1108 fn ed25519_batch_verify_fails() {
1109 let api = MockApi::default();
1110
1111 let mut msg = hex::decode(ED25519_MSG_HEX).unwrap();
1112 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 #[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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 let dels = get_all_delegators(&staking, user_a.clone());
1416 assert_eq!(dels, vec![del1a.clone().into(), del2a.clone().into()]);
1417
1418 let dels = get_all_delegators(&staking, user_b.clone());
1420 assert_eq!(dels, vec![del1b.clone().into()]);
1421
1422 let dels = get_all_delegators(&staking, user_c.clone());
1424 assert_eq!(dels, vec![del2c.clone().into()]);
1425
1426 let dels = get_all_delegators(&staking, String::from("no one"));
1428 assert_eq!(dels, vec![]);
1429
1430 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 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 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 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 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 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 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 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 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 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}