Repository: CosmWasm/sylvia
Pull request #141 (2023-05-26 10:20:35)

Querier transparent calls
PR4
close  #28 

codecov[bot]: ## [Codecov](https://app.codecov.io/gh/CosmWasm/sylvia/pull/141?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=CosmWasm) Report
> Merging [#141](https://app.codecov.io/gh/CosmWasm/sylvia/pull/141?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=CosmWasm) (09c3ac7) into [main](https://app.codecov.io/gh/CosmWasm/sylvia/commit/0f4ca15cdbac4eaabde58bb1836adf738ec13450?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=CosmWasm) (0f4ca15) will **increase** coverage by `0.27%`.
> The diff coverage is `75.00%`.

```diff
@@            Coverage Diff             @@
##             main     #141      +/-   ##
==========================================
+ Coverage   79.86%   80.13%   +0.27%     
==========================================
  Files          33       33              
  Lines        1733     1762      +29     
==========================================
+ Hits         1384     1412      +28     
- Misses        349      350       +1     
```


| [Impacted Files](https://app.codecov.io/gh/CosmWasm/sylvia/pull/141?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=CosmWasm) | Coverage Δ | |
|---|---|---|
| [contracts/cw1-subkeys/src/cw1.rs](https://app.codecov.io/gh/CosmWasm/sylvia/pull/141?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=CosmWasm#diff-Y29udHJhY3RzL2N3MS1zdWJrZXlzL3NyYy9jdzEucnM=) | `100.00% <ø> (ø)` | |
| [contracts/cw1-whitelist/src/cw1.rs](https://app.codecov.io/gh/CosmWasm/sylvia/pull/141?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=CosmWasm#diff-Y29udHJhY3RzL2N3MS13aGl0ZWxpc3Qvc3JjL2N3MS5ycw==) | `100.00% <ø> (ø)` | |
| [contracts/cw1-whitelist/src/whitelist.rs](https://app.codecov.io/gh/CosmWasm/sylvia/pull/141?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=CosmWasm#diff-Y29udHJhY3RzL2N3MS13aGl0ZWxpc3Qvc3JjL3doaXRlbGlzdC5ycw==) | `97.56% <ø> (ø)` | |
| [contracts/cw20-base/src/allowances.rs](https://app.codecov.io/gh/CosmWasm/sylvia/pull/141?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=CosmWasm#diff-Y29udHJhY3RzL2N3MjAtYmFzZS9zcmMvYWxsb3dhbmNlcy5ycw==) | `98.73% <ø> (ø)` | |
| [contracts/cw20-base/src/marketing.rs](https://app.codecov.io/gh/CosmWasm/sylvia/pull/141?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=CosmWasm#diff-Y29udHJhY3RzL2N3MjAtYmFzZS9zcmMvbWFya2V0aW5nLnJz) | `93.10% <ø> (ø)` | |
| [contracts/cw20-base/src/minting.rs](https://app.codecov.io/gh/CosmWasm/sylvia/pull/141?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=CosmWasm#diff-Y29udHJhY3RzL2N3MjAtYmFzZS9zcmMvbWludGluZy5ycw==) | `97.95% <ø> (ø)` | |
| [sylvia-derive/src/parser.rs](https://app.codecov.io/gh/CosmWasm/sylvia/pull/141?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=CosmWasm#diff-c3lsdmlhLWRlcml2ZS9zcmMvcGFyc2VyLnJz) | `80.19% <ø> (ø)` | |
| [sylvia/tests/dispatching.rs](https://app.codecov.io/gh/CosmWasm/sylvia/pull/141?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=CosmWasm#diff-c3lsdmlhL3Rlc3RzL2Rpc3BhdGNoaW5nLnJz) | `73.68% <0.00%> (-26.32%)` | :arrow_down: |
| [sylvia/tests/query\_returns.rs](https://app.codecov.io/gh/CosmWasm/sylvia/pull/141?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=CosmWasm#diff-c3lsdmlhL3Rlc3RzL3F1ZXJ5X3JldHVybnMucnM=) | `0.00% <ø> (ø)` | |
| [sylvia-derive/src/input.rs](https://app.codecov.io/gh/CosmWasm/sylvia/pull/141?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=CosmWasm#diff-c3lsdmlhLWRlcml2ZS9zcmMvaW5wdXQucnM=) | `83.78% <80.00%> (-2.89%)` | :arrow_down: |
| ... and [3 more](https://app.codecov.io/gh/CosmWasm/sylvia/pull/141?src=pr&el=tree-more&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=CosmWasm) | |

... and [2 files with indirect coverage changes](https://app.codecov.io/gh/CosmWasm/sylvia/pull/141/indirect-changes?src=pr&el=tree-more&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=CosmWasm)

:mega: We’re building smart automated test selection to slash your CI/CD build times. [Learn more](https://about.codecov.io/iterative-testing/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=CosmWasm)


Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index a91b777..7672398 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,13 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
 and this project adheres to
 [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
 
+## Unreleased
+
+- New `BoundQuerier` and `Remote` types are generated. Their goal is to make
+  querying other contracts more intuitive.
+- `module` attr for `contract` macro no longer wraps generated code in scope.
+  As from now it will be used to provide path to contract implementation.
+
 ## \[0.4.2\] - 2023-05-24
 
 - Added support of `#[msg(reply)]` defining handler for reply messages,
diff --git a/MIGRATING.md b/MIGRATING.md
new file mode 100644
index 0000000..e409223
--- /dev/null
+++ b/MIGRATING.md
@@ -0,0 +1,20 @@
+# Migrating Contracts
+
+This guide explains what is needed to upgrade contracts when migrating over major releases of `sylvia`. Note that you can also view the [complete CHANGELOG](https://github.com/CosmWasm/sylvia/blob/main/CHANGELOG.md) to understand the differences.
+
+## 0.4.2 -> Unreleased
+
+- `module` attr for macro contract should now point to your contract implemntation
+
+```diff
+-#[contract(module=some_contract)]
+-impl SomeContract {
+-    ...
+-}
++mod some_contract {
++   #[contract]
++   impl SomeContract {
++       ...
++   }
++}
+```
diff --git a/contracts/cw1-subkeys/src/cw1.rs b/contracts/cw1-subkeys/src/cw1.rs
index a76b256..9e217aa 100644
--- a/contracts/cw1-subkeys/src/cw1.rs
+++ b/contracts/cw1-subkeys/src/cw1.rs
@@ -6,7 +6,7 @@ use sylvia::types::{ExecCtx, QueryCtx};
 use crate::contract::Cw1SubkeysContract;
 use crate::error::ContractError;
 
-#[contract]
+#[contract(module=crate::contract)]
 #[messages(cw1 as Cw1)]
 impl Cw1 for Cw1SubkeysContract<'_> {
     type Error = ContractError;
diff --git a/contracts/cw1-subkeys/src/whitelist.rs b/contracts/cw1-subkeys/src/whitelist.rs
index 14637b2..c36556a 100644
--- a/contracts/cw1-subkeys/src/whitelist.rs
+++ b/contracts/cw1-subkeys/src/whitelist.rs
@@ -9,7 +9,7 @@ use crate::error::ContractError;
 
 // This can be skipped by tarpaulin as it's covered in cw1-whitelist
 #[cfg(not(tarpaulin_include))]
-#[contract]
+#[contract(module=crate::contract)]
 #[messages(whitelist as Whitelist)]
 impl Whitelist for Cw1SubkeysContract<'_> {
     type Error = ContractError;
diff --git a/contracts/cw1-whitelist/src/cw1.rs b/contracts/cw1-whitelist/src/cw1.rs
index 570b676..ba00b58 100644
--- a/contracts/cw1-whitelist/src/cw1.rs
+++ b/contracts/cw1-whitelist/src/cw1.rs
@@ -6,7 +6,7 @@ use sylvia::types::{ExecCtx, QueryCtx};
 use crate::contract::Cw1WhitelistContract;
 use crate::error::ContractError;
 
-#[contract]
+#[contract(module=crate::contract)]
 #[messages(cw1 as Cw1)]
 impl Cw1 for Cw1WhitelistContract<'_> {
     type Error = ContractError;
diff --git a/contracts/cw1-whitelist/src/whitelist.rs b/contracts/cw1-whitelist/src/whitelist.rs
index 1d6b069..68e2a79 100644
--- a/contracts/cw1-whitelist/src/whitelist.rs
+++ b/contracts/cw1-whitelist/src/whitelist.rs
@@ -20,7 +20,7 @@ pub trait Whitelist {
     fn admin_list(&self, ctx: QueryCtx) -> StdResult<AdminListResponse>;
 }
 
-#[contract]
+#[contract(module=crate::contract)]
 impl Whitelist for Cw1WhitelistContract<'_> {
     type Error = ContractError;
 
diff --git a/contracts/cw20-base/src/allowances.rs b/contracts/cw20-base/src/allowances.rs
index cf52282..d73d244 100644
--- a/contracts/cw20-base/src/allowances.rs
+++ b/contracts/cw20-base/src/allowances.rs
@@ -17,7 +17,7 @@ use crate::responses::Cw20ReceiveMsg;
 const MAX_LIMIT: u32 = 30;
 const DEFAULT_LIMIT: u32 = 10;
 
-#[contract]
+#[contract(module=crate::contract)]
 #[messages(cw20_allowances as Cw20Allowances)]
 impl Cw20Allowances for Cw20Base<'_> {
     type Error = ContractError;
diff --git a/contracts/cw20-base/src/marketing.rs b/contracts/cw20-base/src/marketing.rs
index b8d88ff..f91e9f6 100644
--- a/contracts/cw20-base/src/marketing.rs
+++ b/contracts/cw20-base/src/marketing.rs
@@ -7,7 +7,7 @@ use cw20_marketing::{Cw20Marketing, EmbeddedLogo, Logo};
 use sylvia::contract;
 use sylvia::types::{ExecCtx, QueryCtx};
 
-#[contract]
+#[contract(module=crate::contract)]
 #[messages(cw20_marketing as Cw20Marketing)]
 impl Cw20Marketing for Cw20Base<'_> {
     type Error = ContractError;
diff --git a/contracts/cw20-base/src/minting.rs b/contracts/cw20-base/src/minting.rs
index e9922b8..75d8d97 100644
--- a/contracts/cw20-base/src/minting.rs
+++ b/contracts/cw20-base/src/minting.rs
@@ -6,7 +6,7 @@ use cw20_minting::Cw20Minting;
 use sylvia::contract;
 use sylvia::types::{ExecCtx, QueryCtx};
 
-#[contract]
+#[contract(module=crate::contract)]
 #[messages(cw20_minting as Cw20Minting)]
 impl Cw20Minting for Cw20Base<'_> {
     type Error = ContractError;
diff --git a/sylvia-derive/src/input.rs b/sylvia-derive/src/input.rs
index 4a32c6b..1544789 100644
--- a/sylvia-derive/src/input.rs
+++ b/sylvia-derive/src/input.rs
@@ -59,35 +59,16 @@ impl<'a> TraitInput<'a> {
         let remote = Remote::new(&[]).emit();
         let querier = MsgVariants::new(self.item.as_variants(), &self.generics).emit_querier();
 
-        if let Some(module) = &self.attributes.module {
-            #[cfg(not(tarpaulin_include))]
-            {
-                quote! {
-                    pub mod #module {
-                        use super::*;
-
-                        #messages
-
-                        #multitest_helpers
-
-                        #remote
-
-                        #querier
-                    }
-                }
-            }
-        } else {
-            #[cfg(not(tarpaulin_include))]
-            {
-                quote! {
-                    #messages
+        #[cfg(not(tarpaulin_include))]
+        {
+            quote! {
+                #messages
 
-                    #multitest_helpers
+                #multitest_helpers
 
-                    #remote
+                #remote
 
-                    #querier
-                }
+                #querier
             }
         }
     }
@@ -159,48 +140,61 @@ impl<'a> ImplInput<'a> {
 
     pub fn process(&self) -> TokenStream {
         let is_trait = self.item.trait_.is_some();
-
         let multitest_helpers = if cfg!(feature = "mt") {
             MultitestHelpers::new(self.item, is_trait, &self.error, &self.generics).emit()
         } else {
             quote! {}
         };
 
-        if is_trait {
-            return multitest_helpers;
+        let interfaces = Interfaces::new(self.item);
+        let variants = MsgVariants::new(self.item.as_variants(), &self.generics);
+
+        match is_trait {
+            true => self.process_interface(&interfaces, variants, multitest_helpers),
+            false => self.process_contract(&interfaces, variants, multitest_helpers),
         }
+    }
 
-        let messages = self.emit_messages();
-        let remote = Remote::new(&self.item.attrs).emit();
-        let querier = MsgVariants::new(self.item.as_variants(), &self.generics).emit_querier();
-        let querier_from_impl = Interfaces::new(self.item).emit_querier_from_impl();
+    fn process_interface(
+        &self,
+        interfaces: &Interfaces,
+        variants: MsgVariants<'a>,
+        multitest_helpers: TokenStream,
+    ) -> TokenStream {
+        let querier_bound_for_impl = self.emit_querier_for_bound_impl(interfaces, variants);
 
         #[cfg(not(tarpaulin_include))]
-        let code = quote! {
-            #messages
-
+        quote! {
             #multitest_helpers
 
-            #remote
+            #querier_bound_for_impl
+        }
+    }
 
-            #querier
+    fn process_contract(
+        &self,
+        interfaces: &Interfaces,
+        variants: MsgVariants<'a>,
+        multitest_helpers: TokenStream,
+    ) -> TokenStream {
+        let messages = self.emit_messages();
+        let remote = Remote::new(&self.item.attrs).emit();
+        let querier = variants.emit_querier();
+        let querier_from_impl = interfaces.emit_querier_from_impl();
 
-            #(#querier_from_impl)*
-        };
+        #[cfg(not(tarpaulin_include))]
+        {
+            quote! {
+                #messages
 
-        if let Some(module) = &self.attributes.module {
-            #[cfg(not(tarpaulin_include))]
-            {
-                quote! {
-                    pub mod #module {
-                        use super::*;
+                #multitest_helpers
 
-                        #code
-                    }
-                }
+                #remote
+
+                #querier
+
+                #(#querier_from_impl)*
             }
-        } else {
-            code
         }
     }
 
@@ -243,4 +237,18 @@ impl<'a> ImplInput<'a> {
     fn emit_glue_msg(&self, name: &Ident, msg_ty: MsgType) -> TokenStream {
         GlueMessage::new(name, self.item, msg_ty, &self.error).emit()
     }
+
+    fn emit_querier_for_bound_impl(
+        &self,
+        interfaces: &Interfaces,
+        variants: MsgVariants<'a>,
+    ) -> TokenStream {
+        let trait_module = interfaces
+            .interfaces()
+            .first()
+            .map(|interface| &interface.module);
+        let contract_module = self.attributes.module.as_ref();
+
+        variants.emit_querier_for_bound_impl(trait_module, contract_module)
+    }
 }
diff --git a/sylvia-derive/src/interfaces.rs b/sylvia-derive/src/interfaces.rs
index bb0cdb8..9125c0f 100644
--- a/sylvia-derive/src/interfaces.rs
+++ b/sylvia-derive/src/interfaces.rs
@@ -34,6 +34,10 @@ impl Interfaces {
         Self { interfaces }
     }
 
+    pub fn interfaces(&self) -> &[ContractMessageAttr] {
+        &self.interfaces
+    }
+
     pub fn emit_querier_from_impl(&self) -> Vec<TokenStream> {
         let sylvia = crate_module();
 
diff --git a/sylvia-derive/src/message.rs b/sylvia-derive/src/message.rs
index b12387f..615e358 100644
--- a/sylvia-derive/src/message.rs
+++ b/sylvia-derive/src/message.rs
@@ -15,7 +15,7 @@ use syn::parse::{Parse, Parser};
 use syn::spanned::Spanned;
 use syn::visit::Visit;
 use syn::{
-    parse_quote, Attribute, GenericParam, Ident, ImplItem, ItemImpl, ItemTrait, Pat, PatType,
+    parse_quote, Attribute, GenericParam, Ident, ImplItem, ItemImpl, ItemTrait, Pat, PatType, Path,
     ReturnType, Signature, TraitItem, Type, WhereClause, WherePredicate,
 };
 
@@ -588,7 +588,7 @@ impl<'a> MsgVariant<'a> {
         }
     }
 
-    pub fn emit_querier_impl(&self) -> TokenStream {
+    pub fn emit_querier_impl(&self, trait_module: Option<&Path>) -> TokenStream {
         let sylvia = crate_module();
         let Self {
             name,
@@ -600,13 +600,16 @@ impl<'a> MsgVariant<'a> {
         let parameters = fields.iter().map(MsgField::emit_method_field);
         let fields_names = fields.iter().map(MsgField::name);
         let variant_name = Ident::new(&name.to_string().to_case(Case::Snake), name.span());
+        let msg = trait_module
+            .map(|module| quote! { #module ::QueryMsg })
+            .unwrap_or_else(|| quote! { QueryMsg });
 
         #[cfg(not(tarpaulin_include))]
         {
             quote! {
                 fn #variant_name(&self, #(#parameters),*) -> Result< #return_type, #sylvia:: cw_std::StdError> {
-                    let query = QueryMsg:: #variant_name (#(#fields_names),*);
-                    self.querier.query_wasm_smart(self.contract, &query)
+                    let query = #msg :: #variant_name (#(#fields_names),*);
+                    self.querier().query_wasm_smart(self.contract(), &query)
                 }
             }
         }
@@ -667,7 +670,7 @@ impl<'a> MsgVariants<'a> {
         let methods_impl = variants
             .iter()
             .filter(|variant| variant.msg_type == MsgType::Query)
-            .map(MsgVariant::emit_querier_impl);
+            .map(|variant| variant.emit_querier_impl(None));
 
         let methods_declaration = variants
             .iter()
@@ -707,6 +710,36 @@ impl<'a> MsgVariants<'a> {
             }
         }
     }
+
+    pub fn emit_querier_for_bound_impl(
+        &self,
+        trait_module: Option<&Path>,
+        contract_module: Option<&Path>,
+    ) -> TokenStream {
+        let sylvia = crate_module();
+        let variants = &self.0;
+
+        let methods_impl = variants
+            .iter()
+            .filter(|variant| variant.msg_type == MsgType::Query)
+            .map(|variant| variant.emit_querier_impl(trait_module));
+
+        let querier = trait_module
+            .map(|module| quote! { #module ::Querier })
+            .unwrap_or_else(|| quote! { Querier });
+        let bound_querier = contract_module
+            .map(|module| quote! { #module ::BoundQuerier})
+            .unwrap_or_else(|| quote! { BoundQuerier });
+
+        #[cfg(not(tarpaulin_include))]
+        {
+            quote! {
+                impl <'a, C: #sylvia ::cw_std::CustomQuery> #querier for #bound_querier<'a, C> {
+                    #(#methods_impl)*
+                }
+            }
+        }
+    }
 }
 
 /// Representation of single message variant field
diff --git a/sylvia-derive/src/parser.rs b/sylvia-derive/src/parser.rs
index 9e7035e..7f28c7d 100644
--- a/sylvia-derive/src/parser.rs
+++ b/sylvia-derive/src/parser.rs
@@ -20,7 +20,7 @@ pub struct InterfaceArgs {
 /// Parser arguments for `contract` macro
 pub struct ContractArgs {
     /// Module name wrapping generated messages, by default no additional module is created
-    pub module: Option<Ident>,
+    pub module: Option<Path>,
 }
 
 impl Parse for InterfaceArgs {
diff --git a/sylvia/examples/basic.rs b/sylvia/examples/basic.rs
index ed4bf97..07f04d7 100644
--- a/sylvia/examples/basic.rs
+++ b/sylvia/examples/basic.rs
@@ -1,8 +1,8 @@
 use anyhow::Error;
-use cosmwasm_std::{Addr, Response, StdError};
+use cosmwasm_std::{Addr, Response};
 use cw_storage_plus::{Item, Map};
-use sylvia::types::{ExecCtx, InstantiateCtx, QueryCtx};
-use sylvia::{contract, interface};
+use sylvia::contract;
+use sylvia::types::InstantiateCtx;
 
 #[derive(
     sylvia::serde::Serialize,
@@ -32,7 +32,12 @@ pub struct MemberResp {
 }
 
 mod group {
-    use super::*;
+    use anyhow::Error;
+    use cosmwasm_std::{Response, StdError};
+    use sylvia::types::{ExecCtx, QueryCtx};
+    use sylvia::{contract, interface};
+
+    use crate::{GroupContract, Member, MemberResp};
 
     #[interface]
     pub trait Group {
@@ -57,7 +62,7 @@ mod group {
         fn member(&self, ctx: QueryCtx, addr: String) -> Result<MemberResp, Self::Error>;
     }
 
-    #[contract]
+    #[contract(module=super)]
     impl Group for GroupContract {
         type Error = Error;
 
@@ -98,7 +103,7 @@ impl Default for GroupContract {
     }
 }
 
-#[contract(module=contract)]
+#[contract]
 #[error(Error)]
 #[messages(group as Group)]
 impl GroupContract {


Test patch:
diff --git a/contracts/cw20-base/src/multitest/receiver.rs b/contracts/cw20-base/src/multitest/receiver.rs
index d0325be..b349461 100644
--- a/contracts/cw20-base/src/multitest/receiver.rs
+++ b/contracts/cw20-base/src/multitest/receiver.rs
@@ -18,7 +18,7 @@ pub trait Receiver {
     ) -> Result<Response, Self::Error>;
 }
 
-#[contract]
+#[contract(module=crate::multitest::receiver_contract)]
 impl Receiver for ReceiverContract {
     type Error = StdError;
 
diff --git a/sylvia/tests/dispatching.rs b/sylvia/tests/dispatching.rs
index 38bb97d..91d4895 100644
--- a/sylvia/tests/dispatching.rs
+++ b/sylvia/tests/dispatching.rs
@@ -1,38 +1,47 @@
 use cosmwasm_std::testing::{mock_dependencies, mock_env, mock_info};
-use cosmwasm_std::{from_binary, Addr, Decimal, Response, StdError};
+use cosmwasm_std::{from_binary, Addr, Decimal, Response, StdError, StdResult};
+use interface::Interface;
 use schemars::JsonSchema;
 use serde::{Deserialize, Serialize};
 use std::cell::RefCell;
 use std::collections::HashMap;
+use sylvia::contract;
 use sylvia::types::{ExecCtx, QueryCtx};
 
-use sylvia::{contract, interface};
+mod interface {
+    use cosmwasm_std::{Addr, Decimal, Response, StdError};
+    use sylvia::interface;
+    use sylvia::types::{ExecCtx, QueryCtx};
 
-#[interface]
-pub trait Interface {
-    type Error: From<StdError>;
+    use crate::{EmptyQueryResponse, QueryResponse};
 
-    #[msg(exec)]
-    fn no_args_execution(&self, ctx: ExecCtx) -> Result<Response, Self::Error>;
+    #[interface]
+    pub trait Interface {
+        type Error: From<StdError>;
 
-    #[msg(exec)]
-    fn argumented_execution(
-        &self,
-        ctx: ExecCtx,
-        addr: Addr,
-        coef: Decimal,
-        desc: String,
-    ) -> Result<Response, Self::Error>;
+        #[msg(exec)]
+        fn no_args_execution(&self, ctx: ExecCtx) -> Result<Response, Self::Error>;
 
-    #[msg(query)]
-    fn no_args_query(&self, ctx: QueryCtx) -> Result<EmptyQueryResponse, Self::Error>;
+        #[msg(exec)]
+        fn argumented_execution(
+            &self,
+            ctx: ExecCtx,
+            addr: Addr,
+            coef: Decimal,
+            desc: String,
+        ) -> Result<Response, Self::Error>;
 
-    #[msg(query)]
-    fn argumented_query(&self, ctx: QueryCtx, user: Addr) -> Result<QueryResponse, Self::Error>;
+        #[msg(query)]
+        fn no_args_query(&self, ctx: QueryCtx) -> Result<EmptyQueryResponse, Self::Error>;
+
+        #[msg(query)]
+        fn argumented_query(&self, ctx: QueryCtx, user: Addr)
+            -> Result<QueryResponse, Self::Error>;
+    }
 }
 
 #[derive(Default)]
-struct Contract {
+pub struct Contract {
     execs: RefCell<u64>,
     queries: RefCell<u64>,
 
@@ -51,6 +60,7 @@ pub struct QueryResponse {
 }
 
 #[contract]
+#[messages(interface as Interface)]
 impl Interface for Contract {
     type Error = StdError;
 
@@ -89,6 +99,20 @@ impl Interface for Contract {
     }
 }
 
+#[cfg(not(tarpaulin_include))]
+#[contract]
+#[messages(interface as Interface)]
+impl Contract {
+    fn new() -> Self {
+        Self::default()
+    }
+
+    #[msg(instantiate)]
+    fn instanciate(&self, _: ExecCtx) -> StdResult<Response> {
+        Ok(Response::new())
+    }
+}
+
 #[test]
 fn dispatch() {
     let contract = Contract::default();
@@ -97,12 +121,12 @@ fn dispatch() {
     let env = mock_env();
     let info = mock_info("owner", &[]);
 
-    let resp = ExecMsg::NoArgsExecution {}
+    let resp = interface::ExecMsg::NoArgsExecution {}
         .dispatch(&contract, (deps.as_mut(), env.clone(), info.clone()))
         .unwrap();
     assert_eq!(resp, Response::new());
 
-    let resp = ExecMsg::ArgumentedExecution {
+    let resp = interface::ExecMsg::ArgumentedExecution {
         addr: Addr::unchecked("addr1"),
         coef: Decimal::percent(30),
         desc: "True".to_owned(),
@@ -111,7 +135,7 @@ fn dispatch() {
     .unwrap();
     assert_eq!(resp, Response::new());
 
-    let resp = ExecMsg::ArgumentedExecution {
+    let resp = interface::ExecMsg::ArgumentedExecution {
         addr: Addr::unchecked("addr2"),
         coef: Decimal::percent(70),
         desc: "False".to_owned(),
@@ -120,12 +144,12 @@ fn dispatch() {
     .unwrap();
     assert_eq!(resp, Response::new());
 
-    let resp = QueryMsg::NoArgsQuery {}
+    let resp = interface::QueryMsg::NoArgsQuery {}
         .dispatch(&contract, (deps.as_ref(), env.clone()))
         .unwrap();
     let _resp: EmptyQueryResponse = from_binary(&resp).unwrap();
 
-    let resp = QueryMsg::ArgumentedQuery {
+    let resp = interface::QueryMsg::ArgumentedQuery {
         user: Addr::unchecked("addr2"),
     }
     .dispatch(&contract, (deps.as_ref(), env))
diff --git a/sylvia/tests/messages_generation.rs b/sylvia/tests/messages_generation.rs
index 8fc3340..3b848f9 100644
--- a/sylvia/tests/messages_generation.rs
+++ b/sylvia/tests/messages_generation.rs
@@ -1,81 +1,96 @@
-use cosmwasm_std::{Addr, Decimal, Response, StdError, StdResult};
-
-use sylvia::types::{ExecCtx, InstantiateCtx, MigrateCtx, QueryCtx};
-use sylvia::{contract, interface};
+use cosmwasm_std::{Addr, Decimal};
 
 #[derive(
     serde::Serialize, serde::Deserialize, Clone, Debug, PartialEq, Eq, schemars::JsonSchema,
 )]
 pub struct QueryResult;
 
-#[interface(module=interface)]
-pub trait Interface {
-    type Error: From<StdError>;
-
-    #[msg(exec)]
-    fn no_args_execution(&self, ctx: ExecCtx) -> Result<Response, Self::Error>;
-
-    #[msg(exec)]
-    fn argumented_execution(
-        &self,
-        ctx: ExecCtx,
-        addr: Addr,
-        coef: Decimal,
-        #[serde(default)] desc: String,
-    ) -> Result<Response, Self::Error>;
-
-    #[msg(query)]
-    fn no_args_query(&self, ctx: QueryCtx) -> Result<QueryResult, Self::Error>;
-
-    #[msg(query)]
-    fn argumented_query(&self, ctx: QueryCtx, user: Addr) -> Result<QueryResult, Self::Error>;
-}
-
-pub struct Contract {}
+mod interface {
+    use cosmwasm_std::{Addr, Decimal, Response, StdError};
+    use sylvia::{
+        interface,
+        types::{ExecCtx, QueryCtx},
+    };
 
-#[cfg(not(tarpaulin_include))]
-// Ignoring coverage of test implementation
-#[contract(module=contract)]
-impl Contract {
-    #[allow(clippy::new_without_default)]
-    pub fn new() -> Self {
-        Self {}
-    }
+    use crate::QueryResult;
 
-    #[msg(instantiate)]
-    pub fn instantiate(&self, _ctx: InstantiateCtx) -> StdResult<Response> {
-        Ok(Response::new())
-    }
+    #[interface]
+    pub trait Interface {
+        type Error: From<StdError>;
 
-    #[msg(migrate)]
-    pub fn migrate(&self, _ctx: MigrateCtx) -> StdResult<Response> {
-        Ok(Response::new())
-    }
+        #[msg(exec)]
+        fn no_args_execution(&self, ctx: ExecCtx) -> Result<Response, Self::Error>;
 
-    #[msg(exec)]
-    fn no_args_execution(&self, _ctx: ExecCtx) -> StdResult<Response> {
-        Ok(Response::new())
-    }
+        #[msg(exec)]
+        fn argumented_execution(
+            &self,
+            ctx: ExecCtx,
+            addr: Addr,
+            coef: Decimal,
+            #[serde(default)] desc: String,
+        ) -> Result<Response, Self::Error>;
 
-    #[msg(exec)]
-    fn argumented_execution(
-        &self,
-        _ctx: ExecCtx,
-        _addr: Addr,
-        #[serde(default)] _coef: Decimal,
-        #[serde(default)] _desc: String,
-    ) -> StdResult<Response> {
-        Ok(Response::new())
-    }
+        #[msg(query)]
+        fn no_args_query(&self, ctx: QueryCtx) -> Result<QueryResult, Self::Error>;
 
-    #[msg(query)]
-    fn no_args_query(&self, _ctx: QueryCtx) -> StdResult<QueryResult> {
-        Ok(QueryResult {})
+        #[msg(query)]
+        fn argumented_query(&self, ctx: QueryCtx, user: Addr) -> Result<QueryResult, Self::Error>;
     }
+}
 
-    #[msg(query)]
-    fn argumented_query(&self, _ctx: QueryCtx, _user: Addr) -> StdResult<QueryResult> {
-        Ok(QueryResult {})
+mod contract {
+    use cosmwasm_std::{Addr, Response, StdResult};
+    use sylvia::contract;
+    use sylvia::types::{ExecCtx, InstantiateCtx, MigrateCtx, QueryCtx};
+
+    use crate::QueryResult;
+
+    pub struct Contract {}
+
+    #[cfg(not(tarpaulin_include))]
+    #[contract]
+    impl Contract {
+        #[allow(clippy::new_without_default)]
+        #[allow(dead_code)]
+        pub fn new() -> Self {
+            Self {}
+        }
+
+        #[msg(instantiate)]
+        pub fn instantiate(&self, _ctx: InstantiateCtx) -> StdResult<Response> {
+            Ok(Response::new())
+        }
+
+        #[msg(migrate)]
+        pub fn migrate(&self, _ctx: MigrateCtx) -> StdResult<Response> {
+            Ok(Response::new())
+        }
+
+        #[msg(exec)]
+        fn no_args_execution(&self, _ctx: ExecCtx) -> StdResult<Response> {
+            Ok(Response::new())
+        }
+
+        #[msg(exec)]
+        fn argumented_execution(
+            &self,
+            _ctx: ExecCtx,
+            _addr: cosmwasm_std::Addr,
+            #[serde(default)] _coef: cosmwasm_std::Decimal,
+            #[serde(default)] _desc: String,
+        ) -> StdResult<Response> {
+            Ok(Response::new())
+        }
+
+        #[msg(query)]
+        fn no_args_query(&self, _ctx: QueryCtx) -> StdResult<QueryResult> {
+            Ok(QueryResult {})
+        }
+
+        #[msg(query)]
+        fn argumented_query(&self, _ctx: QueryCtx, _user: Addr) -> StdResult<QueryResult> {
+            Ok(QueryResult {})
+        }
     }
 }
 
diff --git a/sylvia/tests/querier.rs b/sylvia/tests/querier.rs
index beadd27..59a0135 100644
--- a/sylvia/tests/querier.rs
+++ b/sylvia/tests/querier.rs
@@ -34,7 +34,7 @@ pub mod counter {
         fn decrease_by_count(&self, ctx: ExecCtx) -> StdResult<Response>;
     }
 
-    #[contract]
+    #[contract(module=super)]
     impl Counter for super::CounterContract<'_> {
         type Error = StdError;
 
@@ -52,9 +52,13 @@ pub mod counter {
 
         #[msg(exec)]
         fn copy_count(&self, ctx: ExecCtx) -> StdResult<Response> {
-            let remote = self.remote.load(ctx.deps.storage)?;
-            let querier = remote.querier(&ctx.deps.querier);
-            let other_count = BoundQuerier::from(&querier).count()?.count;
+            let other_count = self
+                .remote
+                .load(ctx.deps.storage)?
+                .querier(&ctx.deps.querier)
+                .count()?
+                .count;
+
             self.count.save(ctx.deps.storage, &other_count)?;
             Ok(Response::new())
         }
diff --git a/sylvia/tests/query_returns.rs b/sylvia/tests/query_returns.rs
index a6b2896..f4dd6d0 100644
--- a/sylvia/tests/query_returns.rs
+++ b/sylvia/tests/query_returns.rs
@@ -2,8 +2,8 @@ use cosmwasm_std::{Response, StdError, StdResult};
 
 use schemars::JsonSchema;
 use serde::{Deserialize, Serialize};
+use sylvia::contract;
 use sylvia::types::{InstantiateCtx, QueryCtx};
-use sylvia::{contract, interface};
 use thiserror::Error;
 
 #[derive(Error, Debug, PartialEq)]
@@ -17,12 +17,19 @@ pub struct QueryResponse;
 
 type QueryResult<E> = Result<QueryResponse, E>;
 
-#[interface(module=msg)]
-pub trait Interface {
-    type Error: From<StdError>;
+mod msg {
+    use cosmwasm_std::StdError;
+    use sylvia::{interface, types::QueryCtx};
 
-    #[msg(query, resp=QueryResponse)]
-    fn query(&self, ctx: QueryCtx, #[serde(default)] name: String) -> QueryResult<Self::Error>;
+    use crate::{QueryResponse, QueryResult};
+
+    #[interface(module=msg)]
+    pub trait Interface {
+        type Error: From<StdError>;
+
+        #[msg(query, resp=QueryResponse)]
+        fn query(&self, ctx: QueryCtx, #[serde(default)] name: String) -> QueryResult<Self::Error>;
+    }
 }
 
 pub struct SomeContract {}
diff --git a/sylvia/tests/separate_module.rs b/sylvia/tests/separate_module.rs
deleted file mode 100644
index 99e80c3..0000000
--- a/sylvia/tests/separate_module.rs
+++ /dev/null
@@ -1,50 +0,0 @@
-use cosmwasm_std::{Addr, Decimal, Response, StdError};
-
-use sylvia::interface;
-use sylvia::types::{ExecCtx, QueryCtx};
-
-#[derive(
-    serde::Serialize, serde::Deserialize, Clone, Debug, PartialEq, Eq, schemars::JsonSchema,
-)]
-pub struct QueryResult;
-
-#[interface(module=msg)]
-pub trait Interface {
-    type Error: From<StdError>;
-
-    #[msg(exec)]
-    fn no_args_execution(&self, ctx: ExecCtx) -> Result<Response, Self::Error>;
-
-    #[msg(exec)]
-    fn argumented_execution(
-        &self,
-        ctx: ExecCtx,
-        addr: Addr,
-        coef: Decimal,
-        desc: String,
-    ) -> Result<Response, Self::Error>;
-
-    #[msg(query)]
-    fn no_args_query(&self, ctx: QueryCtx) -> Result<QueryResult, Self::Error>;
-
-    #[msg(query)]
-    fn argumented_query(
-        &self,
-        ctx: QueryCtx,
-        user: Addr,
-    ) -> Result<Option<QueryResult>, Self::Error>;
-}
-
-#[test]
-fn messages_constructible() {
-    let _no_args_exec = msg::ExecMsg::NoArgsExecution {};
-    let _argumented_exec = msg::ExecMsg::ArgumentedExecution {
-        addr: Addr::unchecked("owner"),
-        coef: Decimal::percent(10),
-        desc: "Some description".to_owned(),
-    };
-    let _no_args_query = msg::QueryMsg::NoArgsQuery {};
-    let _argumented_query = msg::QueryMsg::ArgumentedQuery {
-        user: Addr::unchecked("owner"),
-    };
-}