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(any(feature = "stargate", feature = "ibc2"))]
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 = "ibc2")]
27use crate::ibc2::{
28 Ibc2PacketAckMsg, Ibc2PacketReceiveMsg, Ibc2PacketSendMsg, Ibc2PacketTimeoutMsg, Ibc2Payload,
29};
30#[cfg(feature = "cosmwasm_1_1")]
31use crate::query::SupplyResponse;
32#[cfg(feature = "staking")]
33use crate::query::{
34 AllDelegationsResponse, AllValidatorsResponse, BondedDenomResponse, DelegationResponse,
35 FullDelegation, StakingQuery, Validator, ValidatorResponse,
36};
37use crate::query::{BalanceResponse, BankQuery, CustomQuery, QueryRequest, WasmQuery};
38#[cfg(feature = "cosmwasm_1_3")]
39use crate::query::{DelegatorWithdrawAddressResponse, DistributionQuery};
40use crate::results::{ContractResult, Empty, SystemResult};
41use crate::traits::{Api, Querier, QuerierResult};
42use crate::types::{BlockInfo, ContractInfo, Env, TransactionInfo};
43use crate::{from_json, to_json_binary, Binary, Uint256};
44#[cfg(feature = "cosmwasm_1_3")]
45use crate::{
46 query::{AllDenomMetadataResponse, DecCoin, DenomMetadataResponse},
47 PageRequest,
48};
49use crate::{Attribute, DenomMetadata};
50#[cfg(feature = "stargate")]
51use crate::{ChannelResponse, IbcQuery, PortIdResponse};
52#[cfg(feature = "cosmwasm_1_4")]
53use crate::{Decimal256, DelegationRewardsResponse, DelegatorValidatorsResponse};
54use crate::{RecoverPubkeyError, StdError, StdResult, SystemError, VerificationError};
55
56use super::MockStorage;
57
58pub const MOCK_CONTRACT_ADDR: &str =
59 "cosmwasm1jpev2csrppg792t22rn8z8uew8h3sjcpglcd0qv9g8gj8ky922tscp8avs";
60
61pub fn mock_dependencies() -> OwnedDeps<MockStorage, MockApi, MockQuerier, Empty> {
66 OwnedDeps {
67 storage: MockStorage::default(),
68 api: MockApi::default(),
69 querier: MockQuerier::default(),
70 custom_query_type: PhantomData,
71 }
72}
73
74pub fn mock_dependencies_with_balance(
78 contract_balance: &[Coin],
79) -> OwnedDeps<MockStorage, MockApi, MockQuerier, Empty> {
80 mock_dependencies_with_balances(&[(MOCK_CONTRACT_ADDR, contract_balance)])
81}
82
83pub fn mock_dependencies_with_balances(
86 balances: &[(&str, &[Coin])],
87) -> OwnedDeps<MockStorage, MockApi, MockQuerier> {
88 OwnedDeps {
89 storage: MockStorage::default(),
90 api: MockApi::default(),
91 querier: MockQuerier::new(balances),
92 custom_query_type: PhantomData,
93 }
94}
95
96const BECH32_PREFIX: &str = "cosmwasm";
98
99#[derive(Copy, Clone)]
103pub struct MockApi {
104 bech32_prefix: &'static str,
106}
107
108impl Default for MockApi {
109 fn default() -> Self {
110 MockApi {
111 bech32_prefix: BECH32_PREFIX,
112 }
113 }
114}
115
116impl Api for MockApi {
117 fn addr_validate(&self, input: &str) -> StdResult<Addr> {
118 let canonical = self.addr_canonicalize(input)?;
119 let normalized = self.addr_humanize(&canonical)?;
120 if input != normalized.as_str() {
121 return Err(StdError::msg("Invalid input: address not normalized"));
122 }
123 Ok(Addr::unchecked(input))
124 }
125
126 fn addr_canonicalize(&self, input: &str) -> StdResult<CanonicalAddr> {
127 let hrp_str = CheckedHrpstring::new::<Bech32>(input)?;
128
129 if !hrp_str
130 .hrp()
131 .as_bytes()
132 .eq_ignore_ascii_case(self.bech32_prefix.as_bytes())
133 {
134 return Err(StdError::msg("Wrong bech32 prefix"));
135 }
136
137 let bytes: Vec<u8> = hrp_str.byte_iter().collect();
138 validate_length(&bytes)?;
139 Ok(bytes.into())
140 }
141
142 fn addr_humanize(&self, canonical: &CanonicalAddr) -> StdResult<Addr> {
143 validate_length(canonical.as_ref())?;
144
145 let prefix = Hrp::parse(self.bech32_prefix)?;
146 Ok(encode::<Bech32>(prefix, canonical.as_slice()).map(Addr::unchecked)?)
147 }
148
149 fn bls12_381_aggregate_g1(&self, g1s: &[u8]) -> Result<[u8; 48], VerificationError> {
150 cosmwasm_crypto::bls12_381_aggregate_g1(g1s).map_err(Into::into)
151 }
152
153 fn bls12_381_aggregate_g2(&self, g2s: &[u8]) -> Result<[u8; 96], VerificationError> {
154 cosmwasm_crypto::bls12_381_aggregate_g2(g2s).map_err(Into::into)
155 }
156
157 fn bls12_381_pairing_equality(
158 &self,
159 ps: &[u8],
160 qs: &[u8],
161 r: &[u8],
162 s: &[u8],
163 ) -> Result<bool, VerificationError> {
164 cosmwasm_crypto::bls12_381_pairing_equality(ps, qs, r, s).map_err(Into::into)
165 }
166
167 fn bls12_381_hash_to_g1(
168 &self,
169 hash_function: HashFunction,
170 msg: &[u8],
171 dst: &[u8],
172 ) -> Result<[u8; 48], VerificationError> {
173 Ok(cosmwasm_crypto::bls12_381_hash_to_g1(
174 hash_function.into(),
175 msg,
176 dst,
177 ))
178 }
179
180 fn bls12_381_hash_to_g2(
181 &self,
182 hash_function: HashFunction,
183 msg: &[u8],
184 dst: &[u8],
185 ) -> Result<[u8; 96], VerificationError> {
186 Ok(cosmwasm_crypto::bls12_381_hash_to_g2(
187 hash_function.into(),
188 msg,
189 dst,
190 ))
191 }
192
193 fn secp256k1_verify(
194 &self,
195 message_hash: &[u8],
196 signature: &[u8],
197 public_key: &[u8],
198 ) -> Result<bool, VerificationError> {
199 Ok(cosmwasm_crypto::secp256k1_verify(
200 message_hash,
201 signature,
202 public_key,
203 )?)
204 }
205
206 fn secp256k1_recover_pubkey(
207 &self,
208 message_hash: &[u8],
209 signature: &[u8],
210 recovery_param: u8,
211 ) -> Result<Vec<u8>, RecoverPubkeyError> {
212 let pubkey =
213 cosmwasm_crypto::secp256k1_recover_pubkey(message_hash, signature, recovery_param)?;
214 Ok(pubkey.to_vec())
215 }
216
217 fn secp256r1_verify(
218 &self,
219 message_hash: &[u8],
220 signature: &[u8],
221 public_key: &[u8],
222 ) -> Result<bool, VerificationError> {
223 Ok(cosmwasm_crypto::secp256r1_verify(
224 message_hash,
225 signature,
226 public_key,
227 )?)
228 }
229
230 fn secp256r1_recover_pubkey(
231 &self,
232 message_hash: &[u8],
233 signature: &[u8],
234 recovery_param: u8,
235 ) -> Result<Vec<u8>, RecoverPubkeyError> {
236 let pubkey =
237 cosmwasm_crypto::secp256r1_recover_pubkey(message_hash, signature, recovery_param)?;
238 Ok(pubkey.to_vec())
239 }
240
241 fn ed25519_verify(
242 &self,
243 message: &[u8],
244 signature: &[u8],
245 public_key: &[u8],
246 ) -> Result<bool, VerificationError> {
247 Ok(cosmwasm_crypto::ed25519_verify(
248 message, signature, public_key,
249 )?)
250 }
251
252 fn ed25519_batch_verify(
253 &self,
254 messages: &[&[u8]],
255 signatures: &[&[u8]],
256 public_keys: &[&[u8]],
257 ) -> Result<bool, VerificationError> {
258 Ok(cosmwasm_crypto::ed25519_batch_verify(
259 &mut OsRng,
260 messages,
261 signatures,
262 public_keys,
263 )?)
264 }
265
266 fn debug(&self, #[allow(unused)] message: &str) {
267 println!("{message}");
268 }
269}
270
271impl MockApi {
272 pub fn with_prefix(mut self, prefix: &'static str) -> Self {
288 self.bech32_prefix = prefix;
289 self
290 }
291
292 pub fn addr_make(&self, input: &str) -> Addr {
312 let digest = Sha256::digest(input);
313
314 let prefix = match Hrp::parse(self.bech32_prefix) {
315 Ok(prefix) => prefix,
316 Err(reason) => panic!("Generating address failed with reason: {reason}"),
317 };
318
319 match encode::<Bech32>(prefix, &digest) {
320 Ok(address) => Addr::unchecked(address),
321 Err(reason) => panic!("Generating address failed with reason: {reason}"),
322 }
323 }
324}
325
326fn validate_length(bytes: &[u8]) -> StdResult<()> {
328 match bytes.len() {
329 1..=255 => Ok(()),
330 _ => Err(StdError::msg("Invalid canonical address length")),
331 }
332}
333
334pub fn mock_env() -> Env {
389 let mut envs = Envs::new(BECH32_PREFIX);
390 envs.make()
391}
392
393pub struct Envs {
440 chain_id: String,
441 contract_address: Addr,
442 block_time: u64,
444 last_height: u64,
445 last_time: Timestamp,
446}
447
448#[derive(Clone, Debug)]
468#[non_exhaustive]
469pub struct EnvsOptions {
470 pub bech32_prefix: &'static str, pub block_time: u64,
472 pub initial_height: u64,
474 pub initial_time: Timestamp,
476 pub chain_id: String,
477}
478
479impl Default for EnvsOptions {
480 fn default() -> Self {
481 EnvsOptions {
482 bech32_prefix: BECH32_PREFIX,
483 block_time: 5_000_000_000, initial_height: 12_344,
485 initial_time: Timestamp::from_nanos(1_571_797_419_879_305_533).minus_seconds(5),
486 chain_id: "cosmos-testnet-14002".to_string(),
487 }
488 }
489}
490
491impl Envs {
492 pub fn new(bech32_prefix: &'static str) -> Self {
493 Self::with_options(EnvsOptions {
494 bech32_prefix,
495 ..Default::default()
496 })
497 }
498
499 pub fn with_options(options: EnvsOptions) -> Self {
500 let api = MockApi::default().with_prefix(options.bech32_prefix);
501 Envs {
502 chain_id: options.chain_id,
503 contract_address: api.addr_make("cosmos2contract"),
505 block_time: options.block_time,
506 last_height: options.initial_height,
507 last_time: options.initial_time,
508 }
509 }
510
511 pub fn make(&mut self) -> Env {
512 self.checked_make().unwrap()
513 }
514
515 fn checked_make(&mut self) -> Option<Env> {
516 let height = self.last_height.checked_add(1)?;
517 let time = Timestamp::from_nanos(self.last_time.nanos().checked_add(self.block_time)?);
518
519 self.last_height = height;
520 self.last_time = time;
521
522 Some(Env {
523 block: BlockInfo {
524 height,
525 time,
526 chain_id: self.chain_id.clone(),
527 },
528 transaction: Some(TransactionInfo::new(
529 3,
530 Binary::from_hex(
531 "E5469DACEC17CEF8A260FD37675ED87E7FB6A2B5AD95193C51308006C7E494B3",
532 )
533 .unwrap(),
534 )),
535 contract: ContractInfo {
536 address: self.contract_address.clone(),
537 },
538 })
539 }
540}
541
542impl Default for Envs {
543 fn default() -> Self {
544 Envs::with_options(EnvsOptions::default())
545 }
546}
547
548impl Iterator for Envs {
551 type Item = Env;
552
553 fn next(&mut self) -> Option<Self::Item> {
554 self.checked_make()
555 }
556}
557
558#[cfg(feature = "stargate")]
561pub fn mock_ibc_channel(my_channel_id: &str, order: IbcOrder, version: &str) -> IbcChannel {
562 IbcChannel {
563 endpoint: IbcEndpoint {
564 port_id: "my_port".to_string(),
565 channel_id: my_channel_id.to_string(),
566 },
567 counterparty_endpoint: IbcEndpoint {
568 port_id: "their_port".to_string(),
569 channel_id: "channel-7".to_string(),
570 },
571 order,
572 version: version.to_string(),
573 connection_id: "connection-2".to_string(),
574 }
575}
576
577#[cfg(feature = "stargate")]
579pub fn mock_ibc_channel_open_init(
580 my_channel_id: &str,
581 order: IbcOrder,
582 version: &str,
583) -> IbcChannelOpenMsg {
584 IbcChannelOpenMsg::new_init(mock_ibc_channel(my_channel_id, order, version))
585}
586
587#[cfg(feature = "stargate")]
589pub fn mock_ibc_channel_open_try(
590 my_channel_id: &str,
591 order: IbcOrder,
592 version: &str,
593) -> IbcChannelOpenMsg {
594 IbcChannelOpenMsg::new_try(mock_ibc_channel(my_channel_id, order, version), version)
595}
596
597#[cfg(feature = "stargate")]
599pub fn mock_ibc_channel_connect_ack(
600 my_channel_id: &str,
601 order: IbcOrder,
602 version: &str,
603) -> IbcChannelConnectMsg {
604 IbcChannelConnectMsg::new_ack(mock_ibc_channel(my_channel_id, order, version), version)
605}
606
607#[cfg(feature = "stargate")]
609pub fn mock_ibc_channel_connect_confirm(
610 my_channel_id: &str,
611 order: IbcOrder,
612 version: &str,
613) -> IbcChannelConnectMsg {
614 IbcChannelConnectMsg::new_confirm(mock_ibc_channel(my_channel_id, order, version))
615}
616
617#[cfg(feature = "stargate")]
619pub fn mock_ibc_channel_close_init(
620 my_channel_id: &str,
621 order: IbcOrder,
622 version: &str,
623) -> IbcChannelCloseMsg {
624 IbcChannelCloseMsg::new_init(mock_ibc_channel(my_channel_id, order, version))
625}
626
627#[cfg(feature = "stargate")]
629pub fn mock_ibc_channel_close_confirm(
630 my_channel_id: &str,
631 order: IbcOrder,
632 version: &str,
633) -> IbcChannelCloseMsg {
634 IbcChannelCloseMsg::new_confirm(mock_ibc_channel(my_channel_id, order, version))
635}
636
637#[cfg(feature = "stargate")]
640pub fn mock_ibc_packet_recv(
641 my_channel_id: &str,
642 data: &impl Serialize,
643) -> StdResult<IbcPacketReceiveMsg> {
644 Ok(IbcPacketReceiveMsg::new(
645 IbcPacket {
646 data: to_json_binary(data)?,
647 src: IbcEndpoint {
648 port_id: "their-port".to_string(),
649 channel_id: "channel-1234".to_string(),
650 },
651 dest: IbcEndpoint {
652 port_id: "our-port".to_string(),
653 channel_id: my_channel_id.into(),
654 },
655 sequence: 27,
656 timeout: IbcTimeoutBlock {
657 revision: 1,
658 height: 12345678,
659 }
660 .into(),
661 },
662 Addr::unchecked("relayer"),
663 ))
664}
665
666#[cfg(feature = "ibc2")]
669pub fn mock_ibc2_packet_ack(data: &impl Serialize) -> StdResult<Ibc2PacketAckMsg> {
670 Ok(Ibc2PacketAckMsg::new(
671 "source_id23".to_string(),
672 "channel_id23".to_string(),
673 Ibc2Payload {
674 source_port: "wasm2srcport".to_string(),
675 destination_port: "wasm2destport".to_string(),
676 version: "v2".to_string(),
677 encoding: "json".to_string(),
678 value: to_json_binary(data)?,
679 },
680 Binary::new(vec![]),
681 Addr::unchecked("relayer"),
682 ))
683}
684
685#[cfg(feature = "ibc2")]
688pub fn mock_ibc2_packet_recv(data: &impl Serialize) -> StdResult<Ibc2PacketReceiveMsg> {
689 Ok(Ibc2PacketReceiveMsg::new(
690 Ibc2Payload {
691 source_port: "wasm2srcport".to_string(),
692 destination_port: "wasm2destport".to_string(),
693 version: "v2".to_string(),
694 encoding: "json".to_string(),
695 value: to_json_binary(data)?,
696 },
697 Addr::unchecked("relayer"),
698 "channel_id23".to_string(),
699 "destination-client-id".to_string(),
700 42,
701 ))
702}
703
704#[cfg(feature = "ibc2")]
706pub fn mock_ibc2_packet_timeout(data: &impl Serialize) -> StdResult<Ibc2PacketTimeoutMsg> {
707 let payload = Ibc2Payload {
708 source_port: "wasm2srcport".to_string(),
709 destination_port: "wasm2destport".to_string(),
710 version: "v2".to_string(),
711 encoding: "json".to_string(),
712 value: to_json_binary(data)?,
713 };
714 Ok(Ibc2PacketTimeoutMsg::new(
715 payload,
716 "source_client".to_string(),
717 "destination_client".to_string(),
718 1,
719 Addr::unchecked("relayer"),
720 ))
721}
722
723#[cfg(feature = "ibc2")]
725pub fn mock_ibc2_packet_send(data: &impl Serialize) -> StdResult<Ibc2PacketSendMsg> {
726 let payload = Ibc2Payload {
727 source_port: "wasm2srcport".to_string(),
728 destination_port: "wasm2destport".to_string(),
729 version: "v2".to_string(),
730 encoding: "json".to_string(),
731 value: to_json_binary(data)?,
732 };
733 Ok(Ibc2PacketSendMsg::new(
734 payload,
735 "source_client".to_string(),
736 "destination_client".to_string(),
737 1,
738 Addr::unchecked("signer_contract"),
739 ))
740}
741
742#[cfg(feature = "stargate")]
746fn mock_ibc_packet(my_channel_id: &str, data: &impl Serialize) -> StdResult<IbcPacket> {
747 Ok(IbcPacket {
748 data: to_json_binary(data)?,
749 src: IbcEndpoint {
750 port_id: "their-port".to_string(),
751 channel_id: my_channel_id.into(),
752 },
753 dest: IbcEndpoint {
754 port_id: "our-port".to_string(),
755 channel_id: "channel-1234".to_string(),
756 },
757 sequence: 29,
758 timeout: IbcTimeoutBlock {
759 revision: 1,
760 height: 432332552,
761 }
762 .into(),
763 })
764}
765
766#[cfg(feature = "stargate")]
770pub fn mock_ibc_packet_ack(
771 my_channel_id: &str,
772 data: &impl Serialize,
773 ack: IbcAcknowledgement,
774) -> StdResult<IbcPacketAckMsg> {
775 let packet = mock_ibc_packet(my_channel_id, data)?;
776
777 Ok(IbcPacketAckMsg::new(
778 ack,
779 packet,
780 Addr::unchecked("relayer"),
781 ))
782}
783
784#[cfg(feature = "stargate")]
788pub fn mock_ibc_packet_timeout(
789 my_channel_id: &str,
790 data: &impl Serialize,
791) -> StdResult<IbcPacketTimeoutMsg> {
792 let packet = mock_ibc_packet(my_channel_id, data)?;
793 Ok(IbcPacketTimeoutMsg::new(packet, Addr::unchecked("relayer")))
794}
795
796pub type MockQuerierCustomHandlerResult = SystemResult<ContractResult<Binary>>;
799
800pub struct MockQuerier<C: DeserializeOwned = Empty> {
803 pub bank: BankQuerier,
804 #[cfg(feature = "staking")]
805 pub staking: StakingQuerier,
806 #[cfg(feature = "cosmwasm_1_3")]
807 pub distribution: DistributionQuerier,
808 wasm: WasmQuerier,
809 #[cfg(feature = "stargate")]
810 pub ibc: IbcQuerier,
811 custom_handler: Box<dyn for<'a> Fn(&'a C) -> MockQuerierCustomHandlerResult>,
816}
817
818impl<C: DeserializeOwned> MockQuerier<C> {
819 pub fn new(balances: &[(&str, &[Coin])]) -> Self {
820 MockQuerier {
821 bank: BankQuerier::new(balances),
822 #[cfg(feature = "cosmwasm_1_3")]
823 distribution: DistributionQuerier::default(),
824 #[cfg(feature = "staking")]
825 staking: StakingQuerier::default(),
826 wasm: WasmQuerier::default(),
827 #[cfg(feature = "stargate")]
828 ibc: IbcQuerier::default(),
829 custom_handler: Box::from(|_: &_| -> MockQuerierCustomHandlerResult {
831 SystemResult::Err(SystemError::UnsupportedRequest {
832 kind: "custom".to_string(),
833 })
834 }),
835 }
836 }
837
838 pub fn update_wasm<WH>(&mut self, handler: WH)
839 where
840 WH: Fn(&WasmQuery) -> QuerierResult + 'static,
841 {
842 self.wasm.update_handler(handler)
843 }
844
845 pub fn with_custom_handler<CH>(mut self, handler: CH) -> Self
846 where
847 CH: Fn(&C) -> MockQuerierCustomHandlerResult + 'static,
848 {
849 self.custom_handler = Box::from(handler);
850 self
851 }
852}
853
854impl Default for MockQuerier {
855 fn default() -> Self {
856 MockQuerier::new(&[])
857 }
858}
859
860impl<C: CustomQuery + DeserializeOwned> Querier for MockQuerier<C> {
861 fn raw_query(&self, bin_request: &[u8]) -> QuerierResult {
862 let request: QueryRequest<C> = match from_json(bin_request) {
863 Ok(v) => v,
864 Err(e) => {
865 return SystemResult::Err(SystemError::InvalidRequest {
866 error: format!("Parsing query request: {e}"),
867 request: bin_request.into(),
868 })
869 }
870 };
871 self.handle_query(&request)
872 }
873}
874
875impl<C: CustomQuery + DeserializeOwned> MockQuerier<C> {
876 pub fn handle_query(&self, request: &QueryRequest<C>) -> QuerierResult {
877 match &request {
878 QueryRequest::Bank(bank_query) => self.bank.query(bank_query),
879 QueryRequest::Custom(custom_query) => (*self.custom_handler)(custom_query),
880 #[cfg(feature = "staking")]
881 QueryRequest::Staking(staking_query) => self.staking.query(staking_query),
882 #[cfg(feature = "cosmwasm_1_3")]
883 QueryRequest::Distribution(distribution_query) => {
884 self.distribution.query(distribution_query)
885 }
886 QueryRequest::Wasm(msg) => self.wasm.query(msg),
887 #[cfg(feature = "stargate")]
888 #[allow(deprecated)]
889 QueryRequest::Stargate { .. } => SystemResult::Err(SystemError::UnsupportedRequest {
890 kind: "Stargate".to_string(),
891 }),
892 #[cfg(feature = "cosmwasm_2_0")]
893 QueryRequest::Grpc(_) => SystemResult::Err(SystemError::UnsupportedRequest {
894 kind: "GRPC".to_string(),
895 }),
896 #[cfg(feature = "stargate")]
897 QueryRequest::Ibc(msg) => self.ibc.query(msg),
898 }
899 }
900}
901
902struct WasmQuerier {
903 handler: Box<dyn for<'a> Fn(&'a WasmQuery) -> QuerierResult>,
908}
909
910impl WasmQuerier {
911 fn new(handler: Box<dyn for<'a> Fn(&'a WasmQuery) -> QuerierResult>) -> Self {
912 Self { handler }
913 }
914
915 fn update_handler<WH>(&mut self, handler: WH)
916 where
917 WH: Fn(&WasmQuery) -> QuerierResult + 'static,
918 {
919 self.handler = Box::from(handler)
920 }
921
922 fn query(&self, request: &WasmQuery) -> QuerierResult {
923 (*self.handler)(request)
924 }
925}
926
927impl Default for WasmQuerier {
928 fn default() -> Self {
929 let handler = Box::from(|request: &WasmQuery| -> QuerierResult {
930 let err = match request {
931 WasmQuery::Smart { contract_addr, .. } => SystemError::NoSuchContract {
932 addr: contract_addr.clone(),
933 },
934 WasmQuery::Raw { contract_addr, .. } => SystemError::NoSuchContract {
935 addr: contract_addr.clone(),
936 },
937 WasmQuery::ContractInfo { contract_addr, .. } => SystemError::NoSuchContract {
938 addr: contract_addr.clone(),
939 },
940 #[cfg(feature = "cosmwasm_1_2")]
941 WasmQuery::CodeInfo { code_id, .. } => {
942 SystemError::NoSuchCode { code_id: *code_id }
943 }
944 #[cfg(all(feature = "cosmwasm_3_0", feature = "iterator"))]
945 WasmQuery::RawRange { contract_addr, .. } => SystemError::NoSuchContract {
946 addr: contract_addr.clone(),
947 },
948 };
949 SystemResult::Err(err)
950 });
951 Self::new(handler)
952 }
953}
954
955#[derive(Clone, Default)]
956pub struct BankQuerier {
957 #[allow(dead_code)]
958 supplies: BTreeMap<String, Uint256>,
960 balances: BTreeMap<String, Vec<Coin>>,
963 denom_metadata: BTreeMap<Vec<u8>, DenomMetadata>,
965}
966
967impl BankQuerier {
968 pub fn new(balances: &[(&str, &[Coin])]) -> Self {
969 let balances: BTreeMap<_, _> = balances
970 .iter()
971 .map(|(address, balance)| (address.to_string(), balance.to_vec()))
972 .collect();
973
974 BankQuerier {
975 supplies: Self::calculate_supplies(&balances),
976 balances,
977 denom_metadata: BTreeMap::new(),
978 }
979 }
980
981 pub fn update_balance(
983 &mut self,
984 addr: impl Into<String>,
985 balance: Vec<Coin>,
986 ) -> Option<Vec<Coin>> {
987 let result = self.balances.insert(addr.into(), balance);
988 self.supplies = Self::calculate_supplies(&self.balances);
989
990 result
991 }
992
993 pub fn set_denom_metadata(&mut self, denom_metadata: &[DenomMetadata]) {
994 self.denom_metadata = denom_metadata
995 .iter()
996 .map(|d| (d.base.as_bytes().to_vec(), d.clone()))
997 .collect();
998 }
999
1000 fn calculate_supplies(balances: &BTreeMap<String, Vec<Coin>>) -> BTreeMap<String, Uint256> {
1001 let mut supplies = BTreeMap::new();
1002
1003 let all_coins = balances.iter().flat_map(|(_, coins)| coins);
1004
1005 for coin in all_coins {
1006 *supplies
1007 .entry(coin.denom.clone())
1008 .or_insert_with(Uint256::zero) += coin.amount;
1009 }
1010
1011 supplies
1012 }
1013
1014 pub fn query(&self, request: &BankQuery) -> QuerierResult {
1015 let contract_result: ContractResult<Binary> = match request {
1016 #[cfg(feature = "cosmwasm_1_1")]
1017 BankQuery::Supply { denom } => {
1018 let amount = self
1019 .supplies
1020 .get(denom)
1021 .cloned()
1022 .unwrap_or_else(Uint256::zero);
1023 let bank_res = SupplyResponse {
1024 amount: Coin {
1025 amount,
1026 denom: denom.to_string(),
1027 },
1028 };
1029 to_json_binary(&bank_res).into()
1030 }
1031 BankQuery::Balance { address, denom } => {
1032 let amount = self
1034 .balances
1035 .get(address)
1036 .and_then(|v| v.iter().find(|c| &c.denom == denom).map(|c| c.amount))
1037 .unwrap_or_default();
1038 let bank_res = BalanceResponse {
1039 amount: Coin {
1040 amount,
1041 denom: denom.to_string(),
1042 },
1043 };
1044 to_json_binary(&bank_res).into()
1045 }
1046 #[cfg(feature = "cosmwasm_1_3")]
1047 BankQuery::DenomMetadata { denom } => {
1048 let denom_metadata = self.denom_metadata.get(denom.as_bytes());
1049 match denom_metadata {
1050 Some(m) => {
1051 let metadata_res = DenomMetadataResponse {
1052 metadata: m.clone(),
1053 };
1054 to_json_binary(&metadata_res).into()
1055 }
1056 None => return SystemResult::Err(SystemError::Unknown {}),
1057 }
1058 }
1059 #[cfg(feature = "cosmwasm_1_3")]
1060 BankQuery::AllDenomMetadata { pagination } => {
1061 let default_pagination = PageRequest {
1062 key: None,
1063 limit: 100,
1064 reverse: false,
1065 };
1066 let pagination = pagination.as_ref().unwrap_or(&default_pagination);
1067
1068 let range = match (pagination.reverse, &pagination.key) {
1070 (_, None) => (Bound::Unbounded, Bound::Unbounded),
1071 (true, Some(key)) => (Bound::Unbounded, Bound::Included(key.as_slice())),
1072 (false, Some(key)) => (Bound::Included(key.as_slice()), Bound::Unbounded),
1073 };
1074 let iter = self.denom_metadata.range::<[u8], _>(range);
1075 let iter: Box<dyn Iterator<Item = _>> = if pagination.reverse {
1077 Box::new(iter.rev())
1078 } else {
1079 Box::new(iter)
1080 };
1081
1082 let mut metadata: Vec<_> = iter
1083 .take((pagination.limit.saturating_add(1)) as usize)
1085 .map(|(_, m)| m.clone())
1086 .collect();
1087
1088 let next_key = if metadata.len() > pagination.limit as usize {
1091 metadata.pop().map(|m| Binary::from(m.base.as_bytes()))
1092 } else {
1093 None
1094 };
1095
1096 let metadata_res = AllDenomMetadataResponse { metadata, next_key };
1097 to_json_binary(&metadata_res).into()
1098 }
1099 };
1100 SystemResult::Ok(contract_result)
1102 }
1103}
1104
1105#[cfg(feature = "stargate")]
1106#[derive(Clone, Default)]
1107pub struct IbcQuerier {
1108 port_id: String,
1109 channels: Vec<IbcChannel>,
1110}
1111
1112#[cfg(feature = "stargate")]
1113impl IbcQuerier {
1114 pub fn new(port_id: &str, channels: &[IbcChannel]) -> Self {
1118 IbcQuerier {
1119 port_id: port_id.to_string(),
1120 channels: channels.to_vec(),
1121 }
1122 }
1123
1124 pub fn update(&mut self, port_id: impl Into<String>, channels: &[IbcChannel]) {
1126 self.port_id = port_id.into();
1127 self.channels = channels.to_vec();
1128 }
1129
1130 pub fn query(&self, request: &IbcQuery) -> QuerierResult {
1131 let contract_result: ContractResult<Binary> = match request {
1132 IbcQuery::Channel {
1133 channel_id,
1134 port_id,
1135 } => {
1136 let channel = self
1137 .channels
1138 .iter()
1139 .find(|c| match port_id {
1140 Some(p) => c.endpoint.channel_id.eq(channel_id) && c.endpoint.port_id.eq(p),
1141 None => {
1142 c.endpoint.channel_id.eq(channel_id)
1143 && c.endpoint.port_id == self.port_id
1144 }
1145 })
1146 .cloned();
1147 let res = ChannelResponse { channel };
1148 to_json_binary(&res).into()
1149 }
1150 IbcQuery::PortId {} => {
1151 let res = PortIdResponse {
1152 port_id: self.port_id.clone(),
1153 };
1154 to_json_binary(&res).into()
1155 }
1156 };
1157 SystemResult::Ok(contract_result)
1159 }
1160}
1161
1162#[cfg(feature = "staking")]
1163#[derive(Clone, Default)]
1164pub struct StakingQuerier {
1165 denom: String,
1166 validators: Vec<Validator>,
1167 delegations: Vec<FullDelegation>,
1168}
1169
1170#[cfg(feature = "staking")]
1171impl StakingQuerier {
1172 pub fn new(denom: &str, validators: &[Validator], delegations: &[FullDelegation]) -> Self {
1173 StakingQuerier {
1174 denom: denom.to_string(),
1175 validators: validators.to_vec(),
1176 delegations: delegations.to_vec(),
1177 }
1178 }
1179
1180 pub fn update(
1182 &mut self,
1183 denom: impl Into<String>,
1184 validators: &[Validator],
1185 delegations: &[FullDelegation],
1186 ) {
1187 self.denom = denom.into();
1188 self.validators = validators.to_vec();
1189 self.delegations = delegations.to_vec();
1190 }
1191
1192 pub fn query(&self, request: &StakingQuery) -> QuerierResult {
1193 let contract_result: ContractResult<Binary> = match request {
1194 StakingQuery::BondedDenom {} => {
1195 let res = BondedDenomResponse {
1196 denom: self.denom.clone(),
1197 };
1198 to_json_binary(&res).into()
1199 }
1200 StakingQuery::AllValidators {} => {
1201 let res = AllValidatorsResponse {
1202 validators: self.validators.iter().cloned().map(Into::into).collect(),
1203 };
1204 to_json_binary(&res).into()
1205 }
1206 StakingQuery::Validator { address } => {
1207 let validator: Option<Validator> = self
1208 .validators
1209 .iter()
1210 .find(|validator| validator.address == *address)
1211 .cloned();
1212 let res = ValidatorResponse { validator };
1213 to_json_binary(&res).into()
1214 }
1215 StakingQuery::AllDelegations { delegator } => {
1216 let delegations: Vec<_> = self
1217 .delegations
1218 .iter()
1219 .filter(|d| d.delegator.as_str() == delegator)
1220 .cloned()
1221 .map(|d| d.into())
1222 .collect();
1223 let res = AllDelegationsResponse { delegations };
1224 to_json_binary(&res).into()
1225 }
1226 StakingQuery::Delegation {
1227 delegator,
1228 validator,
1229 } => {
1230 let delegation = self
1231 .delegations
1232 .iter()
1233 .find(|d| d.delegator.as_str() == delegator && d.validator == *validator);
1234 let res = DelegationResponse {
1235 delegation: delegation.cloned(),
1236 };
1237 to_json_binary(&res).into()
1238 }
1239 };
1240 SystemResult::Ok(contract_result)
1242 }
1243}
1244
1245#[cfg(feature = "cosmwasm_1_3")]
1246#[derive(Clone, Default)]
1247pub struct DistributionQuerier {
1248 withdraw_addresses: BTreeMap<String, String>,
1249 rewards: BTreeMap<String, BTreeMap<String, Vec<DecCoin>>>,
1251 validators: BTreeMap<String, BTreeSet<String>>,
1253}
1254
1255#[cfg(feature = "cosmwasm_1_3")]
1256impl DistributionQuerier {
1257 pub fn new<T>(withdraw_addresses: T) -> Self
1258 where
1259 T: IntoIterator<Item = (String, String)>,
1260 {
1261 DistributionQuerier {
1262 withdraw_addresses: withdraw_addresses.into_iter().collect(),
1263 ..Default::default()
1264 }
1265 }
1266
1267 pub fn set_withdraw_address(
1268 &mut self,
1269 delegator_address: impl Into<String>,
1270 withdraw_address: impl Into<String>,
1271 ) {
1272 self.withdraw_addresses
1273 .insert(delegator_address.into(), withdraw_address.into());
1274 }
1275
1276 pub fn set_withdraw_addresses(
1281 &mut self,
1282 withdraw_addresses: impl IntoIterator<Item = (impl Into<String>, impl Into<String>)>,
1283 ) {
1284 for (d, w) in withdraw_addresses {
1285 self.set_withdraw_address(d, w);
1286 }
1287 }
1288
1289 pub fn clear_withdraw_addresses(&mut self) {
1290 self.withdraw_addresses.clear();
1291 }
1292
1293 pub fn set_rewards(
1295 &mut self,
1296 validator: impl Into<String>,
1297 delegator: impl Into<String>,
1298 rewards: Vec<DecCoin>,
1299 ) {
1300 self.rewards
1301 .entry(delegator.into())
1302 .or_default()
1303 .insert(validator.into(), rewards);
1304 }
1305
1306 pub fn set_validators(
1308 &mut self,
1309 delegator: impl Into<String>,
1310 validators: impl IntoIterator<Item = impl Into<String>>,
1311 ) {
1312 self.validators.insert(
1313 delegator.into(),
1314 validators.into_iter().map(Into::into).collect(),
1315 );
1316 }
1317
1318 pub fn query(&self, request: &DistributionQuery) -> QuerierResult {
1319 let contract_result: ContractResult<Binary> = match request {
1320 DistributionQuery::DelegatorWithdrawAddress { delegator_address } => {
1321 let res = DelegatorWithdrawAddressResponse {
1322 withdraw_address: Addr::unchecked(
1323 self.withdraw_addresses
1324 .get(delegator_address)
1325 .unwrap_or(delegator_address),
1326 ),
1327 };
1328 to_json_binary(&res).into()
1329 }
1330 #[cfg(feature = "cosmwasm_1_4")]
1331 DistributionQuery::DelegationRewards {
1332 delegator_address,
1333 validator_address,
1334 } => {
1335 let res = DelegationRewardsResponse {
1336 rewards: self
1337 .rewards
1338 .get(delegator_address)
1339 .and_then(|v| v.get(validator_address))
1340 .cloned()
1341 .unwrap_or_default(),
1342 };
1343 to_json_binary(&res).into()
1344 }
1345 #[cfg(feature = "cosmwasm_1_4")]
1346 DistributionQuery::DelegationTotalRewards { delegator_address } => {
1347 let validator_rewards = self
1348 .validator_rewards(delegator_address)
1349 .unwrap_or_default();
1350 let res = crate::DelegationTotalRewardsResponse {
1351 total: validator_rewards
1352 .iter()
1353 .fold(BTreeMap::<&str, DecCoin>::new(), |mut acc, rewards| {
1354 for coin in &rewards.reward {
1355 acc.entry(&coin.denom)
1356 .or_insert_with(|| DecCoin {
1357 denom: coin.denom.clone(),
1358 amount: Decimal256::zero(),
1359 })
1360 .amount += coin.amount;
1361 }
1362
1363 acc
1364 })
1365 .into_values()
1366 .collect(),
1367 rewards: validator_rewards,
1368 };
1369 to_json_binary(&res).into()
1370 }
1371 #[cfg(feature = "cosmwasm_1_4")]
1372 DistributionQuery::DelegatorValidators { delegator_address } => {
1373 let res = DelegatorValidatorsResponse {
1374 validators: self
1375 .validators
1376 .get(delegator_address)
1377 .map(|set| set.iter().cloned().collect())
1378 .unwrap_or_default(),
1379 };
1380 to_json_binary(&res).into()
1381 }
1382 };
1383 SystemResult::Ok(contract_result)
1385 }
1386
1387 #[cfg(feature = "cosmwasm_1_4")]
1389 fn validator_rewards(&self, delegator_address: &str) -> Option<Vec<crate::DelegatorReward>> {
1390 let validator_rewards = self.rewards.get(delegator_address)?;
1391
1392 Some(
1393 validator_rewards
1394 .iter()
1395 .map(|(validator, rewards)| crate::DelegatorReward {
1396 validator_address: validator.clone(),
1397 reward: rewards.clone(),
1398 })
1399 .collect(),
1400 )
1401 }
1402}
1403
1404pub fn mock_wasmd_attr(key: impl Into<String>, value: impl Into<String>) -> Attribute {
1407 Attribute {
1408 key: key.into(),
1409 value: value.into(),
1410 }
1411}
1412
1413#[cfg(test)]
1414mod tests {
1415 use super::*;
1416 #[allow(unused)]
1417 use crate::coins;
1418 #[cfg(feature = "cosmwasm_1_3")]
1419 use crate::DenomUnit;
1420 use crate::{coin, instantiate2_address, ContractInfoResponse, HexBinary, Response, Storage};
1421 #[cfg(feature = "staking")]
1422 use crate::{Decimal, Delegation};
1423 use base64::{engine::general_purpose, Engine};
1424 use cosmwasm_core::BLS12_381_G1_GENERATOR;
1425 use hex_literal::hex;
1426 use serde::Deserialize;
1427
1428 const SECP256K1_MSG_HASH_HEX: &str =
1429 "5ae8317d34d1e595e3fa7247db80c0af4320cce1116de187f8f7e2e099c0d8d0";
1430 const SECP256K1_SIG_HEX: &str = "207082eb2c3dfa0b454e0906051270ba4074ac93760ba9e7110cd9471475111151eb0dbbc9920e72146fb564f99d039802bf6ef2561446eb126ef364d21ee9c4";
1431 const SECP256K1_PUBKEY_HEX: &str = "04051c1ee2190ecfb174bfe4f90763f2b4ff7517b70a2aec1876ebcfd644c4633fb03f3cfbd94b1f376e34592d9d41ccaf640bb751b00a1fadeb0c01157769eb73";
1432
1433 const SECP256R1_MSG_HASH_HEX: &str =
1434 "5eb28029ebf3c7025ff2fc2f6de6f62aecf6a72139e1cba5f20d11bbef036a7f";
1435 const SECP256R1_SIG_HEX: &str = "e67a9717ccf96841489d6541f4f6adb12d17b59a6bef847b6183b8fcf16a32eb9ae6ba6d637706849a6a9fc388cf0232d85c26ea0d1fe7437adb48de58364333";
1436 const SECP256R1_PUBKEY_HEX: &str = "0468229b48c2fe19d3db034e4c15077eb7471a66031f28a980821873915298ba76303e8ee3742a893f78b810991da697083dd8f11128c47651c27a56740a80c24c";
1437
1438 const ED25519_MSG_HEX: &str = "72";
1439 const ED25519_SIG_HEX: &str = "92a009a9f0d4cab8720e820b5f642540a2b27b5416503f8fb3762223ebdb69da085ac1e43e15996e458f3613d0f11d8c387b2eaeb4302aeeb00d291612bb0c00";
1440 const ED25519_PUBKEY_HEX: &str =
1441 "3d4017c3e843895a92b70aa74d1b7ebc9c982ccf2ec4968cc0cd55f12af4660c";
1442
1443 const DOMAIN_HASH_TO_G2: &[u8] = b"BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_NUL_";
1446
1447 const PK_LEO_MAINNET: [u8; 48] = hex!("868f005eb8e6e4ca0a47c8a77ceaa5309a47978a7c71bc5cce96366b5d7a569937c529eeda66c7293784a9402801af31");
1449
1450 const ETH_BLOCK_HEADER: &[u8] =
1451 include_bytes!("../../../crypto/testdata/eth-headers/1699693797.394876721s.json");
1452
1453 #[test]
1454 fn mock_env_works() {
1455 let env = mock_env();
1456 assert_eq!(
1457 env,
1458 Env {
1459 block: BlockInfo {
1460 height: 12345,
1461 time: Timestamp::from_nanos(1571797419879305533),
1462 chain_id: "cosmos-testnet-14002".to_string()
1463 },
1464 transaction: Some(TransactionInfo::new(
1465 3,
1466 Binary::from_hex(
1467 "E5469DACEC17CEF8A260FD37675ED87E7FB6A2B5AD95193C51308006C7E494B3"
1468 )
1469 .unwrap(),
1470 )),
1471 contract: ContractInfo {
1472 address: Addr::unchecked(MOCK_CONTRACT_ADDR)
1473 }
1474 }
1475 )
1476 }
1477
1478 #[test]
1479 fn envs_works() {
1480 let mut envs = Envs::new("food");
1481
1482 let env = envs.make();
1483 assert_eq!(
1484 env.contract.address.as_str(),
1485 "food1jpev2csrppg792t22rn8z8uew8h3sjcpglcd0qv9g8gj8ky922ts74yrjj"
1486 );
1487 assert_eq!(env.block.height, 12_345);
1488 assert_eq!(
1489 env.block.time,
1490 Timestamp::from_nanos(1_571_797_419_879_305_533)
1491 );
1492
1493 let env = envs.make();
1494 assert_eq!(
1495 env.contract.address.as_str(),
1496 "food1jpev2csrppg792t22rn8z8uew8h3sjcpglcd0qv9g8gj8ky922ts74yrjj"
1497 );
1498 assert_eq!(env.block.height, 12_346);
1499 assert_eq!(
1500 env.block.time,
1501 Timestamp::from_nanos(1_571_797_424_879_305_533)
1502 );
1503
1504 let env = envs.make();
1505 assert_eq!(
1506 env.contract.address.as_str(),
1507 "food1jpev2csrppg792t22rn8z8uew8h3sjcpglcd0qv9g8gj8ky922ts74yrjj"
1508 );
1509 assert_eq!(env.block.height, 12_347);
1510 assert_eq!(
1511 env.block.time,
1512 Timestamp::from_nanos(1_571_797_429_879_305_533)
1513 );
1514 }
1515
1516 #[test]
1517 fn envs_implements_iterator() {
1518 let envs = Envs::new("food");
1519
1520 let result: Vec<_> = envs.into_iter().take(5).collect();
1521
1522 assert_eq!(
1523 result[0].contract.address.as_str(),
1524 "food1jpev2csrppg792t22rn8z8uew8h3sjcpglcd0qv9g8gj8ky922ts74yrjj"
1525 );
1526 assert_eq!(result[0].block.height, 12_345);
1527 assert_eq!(
1528 result[0].block.time,
1529 Timestamp::from_nanos(1_571_797_419_879_305_533)
1530 );
1531
1532 assert_eq!(
1533 result[4].contract.address.as_str(),
1534 "food1jpev2csrppg792t22rn8z8uew8h3sjcpglcd0qv9g8gj8ky922ts74yrjj"
1535 );
1536 assert_eq!(result[4].block.height, 12_349);
1537 assert_eq!(
1538 result[4].block.time,
1539 Timestamp::from_nanos(1_571_797_439_879_305_533)
1540 );
1541
1542 let mut envs = Envs::new("yo");
1544 let first = envs.next().unwrap();
1545 let last = envs.take(1_000_000).last().unwrap();
1546 assert_eq!(first.block.height, 12_345);
1547 assert_eq!(last.block.height, 1_012_345);
1548 assert_eq!(
1549 last.block.time,
1550 first.block.time.plus_seconds(1_000_000 * 5)
1551 );
1552 }
1553
1554 #[test]
1555 fn addr_validate_works() {
1556 let api = MockApi::default();
1558
1559 let humanized = "cosmwasm1h34lmpywh4upnjdg90cjf4j70aee6z8qqfspugamjp42e4q28kqs8s7vcp";
1561 let addr = api.addr_validate(humanized).unwrap();
1562 assert_eq!(addr.as_str(), humanized);
1563
1564 api.addr_validate("").unwrap_err();
1566 api.addr_validate("Foobar123").unwrap_err();
1568 api.addr_validate("FOOBAR123").unwrap_err();
1569 }
1570
1571 #[test]
1572 fn addr_canonicalize_works() {
1573 let api = MockApi::default();
1574
1575 api.addr_canonicalize(
1576 "cosmwasm1h34lmpywh4upnjdg90cjf4j70aee6z8qqfspugamjp42e4q28kqs8s7vcp",
1577 )
1578 .unwrap();
1579
1580 let data1 = api
1582 .addr_canonicalize(
1583 "cosmwasm1h34lmpywh4upnjdg90cjf4j70aee6z8qqfspugamjp42e4q28kqs8s7vcp",
1584 )
1585 .unwrap();
1586 let data2 = api
1587 .addr_canonicalize(
1588 "COSMWASM1H34LMPYWH4UPNJDG90CJF4J70AEE6Z8QQFSPUGAMJP42E4Q28KQS8S7VCP",
1589 )
1590 .unwrap();
1591 assert_eq!(data1, data2);
1592 }
1593
1594 #[test]
1595 fn canonicalize_and_humanize_restores_original() {
1596 let api = MockApi::default();
1598
1599 let original =
1601 String::from("COSMWASM1H34LMPYWH4UPNJDG90CJF4J70AEE6Z8QQFSPUGAMJP42E4Q28KQS8S7VCP");
1602 let canonical = api.addr_canonicalize(&original).unwrap();
1603 let recovered = api.addr_humanize(&canonical).unwrap();
1604 assert_eq!(
1605 recovered.as_str(),
1606 "cosmwasm1h34lmpywh4upnjdg90cjf4j70aee6z8qqfspugamjp42e4q28kqs8s7vcp"
1607 );
1608
1609 let api = MockApi::default().with_prefix("juno");
1611
1612 let original =
1614 String::from("juno1v82su97skv6ucfqvuvswe0t5fph7pfsrtraxf0x33d8ylj5qnrysdvkc95");
1615 let canonical = api.addr_canonicalize(&original).unwrap();
1616 let recovered = api.addr_humanize(&canonical).unwrap();
1617 assert_eq!(recovered.as_str(), original);
1618 }
1619
1620 #[test]
1621 fn addr_canonicalize_short_input() {
1622 let api = MockApi::default();
1623
1624 let empty = "cosmwasm1pj90vm";
1626 assert!(api
1627 .addr_canonicalize(empty)
1628 .unwrap_err()
1629 .to_string()
1630 .contains("Invalid canonical address length"));
1631
1632 let human = "cosmwasm1qqvk2mde";
1634 assert_eq!(api.addr_canonicalize(human).unwrap().as_ref(), [0u8]);
1635 }
1636
1637 #[test]
1638 fn addr_canonicalize_long_input() {
1639 let api = MockApi::default();
1640 let human =
1641 "cosmwasm1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqehqqkz";
1642 let err = api.addr_canonicalize(human).unwrap_err();
1643 assert!(err.to_string().contains("Invalid canonical address length"));
1644 }
1645
1646 #[test]
1647 fn addr_humanize_input_length() {
1648 let api = MockApi::default();
1649 let input = CanonicalAddr::from(vec![]);
1650 assert!(api
1651 .addr_humanize(&input)
1652 .unwrap_err()
1653 .to_string()
1654 .ends_with("Invalid canonical address length"));
1655 }
1656
1657 #[test]
1658 fn bls12_381_aggregate_g1_works() {
1659 #[derive(serde::Deserialize)]
1660 struct EthHeader {
1661 public_keys: Vec<String>,
1662 aggregate_pubkey: String,
1663 }
1664
1665 let api = MockApi::default();
1666 let header: EthHeader = serde_json::from_slice(ETH_BLOCK_HEADER).unwrap();
1667 let expected = general_purpose::STANDARD
1668 .decode(header.aggregate_pubkey)
1669 .unwrap();
1670
1671 let pubkeys: Vec<u8> = header
1672 .public_keys
1673 .into_iter()
1674 .flat_map(|key| general_purpose::STANDARD.decode(key).unwrap())
1675 .collect();
1676 let sum = api.bls12_381_aggregate_g1(&pubkeys).unwrap();
1677
1678 assert_eq!(expected, sum);
1679 }
1680
1681 #[test]
1682 fn bls12_381_aggregate_g2_works() {
1683 let api = MockApi::default();
1684
1685 let points: Vec<u8> = [
1686 hex!("b6ed936746e01f8ecf281f020953fbf1f01debd5657c4a383940b020b26507f6076334f91e2366c96e9ab279fb5158090352ea1c5b0c9274504f4f0e7053af24802e51e4568d164fe986834f41e55c8e850ce1f98458c0cfc9ab380b55285a55"),
1687 hex!("b23c46be3a001c63ca711f87a005c200cc550b9429d5f4eb38d74322144f1b63926da3388979e5321012fb1a0526bcd100b5ef5fe72628ce4cd5e904aeaa3279527843fae5ca9ca675f4f51ed8f83bbf7155da9ecc9663100a885d5dc6df96d9"),
1688 hex!("948a7cb99f76d616c2c564ce9bf4a519f1bea6b0a624a02276443c245854219fabb8d4ce061d255af5330b078d5380681751aa7053da2c98bae898edc218c75f07e24d8802a17cd1f6833b71e58f5eb5b94208b4d0bb3848cecb075ea21be115"),
1689 ]
1690 .into_iter()
1691 .flatten()
1692 .collect();
1693
1694 let expected = hex!("9683b3e6701f9a4b706709577963110043af78a5b41991b998475a3d3fd62abf35ce03b33908418efc95a058494a8ae504354b9f626231f6b3f3c849dfdeaf5017c4780e2aee1850ceaf4b4d9ce70971a3d2cfcd97b7e5ecf6759f8da5f76d31");
1695 let sum = api.bls12_381_aggregate_g2(&points).unwrap();
1696
1697 assert_eq!(sum, expected);
1698 }
1699
1700 #[test]
1701 fn bls12_381_pairing_equality_works() {
1702 let api = MockApi::default();
1703
1704 let dst = b"BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_POP_";
1705 let ps = hex!("a491d1b0ecd9bb917989f0e74f0dea0422eac4a873e5e2644f368dffb9a6e20fd6e10c1b77654d067c0618f6e5a7f79ab301803f8b5ac4a1133581fc676dfedc60d891dd5fa99028805e5ea5b08d3491af75d0707adab3b70c6a6a580217bf81b53d21a4cfd562c469cc81514d4ce5a6b577d8403d32a394dc265dd190b47fa9f829fdd7963afdf972e5e77854051f6f");
1706 let qs: Vec<u8> = [
1707 hex!("0000000000000000000000000000000000000000000000000000000000000000"),
1708 hex!("5656565656565656565656565656565656565656565656565656565656565656"),
1709 hex!("abababababababababababababababababababababababababababababababab"),
1710 ]
1711 .into_iter()
1712 .flat_map(|msg| {
1713 api.bls12_381_hash_to_g2(HashFunction::Sha256, &msg, dst)
1714 .unwrap()
1715 })
1716 .collect();
1717 let s = hex!("9104e74b9dfd3ad502f25d6a5ef57db0ed7d9a0e00f3500586d8ce44231212542fcfaf87840539b398bf07626705cf1105d246ca1062c6c2e1a53029a0f790ed5e3cb1f52f8234dc5144c45fc847c0cd37a92d68e7c5ba7c648a8a339f171244");
1718
1719 let is_valid = api
1720 .bls12_381_pairing_equality(&ps, &qs, &BLS12_381_G1_GENERATOR, &s)
1721 .unwrap();
1722 assert!(is_valid);
1723 }
1724
1725 #[test]
1726 fn bls12_381_hash_to_g1_works() {
1727 let api = MockApi::default();
1730 let msg = b"abc";
1731 let dst = b"QUUX-V01-CS02-with-BLS12381G1_XMD:SHA-256_SSWU_RO_";
1732
1733 let hashed_point = api
1734 .bls12_381_hash_to_g1(HashFunction::Sha256, msg, dst)
1735 .unwrap();
1736 let mut serialized_expected_compressed = hex!("03567bc5ef9c690c2ab2ecdf6a96ef1c139cc0b2f284dca0a9a7943388a49a3aee664ba5379a7655d3c68900be2f6903");
1737 serialized_expected_compressed[0] |= 0b1000_0000;
1739
1740 assert_eq!(hashed_point, serialized_expected_compressed);
1741 }
1742
1743 #[test]
1744 fn bls12_381_hash_to_g2_works() {
1745 let api = MockApi::default();
1746 let msg = b"abc";
1747 let dst = b"QUUX-V01-CS02-with-BLS12381G2_XMD:SHA-256_SSWU_RO_";
1748
1749 let hashed_point = api
1750 .bls12_381_hash_to_g2(HashFunction::Sha256, msg, dst)
1751 .unwrap();
1752 let mut serialized_expected_compressed = hex!("139cddbccdc5e91b9623efd38c49f81a6f83f175e80b06fc374de9eb4b41dfe4ca3a230ed250fbe3a2acf73a41177fd802c2d18e033b960562aae3cab37a27ce00d80ccd5ba4b7fe0e7a210245129dbec7780ccc7954725f4168aff2787776e6");
1753 serialized_expected_compressed[0] |= 0b1000_0000;
1755
1756 assert_eq!(hashed_point, serialized_expected_compressed);
1757 }
1758
1759 #[test]
1760 fn bls12_318_pairing_equality_works() {
1761 fn build_bls_message(round: u64, previous_signature: &[u8]) -> Vec<u8> {
1762 Sha256::new()
1763 .chain_update(previous_signature)
1764 .chain_update(round.to_be_bytes())
1765 .finalize()
1766 .to_vec()
1767 }
1768
1769 let api = MockApi::default();
1770
1771 let previous_signature = hex::decode("a609e19a03c2fcc559e8dae14900aaefe517cb55c840f6e69bc8e4f66c8d18e8a609685d9917efbfb0c37f058c2de88f13d297c7e19e0ab24813079efe57a182554ff054c7638153f9b26a60e7111f71a0ff63d9571704905d3ca6df0b031747").unwrap();
1772 let signature = hex::decode("82f5d3d2de4db19d40a6980e8aa37842a0e55d1df06bd68bddc8d60002e8e959eb9cfa368b3c1b77d18f02a54fe047b80f0989315f83b12a74fd8679c4f12aae86eaf6ab5690b34f1fddd50ee3cc6f6cdf59e95526d5a5d82aaa84fa6f181e42").unwrap();
1773 let round: u64 = 72785;
1774
1775 let msg = build_bls_message(round, &previous_signature);
1776 let msg_point = api
1777 .bls12_381_hash_to_g2(HashFunction::Sha256, &msg, DOMAIN_HASH_TO_G2)
1778 .unwrap();
1779
1780 let is_valid = api
1781 .bls12_381_pairing_equality(
1782 &BLS12_381_G1_GENERATOR,
1783 &signature,
1784 &PK_LEO_MAINNET,
1785 &msg_point,
1786 )
1787 .unwrap();
1788
1789 assert!(is_valid);
1790 }
1791
1792 #[test]
1794 fn secp256k1_verify_works() {
1795 let api = MockApi::default();
1796
1797 let hash = hex::decode(SECP256K1_MSG_HASH_HEX).unwrap();
1798 let signature = hex::decode(SECP256K1_SIG_HEX).unwrap();
1799 let public_key = hex::decode(SECP256K1_PUBKEY_HEX).unwrap();
1800
1801 assert!(api
1802 .secp256k1_verify(&hash, &signature, &public_key)
1803 .unwrap());
1804 }
1805
1806 #[test]
1808 fn secp256k1_verify_fails() {
1809 let api = MockApi::default();
1810
1811 let mut hash = hex::decode(SECP256K1_MSG_HASH_HEX).unwrap();
1812 hash[0] ^= 0x01;
1814 let signature = hex::decode(SECP256K1_SIG_HEX).unwrap();
1815 let public_key = hex::decode(SECP256K1_PUBKEY_HEX).unwrap();
1816
1817 assert!(!api
1818 .secp256k1_verify(&hash, &signature, &public_key)
1819 .unwrap());
1820 }
1821
1822 #[test]
1824 fn secp256k1_verify_errs() {
1825 let api = MockApi::default();
1826
1827 let hash = hex::decode(SECP256K1_MSG_HASH_HEX).unwrap();
1828 let signature = hex::decode(SECP256K1_SIG_HEX).unwrap();
1829 let public_key = vec![];
1830
1831 let res = api.secp256k1_verify(&hash, &signature, &public_key);
1832 assert_eq!(res.unwrap_err(), VerificationError::InvalidPubkeyFormat);
1833 }
1834
1835 #[test]
1836 fn secp256k1_recover_pubkey_works() {
1837 let api = MockApi::default();
1838
1839 let hash = hex!("5ae8317d34d1e595e3fa7247db80c0af4320cce1116de187f8f7e2e099c0d8d0");
1841 let signature = hex!("45c0b7f8c09a9e1f1cea0c25785594427b6bf8f9f878a8af0b1abbb48e16d0920d8becd0c220f67c51217eecfd7184ef0732481c843857e6bc7fc095c4f6b788");
1842 let recovery_param = 1;
1843 let expected = hex!("044a071e8a6e10aada2b8cf39fa3b5fb3400b04e99ea8ae64ceea1a977dbeaf5d5f8c8fbd10b71ab14cd561f7df8eb6da50f8a8d81ba564342244d26d1d4211595");
1844
1845 let pubkey = api
1846 .secp256k1_recover_pubkey(&hash, &signature, recovery_param)
1847 .unwrap();
1848 assert_eq!(pubkey, expected);
1849 }
1850
1851 #[test]
1852 fn secp256k1_recover_pubkey_fails_for_wrong_recovery_param() {
1853 let api = MockApi::default();
1854
1855 let hash = hex!("5ae8317d34d1e595e3fa7247db80c0af4320cce1116de187f8f7e2e099c0d8d0");
1857 let signature = hex!("45c0b7f8c09a9e1f1cea0c25785594427b6bf8f9f878a8af0b1abbb48e16d0920d8becd0c220f67c51217eecfd7184ef0732481c843857e6bc7fc095c4f6b788");
1858 let _recovery_param = 1;
1859 let expected = hex!("044a071e8a6e10aada2b8cf39fa3b5fb3400b04e99ea8ae64ceea1a977dbeaf5d5f8c8fbd10b71ab14cd561f7df8eb6da50f8a8d81ba564342244d26d1d4211595");
1860
1861 let pubkey = api.secp256k1_recover_pubkey(&hash, &signature, 0).unwrap();
1863 assert_eq!(pubkey.len(), 65);
1864 assert_ne!(pubkey, expected);
1865
1866 let result = api.secp256k1_recover_pubkey(&hash, &signature, 42);
1868 match result.unwrap_err() {
1869 RecoverPubkeyError::InvalidRecoveryParam => {}
1870 err => panic!("Unexpected error: {err:?}"),
1871 }
1872 }
1873
1874 #[test]
1875 fn secp256k1_recover_pubkey_fails_for_wrong_hash() {
1876 let api = MockApi::default();
1877
1878 let hash = hex!("5ae8317d34d1e595e3fa7247db80c0af4320cce1116de187f8f7e2e099c0d8d0");
1880 let signature = hex!("45c0b7f8c09a9e1f1cea0c25785594427b6bf8f9f878a8af0b1abbb48e16d0920d8becd0c220f67c51217eecfd7184ef0732481c843857e6bc7fc095c4f6b788");
1881 let recovery_param = 1;
1882 let expected = hex!("044a071e8a6e10aada2b8cf39fa3b5fb3400b04e99ea8ae64ceea1a977dbeaf5d5f8c8fbd10b71ab14cd561f7df8eb6da50f8a8d81ba564342244d26d1d4211595");
1883
1884 let mut corrupted_hash = hash;
1886 corrupted_hash[0] ^= 0x01;
1887 let pubkey = api
1888 .secp256k1_recover_pubkey(&corrupted_hash, &signature, recovery_param)
1889 .unwrap();
1890 assert_eq!(pubkey.len(), 65);
1891 assert_ne!(pubkey, expected);
1892
1893 let mut malformed_hash = hash.to_vec();
1895 malformed_hash.push(0x8a);
1896 let result = api.secp256k1_recover_pubkey(&malformed_hash, &signature, recovery_param);
1897 match result.unwrap_err() {
1898 RecoverPubkeyError::InvalidHashFormat => {}
1899 err => panic!("Unexpected error: {err:?}"),
1900 }
1901 }
1902
1903 #[test]
1905 fn secp256r1_verify_works() {
1906 let api = MockApi::default();
1907
1908 let hash = hex::decode(SECP256R1_MSG_HASH_HEX).unwrap();
1909 let signature = hex::decode(SECP256R1_SIG_HEX).unwrap();
1910 let public_key = hex::decode(SECP256R1_PUBKEY_HEX).unwrap();
1911
1912 assert!(api
1913 .secp256r1_verify(&hash, &signature, &public_key)
1914 .unwrap());
1915 }
1916
1917 #[test]
1919 fn secp256r1_verify_fails() {
1920 let api = MockApi::default();
1921
1922 let mut hash = hex::decode(SECP256R1_MSG_HASH_HEX).unwrap();
1923 hash[0] ^= 0x01;
1925 let signature = hex::decode(SECP256R1_SIG_HEX).unwrap();
1926 let public_key = hex::decode(SECP256R1_PUBKEY_HEX).unwrap();
1927
1928 assert!(!api
1929 .secp256r1_verify(&hash, &signature, &public_key)
1930 .unwrap());
1931 }
1932
1933 #[test]
1935 fn secp256r1_verify_errs() {
1936 let api = MockApi::default();
1937
1938 let hash = hex::decode(SECP256R1_MSG_HASH_HEX).unwrap();
1939 let signature = hex::decode(SECP256R1_SIG_HEX).unwrap();
1940 let public_key = vec![];
1941
1942 let res = api.secp256r1_verify(&hash, &signature, &public_key);
1943 assert_eq!(res.unwrap_err(), VerificationError::InvalidPubkeyFormat);
1944 }
1945
1946 #[test]
1947 fn secp256r1_recover_pubkey_works() {
1948 let api = MockApi::default();
1949
1950 let hash = hex!("17b03f9f00f6692ccdde485fc63c4530751ef35da6f71336610944b0894fcfb8");
1951 let signature = hex!("9886ae46c1415c3bc959e82b760ad760aab66885a84e620aa339fdf102465c422bf3a80bc04faa35ebecc0f4864ac02d349f6f126e0f988501b8d3075409a26c");
1952 let recovery_param = 0;
1953 let expected = hex!("0451f99d2d52d4a6e734484a018b7ca2f895c2929b6754a3a03224d07ae61166ce4737da963c6ef7247fb88d19f9b0c667cac7fe12837fdab88c66f10d3c14cad1");
1954
1955 let pubkey = api
1956 .secp256r1_recover_pubkey(&hash, &signature, recovery_param)
1957 .unwrap();
1958 assert_eq!(pubkey, expected);
1959 }
1960
1961 #[test]
1962 fn secp256r1_recover_pubkey_fails_for_wrong_recovery_param() {
1963 let api = MockApi::default();
1964
1965 let hash = hex!("17b03f9f00f6692ccdde485fc63c4530751ef35da6f71336610944b0894fcfb8");
1966 let signature = hex!("9886ae46c1415c3bc959e82b760ad760aab66885a84e620aa339fdf102465c422bf3a80bc04faa35ebecc0f4864ac02d349f6f126e0f988501b8d3075409a26c");
1967 let expected = hex!("0451f99d2d52d4a6e734484a018b7ca2f895c2929b6754a3a03224d07ae61166ce4737da963c6ef7247fb88d19f9b0c667cac7fe12837fdab88c66f10d3c14cad1");
1968
1969 let pubkey = api.secp256r1_recover_pubkey(&hash, &signature, 1).unwrap();
1971 assert_eq!(pubkey.len(), 65);
1972 assert_ne!(pubkey, expected);
1973
1974 let result = api.secp256r1_recover_pubkey(&hash, &signature, 42);
1976 match result.unwrap_err() {
1977 RecoverPubkeyError::InvalidRecoveryParam => {}
1978 err => panic!("Unexpected error: {err:?}"),
1979 }
1980 }
1981
1982 #[test]
1983 fn secp256r1_recover_pubkey_fails_for_wrong_hash() {
1984 let api = MockApi::default();
1985
1986 let hash = hex!("17b03f9f00f6692ccdde485fc63c4530751ef35da6f71336610944b0894fcfb8");
1987 let signature = hex!("9886ae46c1415c3bc959e82b760ad760aab66885a84e620aa339fdf102465c422bf3a80bc04faa35ebecc0f4864ac02d349f6f126e0f988501b8d3075409a26c");
1988 let recovery_param = 0;
1989 let expected = hex!("0451f99d2d52d4a6e734484a018b7ca2f895c2929b6754a3a03224d07ae61166ce4737da963c6ef7247fb88d19f9b0c667cac7fe12837fdab88c66f10d3c14cad1");
1990
1991 let mut corrupted_hash = hash;
1993 corrupted_hash[0] ^= 0x01;
1994 let pubkey = api
1995 .secp256r1_recover_pubkey(&corrupted_hash, &signature, recovery_param)
1996 .unwrap();
1997 assert_eq!(pubkey.len(), 65);
1998 assert_ne!(pubkey, expected);
1999
2000 let mut malformed_hash = hash.to_vec();
2002 malformed_hash.push(0x8a);
2003 let result = api.secp256r1_recover_pubkey(&malformed_hash, &signature, recovery_param);
2004 match result.unwrap_err() {
2005 RecoverPubkeyError::InvalidHashFormat => {}
2006 err => panic!("Unexpected error: {err:?}"),
2007 }
2008 }
2009
2010 #[test]
2012 fn ed25519_verify_works() {
2013 let api = MockApi::default();
2014
2015 let msg = hex::decode(ED25519_MSG_HEX).unwrap();
2016 let signature = hex::decode(ED25519_SIG_HEX).unwrap();
2017 let public_key = hex::decode(ED25519_PUBKEY_HEX).unwrap();
2018
2019 assert!(api.ed25519_verify(&msg, &signature, &public_key).unwrap());
2020 }
2021
2022 #[test]
2024 fn ed25519_verify_fails() {
2025 let api = MockApi::default();
2026
2027 let mut msg = hex::decode(ED25519_MSG_HEX).unwrap();
2028 msg[0] ^= 0x01;
2030 let signature = hex::decode(ED25519_SIG_HEX).unwrap();
2031 let public_key = hex::decode(ED25519_PUBKEY_HEX).unwrap();
2032
2033 assert!(!api.ed25519_verify(&msg, &signature, &public_key).unwrap());
2034 }
2035
2036 #[test]
2038 fn ed25519_verify_errs() {
2039 let api = MockApi::default();
2040
2041 let msg = hex::decode(ED25519_MSG_HEX).unwrap();
2042 let signature = hex::decode(ED25519_SIG_HEX).unwrap();
2043 let public_key = vec![];
2044
2045 let res = api.ed25519_verify(&msg, &signature, &public_key);
2046 assert_eq!(res.unwrap_err(), VerificationError::InvalidPubkeyFormat);
2047 }
2048
2049 #[test]
2051 fn ed25519_batch_verify_works() {
2052 let api = MockApi::default();
2053
2054 let msg = hex::decode(ED25519_MSG_HEX).unwrap();
2055 let signature = hex::decode(ED25519_SIG_HEX).unwrap();
2056 let public_key = hex::decode(ED25519_PUBKEY_HEX).unwrap();
2057
2058 let msgs: Vec<&[u8]> = vec![&msg];
2059 let signatures: Vec<&[u8]> = vec![&signature];
2060 let public_keys: Vec<&[u8]> = vec![&public_key];
2061
2062 assert!(api
2063 .ed25519_batch_verify(&msgs, &signatures, &public_keys)
2064 .unwrap());
2065 }
2066
2067 #[test]
2069 fn ed25519_batch_verify_fails() {
2070 let api = MockApi::default();
2071
2072 let mut msg = hex::decode(ED25519_MSG_HEX).unwrap();
2073 msg[0] ^= 0x01;
2075 let signature = hex::decode(ED25519_SIG_HEX).unwrap();
2076 let public_key = hex::decode(ED25519_PUBKEY_HEX).unwrap();
2077
2078 let msgs: Vec<&[u8]> = vec![&msg];
2079 let signatures: Vec<&[u8]> = vec![&signature];
2080 let public_keys: Vec<&[u8]> = vec![&public_key];
2081
2082 assert!(!api
2083 .ed25519_batch_verify(&msgs, &signatures, &public_keys)
2084 .unwrap());
2085 }
2086
2087 #[test]
2089 fn ed25519_batch_verify_errs() {
2090 let api = MockApi::default();
2091
2092 let msg = hex::decode(ED25519_MSG_HEX).unwrap();
2093 let signature = hex::decode(ED25519_SIG_HEX).unwrap();
2094 let public_key: Vec<u8> = vec![0u8; 0];
2095
2096 let msgs: Vec<&[u8]> = vec![msg.as_slice()];
2097 let signatures: Vec<&[u8]> = vec![signature.as_slice()];
2098 let public_keys: Vec<&[u8]> = vec![&public_key];
2099
2100 let res = api.ed25519_batch_verify(&msgs, &signatures, &public_keys);
2101 assert_eq!(res.unwrap_err(), VerificationError::InvalidPubkeyFormat);
2102 }
2103
2104 #[cfg(feature = "cosmwasm_1_1")]
2105 #[test]
2106 fn bank_querier_supply() {
2107 let addr1 = String::from("foo");
2108 let balance1 = vec![coin(123, "ELF"), coin(777, "FLY")];
2109
2110 let addr2 = String::from("bar");
2111 let balance2 = coins(321, "ELF");
2112
2113 let bank = BankQuerier::new(&[(&addr1, &balance1), (&addr2, &balance2)]);
2114
2115 let elf = bank
2116 .query(&BankQuery::Supply {
2117 denom: "ELF".to_string(),
2118 })
2119 .unwrap()
2120 .unwrap();
2121 let res: SupplyResponse = from_json(elf).unwrap();
2122 assert_eq!(res.amount, coin(444, "ELF"));
2123
2124 let fly = bank
2125 .query(&BankQuery::Supply {
2126 denom: "FLY".to_string(),
2127 })
2128 .unwrap()
2129 .unwrap();
2130 let res: SupplyResponse = from_json(fly).unwrap();
2131 assert_eq!(res.amount, coin(777, "FLY"));
2132
2133 let atom = bank
2135 .query(&BankQuery::Supply {
2136 denom: "ATOM".to_string(),
2137 })
2138 .unwrap()
2139 .unwrap();
2140 let res: SupplyResponse = from_json(atom).unwrap();
2141 assert_eq!(res.amount, coin(0, "ATOM"));
2142 }
2143
2144 #[test]
2145 fn bank_querier_one_balance() {
2146 let addr = String::from("foobar");
2147 let balance = vec![coin(123, "ELF"), coin(777, "FLY")];
2148 let bank = BankQuerier::new(&[(&addr, &balance)]);
2149
2150 let fly = bank
2152 .query(&BankQuery::Balance {
2153 address: addr.clone(),
2154 denom: "FLY".to_string(),
2155 })
2156 .unwrap()
2157 .unwrap();
2158 let res: BalanceResponse = from_json(fly).unwrap();
2159 assert_eq!(res.amount, coin(777, "FLY"));
2160
2161 let miss = bank
2163 .query(&BankQuery::Balance {
2164 address: addr,
2165 denom: "MISS".to_string(),
2166 })
2167 .unwrap()
2168 .unwrap();
2169 let res: BalanceResponse = from_json(miss).unwrap();
2170 assert_eq!(res.amount, coin(0, "MISS"));
2171 }
2172
2173 #[test]
2174 #[allow(deprecated)]
2175 fn bank_querier_missing_account() {
2176 let addr = String::from("foobar");
2177 let balance = vec![coin(123, "ELF"), coin(777, "FLY")];
2178 let bank = BankQuerier::new(&[(&addr, &balance)]);
2179
2180 let miss = bank
2182 .query(&BankQuery::Balance {
2183 address: String::from("elsewhere"),
2184 denom: "ELF".to_string(),
2185 })
2186 .unwrap()
2187 .unwrap();
2188 let res: BalanceResponse = from_json(miss).unwrap();
2189 assert_eq!(res.amount, coin(0, "ELF"));
2190 }
2191
2192 #[cfg(feature = "cosmwasm_1_3")]
2193 #[test]
2194 fn bank_querier_metadata_works() {
2195 let mut bank = BankQuerier::new(&[]);
2196 bank.set_denom_metadata(
2197 &(0..100)
2198 .map(|i| DenomMetadata {
2199 symbol: format!("FOO{i}"),
2200 name: "Foo".to_string(),
2201 description: "Foo coin".to_string(),
2202 denom_units: vec![DenomUnit {
2203 denom: "ufoo".to_string(),
2204 exponent: 8,
2205 aliases: vec!["microfoo".to_string(), "foobar".to_string()],
2206 }],
2207 display: "FOO".to_string(),
2208 base: format!("ufoo{i}"),
2209 uri: "https://foo.bar".to_string(),
2210 uri_hash: "foo".to_string(),
2211 })
2212 .collect::<Vec<_>>(),
2213 );
2214
2215 let res = bank
2217 .query(&BankQuery::AllDenomMetadata {
2218 pagination: Some(PageRequest {
2219 key: None,
2220 limit: 10,
2221 reverse: false,
2222 }),
2223 })
2224 .unwrap()
2225 .unwrap();
2226 let res: AllDenomMetadataResponse = from_json(res).unwrap();
2227 assert_eq!(res.metadata.len(), 10);
2228 assert!(res.next_key.is_some());
2229
2230 let res2 = bank
2232 .query(&BankQuery::AllDenomMetadata {
2233 pagination: Some(PageRequest {
2234 key: res.next_key,
2235 limit: 10,
2236 reverse: false,
2237 }),
2238 })
2239 .unwrap()
2240 .unwrap();
2241 let res2: AllDenomMetadataResponse = from_json(res2).unwrap();
2242 assert_eq!(res2.metadata.len(), 10);
2243 assert_ne!(res.metadata.last(), res2.metadata.first());
2244 for m in res.metadata {
2246 assert!(!res2.metadata.contains(&m));
2247 }
2248
2249 let res = bank
2251 .query(&BankQuery::AllDenomMetadata {
2252 pagination: Some(PageRequest {
2253 key: None,
2254 limit: 100,
2255 reverse: true,
2256 }),
2257 })
2258 .unwrap()
2259 .unwrap();
2260 let res: AllDenomMetadataResponse = from_json(res).unwrap();
2261 assert_eq!(res.metadata.len(), 100);
2262 assert!(res.next_key.is_none(), "no more data should be available");
2263 assert_eq!(res.metadata[0].symbol, "FOO99", "should have been reversed");
2264
2265 let more_res = bank
2266 .query(&BankQuery::AllDenomMetadata {
2267 pagination: Some(PageRequest {
2268 key: res.next_key,
2269 limit: u32::MAX,
2270 reverse: true,
2271 }),
2272 })
2273 .unwrap()
2274 .unwrap();
2275 let more_res: AllDenomMetadataResponse = from_json(more_res).unwrap();
2276 assert_eq!(
2277 more_res.metadata, res.metadata,
2278 "should be same as previous query"
2279 );
2280 }
2281
2282 #[cfg(feature = "cosmwasm_1_3")]
2283 #[test]
2284 fn distribution_querier_delegator_withdraw_address() {
2285 let mut distribution = DistributionQuerier::default();
2286 distribution.set_withdraw_address("addr0", "withdraw0");
2287
2288 let query = DistributionQuery::DelegatorWithdrawAddress {
2289 delegator_address: "addr0".to_string(),
2290 };
2291
2292 let res = distribution.query(&query).unwrap().unwrap();
2293 let res: DelegatorWithdrawAddressResponse = from_json(res).unwrap();
2294 assert_eq!(res.withdraw_address.as_str(), "withdraw0");
2295
2296 let query = DistributionQuery::DelegatorWithdrawAddress {
2297 delegator_address: "addr1".to_string(),
2298 };
2299
2300 let res = distribution.query(&query).unwrap().unwrap();
2301 let res: DelegatorWithdrawAddressResponse = from_json(res).unwrap();
2302 assert_eq!(res.withdraw_address.as_str(), "addr1");
2303 }
2304
2305 #[cfg(feature = "cosmwasm_1_4")]
2306 #[test]
2307 fn distribution_querier_delegator_validators() {
2308 let mut distribution = DistributionQuerier::default();
2309 distribution.set_validators("addr0", ["valoper1", "valoper2"]);
2310
2311 let query = DistributionQuery::DelegatorValidators {
2312 delegator_address: "addr0".to_string(),
2313 };
2314
2315 let res = distribution.query(&query).unwrap().unwrap();
2316 let res: DelegatorValidatorsResponse = from_json(res).unwrap();
2317 assert_eq!(res.validators, ["valoper1", "valoper2"]);
2318
2319 let query = DistributionQuery::DelegatorValidators {
2320 delegator_address: "addr1".to_string(),
2321 };
2322
2323 let res = distribution.query(&query).unwrap().unwrap();
2324 let res: DelegatorValidatorsResponse = from_json(res).unwrap();
2325 assert_eq!(res.validators, ([] as [String; 0]));
2326 }
2327
2328 #[cfg(feature = "cosmwasm_1_4")]
2329 #[test]
2330 fn distribution_querier_delegation_rewards() {
2331 use crate::{Decimal256, DelegationTotalRewardsResponse, DelegatorReward};
2332
2333 let mut distribution = DistributionQuerier::default();
2334 let valoper0_rewards = vec![
2335 DecCoin::new(Decimal256::from_atomics(1234u128, 0).unwrap(), "uatom"),
2336 DecCoin::new(Decimal256::from_atomics(56781234u128, 4).unwrap(), "utest"),
2337 ];
2338 distribution.set_rewards("valoper0", "addr0", valoper0_rewards.clone());
2339
2340 let query = DistributionQuery::DelegationRewards {
2342 delegator_address: "addr0".to_string(),
2343 validator_address: "valoper0".to_string(),
2344 };
2345 let res = distribution.query(&query).unwrap().unwrap();
2346 let res: DelegationRewardsResponse = from_json(res).unwrap();
2347 assert_eq!(res.rewards, valoper0_rewards);
2348
2349 let query = DistributionQuery::DelegationRewards {
2351 delegator_address: "nonexistent".to_string(),
2352 validator_address: "valoper0".to_string(),
2353 };
2354 let res = distribution.query(&query).unwrap().unwrap();
2355 let res: DelegationRewardsResponse = from_json(res).unwrap();
2356 assert_eq!(res.rewards.len(), 0);
2357
2358 let query = DistributionQuery::DelegationRewards {
2360 delegator_address: "addr0".to_string(),
2361 validator_address: "valopernonexistent".to_string(),
2362 };
2363 let res = distribution.query(&query).unwrap().unwrap();
2364 let res: DelegationRewardsResponse = from_json(res).unwrap();
2365 assert_eq!(res.rewards.len(), 0);
2366
2367 let valoper1_rewards = vec![DecCoin::new(Decimal256::one(), "uatom")];
2369 distribution.set_rewards("valoper1", "addr0", valoper1_rewards.clone());
2370
2371 let query = DistributionQuery::DelegationTotalRewards {
2373 delegator_address: "addr0".to_string(),
2374 };
2375 let res = distribution.query(&query).unwrap().unwrap();
2376 let res: DelegationTotalRewardsResponse = from_json(res).unwrap();
2377 assert_eq!(
2378 res.rewards,
2379 vec![
2380 DelegatorReward {
2381 validator_address: "valoper0".into(),
2382 reward: valoper0_rewards
2383 },
2384 DelegatorReward {
2385 validator_address: "valoper1".into(),
2386 reward: valoper1_rewards
2387 },
2388 ]
2389 );
2390 assert_eq!(
2391 res.total,
2392 [
2393 DecCoin::new(
2394 Decimal256::from_atomics(1234u128, 0).unwrap() + Decimal256::one(),
2395 "uatom"
2396 ),
2397 DecCoin::new(Decimal256::from_atomics(56781234u128, 4).unwrap(), "utest")
2399 ]
2400 );
2401 }
2402
2403 #[cfg(feature = "stargate")]
2404 #[test]
2405 fn ibc_querier_channel_existing() {
2406 let chan1 = mock_ibc_channel("channel-0", IbcOrder::Ordered, "ibc");
2407 let chan2 = mock_ibc_channel("channel-1", IbcOrder::Ordered, "ibc");
2408
2409 let ibc = IbcQuerier::new("myport", &[chan1.clone(), chan2]);
2410
2411 let query = &IbcQuery::Channel {
2413 channel_id: "channel-0".to_string(),
2414 port_id: Some("my_port".to_string()),
2415 };
2416 let raw = ibc.query(query).unwrap().unwrap();
2417 let chan: ChannelResponse = from_json(raw).unwrap();
2418 assert_eq!(chan.channel, Some(chan1));
2419 }
2420
2421 #[cfg(feature = "stargate")]
2422 #[test]
2423 fn ibc_querier_channel_existing_no_port() {
2424 let chan1 = IbcChannel {
2425 endpoint: IbcEndpoint {
2426 port_id: "myport".to_string(),
2427 channel_id: "channel-0".to_string(),
2428 },
2429 counterparty_endpoint: IbcEndpoint {
2430 port_id: "their_port".to_string(),
2431 channel_id: "channel-7".to_string(),
2432 },
2433 order: IbcOrder::Ordered,
2434 version: "ibc".to_string(),
2435 connection_id: "connection-2".to_string(),
2436 };
2437 let chan2 = mock_ibc_channel("channel-1", IbcOrder::Ordered, "ibc");
2438
2439 let ibc = IbcQuerier::new("myport", &[chan1.clone(), chan2]);
2440
2441 let query = &IbcQuery::Channel {
2443 channel_id: "channel-0".to_string(),
2444 port_id: Some("myport".to_string()),
2445 };
2446 let raw = ibc.query(query).unwrap().unwrap();
2447 let chan: ChannelResponse = from_json(raw).unwrap();
2448 assert_eq!(chan.channel, Some(chan1));
2449 }
2450
2451 #[cfg(feature = "stargate")]
2452 #[test]
2453 fn ibc_querier_channel_none() {
2454 let chan1 = mock_ibc_channel("channel-0", IbcOrder::Ordered, "ibc");
2455 let chan2 = mock_ibc_channel("channel-1", IbcOrder::Ordered, "ibc");
2456
2457 let ibc = IbcQuerier::new("myport", &[chan1, chan2]);
2458
2459 let query = &IbcQuery::Channel {
2461 channel_id: "channel-0".to_string(),
2462 port_id: None,
2463 };
2464 let raw = ibc.query(query).unwrap().unwrap();
2465 let chan: ChannelResponse = from_json(raw).unwrap();
2466 assert_eq!(chan.channel, None);
2467 }
2468
2469 #[cfg(feature = "stargate")]
2470 #[test]
2471 fn ibc_querier_port() {
2472 let chan1 = mock_ibc_channel("channel-0", IbcOrder::Ordered, "ibc");
2473
2474 let ibc = IbcQuerier::new("myport", &[chan1]);
2475
2476 let query = &IbcQuery::PortId {};
2478 let raw = ibc.query(query).unwrap().unwrap();
2479 let res: PortIdResponse = from_json(raw).unwrap();
2480 assert_eq!(res.port_id, "myport");
2481 }
2482
2483 #[cfg(feature = "staking")]
2484 #[test]
2485 fn staking_querier_all_validators() {
2486 let val1 = Validator {
2487 address: String::from("validator-one"),
2488 commission: Decimal::percent(1),
2489 max_commission: Decimal::percent(3),
2490 max_change_rate: Decimal::percent(1),
2491 };
2492 let val2 = Validator {
2493 address: String::from("validator-two"),
2494 commission: Decimal::permille(15),
2495 max_commission: Decimal::permille(40),
2496 max_change_rate: Decimal::permille(5),
2497 };
2498
2499 let staking = StakingQuerier::new("ustake", &[val1.clone(), val2.clone()], &[]);
2500
2501 let raw = staking
2503 .query(&StakingQuery::AllValidators {})
2504 .unwrap()
2505 .unwrap();
2506 let vals: AllValidatorsResponse = from_json(raw).unwrap();
2507 assert_eq!(vals.validators, vec![val1.into(), val2.into()]);
2508 }
2509
2510 #[cfg(feature = "staking")]
2511 #[test]
2512 fn staking_querier_validator() {
2513 let address1 = String::from("validator-one");
2514 let address2 = String::from("validator-two");
2515 let address_non_existent = String::from("wannabe-validator");
2516
2517 let val1 = Validator {
2518 address: address1.clone(),
2519 commission: Decimal::percent(1),
2520 max_commission: Decimal::percent(3),
2521 max_change_rate: Decimal::percent(1),
2522 };
2523 let val2 = Validator {
2524 address: address2.clone(),
2525 commission: Decimal::permille(15),
2526 max_commission: Decimal::permille(40),
2527 max_change_rate: Decimal::permille(5),
2528 };
2529
2530 let staking = StakingQuerier::new("ustake", &[val1.clone(), val2.clone()], &[]);
2531
2532 let raw = staking
2534 .query(&StakingQuery::Validator { address: address1 })
2535 .unwrap()
2536 .unwrap();
2537 let res: ValidatorResponse = from_json(raw).unwrap();
2538 assert_eq!(res.validator, Some(val1));
2539
2540 let raw = staking
2542 .query(&StakingQuery::Validator { address: address2 })
2543 .unwrap()
2544 .unwrap();
2545 let res: ValidatorResponse = from_json(raw).unwrap();
2546 assert_eq!(res.validator, Some(val2));
2547
2548 let raw = staking
2550 .query(&StakingQuery::Validator {
2551 address: address_non_existent,
2552 })
2553 .unwrap()
2554 .unwrap();
2555 let res: ValidatorResponse = from_json(raw).unwrap();
2556 assert_eq!(res.validator, None);
2557 }
2558
2559 #[cfg(feature = "staking")]
2560 fn get_all_delegators(
2562 staking: &StakingQuerier,
2563 delegator: impl Into<String>,
2564 ) -> Vec<Delegation> {
2565 let raw = staking
2566 .query(&StakingQuery::AllDelegations {
2567 delegator: delegator.into(),
2568 })
2569 .unwrap()
2570 .unwrap();
2571 let dels: AllDelegationsResponse = from_json(raw).unwrap();
2572 dels.delegations
2573 }
2574
2575 #[cfg(feature = "staking")]
2576 fn get_delegator(
2578 staking: &StakingQuerier,
2579 delegator: impl Into<String>,
2580 validator: impl Into<String>,
2581 ) -> Option<FullDelegation> {
2582 let raw = staking
2583 .query(&StakingQuery::Delegation {
2584 delegator: delegator.into(),
2585 validator: validator.into(),
2586 })
2587 .unwrap()
2588 .unwrap();
2589 let dels: DelegationResponse = from_json(raw).unwrap();
2590 dels.delegation
2591 }
2592
2593 #[cfg(feature = "staking")]
2594 #[test]
2595 fn staking_querier_delegations() {
2596 let val1 = String::from("validator-one");
2597 let val2 = String::from("validator-two");
2598
2599 let user_a = Addr::unchecked("investor");
2600 let user_b = Addr::unchecked("speculator");
2601 let user_c = Addr::unchecked("hodler");
2602
2603 let del1a = FullDelegation {
2605 delegator: user_a.clone(),
2606 validator: val1.clone(),
2607 amount: coin(100, "ustake"),
2608 can_redelegate: coin(100, "ustake"),
2609 accumulated_rewards: coins(5, "ustake"),
2610 };
2611 let del2a = FullDelegation {
2612 delegator: user_a.clone(),
2613 validator: val2.clone(),
2614 amount: coin(500, "ustake"),
2615 can_redelegate: coin(500, "ustake"),
2616 accumulated_rewards: coins(20, "ustake"),
2617 };
2618
2619 let del1b = FullDelegation {
2621 delegator: user_b.clone(),
2622 validator: val1.clone(),
2623 amount: coin(500, "ustake"),
2624 can_redelegate: coin(0, "ustake"),
2625 accumulated_rewards: coins(0, "ustake"),
2626 };
2627
2628 let del2c = FullDelegation {
2630 delegator: user_c.clone(),
2631 validator: val2.clone(),
2632 amount: coin(8888, "ustake"),
2633 can_redelegate: coin(4567, "ustake"),
2634 accumulated_rewards: coins(900, "ustake"),
2635 };
2636
2637 let staking = StakingQuerier::new(
2638 "ustake",
2639 &[],
2640 &[del1a.clone(), del1b.clone(), del2a.clone(), del2c.clone()],
2641 );
2642
2643 let dels = get_all_delegators(&staking, user_a.clone());
2645 assert_eq!(dels, vec![del1a.clone().into(), del2a.clone().into()]);
2646
2647 let dels = get_all_delegators(&staking, user_b.clone());
2649 assert_eq!(dels, vec![del1b.clone().into()]);
2650
2651 let dels = get_all_delegators(&staking, user_c.clone());
2653 assert_eq!(dels, vec![del2c.clone().into()]);
2654
2655 let dels = get_all_delegators(&staking, String::from("no one"));
2657 assert_eq!(dels, vec![]);
2658
2659 let dels = get_delegator(&staking, user_a.clone(), val1.clone());
2661 assert_eq!(dels, Some(del1a));
2662 let dels = get_delegator(&staking, user_a, val2.clone());
2663 assert_eq!(dels, Some(del2a));
2664
2665 let dels = get_delegator(&staking, user_b.clone(), val1.clone());
2667 assert_eq!(dels, Some(del1b));
2668 let dels = get_delegator(&staking, user_b, val2.clone());
2669 assert_eq!(dels, None);
2670
2671 let dels = get_delegator(&staking, user_c.clone(), val1);
2673 assert_eq!(dels, None);
2674 let dels = get_delegator(&staking, user_c, val2);
2675 assert_eq!(dels, Some(del2c));
2676 }
2677
2678 #[test]
2679 fn wasm_querier_works() {
2680 let mut querier = WasmQuerier::default();
2681
2682 let any_addr = "foo".to_string();
2683
2684 let system_err = querier
2686 .query(&WasmQuery::Raw {
2687 contract_addr: any_addr.clone(),
2688 key: b"the key".into(),
2689 })
2690 .unwrap_err();
2691 match system_err {
2692 SystemError::NoSuchContract { addr } => assert_eq!(addr, any_addr),
2693 err => panic!("Unexpected error: {err:?}"),
2694 }
2695
2696 let system_err = querier
2698 .query(&WasmQuery::Smart {
2699 contract_addr: any_addr.clone(),
2700 msg: b"{}".into(),
2701 })
2702 .unwrap_err();
2703 match system_err {
2704 SystemError::NoSuchContract { addr } => assert_eq!(addr, any_addr),
2705 err => panic!("Unexpected error: {err:?}"),
2706 }
2707
2708 let system_err = querier
2710 .query(&WasmQuery::ContractInfo {
2711 contract_addr: any_addr.clone(),
2712 })
2713 .unwrap_err();
2714 match system_err {
2715 SystemError::NoSuchContract { addr } => assert_eq!(addr, any_addr),
2716 err => panic!("Unexpected error: {err:?}"),
2717 }
2718
2719 #[cfg(feature = "cosmwasm_1_2")]
2720 {
2721 let system_err = querier
2723 .query(&WasmQuery::CodeInfo { code_id: 4 })
2724 .unwrap_err();
2725 match system_err {
2726 SystemError::NoSuchCode { code_id } => assert_eq!(code_id, 4),
2727 err => panic!("Unexpected error: {err:?}"),
2728 }
2729 }
2730
2731 #[cfg(all(feature = "cosmwasm_3_0", feature = "iterator"))]
2732 {
2733 let system_err = querier
2735 .query(&WasmQuery::RawRange {
2736 contract_addr: any_addr.clone(),
2737 start: None,
2738 end: None,
2739 limit: 10,
2740 order: crate::Order::Ascending,
2741 })
2742 .unwrap_err();
2743 match system_err {
2744 SystemError::NoSuchContract { addr } => assert_eq!(addr, any_addr),
2745 err => panic!("Unexpected error: {err:?}"),
2746 }
2747 }
2748
2749 querier.update_handler(|request| {
2750 let api = MockApi::default();
2751 let contract1 = api.addr_make("contract1");
2752 let mut storage1 = MockStorage::new();
2753 storage1.set(b"the key", b"the value");
2754
2755 match request {
2756 WasmQuery::Raw { contract_addr, key } => {
2757 let Ok(addr) = api.addr_validate(contract_addr) else {
2758 return SystemResult::Err(SystemError::NoSuchContract {
2759 addr: contract_addr.clone(),
2760 });
2761 };
2762 if addr == contract1 {
2763 if let Some(value) = storage1.get(key) {
2764 SystemResult::Ok(ContractResult::Ok(Binary::new(value)))
2765 } else {
2766 SystemResult::Ok(ContractResult::Ok(Binary::default()))
2767 }
2768 } else {
2769 SystemResult::Err(SystemError::NoSuchContract {
2770 addr: contract_addr.clone(),
2771 })
2772 }
2773 }
2774 WasmQuery::Smart { contract_addr, msg } => {
2775 let Ok(addr) = api.addr_validate(contract_addr) else {
2776 return SystemResult::Err(SystemError::NoSuchContract {
2777 addr: contract_addr.clone(),
2778 });
2779 };
2780 if addr == contract1 {
2781 #[derive(Deserialize)]
2782 struct MyMsg {}
2783 let _msg: MyMsg = match from_json(msg) {
2784 Ok(msg) => msg,
2785 Err(err) => {
2786 return SystemResult::Ok(ContractResult::Err(err.to_string()))
2787 }
2788 };
2789 let response: Response = Response::new().set_data(b"good");
2790 SystemResult::Ok(ContractResult::Ok(to_json_binary(&response).unwrap()))
2791 } else {
2792 SystemResult::Err(SystemError::NoSuchContract {
2793 addr: contract_addr.clone(),
2794 })
2795 }
2796 }
2797 WasmQuery::ContractInfo { contract_addr } => {
2798 let Ok(addr) = api.addr_validate(contract_addr) else {
2799 return SystemResult::Err(SystemError::NoSuchContract {
2800 addr: contract_addr.clone(),
2801 });
2802 };
2803 if addr == contract1 {
2804 let response = ContractInfoResponse {
2805 code_id: 4,
2806 creator: Addr::unchecked("lalala"),
2807 admin: None,
2808 pinned: false,
2809 ibc_port: None,
2810 ibc2_port: None,
2811 };
2812 SystemResult::Ok(ContractResult::Ok(to_json_binary(&response).unwrap()))
2813 } else {
2814 SystemResult::Err(SystemError::NoSuchContract {
2815 addr: contract_addr.clone(),
2816 })
2817 }
2818 }
2819 #[cfg(feature = "cosmwasm_1_2")]
2820 WasmQuery::CodeInfo { code_id } => {
2821 use crate::{Checksum, CodeInfoResponse};
2822 let code_id = *code_id;
2823 if code_id == 4 {
2824 let response = CodeInfoResponse {
2825 code_id,
2826 creator: Addr::unchecked("lalala"),
2827 checksum: Checksum::from_hex(
2828 "84cf20810fd429caf58898c3210fcb71759a27becddae08dbde8668ea2f4725d",
2829 )
2830 .unwrap(),
2831 };
2832 SystemResult::Ok(ContractResult::Ok(to_json_binary(&response).unwrap()))
2833 } else {
2834 SystemResult::Err(SystemError::NoSuchCode { code_id })
2835 }
2836 }
2837 #[cfg(all(feature = "cosmwasm_3_0", feature = "iterator"))]
2838 WasmQuery::RawRange {
2839 contract_addr,
2840 start,
2841 end,
2842 limit,
2843 order,
2844 } => {
2845 let Ok(addr) = api.addr_validate(contract_addr) else {
2846 return SystemResult::Err(SystemError::NoSuchContract {
2847 addr: contract_addr.clone(),
2848 });
2849 };
2850 if addr == contract1 {
2851 let mut data: Vec<_> = storage1
2852 .range(
2853 start.as_ref().map(Binary::as_slice),
2854 end.as_ref().map(Binary::as_slice),
2855 *order,
2856 )
2857 .take(*limit as usize + 1) .map(|(key, value)| (Binary::new(key), Binary::new(value)))
2859 .collect();
2860
2861 let next_key = if data.len() > *limit as usize {
2863 data.pop().map(|(key, _)| key)
2864 } else {
2865 None
2866 };
2867 let raw_range_response = crate::RawRangeResponse { data, next_key };
2868
2869 SystemResult::Ok(ContractResult::Ok(
2870 to_json_binary(&raw_range_response).unwrap(),
2871 ))
2872 } else {
2873 SystemResult::Err(SystemError::NoSuchContract {
2874 addr: contract_addr.clone(),
2875 })
2876 }
2877 }
2878 }
2879 });
2880
2881 let contract_addr = MockApi::default().addr_make("contract1");
2882
2883 let result = querier.query(&WasmQuery::Raw {
2885 contract_addr: contract_addr.clone().into(),
2886 key: b"the key".into(),
2887 });
2888
2889 match result {
2890 SystemResult::Ok(ContractResult::Ok(value)) => assert_eq!(value, b"the value" as &[u8]),
2891 res => panic!("Unexpected result: {res:?}"),
2892 }
2893 let result = querier.query(&WasmQuery::Raw {
2894 contract_addr: contract_addr.clone().into(),
2895 key: b"other key".into(),
2896 });
2897 match result {
2898 SystemResult::Ok(ContractResult::Ok(value)) => assert_eq!(value, b"" as &[u8]),
2899 res => panic!("Unexpected result: {res:?}"),
2900 }
2901
2902 let result = querier.query(&WasmQuery::Smart {
2904 contract_addr: contract_addr.clone().into(),
2905 msg: b"{}".into(),
2906 });
2907 match result {
2908 SystemResult::Ok(ContractResult::Ok(value)) => assert_eq!(
2909 value,
2910 br#"{"messages":[],"attributes":[],"events":[],"data":"Z29vZA=="}"# as &[u8]
2911 ),
2912 res => panic!("Unexpected result: {res:?}"),
2913 }
2914 let result = querier.query(&WasmQuery::Smart {
2915 contract_addr: contract_addr.clone().into(),
2916 msg: b"a broken request".into(),
2917 });
2918 match result {
2919 SystemResult::Ok(ContractResult::Err(err)) => {
2920 assert_eq!(
2921 err,
2922 "kind: Serialization, error: expected value at line 1 column 1"
2923 )
2924 }
2925 res => panic!("Unexpected result: {res:?}"),
2926 }
2927
2928 let result = querier.query(&WasmQuery::ContractInfo {
2930 contract_addr: contract_addr.clone().into(),
2931 });
2932 match result {
2933 SystemResult::Ok(ContractResult::Ok(value)) => assert_eq!(
2934 value,
2935 br#"{"code_id":4,"creator":"lalala","admin":null,"pinned":false,"ibc_port":null,"ibc2_port":null}"#
2936 as &[u8]
2937 ),
2938 res => panic!("Unexpected result: {res:?}"),
2939 }
2940
2941 #[cfg(feature = "cosmwasm_1_2")]
2943 {
2944 let result = querier.query(&WasmQuery::CodeInfo { code_id: 4 });
2945 match result {
2946 SystemResult::Ok(ContractResult::Ok(value)) => assert_eq!(
2947 value,
2948 br#"{"code_id":4,"creator":"lalala","checksum":"84cf20810fd429caf58898c3210fcb71759a27becddae08dbde8668ea2f4725d"}"#
2949 ),
2950 res => panic!("Unexpected result: {res:?}"),
2951 }
2952 }
2953
2954 #[cfg(all(feature = "cosmwasm_3_0", feature = "iterator"))]
2955 {
2956 let result = querier.query(&WasmQuery::RawRange {
2957 contract_addr: contract_addr.clone().into(),
2958 start: Some(Binary::from(b"the key")),
2959 end: Some(Binary::from(b"the keyasdf")),
2960 limit: 10,
2961 order: crate::Order::Ascending,
2962 });
2963 match result {
2964 SystemResult::Ok(ContractResult::Ok(value)) => assert_eq!(
2965 value.as_slice(),
2966 br#"{"data":[["dGhlIGtleQ==","dGhlIHZhbHVl"]],"next_key":null}"#
2967 ),
2968 res => panic!("Unexpected result: {res:?}"),
2969 }
2970 }
2971 }
2972
2973 #[test]
2974 fn making_an_address_works() {
2975 let mock_api = MockApi::default();
2976
2977 assert_eq!(
2978 mock_api.addr_make("creator").to_string(),
2979 "cosmwasm1h34lmpywh4upnjdg90cjf4j70aee6z8qqfspugamjp42e4q28kqs8s7vcp",
2980 );
2981
2982 assert_eq!(
2983 mock_api.addr_make("").to_string(),
2984 "cosmwasm1uwcvgs5clswpfxhm7nyfjmaeysn6us0yvjdexn9yjkv3k7zjhp2sly4xh9",
2985 );
2986
2987 let mock_api = MockApi::default().with_prefix("juno");
2988 assert_eq!(
2989 mock_api.addr_make("creator").to_string(),
2990 "juno1h34lmpywh4upnjdg90cjf4j70aee6z8qqfspugamjp42e4q28kqsksmtyp",
2991 );
2992 }
2993
2994 #[test]
2995 fn colon_in_prefix_is_valid() {
2996 let mock_api = MockApi::default().with_prefix("did:com:");
2997 let addr = mock_api
2998 .addr_validate("did:com:1jkf0kmeyefvyzpwf56m7sne2000ay53r6upttu")
2999 .unwrap();
3000
3001 assert_eq!(
3002 addr.as_str(),
3003 "did:com:1jkf0kmeyefvyzpwf56m7sne2000ay53r6upttu"
3004 );
3005 }
3006
3007 #[test]
3008 #[should_panic(
3009 expected = "Generating address failed with reason: hrp is empty, must have at least 1 character"
3010 )]
3011 fn making_an_address_with_empty_prefix_should_panic() {
3012 MockApi::default().with_prefix("").addr_make("creator");
3013 }
3014
3015 #[test]
3016 #[cfg(feature = "cosmwasm_1_3")]
3017 fn distribution_querier_new_works() {
3018 let addresses = [
3019 ("addr0000".to_string(), "addr0001".to_string()),
3020 ("addr0002".to_string(), "addr0001".to_string()),
3021 ];
3022 let btree_map = BTreeMap::from(addresses.clone());
3023
3024 let hashmap = std::collections::HashMap::from(addresses.clone());
3026 let querier = DistributionQuerier::new(hashmap);
3027 assert_eq!(querier.withdraw_addresses, btree_map);
3028
3029 let querier = DistributionQuerier::new(btree_map.clone());
3031 assert_eq!(querier.withdraw_addresses, btree_map);
3032
3033 let querier = DistributionQuerier::new(addresses);
3035 assert_eq!(querier.withdraw_addresses, btree_map);
3036 }
3037
3038 #[test]
3039 fn instantiate2_address_can_be_humanized() {
3040 let mock_api = MockApi::default();
3041
3042 let contract_addr = mock_api
3043 .addr_canonicalize(mock_api.addr_make("contract").as_str())
3044 .unwrap();
3045 let checksum =
3046 HexBinary::from_hex("9af782a3a1bcbcd22dbb6a45c751551d9af782a3a1bcbcd22dbb6a45c751551d")
3047 .unwrap();
3048 let salt = b"instance 1231";
3049 let canonical_addr = instantiate2_address(&checksum, &contract_addr, salt).unwrap();
3050 mock_api.addr_humanize(&canonical_addr).unwrap();
3052 }
3053}