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