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