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