cw_multi_test/
contracts.rs

1//! # Implementation of the contract trait and contract wrapper
2
3use crate::error::{anyhow, bail, AnyError, AnyResult};
4use cosmwasm_std::{
5    from_json, Binary, Checksum, CosmosMsg, CustomMsg, CustomQuery, Deps, DepsMut, Empty, Env,
6    MessageInfo, QuerierWrapper, Reply, Response, SubMsg,
7};
8use serde::de::DeserializeOwned;
9use std::fmt::{Debug, Display};
10use std::ops::Deref;
11
12/// This trait serves as a primary interface for interacting with contracts.
13#[rustfmt::skip]
14pub trait Contract<C, Q = Empty>
15where
16    C: CustomMsg,
17    Q: CustomQuery,
18{
19    /// Evaluates contract's `execute` entry-point.
20    fn execute(&self, deps: DepsMut<Q>, env: Env, info: MessageInfo, msg: Vec<u8>) -> AnyResult<Response<C>>;
21
22    /// Evaluates contract's `instantiate` entry-point.
23    fn instantiate(&self, deps: DepsMut<Q>, env: Env, info: MessageInfo, msg: Vec<u8>) -> AnyResult<Response<C>>;
24
25    /// Evaluates contract's `query` entry-point.
26    fn query(&self, deps: Deps<Q>, env: Env, msg: Vec<u8>) -> AnyResult<Binary>;
27
28    /// Evaluates contract's `sudo` entry-point.
29    fn sudo(&self, deps: DepsMut<Q>, env: Env, msg: Vec<u8>) -> AnyResult<Response<C>>;
30
31    /// Evaluates contract's `reply` entry-point.
32    fn reply(&self, deps: DepsMut<Q>, env: Env, msg: Reply) -> AnyResult<Response<C>>;
33
34    /// Evaluates contract's `migrate` entry-point.
35    fn migrate(&self, deps: DepsMut<Q>, env: Env, msg: Vec<u8>) -> AnyResult<Response<C>>;
36
37    /// Returns the provided checksum of the contract's Wasm blob.
38    fn checksum(&self) -> Option<Checksum> {
39        None
40    }
41}
42
43#[rustfmt::skip]
44mod closures {
45    use super::*;
46
47    // function types
48    pub type ContractFn<T, C, E, Q> = fn(deps: DepsMut<Q>, env: Env, info: MessageInfo, msg: T) -> Result<Response<C>, E>;
49    pub type PermissionedFn<T, C, E, Q> = fn(deps: DepsMut<Q>, env: Env, msg: T) -> Result<Response<C>, E>;
50    pub type ReplyFn<C, E, Q> = fn(deps: DepsMut<Q>, env: Env, msg: Reply) -> Result<Response<C>, E>;
51    pub type QueryFn<T, E, Q> = fn(deps: Deps<Q>, env: Env, msg: T) -> Result<Binary, E>;
52
53    // closure types
54    pub type ContractClosure<T, C, E, Q> = Box<dyn Fn(DepsMut<Q>, Env, MessageInfo, T) -> Result<Response<C>, E>>;
55    pub type PermissionedClosure<T, C, E, Q> = Box<dyn Fn(DepsMut<Q>, Env, T) -> Result<Response<C>, E>>;
56    pub type ReplyClosure<C, E, Q> = Box<dyn Fn(DepsMut<Q>, Env, Reply) -> Result<Response<C>, E>>;
57    pub type QueryClosure<T, E, Q> = Box<dyn Fn(Deps<Q>, Env, T) -> Result<Binary, E>>;
58}
59
60use closures::*;
61
62/// This structure wraps the [Contract] trait implementor
63/// and provides generic access to the contract's entry-points.
64///
65/// List of generic types used in [ContractWrapper]:
66/// - **T1** type of message passed to [execute] entry-point.
67/// - **T2** type of message passed to [instantiate] entry-point.
68/// - **T3** type of message passed to [query] entry-point.
69/// - **T4** type of message passed to [sudo] entry-point.
70/// - instead of **~~T5~~**, always the `Reply` type is used in [reply] entry-point.
71/// - **T6** type of message passed to [migrate] entry-point.
72/// - **E1** type of error returned from [execute] entry-point.
73/// - **E2** type of error returned from [instantiate] entry-point.
74/// - **E3** type of error returned from [query] entry-point.
75/// - **E4** type of error returned from [sudo] entry-point.
76/// - **E5** type of error returned from [reply] entry-point.
77/// - **E6** type of error returned from [migrate] entry-point.
78/// - **C** type of custom message returned from all entry-points except [query].
79/// - **Q** type of custom query in `Querier` passed as 'Deps' or 'DepsMut' to all entry-points.
80///
81/// The following table summarizes the purpose of all generic types used in [ContractWrapper].
82/// ```text
83/// ┌─────────────┬────────────────┬─────────────────────┬─────────┬─────────┬───────┬───────┐
84/// │  Contract   │    Contract    │                     │         │         │       │       │
85/// │ entry-point │    wrapper     │    Closure type     │ Message │ Message │ Error │ Query │
86/// │             │    member      │                     │   IN    │   OUT   │  OUT  │       │
87/// ╞═════════════╪════════════════╪═════════════════════╪═════════╪═════════╪═══════╪═══════╡
88/// │     (1)     │                │                     │         │         │       │       │
89/// ╞═════════════╪════════════════╪═════════════════════╪═════════╪═════════╪═══════╪═══════╡
90/// │ execute     │ execute_fn     │ ContractClosure     │   T1    │    C    │  E1   │   Q   │
91/// ├─────────────┼────────────────┼─────────────────────┼─────────┼─────────┼───────┼───────┤
92/// │ instantiate │ instantiate_fn │ ContractClosure     │   T2    │    C    │  E2   │   Q   │
93/// ├─────────────┼────────────────┼─────────────────────┼─────────┼─────────┼───────┼───────┤
94/// │ query       │ query_fn       │ QueryClosure        │   T3    │ Binary  │  E3   │   Q   │
95/// ├─────────────┼────────────────┼─────────────────────┼─────────┼─────────┼───────┼───────┤
96/// │ sudo        │ sudo_fn        │ PermissionedClosure │   T4    │    C    │  E4   │   Q   │
97/// ├─────────────┼────────────────┼─────────────────────┼─────────┼─────────┼───────┼───────┤
98/// │ reply       │ reply_fn       │ ReplyClosure        │  Reply  │    C    │  E5   │   Q   │
99/// ├─────────────┼────────────────┼─────────────────────┼─────────┼─────────┼───────┼───────┤
100/// │ migrate     │ migrate_fn     │ PermissionedClosure │   T6    │    C    │  E6   │   Q   │
101/// └─────────────┴────────────────┴─────────────────────┴─────────┴─────────┴───────┴───────┘
102/// ```
103/// The general schema depicting which generic type is used in entry points is shown below.
104/// Entry point, when called, is provided minimum two arguments: custom query of type **Q**
105/// (inside `Deps` or `DepsMut`) and input message of type **T1**, **T2**, **T3**, **T4**,
106/// **Reply** or **T6**. As a result, entry point returns custom output message of type
107/// Response<**C**> or **Binary** and an error of type **E1**, **E2**, **E3**, **E4**, **E5**
108/// or **E6**.
109///
110/// ```text
111///    entry_point(query, .., message_in) -> Result<message_out, error>
112///                  ┬           ┬                      ┬          ┬
113///             Q >──┘           │                      │          └──> E1,E2,E3,E4,E5,E6
114///    T1,T2,T3,T4,Reply,T6 >────┘                      └─────────────> C,Binary
115/// ```
116/// Generic type **C** defines a custom message that is specific for the **whole blockchain**.
117/// Similarly, the generic type **Q** defines a custom query that is also specific
118/// to the **whole blockchain**. Other generic types are specific to the implemented contract.
119/// So all smart contracts used in the same blockchain will have the same types for **C** and **Q**,
120/// but each contract may use different type for other generic types.
121/// It means that e.g. **T1** in smart contract `A` may differ from **T1** in smart contract `B`.
122///
123/// [execute]: Contract::execute
124/// [instantiate]: Contract::instantiate
125/// [query]: Contract::query
126/// [sudo]: Contract::sudo
127/// [reply]: Contract::reply
128/// [migrate]: Contract::migrate
129pub struct ContractWrapper<
130    T1,
131    T2,
132    T3,
133    E1,
134    E2,
135    E3,
136    C = Empty,
137    Q = Empty,
138    T4 = Empty,
139    E4 = AnyError,
140    E5 = AnyError,
141    T6 = Empty,
142    E6 = AnyError,
143> where
144    T1: DeserializeOwned, // Type of message passed to `execute` entry-point.
145    T2: DeserializeOwned, // Type of message passed to `instantiate` entry-point.
146    T3: DeserializeOwned, // Type of message passed to `query` entry-point.
147    T4: DeserializeOwned, // Type of message passed to `sudo` entry-point.
148    T6: DeserializeOwned, // Type of message passed to `migrate` entry-point.
149    E1: Display + Debug + Send + Sync, // Type of error returned from `execute` entry-point.
150    E2: Display + Debug + Send + Sync, // Type of error returned from `instantiate` entry-point.
151    E3: Display + Debug + Send + Sync, // Type of error returned from `query` entry-point.
152    E4: Display + Debug + Send + Sync, // Type of error returned from `sudo` entry-point.
153    E5: Display + Debug + Send + Sync, // Type of error returned from `reply` entry-point.
154    E6: Display + Debug + Send + Sync, // Type of error returned from `migrate` entry-point.
155    C: CustomMsg,         // Type of custom message returned from all entry-points except `query`.
156    Q: CustomQuery + DeserializeOwned, // Type of custom query in querier passed as deps/deps_mut to all entry-points.
157{
158    execute_fn: ContractClosure<T1, C, E1, Q>,
159    instantiate_fn: ContractClosure<T2, C, E2, Q>,
160    query_fn: QueryClosure<T3, E3, Q>,
161    sudo_fn: Option<PermissionedClosure<T4, C, E4, Q>>,
162    reply_fn: Option<ReplyClosure<C, E5, Q>>,
163    migrate_fn: Option<PermissionedClosure<T6, C, E6, Q>>,
164    checksum: Option<Checksum>,
165}
166
167impl<T1, T2, T3, E1, E2, E3, C, Q> ContractWrapper<T1, T2, T3, E1, E2, E3, C, Q>
168where
169    T1: DeserializeOwned + 'static, // Type of message passed to `execute` entry-point.
170    T2: DeserializeOwned + 'static, // Type of message passed to `instantiate` entry-point.
171    T3: DeserializeOwned + 'static, // Type of message passed to `query` entry-point.
172    E1: Display + Debug + Send + Sync + 'static, // Type of error returned from `execute` entry-point.
173    E2: Display + Debug + Send + Sync + 'static, // Type of error returned from `instantiate` entry-point.
174    E3: Display + Debug + Send + Sync + 'static, // Type of error returned from `query` entry-point.
175    C: CustomMsg + 'static, // Type of custom message returned from all entry-points except `query`.
176    Q: CustomQuery + DeserializeOwned + 'static, // Type of custom query in querier passed as deps/deps_mut to all entry-points.
177{
178    /// Creates a new contract wrapper with default settings.
179    pub fn new(
180        execute_fn: ContractFn<T1, C, E1, Q>,
181        instantiate_fn: ContractFn<T2, C, E2, Q>,
182        query_fn: QueryFn<T3, E3, Q>,
183    ) -> Self {
184        Self {
185            execute_fn: Box::new(execute_fn),
186            instantiate_fn: Box::new(instantiate_fn),
187            query_fn: Box::new(query_fn),
188            sudo_fn: None,
189            reply_fn: None,
190            migrate_fn: None,
191            checksum: None,
192        }
193    }
194
195    /// This will take a contract that returns `Response<Empty>` and will _upgrade_ it
196    /// to `Response<C>` if needed, to be compatible with a chain-specific extension.
197    pub fn new_with_empty(
198        execute_fn: ContractFn<T1, Empty, E1, Empty>,
199        instantiate_fn: ContractFn<T2, Empty, E2, Empty>,
200        query_fn: QueryFn<T3, E3, Empty>,
201    ) -> Self {
202        Self {
203            execute_fn: customize_contract_fn(execute_fn),
204            instantiate_fn: customize_contract_fn(instantiate_fn),
205            query_fn: customize_query_fn(query_fn),
206            sudo_fn: None,
207            reply_fn: None,
208            migrate_fn: None,
209            checksum: None,
210        }
211    }
212}
213
214#[allow(clippy::type_complexity)]
215impl<T1, T2, T3, E1, E2, E3, C, Q, T4, E4, E5, T6, E6>
216    ContractWrapper<T1, T2, T3, E1, E2, E3, C, Q, T4, E4, E5, T6, E6>
217where
218    T1: DeserializeOwned, // Type of message passed to `execute` entry-point.
219    T2: DeserializeOwned, // Type of message passed to `instantiate` entry-point.
220    T3: DeserializeOwned, // Type of message passed to `query` entry-point.
221    T4: DeserializeOwned, // Type of message passed to `sudo` entry-point.
222    T6: DeserializeOwned, // Type of message passed to `migrate` entry-point.
223    E1: Display + Debug + Send + Sync, // Type of error returned from `execute` entry-point.
224    E2: Display + Debug + Send + Sync, // Type of error returned from `instantiate` entry-point.
225    E3: Display + Debug + Send + Sync, // Type of error returned from `query` entry-point.
226    E4: Display + Debug + Send + Sync, // Type of error returned from `sudo` entry-point.
227    E5: Display + Debug + Send + Sync, // Type of error returned from `reply` entry-point.
228    E6: Display + Debug + Send + Sync, // Type of error returned from `migrate` entry-point.
229    C: CustomMsg + 'static, // Type of custom message returned from all entry-points except `query`.
230    Q: CustomQuery + DeserializeOwned + 'static, // Type of custom query in querier passed as deps/deps_mut to all entry-points.
231{
232    /// Populates [ContractWrapper] with contract's `sudo` entry-point and custom message type.
233    pub fn with_sudo<T4A, E4A>(
234        self,
235        sudo_fn: PermissionedFn<T4A, C, E4A, Q>,
236    ) -> ContractWrapper<T1, T2, T3, E1, E2, E3, C, Q, T4A, E4A, E5, T6, E6>
237    where
238        T4A: DeserializeOwned + 'static,
239        E4A: Display + Debug + Send + Sync + 'static,
240    {
241        ContractWrapper {
242            execute_fn: self.execute_fn,
243            instantiate_fn: self.instantiate_fn,
244            query_fn: self.query_fn,
245            sudo_fn: Some(Box::new(sudo_fn)),
246            reply_fn: self.reply_fn,
247            migrate_fn: self.migrate_fn,
248            checksum: None,
249        }
250    }
251
252    /// Populates [ContractWrapper] with contract's `sudo` entry-point and `Empty` as a custom message.
253    pub fn with_sudo_empty<T4A, E4A>(
254        self,
255        sudo_fn: PermissionedFn<T4A, Empty, E4A, Empty>,
256    ) -> ContractWrapper<T1, T2, T3, E1, E2, E3, C, Q, T4A, E4A, E5, T6, E6>
257    where
258        T4A: DeserializeOwned + 'static,
259        E4A: Display + Debug + Send + Sync + 'static,
260    {
261        ContractWrapper {
262            execute_fn: self.execute_fn,
263            instantiate_fn: self.instantiate_fn,
264            query_fn: self.query_fn,
265            sudo_fn: Some(customize_permissioned_fn(sudo_fn)),
266            reply_fn: self.reply_fn,
267            migrate_fn: self.migrate_fn,
268            checksum: None,
269        }
270    }
271
272    /// Populates [ContractWrapper] with contract's `reply` entry-point and custom message type.
273    pub fn with_reply<E5A>(
274        self,
275        reply_fn: ReplyFn<C, E5A, Q>,
276    ) -> ContractWrapper<T1, T2, T3, E1, E2, E3, C, Q, T4, E4, E5A, T6, E6>
277    where
278        E5A: Display + Debug + Send + Sync + 'static,
279    {
280        ContractWrapper {
281            execute_fn: self.execute_fn,
282            instantiate_fn: self.instantiate_fn,
283            query_fn: self.query_fn,
284            sudo_fn: self.sudo_fn,
285            reply_fn: Some(Box::new(reply_fn)),
286            migrate_fn: self.migrate_fn,
287            checksum: None,
288        }
289    }
290
291    /// Populates [ContractWrapper] with contract's `reply` entry-point and `Empty` as a custom message.
292    pub fn with_reply_empty<E5A>(
293        self,
294        reply_fn: ReplyFn<Empty, E5A, Empty>,
295    ) -> ContractWrapper<T1, T2, T3, E1, E2, E3, C, Q, T4, E4, E5A, T6, E6>
296    where
297        E5A: Display + Debug + Send + Sync + 'static,
298    {
299        ContractWrapper {
300            execute_fn: self.execute_fn,
301            instantiate_fn: self.instantiate_fn,
302            query_fn: self.query_fn,
303            sudo_fn: self.sudo_fn,
304            reply_fn: Some(customize_permissioned_fn(reply_fn)),
305            migrate_fn: self.migrate_fn,
306            checksum: None,
307        }
308    }
309
310    /// Populates [ContractWrapper] with contract's `migrate` entry-point and custom message type.
311    pub fn with_migrate<T6A, E6A>(
312        self,
313        migrate_fn: PermissionedFn<T6A, C, E6A, Q>,
314    ) -> ContractWrapper<T1, T2, T3, E1, E2, E3, C, Q, T4, E4, E5, T6A, E6A>
315    where
316        T6A: DeserializeOwned + 'static,
317        E6A: Display + Debug + Send + Sync + 'static,
318    {
319        ContractWrapper {
320            execute_fn: self.execute_fn,
321            instantiate_fn: self.instantiate_fn,
322            query_fn: self.query_fn,
323            sudo_fn: self.sudo_fn,
324            reply_fn: self.reply_fn,
325            migrate_fn: Some(Box::new(migrate_fn)),
326            checksum: None,
327        }
328    }
329
330    /// Populates [ContractWrapper] with contract's `migrate` entry-point and `Empty` as a custom message.
331    pub fn with_migrate_empty<T6A, E6A>(
332        self,
333        migrate_fn: PermissionedFn<T6A, Empty, E6A, Empty>,
334    ) -> ContractWrapper<T1, T2, T3, E1, E2, E3, C, Q, T4, E4, E5, T6A, E6A>
335    where
336        T6A: DeserializeOwned + 'static,
337        E6A: Display + Debug + Send + Sync + 'static,
338    {
339        ContractWrapper {
340            execute_fn: self.execute_fn,
341            instantiate_fn: self.instantiate_fn,
342            query_fn: self.query_fn,
343            sudo_fn: self.sudo_fn,
344            reply_fn: self.reply_fn,
345            migrate_fn: Some(customize_permissioned_fn(migrate_fn)),
346            checksum: None,
347        }
348    }
349
350    /// Populates [ContractWrapper] with the provided checksum of the contract's Wasm blob.
351    pub fn with_checksum(mut self, checksum: Checksum) -> Self {
352        self.checksum = Some(checksum);
353        self
354    }
355}
356
357fn customize_contract_fn<T, C, E, Q>(
358    raw_fn: ContractFn<T, Empty, E, Empty>,
359) -> ContractClosure<T, C, E, Q>
360where
361    T: DeserializeOwned + 'static,
362    E: Display + Debug + Send + Sync + 'static,
363    C: CustomMsg,
364    Q: CustomQuery + DeserializeOwned,
365{
366    Box::new(
367        move |mut deps: DepsMut<Q>,
368              env: Env,
369              info: MessageInfo,
370              msg: T|
371              -> Result<Response<C>, E> {
372            let deps = decustomize_deps_mut(&mut deps);
373            raw_fn(deps, env, info, msg).map(customize_response::<C>)
374        },
375    )
376}
377
378fn customize_query_fn<T, E, Q>(raw_fn: QueryFn<T, E, Empty>) -> QueryClosure<T, E, Q>
379where
380    T: DeserializeOwned + 'static,
381    E: Display + Debug + Send + Sync + 'static,
382    Q: CustomQuery + DeserializeOwned,
383{
384    Box::new(
385        move |deps: Deps<Q>, env: Env, msg: T| -> Result<Binary, E> {
386            let deps = decustomize_deps(&deps);
387            raw_fn(deps, env, msg)
388        },
389    )
390}
391
392fn customize_permissioned_fn<T, C, E, Q>(
393    raw_fn: PermissionedFn<T, Empty, E, Empty>,
394) -> PermissionedClosure<T, C, E, Q>
395where
396    T: DeserializeOwned + 'static,
397    E: Display + Debug + Send + Sync + 'static,
398    C: CustomMsg,
399    Q: CustomQuery + DeserializeOwned,
400{
401    Box::new(
402        move |mut deps: DepsMut<Q>, env: Env, msg: T| -> Result<Response<C>, E> {
403            let deps = decustomize_deps_mut(&mut deps);
404            raw_fn(deps, env, msg).map(customize_response::<C>)
405        },
406    )
407}
408
409fn decustomize_deps_mut<'a, Q>(deps: &'a mut DepsMut<Q>) -> DepsMut<'a, Empty>
410where
411    Q: CustomQuery + DeserializeOwned,
412{
413    DepsMut {
414        storage: deps.storage,
415        api: deps.api,
416        querier: QuerierWrapper::new(deps.querier.deref()),
417    }
418}
419
420fn decustomize_deps<'a, Q>(deps: &'a Deps<'a, Q>) -> Deps<'a, Empty>
421where
422    Q: CustomQuery + DeserializeOwned,
423{
424    Deps {
425        storage: deps.storage,
426        api: deps.api,
427        querier: QuerierWrapper::new(deps.querier.deref()),
428    }
429}
430
431fn customize_response<C>(resp: Response<Empty>) -> Response<C>
432where
433    C: CustomMsg,
434{
435    let mut customized_resp = Response::<C>::new()
436        .add_submessages(resp.messages.into_iter().map(customize_msg::<C>))
437        .add_events(resp.events)
438        .add_attributes(resp.attributes);
439    customized_resp.data = resp.data;
440    customized_resp
441}
442
443fn customize_msg<C>(msg: SubMsg<Empty>) -> SubMsg<C>
444where
445    C: CustomMsg,
446{
447    SubMsg {
448        id: msg.id,
449        payload: msg.payload,
450        msg: match msg.msg {
451            CosmosMsg::Wasm(wasm) => CosmosMsg::Wasm(wasm),
452            CosmosMsg::Bank(bank) => CosmosMsg::Bank(bank),
453            #[cfg(feature = "staking")]
454            CosmosMsg::Staking(staking) => CosmosMsg::Staking(staking),
455            #[cfg(feature = "staking")]
456            CosmosMsg::Distribution(distribution) => CosmosMsg::Distribution(distribution),
457            CosmosMsg::Custom(_) => unreachable!(),
458            #[cfg(feature = "stargate")]
459            CosmosMsg::Ibc(ibc) => CosmosMsg::Ibc(ibc),
460            #[cfg(feature = "cosmwasm_2_0")]
461            CosmosMsg::Any(any) => CosmosMsg::Any(any),
462            other => panic!("unknown message variant {:?}", other),
463        },
464        gas_limit: msg.gas_limit,
465        reply_on: msg.reply_on,
466    }
467}
468
469impl<T1, T2, T3, E1, E2, E3, C, T4, E4, E5, T6, E6, Q> Contract<C, Q>
470    for ContractWrapper<T1, T2, T3, E1, E2, E3, C, Q, T4, E4, E5, T6, E6>
471where
472    T1: DeserializeOwned, // Type of message passed to `execute` entry-point.
473    T2: DeserializeOwned, // Type of message passed to `instantiate` entry-point.
474    T3: DeserializeOwned, // Type of message passed to `query` entry-point.
475    T4: DeserializeOwned, // Type of message passed to `sudo` entry-point.
476    T6: DeserializeOwned, // Type of message passed to `migrate` entry-point.
477    E1: Display + Debug + Send + Sync + 'static, // Type of error returned from `execute` entry-point.
478    E2: Display + Debug + Send + Sync + 'static, // Type of error returned from `instantiate` entry-point.
479    E3: Display + Debug + Send + Sync + 'static, // Type of error returned from `query` entry-point.
480    E4: Display + Debug + Send + Sync + 'static, // Type of error returned from `sudo` entry-point.
481    E5: Display + Debug + Send + Sync + 'static, // Type of error returned from `reply` entry-point.
482    E6: Display + Debug + Send + Sync + 'static, // Type of error returned from `migrate` entry-point.
483    C: CustomMsg, // Type of custom message returned from all entry-points except `query`.
484    Q: CustomQuery + DeserializeOwned, // Type of custom query in querier passed as deps/deps_mut to all entry-points.
485{
486    /// Calls [execute] on wrapped [Contract] trait implementor.
487    ///
488    /// [execute]: Contract::execute
489    fn execute(
490        &self,
491        deps: DepsMut<Q>,
492        env: Env,
493        info: MessageInfo,
494        msg: Vec<u8>,
495    ) -> AnyResult<Response<C>> {
496        let msg: T1 = from_json(msg)?;
497        (self.execute_fn)(deps, env, info, msg).map_err(|err: E1| anyhow!(err))
498    }
499
500    /// Calls [instantiate] on wrapped [Contract] trait implementor.
501    ///
502    /// [instantiate]: Contract::instantiate
503    fn instantiate(
504        &self,
505        deps: DepsMut<Q>,
506        env: Env,
507        info: MessageInfo,
508        msg: Vec<u8>,
509    ) -> AnyResult<Response<C>> {
510        let msg: T2 = from_json(msg)?;
511        (self.instantiate_fn)(deps, env, info, msg).map_err(|err: E2| anyhow!(err))
512    }
513
514    /// Calls [query] on wrapped [Contract] trait implementor.
515    ///
516    /// [query]: Contract::query
517    fn query(&self, deps: Deps<Q>, env: Env, msg: Vec<u8>) -> AnyResult<Binary> {
518        let msg: T3 = from_json(msg)?;
519        (self.query_fn)(deps, env, msg).map_err(|err: E3| anyhow!(err))
520    }
521
522    /// Calls [sudo] on wrapped [Contract] trait implementor.
523    /// Returns an error when the contract does not implement [sudo].
524    ///
525    /// [sudo]: Contract::sudo
526    fn sudo(&self, deps: DepsMut<Q>, env: Env, msg: Vec<u8>) -> AnyResult<Response<C>> {
527        let msg: T4 = from_json(msg)?;
528        match &self.sudo_fn {
529            Some(sudo) => sudo(deps, env, msg).map_err(|err: E4| anyhow!(err)),
530            None => bail!("sudo is not implemented for contract"),
531        }
532    }
533
534    /// Calls [reply] on wrapped [Contract] trait implementor.
535    /// Returns an error when the contract does not implement [reply].
536    ///
537    /// [reply]: Contract::reply
538    fn reply(&self, deps: DepsMut<Q>, env: Env, reply_data: Reply) -> AnyResult<Response<C>> {
539        let msg: Reply = reply_data;
540        match &self.reply_fn {
541            Some(reply) => reply(deps, env, msg).map_err(|err: E5| anyhow!(err)),
542            None => bail!("reply is not implemented for contract"),
543        }
544    }
545
546    /// Calls [migrate] on wrapped [Contract] trait implementor.
547    /// Returns an error when the contract does not implement [migrate].
548    ///
549    /// [migrate]: Contract::migrate
550    fn migrate(&self, deps: DepsMut<Q>, env: Env, msg: Vec<u8>) -> AnyResult<Response<C>> {
551        let msg: T6 = from_json(msg)?;
552        match &self.migrate_fn {
553            Some(migrate) => migrate(deps, env, msg).map_err(|err: E6| anyhow!(err)),
554            None => bail!("migrate is not implemented for contract"),
555        }
556    }
557
558    /// Returns the provided checksum of the contract's Wasm blob.
559    fn checksum(&self) -> Option<Checksum> {
560        self.checksum
561    }
562}