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 42,
700 ))
701}
702
703#[cfg(feature = "ibc2")]
705pub fn mock_ibc2_packet_timeout(data: &impl Serialize) -> StdResult<Ibc2PacketTimeoutMsg> {
706 let payload = Ibc2Payload {
707 source_port: "wasm2srcport".to_string(),
708 destination_port: "wasm2destport".to_string(),
709 version: "v2".to_string(),
710 encoding: "json".to_string(),
711 value: to_json_binary(data)?,
712 };
713 Ok(Ibc2PacketTimeoutMsg::new(
714 payload,
715 "source_client".to_string(),
716 "destination_client".to_string(),
717 1,
718 Addr::unchecked("relayer"),
719 ))
720}
721
722#[cfg(feature = "ibc2")]
724pub fn mock_ibc2_packet_send(data: &impl Serialize) -> StdResult<Ibc2PacketSendMsg> {
725 let payload = Ibc2Payload {
726 source_port: "wasm2srcport".to_string(),
727 destination_port: "wasm2destport".to_string(),
728 version: "v2".to_string(),
729 encoding: "json".to_string(),
730 value: to_json_binary(data)?,
731 };
732 Ok(Ibc2PacketSendMsg::new(
733 payload,
734 "source_client".to_string(),
735 "destination_client".to_string(),
736 1,
737 Addr::unchecked("signer_contract"),
738 ))
739}
740
741#[cfg(feature = "stargate")]
745fn mock_ibc_packet(my_channel_id: &str, data: &impl Serialize) -> StdResult<IbcPacket> {
746 Ok(IbcPacket {
747 data: to_json_binary(data)?,
748 src: IbcEndpoint {
749 port_id: "their-port".to_string(),
750 channel_id: my_channel_id.into(),
751 },
752 dest: IbcEndpoint {
753 port_id: "our-port".to_string(),
754 channel_id: "channel-1234".to_string(),
755 },
756 sequence: 29,
757 timeout: IbcTimeoutBlock {
758 revision: 1,
759 height: 432332552,
760 }
761 .into(),
762 })
763}
764
765#[cfg(feature = "stargate")]
769pub fn mock_ibc_packet_ack(
770 my_channel_id: &str,
771 data: &impl Serialize,
772 ack: IbcAcknowledgement,
773) -> StdResult<IbcPacketAckMsg> {
774 let packet = mock_ibc_packet(my_channel_id, data)?;
775
776 Ok(IbcPacketAckMsg::new(
777 ack,
778 packet,
779 Addr::unchecked("relayer"),
780 ))
781}
782
783#[cfg(feature = "stargate")]
787pub fn mock_ibc_packet_timeout(
788 my_channel_id: &str,
789 data: &impl Serialize,
790) -> StdResult<IbcPacketTimeoutMsg> {
791 let packet = mock_ibc_packet(my_channel_id, data)?;
792 Ok(IbcPacketTimeoutMsg::new(packet, Addr::unchecked("relayer")))
793}
794
795pub type MockQuerierCustomHandlerResult = SystemResult<ContractResult<Binary>>;
798
799pub struct MockQuerier<C: DeserializeOwned = Empty> {
802 pub bank: BankQuerier,
803 #[cfg(feature = "staking")]
804 pub staking: StakingQuerier,
805 #[cfg(feature = "cosmwasm_1_3")]
806 pub distribution: DistributionQuerier,
807 wasm: WasmQuerier,
808 #[cfg(feature = "stargate")]
809 pub ibc: IbcQuerier,
810 custom_handler: Box<dyn for<'a> Fn(&'a C) -> MockQuerierCustomHandlerResult>,
815}
816
817impl<C: DeserializeOwned> MockQuerier<C> {
818 pub fn new(balances: &[(&str, &[Coin])]) -> Self {
819 MockQuerier {
820 bank: BankQuerier::new(balances),
821 #[cfg(feature = "cosmwasm_1_3")]
822 distribution: DistributionQuerier::default(),
823 #[cfg(feature = "staking")]
824 staking: StakingQuerier::default(),
825 wasm: WasmQuerier::default(),
826 #[cfg(feature = "stargate")]
827 ibc: IbcQuerier::default(),
828 custom_handler: Box::from(|_: &_| -> MockQuerierCustomHandlerResult {
830 SystemResult::Err(SystemError::UnsupportedRequest {
831 kind: "custom".to_string(),
832 })
833 }),
834 }
835 }
836
837 pub fn update_wasm<WH>(&mut self, handler: WH)
838 where
839 WH: Fn(&WasmQuery) -> QuerierResult + 'static,
840 {
841 self.wasm.update_handler(handler)
842 }
843
844 pub fn with_custom_handler<CH>(mut self, handler: CH) -> Self
845 where
846 CH: Fn(&C) -> MockQuerierCustomHandlerResult + 'static,
847 {
848 self.custom_handler = Box::from(handler);
849 self
850 }
851}
852
853impl Default for MockQuerier {
854 fn default() -> Self {
855 MockQuerier::new(&[])
856 }
857}
858
859impl<C: CustomQuery + DeserializeOwned> Querier for MockQuerier<C> {
860 fn raw_query(&self, bin_request: &[u8]) -> QuerierResult {
861 let request: QueryRequest<C> = match from_json(bin_request) {
862 Ok(v) => v,
863 Err(e) => {
864 return SystemResult::Err(SystemError::InvalidRequest {
865 error: format!("Parsing query request: {e}"),
866 request: bin_request.into(),
867 })
868 }
869 };
870 self.handle_query(&request)
871 }
872}
873
874impl<C: CustomQuery + DeserializeOwned> MockQuerier<C> {
875 pub fn handle_query(&self, request: &QueryRequest<C>) -> QuerierResult {
876 match &request {
877 QueryRequest::Bank(bank_query) => self.bank.query(bank_query),
878 QueryRequest::Custom(custom_query) => (*self.custom_handler)(custom_query),
879 #[cfg(feature = "staking")]
880 QueryRequest::Staking(staking_query) => self.staking.query(staking_query),
881 #[cfg(feature = "cosmwasm_1_3")]
882 QueryRequest::Distribution(distribution_query) => {
883 self.distribution.query(distribution_query)
884 }
885 QueryRequest::Wasm(msg) => self.wasm.query(msg),
886 #[cfg(feature = "stargate")]
887 #[allow(deprecated)]
888 QueryRequest::Stargate { .. } => SystemResult::Err(SystemError::UnsupportedRequest {
889 kind: "Stargate".to_string(),
890 }),
891 #[cfg(feature = "cosmwasm_2_0")]
892 QueryRequest::Grpc(_) => SystemResult::Err(SystemError::UnsupportedRequest {
893 kind: "GRPC".to_string(),
894 }),
895 #[cfg(feature = "stargate")]
896 QueryRequest::Ibc(msg) => self.ibc.query(msg),
897 }
898 }
899}
900
901struct WasmQuerier {
902 handler: Box<dyn for<'a> Fn(&'a WasmQuery) -> QuerierResult>,
907}
908
909impl WasmQuerier {
910 fn new(handler: Box<dyn for<'a> Fn(&'a WasmQuery) -> QuerierResult>) -> Self {
911 Self { handler }
912 }
913
914 fn update_handler<WH>(&mut self, handler: WH)
915 where
916 WH: Fn(&WasmQuery) -> QuerierResult + 'static,
917 {
918 self.handler = Box::from(handler)
919 }
920
921 fn query(&self, request: &WasmQuery) -> QuerierResult {
922 (*self.handler)(request)
923 }
924}
925
926impl Default for WasmQuerier {
927 fn default() -> Self {
928 let handler = Box::from(|request: &WasmQuery| -> QuerierResult {
929 let err = match request {
930 WasmQuery::Smart { contract_addr, .. } => SystemError::NoSuchContract {
931 addr: contract_addr.clone(),
932 },
933 WasmQuery::Raw { contract_addr, .. } => SystemError::NoSuchContract {
934 addr: contract_addr.clone(),
935 },
936 WasmQuery::ContractInfo { contract_addr, .. } => SystemError::NoSuchContract {
937 addr: contract_addr.clone(),
938 },
939 #[cfg(feature = "cosmwasm_1_2")]
940 WasmQuery::CodeInfo { code_id, .. } => {
941 SystemError::NoSuchCode { code_id: *code_id }
942 }
943 #[cfg(all(feature = "cosmwasm_3_0", feature = "iterator"))]
944 WasmQuery::RawRange { contract_addr, .. } => SystemError::NoSuchContract {
945 addr: contract_addr.clone(),
946 },
947 };
948 SystemResult::Err(err)
949 });
950 Self::new(handler)
951 }
952}
953
954#[derive(Clone, Default)]
955pub struct BankQuerier {
956 #[allow(dead_code)]
957 supplies: BTreeMap<String, Uint256>,
959 balances: BTreeMap<String, Vec<Coin>>,
962 denom_metadata: BTreeMap<Vec<u8>, DenomMetadata>,
964}
965
966impl BankQuerier {
967 pub fn new(balances: &[(&str, &[Coin])]) -> Self {
968 let balances: BTreeMap<_, _> = balances
969 .iter()
970 .map(|(address, balance)| (address.to_string(), balance.to_vec()))
971 .collect();
972
973 BankQuerier {
974 supplies: Self::calculate_supplies(&balances),
975 balances,
976 denom_metadata: BTreeMap::new(),
977 }
978 }
979
980 pub fn update_balance(
982 &mut self,
983 addr: impl Into<String>,
984 balance: Vec<Coin>,
985 ) -> Option<Vec<Coin>> {
986 let result = self.balances.insert(addr.into(), balance);
987 self.supplies = Self::calculate_supplies(&self.balances);
988
989 result
990 }
991
992 pub fn set_denom_metadata(&mut self, denom_metadata: &[DenomMetadata]) {
993 self.denom_metadata = denom_metadata
994 .iter()
995 .map(|d| (d.base.as_bytes().to_vec(), d.clone()))
996 .collect();
997 }
998
999 fn calculate_supplies(balances: &BTreeMap<String, Vec<Coin>>) -> BTreeMap<String, Uint256> {
1000 let mut supplies = BTreeMap::new();
1001
1002 let all_coins = balances.iter().flat_map(|(_, coins)| coins);
1003
1004 for coin in all_coins {
1005 *supplies
1006 .entry(coin.denom.clone())
1007 .or_insert_with(Uint256::zero) += coin.amount;
1008 }
1009
1010 supplies
1011 }
1012
1013 pub fn query(&self, request: &BankQuery) -> QuerierResult {
1014 let contract_result: ContractResult<Binary> = match request {
1015 #[cfg(feature = "cosmwasm_1_1")]
1016 BankQuery::Supply { denom } => {
1017 let amount = self
1018 .supplies
1019 .get(denom)
1020 .cloned()
1021 .unwrap_or_else(Uint256::zero);
1022 let bank_res = SupplyResponse {
1023 amount: Coin {
1024 amount,
1025 denom: denom.to_string(),
1026 },
1027 };
1028 to_json_binary(&bank_res).into()
1029 }
1030 BankQuery::Balance { address, denom } => {
1031 let amount = self
1033 .balances
1034 .get(address)
1035 .and_then(|v| v.iter().find(|c| &c.denom == denom).map(|c| c.amount))
1036 .unwrap_or_default();
1037 let bank_res = BalanceResponse {
1038 amount: Coin {
1039 amount,
1040 denom: denom.to_string(),
1041 },
1042 };
1043 to_json_binary(&bank_res).into()
1044 }
1045 #[cfg(feature = "cosmwasm_1_3")]
1046 BankQuery::DenomMetadata { denom } => {
1047 let denom_metadata = self.denom_metadata.get(denom.as_bytes());
1048 match denom_metadata {
1049 Some(m) => {
1050 let metadata_res = DenomMetadataResponse {
1051 metadata: m.clone(),
1052 };
1053 to_json_binary(&metadata_res).into()
1054 }
1055 None => return SystemResult::Err(SystemError::Unknown {}),
1056 }
1057 }
1058 #[cfg(feature = "cosmwasm_1_3")]
1059 BankQuery::AllDenomMetadata { pagination } => {
1060 let default_pagination = PageRequest {
1061 key: None,
1062 limit: 100,
1063 reverse: false,
1064 };
1065 let pagination = pagination.as_ref().unwrap_or(&default_pagination);
1066
1067 let range = match (pagination.reverse, &pagination.key) {
1069 (_, None) => (Bound::Unbounded, Bound::Unbounded),
1070 (true, Some(key)) => (Bound::Unbounded, Bound::Included(key.as_slice())),
1071 (false, Some(key)) => (Bound::Included(key.as_slice()), Bound::Unbounded),
1072 };
1073 let iter = self.denom_metadata.range::<[u8], _>(range);
1074 let iter: Box<dyn Iterator<Item = _>> = if pagination.reverse {
1076 Box::new(iter.rev())
1077 } else {
1078 Box::new(iter)
1079 };
1080
1081 let mut metadata: Vec<_> = iter
1082 .take((pagination.limit.saturating_add(1)) as usize)
1084 .map(|(_, m)| m.clone())
1085 .collect();
1086
1087 let next_key = if metadata.len() > pagination.limit as usize {
1090 metadata.pop().map(|m| Binary::from(m.base.as_bytes()))
1091 } else {
1092 None
1093 };
1094
1095 let metadata_res = AllDenomMetadataResponse { metadata, next_key };
1096 to_json_binary(&metadata_res).into()
1097 }
1098 };
1099 SystemResult::Ok(contract_result)
1101 }
1102}
1103
1104#[cfg(feature = "stargate")]
1105#[derive(Clone, Default)]
1106pub struct IbcQuerier {
1107 port_id: String,
1108 channels: Vec<IbcChannel>,
1109}
1110
1111#[cfg(feature = "stargate")]
1112impl IbcQuerier {
1113 pub fn new(port_id: &str, channels: &[IbcChannel]) -> Self {
1117 IbcQuerier {
1118 port_id: port_id.to_string(),
1119 channels: channels.to_vec(),
1120 }
1121 }
1122
1123 pub fn update(&mut self, port_id: impl Into<String>, channels: &[IbcChannel]) {
1125 self.port_id = port_id.into();
1126 self.channels = channels.to_vec();
1127 }
1128
1129 pub fn query(&self, request: &IbcQuery) -> QuerierResult {
1130 let contract_result: ContractResult<Binary> = match request {
1131 IbcQuery::Channel {
1132 channel_id,
1133 port_id,
1134 } => {
1135 let channel = self
1136 .channels
1137 .iter()
1138 .find(|c| match port_id {
1139 Some(p) => c.endpoint.channel_id.eq(channel_id) && c.endpoint.port_id.eq(p),
1140 None => {
1141 c.endpoint.channel_id.eq(channel_id)
1142 && c.endpoint.port_id == self.port_id
1143 }
1144 })
1145 .cloned();
1146 let res = ChannelResponse { channel };
1147 to_json_binary(&res).into()
1148 }
1149 IbcQuery::PortId {} => {
1150 let res = PortIdResponse {
1151 port_id: self.port_id.clone(),
1152 };
1153 to_json_binary(&res).into()
1154 }
1155 };
1156 SystemResult::Ok(contract_result)
1158 }
1159}
1160
1161#[cfg(feature = "staking")]
1162#[derive(Clone, Default)]
1163pub struct StakingQuerier {
1164 denom: String,
1165 validators: Vec<Validator>,
1166 delegations: Vec<FullDelegation>,
1167}
1168
1169#[cfg(feature = "staking")]
1170impl StakingQuerier {
1171 pub fn new(denom: &str, validators: &[Validator], delegations: &[FullDelegation]) -> Self {
1172 StakingQuerier {
1173 denom: denom.to_string(),
1174 validators: validators.to_vec(),
1175 delegations: delegations.to_vec(),
1176 }
1177 }
1178
1179 pub fn update(
1181 &mut self,
1182 denom: impl Into<String>,
1183 validators: &[Validator],
1184 delegations: &[FullDelegation],
1185 ) {
1186 self.denom = denom.into();
1187 self.validators = validators.to_vec();
1188 self.delegations = delegations.to_vec();
1189 }
1190
1191 pub fn query(&self, request: &StakingQuery) -> QuerierResult {
1192 let contract_result: ContractResult<Binary> = match request {
1193 StakingQuery::BondedDenom {} => {
1194 let res = BondedDenomResponse {
1195 denom: self.denom.clone(),
1196 };
1197 to_json_binary(&res).into()
1198 }
1199 StakingQuery::AllValidators {} => {
1200 let res = AllValidatorsResponse {
1201 validators: self.validators.iter().cloned().map(Into::into).collect(),
1202 };
1203 to_json_binary(&res).into()
1204 }
1205 StakingQuery::Validator { address } => {
1206 let validator: Option<Validator> = self
1207 .validators
1208 .iter()
1209 .find(|validator| validator.address == *address)
1210 .cloned();
1211 let res = ValidatorResponse { validator };
1212 to_json_binary(&res).into()
1213 }
1214 StakingQuery::AllDelegations { delegator } => {
1215 let delegations: Vec<_> = self
1216 .delegations
1217 .iter()
1218 .filter(|d| d.delegator.as_str() == delegator)
1219 .cloned()
1220 .map(|d| d.into())
1221 .collect();
1222 let res = AllDelegationsResponse { delegations };
1223 to_json_binary(&res).into()
1224 }
1225 StakingQuery::Delegation {
1226 delegator,
1227 validator,
1228 } => {
1229 let delegation = self
1230 .delegations
1231 .iter()
1232 .find(|d| d.delegator.as_str() == delegator && d.validator == *validator);
1233 let res = DelegationResponse {
1234 delegation: delegation.cloned(),
1235 };
1236 to_json_binary(&res).into()
1237 }
1238 };
1239 SystemResult::Ok(contract_result)
1241 }
1242}
1243
1244#[cfg(feature = "cosmwasm_1_3")]
1245#[derive(Clone, Default)]
1246pub struct DistributionQuerier {
1247 withdraw_addresses: BTreeMap<String, String>,
1248 rewards: BTreeMap<String, BTreeMap<String, Vec<DecCoin>>>,
1250 validators: BTreeMap<String, BTreeSet<String>>,
1252}
1253
1254#[cfg(feature = "cosmwasm_1_3")]
1255impl DistributionQuerier {
1256 pub fn new<T>(withdraw_addresses: T) -> Self
1257 where
1258 T: IntoIterator<Item = (String, String)>,
1259 {
1260 DistributionQuerier {
1261 withdraw_addresses: withdraw_addresses.into_iter().collect(),
1262 ..Default::default()
1263 }
1264 }
1265
1266 pub fn set_withdraw_address(
1267 &mut self,
1268 delegator_address: impl Into<String>,
1269 withdraw_address: impl Into<String>,
1270 ) {
1271 self.withdraw_addresses
1272 .insert(delegator_address.into(), withdraw_address.into());
1273 }
1274
1275 pub fn set_withdraw_addresses(
1280 &mut self,
1281 withdraw_addresses: impl IntoIterator<Item = (impl Into<String>, impl Into<String>)>,
1282 ) {
1283 for (d, w) in withdraw_addresses {
1284 self.set_withdraw_address(d, w);
1285 }
1286 }
1287
1288 pub fn clear_withdraw_addresses(&mut self) {
1289 self.withdraw_addresses.clear();
1290 }
1291
1292 pub fn set_rewards(
1294 &mut self,
1295 validator: impl Into<String>,
1296 delegator: impl Into<String>,
1297 rewards: Vec<DecCoin>,
1298 ) {
1299 self.rewards
1300 .entry(delegator.into())
1301 .or_default()
1302 .insert(validator.into(), rewards);
1303 }
1304
1305 pub fn set_validators(
1307 &mut self,
1308 delegator: impl Into<String>,
1309 validators: impl IntoIterator<Item = impl Into<String>>,
1310 ) {
1311 self.validators.insert(
1312 delegator.into(),
1313 validators.into_iter().map(Into::into).collect(),
1314 );
1315 }
1316
1317 pub fn query(&self, request: &DistributionQuery) -> QuerierResult {
1318 let contract_result: ContractResult<Binary> = match request {
1319 DistributionQuery::DelegatorWithdrawAddress { delegator_address } => {
1320 let res = DelegatorWithdrawAddressResponse {
1321 withdraw_address: Addr::unchecked(
1322 self.withdraw_addresses
1323 .get(delegator_address)
1324 .unwrap_or(delegator_address),
1325 ),
1326 };
1327 to_json_binary(&res).into()
1328 }
1329 #[cfg(feature = "cosmwasm_1_4")]
1330 DistributionQuery::DelegationRewards {
1331 delegator_address,
1332 validator_address,
1333 } => {
1334 let res = DelegationRewardsResponse {
1335 rewards: self
1336 .rewards
1337 .get(delegator_address)
1338 .and_then(|v| v.get(validator_address))
1339 .cloned()
1340 .unwrap_or_default(),
1341 };
1342 to_json_binary(&res).into()
1343 }
1344 #[cfg(feature = "cosmwasm_1_4")]
1345 DistributionQuery::DelegationTotalRewards { delegator_address } => {
1346 let validator_rewards = self
1347 .validator_rewards(delegator_address)
1348 .unwrap_or_default();
1349 let res = crate::DelegationTotalRewardsResponse {
1350 total: validator_rewards
1351 .iter()
1352 .fold(BTreeMap::<&str, DecCoin>::new(), |mut acc, rewards| {
1353 for coin in &rewards.reward {
1354 acc.entry(&coin.denom)
1355 .or_insert_with(|| DecCoin {
1356 denom: coin.denom.clone(),
1357 amount: Decimal256::zero(),
1358 })
1359 .amount += coin.amount;
1360 }
1361
1362 acc
1363 })
1364 .into_values()
1365 .collect(),
1366 rewards: validator_rewards,
1367 };
1368 to_json_binary(&res).into()
1369 }
1370 #[cfg(feature = "cosmwasm_1_4")]
1371 DistributionQuery::DelegatorValidators { delegator_address } => {
1372 let res = DelegatorValidatorsResponse {
1373 validators: self
1374 .validators
1375 .get(delegator_address)
1376 .map(|set| set.iter().cloned().collect())
1377 .unwrap_or_default(),
1378 };
1379 to_json_binary(&res).into()
1380 }
1381 };
1382 SystemResult::Ok(contract_result)
1384 }
1385
1386 #[cfg(feature = "cosmwasm_1_4")]
1388 fn validator_rewards(&self, delegator_address: &str) -> Option<Vec<crate::DelegatorReward>> {
1389 let validator_rewards = self.rewards.get(delegator_address)?;
1390
1391 Some(
1392 validator_rewards
1393 .iter()
1394 .map(|(validator, rewards)| crate::DelegatorReward {
1395 validator_address: validator.clone(),
1396 reward: rewards.clone(),
1397 })
1398 .collect(),
1399 )
1400 }
1401}
1402
1403pub fn mock_wasmd_attr(key: impl Into<String>, value: impl Into<String>) -> Attribute {
1406 Attribute {
1407 key: key.into(),
1408 value: value.into(),
1409 }
1410}
1411
1412#[cfg(test)]
1413mod tests {
1414 use super::*;
1415 #[allow(unused)]
1416 use crate::coins;
1417 #[cfg(feature = "cosmwasm_1_3")]
1418 use crate::DenomUnit;
1419 use crate::{coin, instantiate2_address, ContractInfoResponse, HexBinary, Response, Storage};
1420 #[cfg(feature = "staking")]
1421 use crate::{Decimal, Delegation};
1422 use base64::{engine::general_purpose, Engine};
1423 use cosmwasm_core::BLS12_381_G1_GENERATOR;
1424 use hex_literal::hex;
1425 use serde::Deserialize;
1426
1427 const SECP256K1_MSG_HASH_HEX: &str =
1428 "5ae8317d34d1e595e3fa7247db80c0af4320cce1116de187f8f7e2e099c0d8d0";
1429 const SECP256K1_SIG_HEX: &str = "207082eb2c3dfa0b454e0906051270ba4074ac93760ba9e7110cd9471475111151eb0dbbc9920e72146fb564f99d039802bf6ef2561446eb126ef364d21ee9c4";
1430 const SECP256K1_PUBKEY_HEX: &str = "04051c1ee2190ecfb174bfe4f90763f2b4ff7517b70a2aec1876ebcfd644c4633fb03f3cfbd94b1f376e34592d9d41ccaf640bb751b00a1fadeb0c01157769eb73";
1431
1432 const SECP256R1_MSG_HASH_HEX: &str =
1433 "5eb28029ebf3c7025ff2fc2f6de6f62aecf6a72139e1cba5f20d11bbef036a7f";
1434 const SECP256R1_SIG_HEX: &str = "e67a9717ccf96841489d6541f4f6adb12d17b59a6bef847b6183b8fcf16a32eb9ae6ba6d637706849a6a9fc388cf0232d85c26ea0d1fe7437adb48de58364333";
1435 const SECP256R1_PUBKEY_HEX: &str = "0468229b48c2fe19d3db034e4c15077eb7471a66031f28a980821873915298ba76303e8ee3742a893f78b810991da697083dd8f11128c47651c27a56740a80c24c";
1436
1437 const ED25519_MSG_HEX: &str = "72";
1438 const ED25519_SIG_HEX: &str = "92a009a9f0d4cab8720e820b5f642540a2b27b5416503f8fb3762223ebdb69da085ac1e43e15996e458f3613d0f11d8c387b2eaeb4302aeeb00d291612bb0c00";
1439 const ED25519_PUBKEY_HEX: &str =
1440 "3d4017c3e843895a92b70aa74d1b7ebc9c982ccf2ec4968cc0cd55f12af4660c";
1441
1442 const DOMAIN_HASH_TO_G2: &[u8] = b"BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_NUL_";
1445
1446 const PK_LEO_MAINNET: [u8; 48] = hex!("868f005eb8e6e4ca0a47c8a77ceaa5309a47978a7c71bc5cce96366b5d7a569937c529eeda66c7293784a9402801af31");
1448
1449 const ETH_BLOCK_HEADER: &[u8] =
1450 include_bytes!("../../../crypto/testdata/eth-headers/1699693797.394876721s.json");
1451
1452 #[test]
1453 fn mock_env_works() {
1454 let env = mock_env();
1455 assert_eq!(
1456 env,
1457 Env {
1458 block: BlockInfo {
1459 height: 12345,
1460 time: Timestamp::from_nanos(1571797419879305533),
1461 chain_id: "cosmos-testnet-14002".to_string()
1462 },
1463 transaction: Some(TransactionInfo::new(
1464 3,
1465 Binary::from_hex(
1466 "E5469DACEC17CEF8A260FD37675ED87E7FB6A2B5AD95193C51308006C7E494B3"
1467 )
1468 .unwrap(),
1469 )),
1470 contract: ContractInfo {
1471 address: Addr::unchecked(MOCK_CONTRACT_ADDR)
1472 }
1473 }
1474 )
1475 }
1476
1477 #[test]
1478 fn envs_works() {
1479 let mut envs = Envs::new("food");
1480
1481 let env = envs.make();
1482 assert_eq!(
1483 env.contract.address.as_str(),
1484 "food1jpev2csrppg792t22rn8z8uew8h3sjcpglcd0qv9g8gj8ky922ts74yrjj"
1485 );
1486 assert_eq!(env.block.height, 12_345);
1487 assert_eq!(
1488 env.block.time,
1489 Timestamp::from_nanos(1_571_797_419_879_305_533)
1490 );
1491
1492 let env = envs.make();
1493 assert_eq!(
1494 env.contract.address.as_str(),
1495 "food1jpev2csrppg792t22rn8z8uew8h3sjcpglcd0qv9g8gj8ky922ts74yrjj"
1496 );
1497 assert_eq!(env.block.height, 12_346);
1498 assert_eq!(
1499 env.block.time,
1500 Timestamp::from_nanos(1_571_797_424_879_305_533)
1501 );
1502
1503 let env = envs.make();
1504 assert_eq!(
1505 env.contract.address.as_str(),
1506 "food1jpev2csrppg792t22rn8z8uew8h3sjcpglcd0qv9g8gj8ky922ts74yrjj"
1507 );
1508 assert_eq!(env.block.height, 12_347);
1509 assert_eq!(
1510 env.block.time,
1511 Timestamp::from_nanos(1_571_797_429_879_305_533)
1512 );
1513 }
1514
1515 #[test]
1516 fn envs_implements_iterator() {
1517 let envs = Envs::new("food");
1518
1519 let result: Vec<_> = envs.into_iter().take(5).collect();
1520
1521 assert_eq!(
1522 result[0].contract.address.as_str(),
1523 "food1jpev2csrppg792t22rn8z8uew8h3sjcpglcd0qv9g8gj8ky922ts74yrjj"
1524 );
1525 assert_eq!(result[0].block.height, 12_345);
1526 assert_eq!(
1527 result[0].block.time,
1528 Timestamp::from_nanos(1_571_797_419_879_305_533)
1529 );
1530
1531 assert_eq!(
1532 result[4].contract.address.as_str(),
1533 "food1jpev2csrppg792t22rn8z8uew8h3sjcpglcd0qv9g8gj8ky922ts74yrjj"
1534 );
1535 assert_eq!(result[4].block.height, 12_349);
1536 assert_eq!(
1537 result[4].block.time,
1538 Timestamp::from_nanos(1_571_797_439_879_305_533)
1539 );
1540
1541 let mut envs = Envs::new("yo");
1543 let first = envs.next().unwrap();
1544 let last = envs.take(1_000_000).last().unwrap();
1545 assert_eq!(first.block.height, 12_345);
1546 assert_eq!(last.block.height, 1_012_345);
1547 assert_eq!(
1548 last.block.time,
1549 first.block.time.plus_seconds(1_000_000 * 5)
1550 );
1551 }
1552
1553 #[test]
1554 fn addr_validate_works() {
1555 let api = MockApi::default();
1557
1558 let humanized = "cosmwasm1h34lmpywh4upnjdg90cjf4j70aee6z8qqfspugamjp42e4q28kqs8s7vcp";
1560 let addr = api.addr_validate(humanized).unwrap();
1561 assert_eq!(addr.as_str(), humanized);
1562
1563 api.addr_validate("").unwrap_err();
1565 api.addr_validate("Foobar123").unwrap_err();
1567 api.addr_validate("FOOBAR123").unwrap_err();
1568 }
1569
1570 #[test]
1571 fn addr_canonicalize_works() {
1572 let api = MockApi::default();
1573
1574 api.addr_canonicalize(
1575 "cosmwasm1h34lmpywh4upnjdg90cjf4j70aee6z8qqfspugamjp42e4q28kqs8s7vcp",
1576 )
1577 .unwrap();
1578
1579 let data1 = api
1581 .addr_canonicalize(
1582 "cosmwasm1h34lmpywh4upnjdg90cjf4j70aee6z8qqfspugamjp42e4q28kqs8s7vcp",
1583 )
1584 .unwrap();
1585 let data2 = api
1586 .addr_canonicalize(
1587 "COSMWASM1H34LMPYWH4UPNJDG90CJF4J70AEE6Z8QQFSPUGAMJP42E4Q28KQS8S7VCP",
1588 )
1589 .unwrap();
1590 assert_eq!(data1, data2);
1591 }
1592
1593 #[test]
1594 fn canonicalize_and_humanize_restores_original() {
1595 let api = MockApi::default();
1597
1598 let original =
1600 String::from("COSMWASM1H34LMPYWH4UPNJDG90CJF4J70AEE6Z8QQFSPUGAMJP42E4Q28KQS8S7VCP");
1601 let canonical = api.addr_canonicalize(&original).unwrap();
1602 let recovered = api.addr_humanize(&canonical).unwrap();
1603 assert_eq!(
1604 recovered.as_str(),
1605 "cosmwasm1h34lmpywh4upnjdg90cjf4j70aee6z8qqfspugamjp42e4q28kqs8s7vcp"
1606 );
1607
1608 let api = MockApi::default().with_prefix("juno");
1610
1611 let original =
1613 String::from("juno1v82su97skv6ucfqvuvswe0t5fph7pfsrtraxf0x33d8ylj5qnrysdvkc95");
1614 let canonical = api.addr_canonicalize(&original).unwrap();
1615 let recovered = api.addr_humanize(&canonical).unwrap();
1616 assert_eq!(recovered.as_str(), original);
1617 }
1618
1619 #[test]
1620 fn addr_canonicalize_short_input() {
1621 let api = MockApi::default();
1622
1623 let empty = "cosmwasm1pj90vm";
1625 assert!(api
1626 .addr_canonicalize(empty)
1627 .unwrap_err()
1628 .to_string()
1629 .contains("Invalid canonical address length"));
1630
1631 let human = "cosmwasm1qqvk2mde";
1633 assert_eq!(api.addr_canonicalize(human).unwrap().as_ref(), [0u8]);
1634 }
1635
1636 #[test]
1637 fn addr_canonicalize_long_input() {
1638 let api = MockApi::default();
1639 let human =
1640 "cosmwasm1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqehqqkz";
1641 let err = api.addr_canonicalize(human).unwrap_err();
1642 assert!(err.to_string().contains("Invalid canonical address length"));
1643 }
1644
1645 #[test]
1646 fn addr_humanize_input_length() {
1647 let api = MockApi::default();
1648 let input = CanonicalAddr::from(vec![]);
1649 assert!(api
1650 .addr_humanize(&input)
1651 .unwrap_err()
1652 .to_string()
1653 .ends_with("Invalid canonical address length"));
1654 }
1655
1656 #[test]
1657 fn bls12_381_aggregate_g1_works() {
1658 #[derive(serde::Deserialize)]
1659 struct EthHeader {
1660 public_keys: Vec<String>,
1661 aggregate_pubkey: String,
1662 }
1663
1664 let api = MockApi::default();
1665 let header: EthHeader = serde_json::from_slice(ETH_BLOCK_HEADER).unwrap();
1666 let expected = general_purpose::STANDARD
1667 .decode(header.aggregate_pubkey)
1668 .unwrap();
1669
1670 let pubkeys: Vec<u8> = header
1671 .public_keys
1672 .into_iter()
1673 .flat_map(|key| general_purpose::STANDARD.decode(key).unwrap())
1674 .collect();
1675 let sum = api.bls12_381_aggregate_g1(&pubkeys).unwrap();
1676
1677 assert_eq!(expected, sum);
1678 }
1679
1680 #[test]
1681 fn bls12_381_aggregate_g2_works() {
1682 let api = MockApi::default();
1683
1684 let points: Vec<u8> = [
1685 hex!("b6ed936746e01f8ecf281f020953fbf1f01debd5657c4a383940b020b26507f6076334f91e2366c96e9ab279fb5158090352ea1c5b0c9274504f4f0e7053af24802e51e4568d164fe986834f41e55c8e850ce1f98458c0cfc9ab380b55285a55"),
1686 hex!("b23c46be3a001c63ca711f87a005c200cc550b9429d5f4eb38d74322144f1b63926da3388979e5321012fb1a0526bcd100b5ef5fe72628ce4cd5e904aeaa3279527843fae5ca9ca675f4f51ed8f83bbf7155da9ecc9663100a885d5dc6df96d9"),
1687 hex!("948a7cb99f76d616c2c564ce9bf4a519f1bea6b0a624a02276443c245854219fabb8d4ce061d255af5330b078d5380681751aa7053da2c98bae898edc218c75f07e24d8802a17cd1f6833b71e58f5eb5b94208b4d0bb3848cecb075ea21be115"),
1688 ]
1689 .into_iter()
1690 .flatten()
1691 .collect();
1692
1693 let expected = hex!("9683b3e6701f9a4b706709577963110043af78a5b41991b998475a3d3fd62abf35ce03b33908418efc95a058494a8ae504354b9f626231f6b3f3c849dfdeaf5017c4780e2aee1850ceaf4b4d9ce70971a3d2cfcd97b7e5ecf6759f8da5f76d31");
1694 let sum = api.bls12_381_aggregate_g2(&points).unwrap();
1695
1696 assert_eq!(sum, expected);
1697 }
1698
1699 #[test]
1700 fn bls12_381_pairing_equality_works() {
1701 let api = MockApi::default();
1702
1703 let dst = b"BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_POP_";
1704 let ps = hex!("a491d1b0ecd9bb917989f0e74f0dea0422eac4a873e5e2644f368dffb9a6e20fd6e10c1b77654d067c0618f6e5a7f79ab301803f8b5ac4a1133581fc676dfedc60d891dd5fa99028805e5ea5b08d3491af75d0707adab3b70c6a6a580217bf81b53d21a4cfd562c469cc81514d4ce5a6b577d8403d32a394dc265dd190b47fa9f829fdd7963afdf972e5e77854051f6f");
1705 let qs: Vec<u8> = [
1706 hex!("0000000000000000000000000000000000000000000000000000000000000000"),
1707 hex!("5656565656565656565656565656565656565656565656565656565656565656"),
1708 hex!("abababababababababababababababababababababababababababababababab"),
1709 ]
1710 .into_iter()
1711 .flat_map(|msg| {
1712 api.bls12_381_hash_to_g2(HashFunction::Sha256, &msg, dst)
1713 .unwrap()
1714 })
1715 .collect();
1716 let s = hex!("9104e74b9dfd3ad502f25d6a5ef57db0ed7d9a0e00f3500586d8ce44231212542fcfaf87840539b398bf07626705cf1105d246ca1062c6c2e1a53029a0f790ed5e3cb1f52f8234dc5144c45fc847c0cd37a92d68e7c5ba7c648a8a339f171244");
1717
1718 let is_valid = api
1719 .bls12_381_pairing_equality(&ps, &qs, &BLS12_381_G1_GENERATOR, &s)
1720 .unwrap();
1721 assert!(is_valid);
1722 }
1723
1724 #[test]
1725 fn bls12_381_hash_to_g1_works() {
1726 let api = MockApi::default();
1729 let msg = b"abc";
1730 let dst = b"QUUX-V01-CS02-with-BLS12381G1_XMD:SHA-256_SSWU_RO_";
1731
1732 let hashed_point = api
1733 .bls12_381_hash_to_g1(HashFunction::Sha256, msg, dst)
1734 .unwrap();
1735 let mut serialized_expected_compressed = hex!("03567bc5ef9c690c2ab2ecdf6a96ef1c139cc0b2f284dca0a9a7943388a49a3aee664ba5379a7655d3c68900be2f6903");
1736 serialized_expected_compressed[0] |= 0b1000_0000;
1738
1739 assert_eq!(hashed_point, serialized_expected_compressed);
1740 }
1741
1742 #[test]
1743 fn bls12_381_hash_to_g2_works() {
1744 let api = MockApi::default();
1745 let msg = b"abc";
1746 let dst = b"QUUX-V01-CS02-with-BLS12381G2_XMD:SHA-256_SSWU_RO_";
1747
1748 let hashed_point = api
1749 .bls12_381_hash_to_g2(HashFunction::Sha256, msg, dst)
1750 .unwrap();
1751 let mut serialized_expected_compressed = hex!("139cddbccdc5e91b9623efd38c49f81a6f83f175e80b06fc374de9eb4b41dfe4ca3a230ed250fbe3a2acf73a41177fd802c2d18e033b960562aae3cab37a27ce00d80ccd5ba4b7fe0e7a210245129dbec7780ccc7954725f4168aff2787776e6");
1752 serialized_expected_compressed[0] |= 0b1000_0000;
1754
1755 assert_eq!(hashed_point, serialized_expected_compressed);
1756 }
1757
1758 #[test]
1759 fn bls12_318_pairing_equality_works() {
1760 fn build_bls_message(round: u64, previous_signature: &[u8]) -> Vec<u8> {
1761 Sha256::new()
1762 .chain_update(previous_signature)
1763 .chain_update(round.to_be_bytes())
1764 .finalize()
1765 .to_vec()
1766 }
1767
1768 let api = MockApi::default();
1769
1770 let previous_signature = hex::decode("a609e19a03c2fcc559e8dae14900aaefe517cb55c840f6e69bc8e4f66c8d18e8a609685d9917efbfb0c37f058c2de88f13d297c7e19e0ab24813079efe57a182554ff054c7638153f9b26a60e7111f71a0ff63d9571704905d3ca6df0b031747").unwrap();
1771 let signature = hex::decode("82f5d3d2de4db19d40a6980e8aa37842a0e55d1df06bd68bddc8d60002e8e959eb9cfa368b3c1b77d18f02a54fe047b80f0989315f83b12a74fd8679c4f12aae86eaf6ab5690b34f1fddd50ee3cc6f6cdf59e95526d5a5d82aaa84fa6f181e42").unwrap();
1772 let round: u64 = 72785;
1773
1774 let msg = build_bls_message(round, &previous_signature);
1775 let msg_point = api
1776 .bls12_381_hash_to_g2(HashFunction::Sha256, &msg, DOMAIN_HASH_TO_G2)
1777 .unwrap();
1778
1779 let is_valid = api
1780 .bls12_381_pairing_equality(
1781 &BLS12_381_G1_GENERATOR,
1782 &signature,
1783 &PK_LEO_MAINNET,
1784 &msg_point,
1785 )
1786 .unwrap();
1787
1788 assert!(is_valid);
1789 }
1790
1791 #[test]
1793 fn secp256k1_verify_works() {
1794 let api = MockApi::default();
1795
1796 let hash = hex::decode(SECP256K1_MSG_HASH_HEX).unwrap();
1797 let signature = hex::decode(SECP256K1_SIG_HEX).unwrap();
1798 let public_key = hex::decode(SECP256K1_PUBKEY_HEX).unwrap();
1799
1800 assert!(api
1801 .secp256k1_verify(&hash, &signature, &public_key)
1802 .unwrap());
1803 }
1804
1805 #[test]
1807 fn secp256k1_verify_fails() {
1808 let api = MockApi::default();
1809
1810 let mut hash = hex::decode(SECP256K1_MSG_HASH_HEX).unwrap();
1811 hash[0] ^= 0x01;
1813 let signature = hex::decode(SECP256K1_SIG_HEX).unwrap();
1814 let public_key = hex::decode(SECP256K1_PUBKEY_HEX).unwrap();
1815
1816 assert!(!api
1817 .secp256k1_verify(&hash, &signature, &public_key)
1818 .unwrap());
1819 }
1820
1821 #[test]
1823 fn secp256k1_verify_errs() {
1824 let api = MockApi::default();
1825
1826 let hash = hex::decode(SECP256K1_MSG_HASH_HEX).unwrap();
1827 let signature = hex::decode(SECP256K1_SIG_HEX).unwrap();
1828 let public_key = vec![];
1829
1830 let res = api.secp256k1_verify(&hash, &signature, &public_key);
1831 assert_eq!(res.unwrap_err(), VerificationError::InvalidPubkeyFormat);
1832 }
1833
1834 #[test]
1835 fn secp256k1_recover_pubkey_works() {
1836 let api = MockApi::default();
1837
1838 let hash = hex!("5ae8317d34d1e595e3fa7247db80c0af4320cce1116de187f8f7e2e099c0d8d0");
1840 let signature = hex!("45c0b7f8c09a9e1f1cea0c25785594427b6bf8f9f878a8af0b1abbb48e16d0920d8becd0c220f67c51217eecfd7184ef0732481c843857e6bc7fc095c4f6b788");
1841 let recovery_param = 1;
1842 let expected = hex!("044a071e8a6e10aada2b8cf39fa3b5fb3400b04e99ea8ae64ceea1a977dbeaf5d5f8c8fbd10b71ab14cd561f7df8eb6da50f8a8d81ba564342244d26d1d4211595");
1843
1844 let pubkey = api
1845 .secp256k1_recover_pubkey(&hash, &signature, recovery_param)
1846 .unwrap();
1847 assert_eq!(pubkey, expected);
1848 }
1849
1850 #[test]
1851 fn secp256k1_recover_pubkey_fails_for_wrong_recovery_param() {
1852 let api = MockApi::default();
1853
1854 let hash = hex!("5ae8317d34d1e595e3fa7247db80c0af4320cce1116de187f8f7e2e099c0d8d0");
1856 let signature = hex!("45c0b7f8c09a9e1f1cea0c25785594427b6bf8f9f878a8af0b1abbb48e16d0920d8becd0c220f67c51217eecfd7184ef0732481c843857e6bc7fc095c4f6b788");
1857 let _recovery_param = 1;
1858 let expected = hex!("044a071e8a6e10aada2b8cf39fa3b5fb3400b04e99ea8ae64ceea1a977dbeaf5d5f8c8fbd10b71ab14cd561f7df8eb6da50f8a8d81ba564342244d26d1d4211595");
1859
1860 let pubkey = api.secp256k1_recover_pubkey(&hash, &signature, 0).unwrap();
1862 assert_eq!(pubkey.len(), 65);
1863 assert_ne!(pubkey, expected);
1864
1865 let result = api.secp256k1_recover_pubkey(&hash, &signature, 42);
1867 match result.unwrap_err() {
1868 RecoverPubkeyError::InvalidRecoveryParam => {}
1869 err => panic!("Unexpected error: {err:?}"),
1870 }
1871 }
1872
1873 #[test]
1874 fn secp256k1_recover_pubkey_fails_for_wrong_hash() {
1875 let api = MockApi::default();
1876
1877 let hash = hex!("5ae8317d34d1e595e3fa7247db80c0af4320cce1116de187f8f7e2e099c0d8d0");
1879 let signature = hex!("45c0b7f8c09a9e1f1cea0c25785594427b6bf8f9f878a8af0b1abbb48e16d0920d8becd0c220f67c51217eecfd7184ef0732481c843857e6bc7fc095c4f6b788");
1880 let recovery_param = 1;
1881 let expected = hex!("044a071e8a6e10aada2b8cf39fa3b5fb3400b04e99ea8ae64ceea1a977dbeaf5d5f8c8fbd10b71ab14cd561f7df8eb6da50f8a8d81ba564342244d26d1d4211595");
1882
1883 let mut corrupted_hash = hash;
1885 corrupted_hash[0] ^= 0x01;
1886 let pubkey = api
1887 .secp256k1_recover_pubkey(&corrupted_hash, &signature, recovery_param)
1888 .unwrap();
1889 assert_eq!(pubkey.len(), 65);
1890 assert_ne!(pubkey, expected);
1891
1892 let mut malformed_hash = hash.to_vec();
1894 malformed_hash.push(0x8a);
1895 let result = api.secp256k1_recover_pubkey(&malformed_hash, &signature, recovery_param);
1896 match result.unwrap_err() {
1897 RecoverPubkeyError::InvalidHashFormat => {}
1898 err => panic!("Unexpected error: {err:?}"),
1899 }
1900 }
1901
1902 #[test]
1904 fn secp256r1_verify_works() {
1905 let api = MockApi::default();
1906
1907 let hash = hex::decode(SECP256R1_MSG_HASH_HEX).unwrap();
1908 let signature = hex::decode(SECP256R1_SIG_HEX).unwrap();
1909 let public_key = hex::decode(SECP256R1_PUBKEY_HEX).unwrap();
1910
1911 assert!(api
1912 .secp256r1_verify(&hash, &signature, &public_key)
1913 .unwrap());
1914 }
1915
1916 #[test]
1918 fn secp256r1_verify_fails() {
1919 let api = MockApi::default();
1920
1921 let mut hash = hex::decode(SECP256R1_MSG_HASH_HEX).unwrap();
1922 hash[0] ^= 0x01;
1924 let signature = hex::decode(SECP256R1_SIG_HEX).unwrap();
1925 let public_key = hex::decode(SECP256R1_PUBKEY_HEX).unwrap();
1926
1927 assert!(!api
1928 .secp256r1_verify(&hash, &signature, &public_key)
1929 .unwrap());
1930 }
1931
1932 #[test]
1934 fn secp256r1_verify_errs() {
1935 let api = MockApi::default();
1936
1937 let hash = hex::decode(SECP256R1_MSG_HASH_HEX).unwrap();
1938 let signature = hex::decode(SECP256R1_SIG_HEX).unwrap();
1939 let public_key = vec![];
1940
1941 let res = api.secp256r1_verify(&hash, &signature, &public_key);
1942 assert_eq!(res.unwrap_err(), VerificationError::InvalidPubkeyFormat);
1943 }
1944
1945 #[test]
1946 fn secp256r1_recover_pubkey_works() {
1947 let api = MockApi::default();
1948
1949 let hash = hex!("17b03f9f00f6692ccdde485fc63c4530751ef35da6f71336610944b0894fcfb8");
1950 let signature = hex!("9886ae46c1415c3bc959e82b760ad760aab66885a84e620aa339fdf102465c422bf3a80bc04faa35ebecc0f4864ac02d349f6f126e0f988501b8d3075409a26c");
1951 let recovery_param = 0;
1952 let expected = hex!("0451f99d2d52d4a6e734484a018b7ca2f895c2929b6754a3a03224d07ae61166ce4737da963c6ef7247fb88d19f9b0c667cac7fe12837fdab88c66f10d3c14cad1");
1953
1954 let pubkey = api
1955 .secp256r1_recover_pubkey(&hash, &signature, recovery_param)
1956 .unwrap();
1957 assert_eq!(pubkey, expected);
1958 }
1959
1960 #[test]
1961 fn secp256r1_recover_pubkey_fails_for_wrong_recovery_param() {
1962 let api = MockApi::default();
1963
1964 let hash = hex!("17b03f9f00f6692ccdde485fc63c4530751ef35da6f71336610944b0894fcfb8");
1965 let signature = hex!("9886ae46c1415c3bc959e82b760ad760aab66885a84e620aa339fdf102465c422bf3a80bc04faa35ebecc0f4864ac02d349f6f126e0f988501b8d3075409a26c");
1966 let expected = hex!("0451f99d2d52d4a6e734484a018b7ca2f895c2929b6754a3a03224d07ae61166ce4737da963c6ef7247fb88d19f9b0c667cac7fe12837fdab88c66f10d3c14cad1");
1967
1968 let pubkey = api.secp256r1_recover_pubkey(&hash, &signature, 1).unwrap();
1970 assert_eq!(pubkey.len(), 65);
1971 assert_ne!(pubkey, expected);
1972
1973 let result = api.secp256r1_recover_pubkey(&hash, &signature, 42);
1975 match result.unwrap_err() {
1976 RecoverPubkeyError::InvalidRecoveryParam => {}
1977 err => panic!("Unexpected error: {err:?}"),
1978 }
1979 }
1980
1981 #[test]
1982 fn secp256r1_recover_pubkey_fails_for_wrong_hash() {
1983 let api = MockApi::default();
1984
1985 let hash = hex!("17b03f9f00f6692ccdde485fc63c4530751ef35da6f71336610944b0894fcfb8");
1986 let signature = hex!("9886ae46c1415c3bc959e82b760ad760aab66885a84e620aa339fdf102465c422bf3a80bc04faa35ebecc0f4864ac02d349f6f126e0f988501b8d3075409a26c");
1987 let recovery_param = 0;
1988 let expected = hex!("0451f99d2d52d4a6e734484a018b7ca2f895c2929b6754a3a03224d07ae61166ce4737da963c6ef7247fb88d19f9b0c667cac7fe12837fdab88c66f10d3c14cad1");
1989
1990 let mut corrupted_hash = hash;
1992 corrupted_hash[0] ^= 0x01;
1993 let pubkey = api
1994 .secp256r1_recover_pubkey(&corrupted_hash, &signature, recovery_param)
1995 .unwrap();
1996 assert_eq!(pubkey.len(), 65);
1997 assert_ne!(pubkey, expected);
1998
1999 let mut malformed_hash = hash.to_vec();
2001 malformed_hash.push(0x8a);
2002 let result = api.secp256r1_recover_pubkey(&malformed_hash, &signature, recovery_param);
2003 match result.unwrap_err() {
2004 RecoverPubkeyError::InvalidHashFormat => {}
2005 err => panic!("Unexpected error: {err:?}"),
2006 }
2007 }
2008
2009 #[test]
2011 fn ed25519_verify_works() {
2012 let api = MockApi::default();
2013
2014 let msg = hex::decode(ED25519_MSG_HEX).unwrap();
2015 let signature = hex::decode(ED25519_SIG_HEX).unwrap();
2016 let public_key = hex::decode(ED25519_PUBKEY_HEX).unwrap();
2017
2018 assert!(api.ed25519_verify(&msg, &signature, &public_key).unwrap());
2019 }
2020
2021 #[test]
2023 fn ed25519_verify_fails() {
2024 let api = MockApi::default();
2025
2026 let mut msg = hex::decode(ED25519_MSG_HEX).unwrap();
2027 msg[0] ^= 0x01;
2029 let signature = hex::decode(ED25519_SIG_HEX).unwrap();
2030 let public_key = hex::decode(ED25519_PUBKEY_HEX).unwrap();
2031
2032 assert!(!api.ed25519_verify(&msg, &signature, &public_key).unwrap());
2033 }
2034
2035 #[test]
2037 fn ed25519_verify_errs() {
2038 let api = MockApi::default();
2039
2040 let msg = hex::decode(ED25519_MSG_HEX).unwrap();
2041 let signature = hex::decode(ED25519_SIG_HEX).unwrap();
2042 let public_key = vec![];
2043
2044 let res = api.ed25519_verify(&msg, &signature, &public_key);
2045 assert_eq!(res.unwrap_err(), VerificationError::InvalidPubkeyFormat);
2046 }
2047
2048 #[test]
2050 fn ed25519_batch_verify_works() {
2051 let api = MockApi::default();
2052
2053 let msg = hex::decode(ED25519_MSG_HEX).unwrap();
2054 let signature = hex::decode(ED25519_SIG_HEX).unwrap();
2055 let public_key = hex::decode(ED25519_PUBKEY_HEX).unwrap();
2056
2057 let msgs: Vec<&[u8]> = vec![&msg];
2058 let signatures: Vec<&[u8]> = vec![&signature];
2059 let public_keys: Vec<&[u8]> = vec![&public_key];
2060
2061 assert!(api
2062 .ed25519_batch_verify(&msgs, &signatures, &public_keys)
2063 .unwrap());
2064 }
2065
2066 #[test]
2068 fn ed25519_batch_verify_fails() {
2069 let api = MockApi::default();
2070
2071 let mut msg = hex::decode(ED25519_MSG_HEX).unwrap();
2072 msg[0] ^= 0x01;
2074 let signature = hex::decode(ED25519_SIG_HEX).unwrap();
2075 let public_key = hex::decode(ED25519_PUBKEY_HEX).unwrap();
2076
2077 let msgs: Vec<&[u8]> = vec![&msg];
2078 let signatures: Vec<&[u8]> = vec![&signature];
2079 let public_keys: Vec<&[u8]> = vec![&public_key];
2080
2081 assert!(!api
2082 .ed25519_batch_verify(&msgs, &signatures, &public_keys)
2083 .unwrap());
2084 }
2085
2086 #[test]
2088 fn ed25519_batch_verify_errs() {
2089 let api = MockApi::default();
2090
2091 let msg = hex::decode(ED25519_MSG_HEX).unwrap();
2092 let signature = hex::decode(ED25519_SIG_HEX).unwrap();
2093 let public_key: Vec<u8> = vec![0u8; 0];
2094
2095 let msgs: Vec<&[u8]> = vec![msg.as_slice()];
2096 let signatures: Vec<&[u8]> = vec![signature.as_slice()];
2097 let public_keys: Vec<&[u8]> = vec![&public_key];
2098
2099 let res = api.ed25519_batch_verify(&msgs, &signatures, &public_keys);
2100 assert_eq!(res.unwrap_err(), VerificationError::InvalidPubkeyFormat);
2101 }
2102
2103 #[cfg(feature = "cosmwasm_1_1")]
2104 #[test]
2105 fn bank_querier_supply() {
2106 let addr1 = String::from("foo");
2107 let balance1 = vec![coin(123, "ELF"), coin(777, "FLY")];
2108
2109 let addr2 = String::from("bar");
2110 let balance2 = coins(321, "ELF");
2111
2112 let bank = BankQuerier::new(&[(&addr1, &balance1), (&addr2, &balance2)]);
2113
2114 let elf = bank
2115 .query(&BankQuery::Supply {
2116 denom: "ELF".to_string(),
2117 })
2118 .unwrap()
2119 .unwrap();
2120 let res: SupplyResponse = from_json(elf).unwrap();
2121 assert_eq!(res.amount, coin(444, "ELF"));
2122
2123 let fly = bank
2124 .query(&BankQuery::Supply {
2125 denom: "FLY".to_string(),
2126 })
2127 .unwrap()
2128 .unwrap();
2129 let res: SupplyResponse = from_json(fly).unwrap();
2130 assert_eq!(res.amount, coin(777, "FLY"));
2131
2132 let atom = bank
2134 .query(&BankQuery::Supply {
2135 denom: "ATOM".to_string(),
2136 })
2137 .unwrap()
2138 .unwrap();
2139 let res: SupplyResponse = from_json(atom).unwrap();
2140 assert_eq!(res.amount, coin(0, "ATOM"));
2141 }
2142
2143 #[test]
2144 fn bank_querier_one_balance() {
2145 let addr = String::from("foobar");
2146 let balance = vec![coin(123, "ELF"), coin(777, "FLY")];
2147 let bank = BankQuerier::new(&[(&addr, &balance)]);
2148
2149 let fly = bank
2151 .query(&BankQuery::Balance {
2152 address: addr.clone(),
2153 denom: "FLY".to_string(),
2154 })
2155 .unwrap()
2156 .unwrap();
2157 let res: BalanceResponse = from_json(fly).unwrap();
2158 assert_eq!(res.amount, coin(777, "FLY"));
2159
2160 let miss = bank
2162 .query(&BankQuery::Balance {
2163 address: addr,
2164 denom: "MISS".to_string(),
2165 })
2166 .unwrap()
2167 .unwrap();
2168 let res: BalanceResponse = from_json(miss).unwrap();
2169 assert_eq!(res.amount, coin(0, "MISS"));
2170 }
2171
2172 #[test]
2173 #[allow(deprecated)]
2174 fn bank_querier_missing_account() {
2175 let addr = String::from("foobar");
2176 let balance = vec![coin(123, "ELF"), coin(777, "FLY")];
2177 let bank = BankQuerier::new(&[(&addr, &balance)]);
2178
2179 let miss = bank
2181 .query(&BankQuery::Balance {
2182 address: String::from("elsewhere"),
2183 denom: "ELF".to_string(),
2184 })
2185 .unwrap()
2186 .unwrap();
2187 let res: BalanceResponse = from_json(miss).unwrap();
2188 assert_eq!(res.amount, coin(0, "ELF"));
2189 }
2190
2191 #[cfg(feature = "cosmwasm_1_3")]
2192 #[test]
2193 fn bank_querier_metadata_works() {
2194 let mut bank = BankQuerier::new(&[]);
2195 bank.set_denom_metadata(
2196 &(0..100)
2197 .map(|i| DenomMetadata {
2198 symbol: format!("FOO{i}"),
2199 name: "Foo".to_string(),
2200 description: "Foo coin".to_string(),
2201 denom_units: vec![DenomUnit {
2202 denom: "ufoo".to_string(),
2203 exponent: 8,
2204 aliases: vec!["microfoo".to_string(), "foobar".to_string()],
2205 }],
2206 display: "FOO".to_string(),
2207 base: format!("ufoo{i}"),
2208 uri: "https://foo.bar".to_string(),
2209 uri_hash: "foo".to_string(),
2210 })
2211 .collect::<Vec<_>>(),
2212 );
2213
2214 let res = bank
2216 .query(&BankQuery::AllDenomMetadata {
2217 pagination: Some(PageRequest {
2218 key: None,
2219 limit: 10,
2220 reverse: false,
2221 }),
2222 })
2223 .unwrap()
2224 .unwrap();
2225 let res: AllDenomMetadataResponse = from_json(res).unwrap();
2226 assert_eq!(res.metadata.len(), 10);
2227 assert!(res.next_key.is_some());
2228
2229 let res2 = bank
2231 .query(&BankQuery::AllDenomMetadata {
2232 pagination: Some(PageRequest {
2233 key: res.next_key,
2234 limit: 10,
2235 reverse: false,
2236 }),
2237 })
2238 .unwrap()
2239 .unwrap();
2240 let res2: AllDenomMetadataResponse = from_json(res2).unwrap();
2241 assert_eq!(res2.metadata.len(), 10);
2242 assert_ne!(res.metadata.last(), res2.metadata.first());
2243 for m in res.metadata {
2245 assert!(!res2.metadata.contains(&m));
2246 }
2247
2248 let res = bank
2250 .query(&BankQuery::AllDenomMetadata {
2251 pagination: Some(PageRequest {
2252 key: None,
2253 limit: 100,
2254 reverse: true,
2255 }),
2256 })
2257 .unwrap()
2258 .unwrap();
2259 let res: AllDenomMetadataResponse = from_json(res).unwrap();
2260 assert_eq!(res.metadata.len(), 100);
2261 assert!(res.next_key.is_none(), "no more data should be available");
2262 assert_eq!(res.metadata[0].symbol, "FOO99", "should have been reversed");
2263
2264 let more_res = bank
2265 .query(&BankQuery::AllDenomMetadata {
2266 pagination: Some(PageRequest {
2267 key: res.next_key,
2268 limit: u32::MAX,
2269 reverse: true,
2270 }),
2271 })
2272 .unwrap()
2273 .unwrap();
2274 let more_res: AllDenomMetadataResponse = from_json(more_res).unwrap();
2275 assert_eq!(
2276 more_res.metadata, res.metadata,
2277 "should be same as previous query"
2278 );
2279 }
2280
2281 #[cfg(feature = "cosmwasm_1_3")]
2282 #[test]
2283 fn distribution_querier_delegator_withdraw_address() {
2284 let mut distribution = DistributionQuerier::default();
2285 distribution.set_withdraw_address("addr0", "withdraw0");
2286
2287 let query = DistributionQuery::DelegatorWithdrawAddress {
2288 delegator_address: "addr0".to_string(),
2289 };
2290
2291 let res = distribution.query(&query).unwrap().unwrap();
2292 let res: DelegatorWithdrawAddressResponse = from_json(res).unwrap();
2293 assert_eq!(res.withdraw_address.as_str(), "withdraw0");
2294
2295 let query = DistributionQuery::DelegatorWithdrawAddress {
2296 delegator_address: "addr1".to_string(),
2297 };
2298
2299 let res = distribution.query(&query).unwrap().unwrap();
2300 let res: DelegatorWithdrawAddressResponse = from_json(res).unwrap();
2301 assert_eq!(res.withdraw_address.as_str(), "addr1");
2302 }
2303
2304 #[cfg(feature = "cosmwasm_1_4")]
2305 #[test]
2306 fn distribution_querier_delegator_validators() {
2307 let mut distribution = DistributionQuerier::default();
2308 distribution.set_validators("addr0", ["valoper1", "valoper2"]);
2309
2310 let query = DistributionQuery::DelegatorValidators {
2311 delegator_address: "addr0".to_string(),
2312 };
2313
2314 let res = distribution.query(&query).unwrap().unwrap();
2315 let res: DelegatorValidatorsResponse = from_json(res).unwrap();
2316 assert_eq!(res.validators, ["valoper1", "valoper2"]);
2317
2318 let query = DistributionQuery::DelegatorValidators {
2319 delegator_address: "addr1".to_string(),
2320 };
2321
2322 let res = distribution.query(&query).unwrap().unwrap();
2323 let res: DelegatorValidatorsResponse = from_json(res).unwrap();
2324 assert_eq!(res.validators, ([] as [String; 0]));
2325 }
2326
2327 #[cfg(feature = "cosmwasm_1_4")]
2328 #[test]
2329 fn distribution_querier_delegation_rewards() {
2330 use crate::{Decimal256, DelegationTotalRewardsResponse, DelegatorReward};
2331
2332 let mut distribution = DistributionQuerier::default();
2333 let valoper0_rewards = vec![
2334 DecCoin::new(Decimal256::from_atomics(1234u128, 0).unwrap(), "uatom"),
2335 DecCoin::new(Decimal256::from_atomics(56781234u128, 4).unwrap(), "utest"),
2336 ];
2337 distribution.set_rewards("valoper0", "addr0", valoper0_rewards.clone());
2338
2339 let query = DistributionQuery::DelegationRewards {
2341 delegator_address: "addr0".to_string(),
2342 validator_address: "valoper0".to_string(),
2343 };
2344 let res = distribution.query(&query).unwrap().unwrap();
2345 let res: DelegationRewardsResponse = from_json(res).unwrap();
2346 assert_eq!(res.rewards, valoper0_rewards);
2347
2348 let query = DistributionQuery::DelegationRewards {
2350 delegator_address: "nonexistent".to_string(),
2351 validator_address: "valoper0".to_string(),
2352 };
2353 let res = distribution.query(&query).unwrap().unwrap();
2354 let res: DelegationRewardsResponse = from_json(res).unwrap();
2355 assert_eq!(res.rewards.len(), 0);
2356
2357 let query = DistributionQuery::DelegationRewards {
2359 delegator_address: "addr0".to_string(),
2360 validator_address: "valopernonexistent".to_string(),
2361 };
2362 let res = distribution.query(&query).unwrap().unwrap();
2363 let res: DelegationRewardsResponse = from_json(res).unwrap();
2364 assert_eq!(res.rewards.len(), 0);
2365
2366 let valoper1_rewards = vec![DecCoin::new(Decimal256::one(), "uatom")];
2368 distribution.set_rewards("valoper1", "addr0", valoper1_rewards.clone());
2369
2370 let query = DistributionQuery::DelegationTotalRewards {
2372 delegator_address: "addr0".to_string(),
2373 };
2374 let res = distribution.query(&query).unwrap().unwrap();
2375 let res: DelegationTotalRewardsResponse = from_json(res).unwrap();
2376 assert_eq!(
2377 res.rewards,
2378 vec![
2379 DelegatorReward {
2380 validator_address: "valoper0".into(),
2381 reward: valoper0_rewards
2382 },
2383 DelegatorReward {
2384 validator_address: "valoper1".into(),
2385 reward: valoper1_rewards
2386 },
2387 ]
2388 );
2389 assert_eq!(
2390 res.total,
2391 [
2392 DecCoin::new(
2393 Decimal256::from_atomics(1234u128, 0).unwrap() + Decimal256::one(),
2394 "uatom"
2395 ),
2396 DecCoin::new(Decimal256::from_atomics(56781234u128, 4).unwrap(), "utest")
2398 ]
2399 );
2400 }
2401
2402 #[cfg(feature = "stargate")]
2403 #[test]
2404 fn ibc_querier_channel_existing() {
2405 let chan1 = mock_ibc_channel("channel-0", IbcOrder::Ordered, "ibc");
2406 let chan2 = mock_ibc_channel("channel-1", IbcOrder::Ordered, "ibc");
2407
2408 let ibc = IbcQuerier::new("myport", &[chan1.clone(), chan2]);
2409
2410 let query = &IbcQuery::Channel {
2412 channel_id: "channel-0".to_string(),
2413 port_id: Some("my_port".to_string()),
2414 };
2415 let raw = ibc.query(query).unwrap().unwrap();
2416 let chan: ChannelResponse = from_json(raw).unwrap();
2417 assert_eq!(chan.channel, Some(chan1));
2418 }
2419
2420 #[cfg(feature = "stargate")]
2421 #[test]
2422 fn ibc_querier_channel_existing_no_port() {
2423 let chan1 = IbcChannel {
2424 endpoint: IbcEndpoint {
2425 port_id: "myport".to_string(),
2426 channel_id: "channel-0".to_string(),
2427 },
2428 counterparty_endpoint: IbcEndpoint {
2429 port_id: "their_port".to_string(),
2430 channel_id: "channel-7".to_string(),
2431 },
2432 order: IbcOrder::Ordered,
2433 version: "ibc".to_string(),
2434 connection_id: "connection-2".to_string(),
2435 };
2436 let chan2 = mock_ibc_channel("channel-1", IbcOrder::Ordered, "ibc");
2437
2438 let ibc = IbcQuerier::new("myport", &[chan1.clone(), chan2]);
2439
2440 let query = &IbcQuery::Channel {
2442 channel_id: "channel-0".to_string(),
2443 port_id: Some("myport".to_string()),
2444 };
2445 let raw = ibc.query(query).unwrap().unwrap();
2446 let chan: ChannelResponse = from_json(raw).unwrap();
2447 assert_eq!(chan.channel, Some(chan1));
2448 }
2449
2450 #[cfg(feature = "stargate")]
2451 #[test]
2452 fn ibc_querier_channel_none() {
2453 let chan1 = mock_ibc_channel("channel-0", IbcOrder::Ordered, "ibc");
2454 let chan2 = mock_ibc_channel("channel-1", IbcOrder::Ordered, "ibc");
2455
2456 let ibc = IbcQuerier::new("myport", &[chan1, chan2]);
2457
2458 let query = &IbcQuery::Channel {
2460 channel_id: "channel-0".to_string(),
2461 port_id: None,
2462 };
2463 let raw = ibc.query(query).unwrap().unwrap();
2464 let chan: ChannelResponse = from_json(raw).unwrap();
2465 assert_eq!(chan.channel, None);
2466 }
2467
2468 #[cfg(feature = "stargate")]
2469 #[test]
2470 fn ibc_querier_port() {
2471 let chan1 = mock_ibc_channel("channel-0", IbcOrder::Ordered, "ibc");
2472
2473 let ibc = IbcQuerier::new("myport", &[chan1]);
2474
2475 let query = &IbcQuery::PortId {};
2477 let raw = ibc.query(query).unwrap().unwrap();
2478 let res: PortIdResponse = from_json(raw).unwrap();
2479 assert_eq!(res.port_id, "myport");
2480 }
2481
2482 #[cfg(feature = "staking")]
2483 #[test]
2484 fn staking_querier_all_validators() {
2485 let val1 = Validator {
2486 address: String::from("validator-one"),
2487 commission: Decimal::percent(1),
2488 max_commission: Decimal::percent(3),
2489 max_change_rate: Decimal::percent(1),
2490 };
2491 let val2 = Validator {
2492 address: String::from("validator-two"),
2493 commission: Decimal::permille(15),
2494 max_commission: Decimal::permille(40),
2495 max_change_rate: Decimal::permille(5),
2496 };
2497
2498 let staking = StakingQuerier::new("ustake", &[val1.clone(), val2.clone()], &[]);
2499
2500 let raw = staking
2502 .query(&StakingQuery::AllValidators {})
2503 .unwrap()
2504 .unwrap();
2505 let vals: AllValidatorsResponse = from_json(raw).unwrap();
2506 assert_eq!(vals.validators, vec![val1.into(), val2.into()]);
2507 }
2508
2509 #[cfg(feature = "staking")]
2510 #[test]
2511 fn staking_querier_validator() {
2512 let address1 = String::from("validator-one");
2513 let address2 = String::from("validator-two");
2514 let address_non_existent = String::from("wannabe-validator");
2515
2516 let val1 = Validator {
2517 address: address1.clone(),
2518 commission: Decimal::percent(1),
2519 max_commission: Decimal::percent(3),
2520 max_change_rate: Decimal::percent(1),
2521 };
2522 let val2 = Validator {
2523 address: address2.clone(),
2524 commission: Decimal::permille(15),
2525 max_commission: Decimal::permille(40),
2526 max_change_rate: Decimal::permille(5),
2527 };
2528
2529 let staking = StakingQuerier::new("ustake", &[val1.clone(), val2.clone()], &[]);
2530
2531 let raw = staking
2533 .query(&StakingQuery::Validator { address: address1 })
2534 .unwrap()
2535 .unwrap();
2536 let res: ValidatorResponse = from_json(raw).unwrap();
2537 assert_eq!(res.validator, Some(val1));
2538
2539 let raw = staking
2541 .query(&StakingQuery::Validator { address: address2 })
2542 .unwrap()
2543 .unwrap();
2544 let res: ValidatorResponse = from_json(raw).unwrap();
2545 assert_eq!(res.validator, Some(val2));
2546
2547 let raw = staking
2549 .query(&StakingQuery::Validator {
2550 address: address_non_existent,
2551 })
2552 .unwrap()
2553 .unwrap();
2554 let res: ValidatorResponse = from_json(raw).unwrap();
2555 assert_eq!(res.validator, None);
2556 }
2557
2558 #[cfg(feature = "staking")]
2559 fn get_all_delegators(
2561 staking: &StakingQuerier,
2562 delegator: impl Into<String>,
2563 ) -> Vec<Delegation> {
2564 let raw = staking
2565 .query(&StakingQuery::AllDelegations {
2566 delegator: delegator.into(),
2567 })
2568 .unwrap()
2569 .unwrap();
2570 let dels: AllDelegationsResponse = from_json(raw).unwrap();
2571 dels.delegations
2572 }
2573
2574 #[cfg(feature = "staking")]
2575 fn get_delegator(
2577 staking: &StakingQuerier,
2578 delegator: impl Into<String>,
2579 validator: impl Into<String>,
2580 ) -> Option<FullDelegation> {
2581 let raw = staking
2582 .query(&StakingQuery::Delegation {
2583 delegator: delegator.into(),
2584 validator: validator.into(),
2585 })
2586 .unwrap()
2587 .unwrap();
2588 let dels: DelegationResponse = from_json(raw).unwrap();
2589 dels.delegation
2590 }
2591
2592 #[cfg(feature = "staking")]
2593 #[test]
2594 fn staking_querier_delegations() {
2595 let val1 = String::from("validator-one");
2596 let val2 = String::from("validator-two");
2597
2598 let user_a = Addr::unchecked("investor");
2599 let user_b = Addr::unchecked("speculator");
2600 let user_c = Addr::unchecked("hodler");
2601
2602 let del1a = FullDelegation {
2604 delegator: user_a.clone(),
2605 validator: val1.clone(),
2606 amount: coin(100, "ustake"),
2607 can_redelegate: coin(100, "ustake"),
2608 accumulated_rewards: coins(5, "ustake"),
2609 };
2610 let del2a = FullDelegation {
2611 delegator: user_a.clone(),
2612 validator: val2.clone(),
2613 amount: coin(500, "ustake"),
2614 can_redelegate: coin(500, "ustake"),
2615 accumulated_rewards: coins(20, "ustake"),
2616 };
2617
2618 let del1b = FullDelegation {
2620 delegator: user_b.clone(),
2621 validator: val1.clone(),
2622 amount: coin(500, "ustake"),
2623 can_redelegate: coin(0, "ustake"),
2624 accumulated_rewards: coins(0, "ustake"),
2625 };
2626
2627 let del2c = FullDelegation {
2629 delegator: user_c.clone(),
2630 validator: val2.clone(),
2631 amount: coin(8888, "ustake"),
2632 can_redelegate: coin(4567, "ustake"),
2633 accumulated_rewards: coins(900, "ustake"),
2634 };
2635
2636 let staking = StakingQuerier::new(
2637 "ustake",
2638 &[],
2639 &[del1a.clone(), del1b.clone(), del2a.clone(), del2c.clone()],
2640 );
2641
2642 let dels = get_all_delegators(&staking, user_a.clone());
2644 assert_eq!(dels, vec![del1a.clone().into(), del2a.clone().into()]);
2645
2646 let dels = get_all_delegators(&staking, user_b.clone());
2648 assert_eq!(dels, vec![del1b.clone().into()]);
2649
2650 let dels = get_all_delegators(&staking, user_c.clone());
2652 assert_eq!(dels, vec![del2c.clone().into()]);
2653
2654 let dels = get_all_delegators(&staking, String::from("no one"));
2656 assert_eq!(dels, vec![]);
2657
2658 let dels = get_delegator(&staking, user_a.clone(), val1.clone());
2660 assert_eq!(dels, Some(del1a));
2661 let dels = get_delegator(&staking, user_a, val2.clone());
2662 assert_eq!(dels, Some(del2a));
2663
2664 let dels = get_delegator(&staking, user_b.clone(), val1.clone());
2666 assert_eq!(dels, Some(del1b));
2667 let dels = get_delegator(&staking, user_b, val2.clone());
2668 assert_eq!(dels, None);
2669
2670 let dels = get_delegator(&staking, user_c.clone(), val1);
2672 assert_eq!(dels, None);
2673 let dels = get_delegator(&staking, user_c, val2);
2674 assert_eq!(dels, Some(del2c));
2675 }
2676
2677 #[test]
2678 fn wasm_querier_works() {
2679 let mut querier = WasmQuerier::default();
2680
2681 let any_addr = "foo".to_string();
2682
2683 let system_err = querier
2685 .query(&WasmQuery::Raw {
2686 contract_addr: any_addr.clone(),
2687 key: b"the key".into(),
2688 })
2689 .unwrap_err();
2690 match system_err {
2691 SystemError::NoSuchContract { addr } => assert_eq!(addr, any_addr),
2692 err => panic!("Unexpected error: {err:?}"),
2693 }
2694
2695 let system_err = querier
2697 .query(&WasmQuery::Smart {
2698 contract_addr: any_addr.clone(),
2699 msg: b"{}".into(),
2700 })
2701 .unwrap_err();
2702 match system_err {
2703 SystemError::NoSuchContract { addr } => assert_eq!(addr, any_addr),
2704 err => panic!("Unexpected error: {err:?}"),
2705 }
2706
2707 let system_err = querier
2709 .query(&WasmQuery::ContractInfo {
2710 contract_addr: any_addr.clone(),
2711 })
2712 .unwrap_err();
2713 match system_err {
2714 SystemError::NoSuchContract { addr } => assert_eq!(addr, any_addr),
2715 err => panic!("Unexpected error: {err:?}"),
2716 }
2717
2718 #[cfg(feature = "cosmwasm_1_2")]
2719 {
2720 let system_err = querier
2722 .query(&WasmQuery::CodeInfo { code_id: 4 })
2723 .unwrap_err();
2724 match system_err {
2725 SystemError::NoSuchCode { code_id } => assert_eq!(code_id, 4),
2726 err => panic!("Unexpected error: {err:?}"),
2727 }
2728 }
2729
2730 #[cfg(all(feature = "cosmwasm_3_0", feature = "iterator"))]
2731 {
2732 let system_err = querier
2734 .query(&WasmQuery::RawRange {
2735 contract_addr: any_addr.clone(),
2736 start: None,
2737 end: None,
2738 limit: 10,
2739 order: crate::Order::Ascending,
2740 })
2741 .unwrap_err();
2742 match system_err {
2743 SystemError::NoSuchContract { addr } => assert_eq!(addr, any_addr),
2744 err => panic!("Unexpected error: {err:?}"),
2745 }
2746 }
2747
2748 querier.update_handler(|request| {
2749 let api = MockApi::default();
2750 let contract1 = api.addr_make("contract1");
2751 let mut storage1 = MockStorage::new();
2752 storage1.set(b"the key", b"the value");
2753
2754 match request {
2755 WasmQuery::Raw { contract_addr, key } => {
2756 let Ok(addr) = api.addr_validate(contract_addr) else {
2757 return SystemResult::Err(SystemError::NoSuchContract {
2758 addr: contract_addr.clone(),
2759 });
2760 };
2761 if addr == contract1 {
2762 if let Some(value) = storage1.get(key) {
2763 SystemResult::Ok(ContractResult::Ok(Binary::new(value)))
2764 } else {
2765 SystemResult::Ok(ContractResult::Ok(Binary::default()))
2766 }
2767 } else {
2768 SystemResult::Err(SystemError::NoSuchContract {
2769 addr: contract_addr.clone(),
2770 })
2771 }
2772 }
2773 WasmQuery::Smart { contract_addr, msg } => {
2774 let Ok(addr) = api.addr_validate(contract_addr) else {
2775 return SystemResult::Err(SystemError::NoSuchContract {
2776 addr: contract_addr.clone(),
2777 });
2778 };
2779 if addr == contract1 {
2780 #[derive(Deserialize)]
2781 struct MyMsg {}
2782 let _msg: MyMsg = match from_json(msg) {
2783 Ok(msg) => msg,
2784 Err(err) => {
2785 return SystemResult::Ok(ContractResult::Err(err.to_string()))
2786 }
2787 };
2788 let response: Response = Response::new().set_data(b"good");
2789 SystemResult::Ok(ContractResult::Ok(to_json_binary(&response).unwrap()))
2790 } else {
2791 SystemResult::Err(SystemError::NoSuchContract {
2792 addr: contract_addr.clone(),
2793 })
2794 }
2795 }
2796 WasmQuery::ContractInfo { contract_addr } => {
2797 let Ok(addr) = api.addr_validate(contract_addr) else {
2798 return SystemResult::Err(SystemError::NoSuchContract {
2799 addr: contract_addr.clone(),
2800 });
2801 };
2802 if addr == contract1 {
2803 let response = ContractInfoResponse {
2804 code_id: 4,
2805 creator: Addr::unchecked("lalala"),
2806 admin: None,
2807 pinned: false,
2808 ibc_port: None,
2809 ibc2_port: None,
2810 };
2811 SystemResult::Ok(ContractResult::Ok(to_json_binary(&response).unwrap()))
2812 } else {
2813 SystemResult::Err(SystemError::NoSuchContract {
2814 addr: contract_addr.clone(),
2815 })
2816 }
2817 }
2818 #[cfg(feature = "cosmwasm_1_2")]
2819 WasmQuery::CodeInfo { code_id } => {
2820 use crate::{Checksum, CodeInfoResponse};
2821 let code_id = *code_id;
2822 if code_id == 4 {
2823 let response = CodeInfoResponse {
2824 code_id,
2825 creator: Addr::unchecked("lalala"),
2826 checksum: Checksum::from_hex(
2827 "84cf20810fd429caf58898c3210fcb71759a27becddae08dbde8668ea2f4725d",
2828 )
2829 .unwrap(),
2830 };
2831 SystemResult::Ok(ContractResult::Ok(to_json_binary(&response).unwrap()))
2832 } else {
2833 SystemResult::Err(SystemError::NoSuchCode { code_id })
2834 }
2835 }
2836 #[cfg(all(feature = "cosmwasm_3_0", feature = "iterator"))]
2837 WasmQuery::RawRange {
2838 contract_addr,
2839 start,
2840 end,
2841 limit,
2842 order,
2843 } => {
2844 let Ok(addr) = api.addr_validate(contract_addr) else {
2845 return SystemResult::Err(SystemError::NoSuchContract {
2846 addr: contract_addr.clone(),
2847 });
2848 };
2849 if addr == contract1 {
2850 let mut data: Vec<_> = storage1
2851 .range(
2852 start.as_ref().map(Binary::as_slice),
2853 end.as_ref().map(Binary::as_slice),
2854 *order,
2855 )
2856 .take(*limit as usize + 1) .map(|(key, value)| (Binary::new(key), Binary::new(value)))
2858 .collect();
2859
2860 let next_key = if data.len() > *limit as usize {
2862 data.pop().map(|(key, _)| key)
2863 } else {
2864 None
2865 };
2866 let raw_range_response = crate::RawRangeResponse { data, next_key };
2867
2868 SystemResult::Ok(ContractResult::Ok(
2869 to_json_binary(&raw_range_response).unwrap(),
2870 ))
2871 } else {
2872 SystemResult::Err(SystemError::NoSuchContract {
2873 addr: contract_addr.clone(),
2874 })
2875 }
2876 }
2877 }
2878 });
2879
2880 let contract_addr = MockApi::default().addr_make("contract1");
2881
2882 let result = querier.query(&WasmQuery::Raw {
2884 contract_addr: contract_addr.clone().into(),
2885 key: b"the key".into(),
2886 });
2887
2888 match result {
2889 SystemResult::Ok(ContractResult::Ok(value)) => assert_eq!(value, b"the value" as &[u8]),
2890 res => panic!("Unexpected result: {res:?}"),
2891 }
2892 let result = querier.query(&WasmQuery::Raw {
2893 contract_addr: contract_addr.clone().into(),
2894 key: b"other key".into(),
2895 });
2896 match result {
2897 SystemResult::Ok(ContractResult::Ok(value)) => assert_eq!(value, b"" as &[u8]),
2898 res => panic!("Unexpected result: {res:?}"),
2899 }
2900
2901 let result = querier.query(&WasmQuery::Smart {
2903 contract_addr: contract_addr.clone().into(),
2904 msg: b"{}".into(),
2905 });
2906 match result {
2907 SystemResult::Ok(ContractResult::Ok(value)) => assert_eq!(
2908 value,
2909 br#"{"messages":[],"attributes":[],"events":[],"data":"Z29vZA=="}"# as &[u8]
2910 ),
2911 res => panic!("Unexpected result: {res:?}"),
2912 }
2913 let result = querier.query(&WasmQuery::Smart {
2914 contract_addr: contract_addr.clone().into(),
2915 msg: b"a broken request".into(),
2916 });
2917 match result {
2918 SystemResult::Ok(ContractResult::Err(err)) => {
2919 assert_eq!(
2920 err,
2921 "kind: Serialization, error: expected value at line 1 column 1"
2922 )
2923 }
2924 res => panic!("Unexpected result: {res:?}"),
2925 }
2926
2927 let result = querier.query(&WasmQuery::ContractInfo {
2929 contract_addr: contract_addr.clone().into(),
2930 });
2931 match result {
2932 SystemResult::Ok(ContractResult::Ok(value)) => assert_eq!(
2933 value,
2934 br#"{"code_id":4,"creator":"lalala","admin":null,"pinned":false,"ibc_port":null,"ibc2_port":null}"#
2935 as &[u8]
2936 ),
2937 res => panic!("Unexpected result: {res:?}"),
2938 }
2939
2940 #[cfg(feature = "cosmwasm_1_2")]
2942 {
2943 let result = querier.query(&WasmQuery::CodeInfo { code_id: 4 });
2944 match result {
2945 SystemResult::Ok(ContractResult::Ok(value)) => assert_eq!(
2946 value,
2947 br#"{"code_id":4,"creator":"lalala","checksum":"84cf20810fd429caf58898c3210fcb71759a27becddae08dbde8668ea2f4725d"}"#
2948 ),
2949 res => panic!("Unexpected result: {res:?}"),
2950 }
2951 }
2952
2953 #[cfg(all(feature = "cosmwasm_3_0", feature = "iterator"))]
2954 {
2955 let result = querier.query(&WasmQuery::RawRange {
2956 contract_addr: contract_addr.clone().into(),
2957 start: Some(Binary::from(b"the key")),
2958 end: Some(Binary::from(b"the keyasdf")),
2959 limit: 10,
2960 order: crate::Order::Ascending,
2961 });
2962 match result {
2963 SystemResult::Ok(ContractResult::Ok(value)) => assert_eq!(
2964 value.as_slice(),
2965 br#"{"data":[["dGhlIGtleQ==","dGhlIHZhbHVl"]],"next_key":null}"#
2966 ),
2967 res => panic!("Unexpected result: {res:?}"),
2968 }
2969 }
2970 }
2971
2972 #[test]
2973 fn making_an_address_works() {
2974 let mock_api = MockApi::default();
2975
2976 assert_eq!(
2977 mock_api.addr_make("creator").to_string(),
2978 "cosmwasm1h34lmpywh4upnjdg90cjf4j70aee6z8qqfspugamjp42e4q28kqs8s7vcp",
2979 );
2980
2981 assert_eq!(
2982 mock_api.addr_make("").to_string(),
2983 "cosmwasm1uwcvgs5clswpfxhm7nyfjmaeysn6us0yvjdexn9yjkv3k7zjhp2sly4xh9",
2984 );
2985
2986 let mock_api = MockApi::default().with_prefix("juno");
2987 assert_eq!(
2988 mock_api.addr_make("creator").to_string(),
2989 "juno1h34lmpywh4upnjdg90cjf4j70aee6z8qqfspugamjp42e4q28kqsksmtyp",
2990 );
2991 }
2992
2993 #[test]
2994 fn colon_in_prefix_is_valid() {
2995 let mock_api = MockApi::default().with_prefix("did:com:");
2996 let addr = mock_api
2997 .addr_validate("did:com:1jkf0kmeyefvyzpwf56m7sne2000ay53r6upttu")
2998 .unwrap();
2999
3000 assert_eq!(
3001 addr.as_str(),
3002 "did:com:1jkf0kmeyefvyzpwf56m7sne2000ay53r6upttu"
3003 );
3004 }
3005
3006 #[test]
3007 #[should_panic(
3008 expected = "Generating address failed with reason: hrp is empty, must have at least 1 character"
3009 )]
3010 fn making_an_address_with_empty_prefix_should_panic() {
3011 MockApi::default().with_prefix("").addr_make("creator");
3012 }
3013
3014 #[test]
3015 #[cfg(feature = "cosmwasm_1_3")]
3016 fn distribution_querier_new_works() {
3017 let addresses = [
3018 ("addr0000".to_string(), "addr0001".to_string()),
3019 ("addr0002".to_string(), "addr0001".to_string()),
3020 ];
3021 let btree_map = BTreeMap::from(addresses.clone());
3022
3023 let hashmap = std::collections::HashMap::from(addresses.clone());
3025 let querier = DistributionQuerier::new(hashmap);
3026 assert_eq!(querier.withdraw_addresses, btree_map);
3027
3028 let querier = DistributionQuerier::new(btree_map.clone());
3030 assert_eq!(querier.withdraw_addresses, btree_map);
3031
3032 let querier = DistributionQuerier::new(addresses);
3034 assert_eq!(querier.withdraw_addresses, btree_map);
3035 }
3036
3037 #[test]
3038 fn instantiate2_address_can_be_humanized() {
3039 let mock_api = MockApi::default();
3040
3041 let contract_addr = mock_api
3042 .addr_canonicalize(mock_api.addr_make("contract").as_str())
3043 .unwrap();
3044 let checksum =
3045 HexBinary::from_hex("9af782a3a1bcbcd22dbb6a45c751551d9af782a3a1bcbcd22dbb6a45c751551d")
3046 .unwrap();
3047 let salt = b"instance 1231";
3048 let canonical_addr = instantiate2_address(&checksum, &contract_addr, salt).unwrap();
3049 mock_api.addr_humanize(&canonical_addr).unwrap();
3051 }
3052}