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