From 09452d0fde84d3db3e891de30639d038b4cfc1ff Mon Sep 17 00:00:00 2001
From: Tomasz Kulik <tomek.kulik2@gmail.com>
Date: Fri, 9 May 2025 17:36:43 +0200
Subject: [PATCH] feat: Remove the generic param from CosmosMsg

---
 contracts/hackatom/tests/integration.rs       |   8 +-
 .../ibc-reflect-send/tests/integration.rs     |   4 +-
 contracts/ibc2/src/contract.rs                |   2 +-
 packages/std/src/ibc.rs                       |  32 ++--
 packages/std/src/results/cosmos_msg.rs        |  78 ++-------
 packages/std/src/results/response.rs          |  81 ++--------
 packages/std/src/results/submessages.rs       |  34 ++--
 packages/vm/benches/main.rs                   |  22 +--
 packages/vm/examples/heap_profiling.rs        |   6 +-
 packages/vm/examples/multi_threaded_cache.rs  |   6 +-
 packages/vm/src/cache.rs                      |  38 ++---
 packages/vm/src/calls.rs                      | 150 ++++++++----------
 packages/vm/src/instance.rs                   |  22 +--
 packages/vm/src/testing/calls.rs              |  49 +++---
 14 files changed, 193 insertions(+), 339 deletions(-)

diff --git a/contracts/hackatom/tests/integration.rs b/contracts/hackatom/tests/integration.rs
index 0b2f7efc1d..fc65a38657 100644
--- a/contracts/hackatom/tests/integration.rs
+++ b/contracts/hackatom/tests/integration.rs
@@ -321,7 +321,7 @@ fn execute_cpu_loop() {
 
     let execute_info = mock_info(creator.as_str(), &[]);
     // Note: we need to use the production-call, not the testing call (which unwraps any vm error)
-    let execute_res = call_execute::<_, _, _, Empty>(
+    let execute_res = call_execute::<_, _, _>(
         &mut deps,
         &mock_env(),
         &execute_info,
@@ -343,7 +343,7 @@ fn execute_storage_loop() {
 
     let execute_info = mock_info(creator.as_str(), &[]);
     // Note: we need to use the production-call, not the testing call (which unwraps any vm error)
-    let execute_res = call_execute::<_, _, _, Empty>(
+    let execute_res = call_execute::<_, _, _>(
         &mut deps,
         &mock_env(),
         &execute_info,
@@ -365,7 +365,7 @@ fn execute_memory_loop() {
 
     let execute_info = mock_info(creator.as_str(), &[]);
     // Note: we need to use the production-call, not the testing call (which unwraps any vm error)
-    let execute_res = call_execute::<_, _, _, Empty>(
+    let execute_res = call_execute::<_, _, _>(
         &mut deps,
         &mock_env(),
         &execute_info,
@@ -445,7 +445,7 @@ fn execute_panic() {
     let execute_info = mock_info(creator.as_str(), &[]);
     // panic inside contract should not panic out here
     // Note: we need to use the production-call, not the testing call (which unwraps any vm error)
-    let execute_res = call_execute::<_, _, _, Empty>(
+    let execute_res = call_execute::<_, _, _>(
         &mut deps,
         &mock_env(),
         &execute_info,
diff --git a/contracts/ibc-reflect-send/tests/integration.rs b/contracts/ibc-reflect-send/tests/integration.rs
index fbdaa3414c..3edc656d3c 100644
--- a/contracts/ibc-reflect-send/tests/integration.rs
+++ b/contracts/ibc-reflect-send/tests/integration.rs
@@ -210,7 +210,7 @@ fn send_remote_funds() {
         transfer_channel_id: transfer_channel_id.into(),
     };
     let info = mock_info(CREATOR, &coins(12344, "utrgd"));
-    execute::<_, _, _, _, Empty>(&mut deps, mock_env(), info, msg).unwrap_err();
+    execute::<_, _, _, _>(&mut deps, mock_env(), info, msg).unwrap_err();
 
     // let's try with no sent funds in the message
     let msg = ExecuteMsg::SendFunds {
@@ -218,7 +218,7 @@ fn send_remote_funds() {
         transfer_channel_id: transfer_channel_id.into(),
     };
     let info = mock_info(CREATOR, &[]);
-    execute::<_, _, _, _, Empty>(&mut deps, mock_env(), info, msg).unwrap_err();
+    execute::<_, _, _, _>(&mut deps, mock_env(), info, msg).unwrap_err();
 
     // 3rd times the charm
     let msg = ExecuteMsg::SendFunds {
diff --git a/contracts/ibc2/src/contract.rs b/contracts/ibc2/src/contract.rs
index a0dc05dcc5..4e3073be9e 100644
--- a/contracts/ibc2/src/contract.rs
+++ b/contracts/ibc2/src/contract.rs
@@ -45,7 +45,7 @@ pub fn ibc2_packet_receive(
     deps: DepsMut,
     env: Env,
     msg: Ibc2PacketReceiveMsg,
-) -> StdResult<IbcReceiveResponse> {
+) -> Result<IbcReceiveResponse, StdError> {
     let binary_payload = &msg.payload.value;
     let json_payload: IbcPayload = from_json(binary_payload)?;
 
diff --git a/packages/std/src/ibc.rs b/packages/std/src/ibc.rs
index 58505db626..f62bbd9bc9 100644
--- a/packages/std/src/ibc.rs
+++ b/packages/std/src/ibc.rs
@@ -7,7 +7,7 @@ use serde::{Deserialize, Serialize};
 
 use crate::coin::Coin;
 use crate::prelude::*;
-use crate::results::{Attribute, CosmosMsg, Empty, Event, SubMsg};
+use crate::results::{Attribute, CosmosMsg, Event, SubMsg};
 use crate::StdResult;
 use crate::{to_json_binary, Binary};
 use crate::{Addr, Timestamp};
@@ -560,12 +560,12 @@ impl IbcPacketTimeoutMsg {
 /// will use other Response types
 #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
 #[non_exhaustive]
-pub struct IbcBasicResponse<T = Empty> {
+pub struct IbcBasicResponse {
     /// Optional list of messages to pass. These will be executed in order.
     /// If the ReplyOn member is set, they will invoke this contract's `reply` entry point
     /// after execution. Otherwise, they act like "fire and forget".
     /// Use `SubMsg::new` to create messages with the older "fire and forget" semantics.
-    pub messages: Vec<SubMsg<T>>,
+    pub messages: Vec<SubMsg>,
     /// The attributes that will be emitted as part of a `wasm` event.
     ///
     /// More info about events (and their attributes) can be found in [*Cosmos SDK* docs].
@@ -582,7 +582,7 @@ pub struct IbcBasicResponse<T = Empty> {
 }
 
 // Custom implementation in order to implement it for all `T`, even if `T` is not `Default`.
-impl<T> Default for IbcBasicResponse<T> {
+impl Default for IbcBasicResponse {
     fn default() -> Self {
         IbcBasicResponse {
             messages: vec![],
@@ -592,7 +592,7 @@ impl<T> Default for IbcBasicResponse<T> {
     }
 }
 
-impl<T> IbcBasicResponse<T> {
+impl IbcBasicResponse {
     pub fn new() -> Self {
         Self::default()
     }
@@ -605,14 +605,14 @@ impl<T> IbcBasicResponse<T> {
 
     /// This creates a "fire and forget" message, by using `SubMsg::new()` to wrap it,
     /// and adds it to the list of messages to process.
-    pub fn add_message(mut self, msg: impl Into<CosmosMsg<T>>) -> Self {
+    pub fn add_message(mut self, msg: impl Into<CosmosMsg>) -> Self {
         self.messages.push(SubMsg::new(msg));
         self
     }
 
     /// This takes an explicit SubMsg (creates via e.g. `reply_on_error`)
     /// and adds it to the list of messages to process.
-    pub fn add_submessage(mut self, msg: SubMsg<T>) -> Self {
+    pub fn add_submessage(mut self, msg: SubMsg) -> Self {
         self.messages.push(msg);
         self
     }
@@ -664,7 +664,7 @@ impl<T> IbcBasicResponse<T> {
     ///     IbcBasicResponse::new().add_messages(msgs)
     /// }
     /// ```
-    pub fn add_messages<M: Into<CosmosMsg<T>>>(self, msgs: impl IntoIterator<Item = M>) -> Self {
+    pub fn add_messages<M: Into<CosmosMsg>>(self, msgs: impl IntoIterator<Item = M>) -> Self {
         self.add_submessages(msgs.into_iter().map(SubMsg::new))
     }
 
@@ -679,7 +679,7 @@ impl<T> IbcBasicResponse<T> {
     ///     IbcBasicResponse::new().add_submessages(msgs)
     /// }
     /// ```
-    pub fn add_submessages(mut self, msgs: impl IntoIterator<Item = SubMsg<T>>) -> Self {
+    pub fn add_submessages(mut self, msgs: impl IntoIterator<Item = SubMsg>) -> Self {
         self.messages.extend(msgs);
         self
     }
@@ -702,7 +702,7 @@ impl<T> IbcBasicResponse<T> {
 /// and not inform the calling chain).
 #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
 #[non_exhaustive]
-pub struct IbcReceiveResponse<T = Empty> {
+pub struct IbcReceiveResponse {
     /// The bytes we return to the contract that sent the packet.
     /// This may represent a success or error of execution.
     /// In case of `None`, no acknowledgement is written.
@@ -711,7 +711,7 @@ pub struct IbcReceiveResponse<T = Empty> {
     /// If the ReplyOn member is set, they will invoke this contract's `reply` entry point
     /// after execution. Otherwise, they act like "fire and forget".
     /// Use `call` or `msg.into()` to create messages with the older "fire and forget" semantics.
-    pub messages: Vec<SubMsg<T>>,
+    pub messages: Vec<SubMsg>,
     /// The attributes that will be emitted as part of a "wasm" event.
     ///
     /// More info about events (and their attributes) can be found in [*Cosmos SDK* docs].
@@ -727,7 +727,7 @@ pub struct IbcReceiveResponse<T = Empty> {
     pub events: Vec<Event>,
 }
 
-impl<T> IbcReceiveResponse<T> {
+impl IbcReceiveResponse {
     /// Create a new response with the given acknowledgement.
     ///
     /// ## Examples
@@ -803,14 +803,14 @@ impl<T> IbcReceiveResponse<T> {
 
     /// This creates a "fire and forget" message, by using `SubMsg::new()` to wrap it,
     /// and adds it to the list of messages to process.
-    pub fn add_message(mut self, msg: impl Into<CosmosMsg<T>>) -> Self {
+    pub fn add_message(mut self, msg: impl Into<CosmosMsg>) -> Self {
         self.messages.push(SubMsg::new(msg));
         self
     }
 
     /// This takes an explicit SubMsg (creates via e.g. `reply_on_error`)
     /// and adds it to the list of messages to process.
-    pub fn add_submessage(mut self, msg: SubMsg<T>) -> Self {
+    pub fn add_submessage(mut self, msg: SubMsg) -> Self {
         self.messages.push(msg);
         self
     }
@@ -862,7 +862,7 @@ impl<T> IbcReceiveResponse<T> {
     ///     IbcReceiveResponse::new(StdAck::success(b"\x01")).add_messages(msgs)
     /// }
     /// ```
-    pub fn add_messages<M: Into<CosmosMsg<T>>>(self, msgs: impl IntoIterator<Item = M>) -> Self {
+    pub fn add_messages<M: Into<CosmosMsg>>(self, msgs: impl IntoIterator<Item = M>) -> Self {
         self.add_submessages(msgs.into_iter().map(SubMsg::new))
     }
 
@@ -877,7 +877,7 @@ impl<T> IbcReceiveResponse<T> {
     ///     IbcReceiveResponse::new(StdAck::success(b"\x01")).add_submessages(msgs)
     /// }
     /// ```
-    pub fn add_submessages(mut self, msgs: impl IntoIterator<Item = SubMsg<T>>) -> Self {
+    pub fn add_submessages(mut self, msgs: impl IntoIterator<Item = SubMsg>) -> Self {
         self.messages.extend(msgs);
         self
     }
diff --git a/packages/std/src/results/cosmos_msg.rs b/packages/std/src/results/cosmos_msg.rs
index 85bbe23d15..973a6c4334 100644
--- a/packages/std/src/results/cosmos_msg.rs
+++ b/packages/std/src/results/cosmos_msg.rs
@@ -56,11 +56,11 @@ impl CustomMsg for Empty {}
 #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
 #[serde(rename_all = "snake_case")]
 // See https://github.com/serde-rs/serde/issues/1296 why we cannot add De-Serialize trait bounds to T
-pub enum CosmosMsg<T = Empty> {
+pub enum CosmosMsg {
     Bank(BankMsg),
     // by default we use RawMsg, but a contract can override that
     // to call into more app-specific code (whatever they define)
-    Custom(T),
+    Custom(Binary),
     #[cfg(feature = "staking")]
     Staking(StakingMsg),
     #[cfg(feature = "staking")]
@@ -90,34 +90,6 @@ pub enum CosmosMsg<T = Empty> {
     Ibc2(Ibc2Msg),
 }
 
-impl<T> CosmosMsg<T> {
-    /// Convert this [`CosmosMsg<T>`] to a [`CosmosMsg<U>`] with a different custom message type.
-    /// This allows easier interactions between code written for a specific chain and
-    /// code written for multiple chains.
-    /// If this is the [`CosmosMsg::Custom`] variant, the function returns `None`.
-    pub fn change_custom<U>(self) -> Option<CosmosMsg<U>> {
-        Some(match self {
-            CosmosMsg::Bank(msg) => CosmosMsg::Bank(msg),
-            CosmosMsg::Custom(_) => return None,
-            #[cfg(feature = "staking")]
-            CosmosMsg::Staking(msg) => CosmosMsg::Staking(msg),
-            #[cfg(feature = "staking")]
-            CosmosMsg::Distribution(msg) => CosmosMsg::Distribution(msg),
-            #[cfg(feature = "stargate")]
-            CosmosMsg::Stargate { type_url, value } => CosmosMsg::Stargate { type_url, value },
-            #[cfg(feature = "cosmwasm_2_0")]
-            CosmosMsg::Any(msg) => CosmosMsg::Any(msg),
-            #[cfg(feature = "stargate")]
-            CosmosMsg::Ibc(msg) => CosmosMsg::Ibc(msg),
-            CosmosMsg::Wasm(msg) => CosmosMsg::Wasm(msg),
-            #[cfg(feature = "stargate")]
-            CosmosMsg::Gov(msg) => CosmosMsg::Gov(msg),
-            #[cfg(feature = "ibc2")]
-            CosmosMsg::Ibc2(msg) => CosmosMsg::Ibc2(msg),
-        })
-    }
-}
-
 /// The message types of the bank module.
 ///
 /// See https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/bank/v1beta1/tx.proto
@@ -443,21 +415,21 @@ pub fn wasm_execute(
     })
 }
 
-impl<T> From<BankMsg> for CosmosMsg<T> {
+impl From<BankMsg> for CosmosMsg {
     fn from(msg: BankMsg) -> Self {
         CosmosMsg::Bank(msg)
     }
 }
 
 #[cfg(feature = "staking")]
-impl<T> From<StakingMsg> for CosmosMsg<T> {
+impl From<StakingMsg> for CosmosMsg {
     fn from(msg: StakingMsg) -> Self {
         CosmosMsg::Staking(msg)
     }
 }
 
 #[cfg(feature = "staking")]
-impl<T> From<DistributionMsg> for CosmosMsg<T> {
+impl From<DistributionMsg> for CosmosMsg {
     fn from(msg: DistributionMsg) -> Self {
         CosmosMsg::Distribution(msg)
     }
@@ -466,34 +438,34 @@ impl<T> From<DistributionMsg> for CosmosMsg<T> {
 // By implementing `From<MyType> for cosmwasm_std::AnyMsg`,
 // you automatically get a MyType -> CosmosMsg conversion.
 #[cfg(feature = "cosmwasm_2_0")]
-impl<S: Into<AnyMsg>, T> From<S> for CosmosMsg<T> {
+impl<S: Into<AnyMsg>> From<S> for CosmosMsg {
     fn from(source: S) -> Self {
-        CosmosMsg::<T>::Any(source.into())
+        CosmosMsg::Any(source.into())
     }
 }
 
-impl<T> From<WasmMsg> for CosmosMsg<T> {
+impl From<WasmMsg> for CosmosMsg {
     fn from(msg: WasmMsg) -> Self {
         CosmosMsg::Wasm(msg)
     }
 }
 
 #[cfg(feature = "stargate")]
-impl<T> From<IbcMsg> for CosmosMsg<T> {
+impl From<IbcMsg> for CosmosMsg {
     fn from(msg: IbcMsg) -> Self {
         CosmosMsg::Ibc(msg)
     }
 }
 
 #[cfg(feature = "stargate")]
-impl<T> From<GovMsg> for CosmosMsg<T> {
+impl From<GovMsg> for CosmosMsg {
     fn from(msg: GovMsg) -> Self {
         CosmosMsg::Gov(msg)
     }
 }
 
 #[cfg(feature = "ibc2")]
-impl<T> From<Ibc2Msg> for CosmosMsg<T> {
+impl From<Ibc2Msg> for CosmosMsg {
     fn from(msg: Ibc2Msg) -> Self {
         CosmosMsg::Ibc2(msg)
     }
@@ -503,7 +475,6 @@ impl<T> From<Ibc2Msg> for CosmosMsg<T> {
 mod tests {
     use super::*;
     use crate::{coin, coins};
-    use fmt::Debug;
 
     #[test]
     fn from_bank_msg_works() {
@@ -736,31 +707,4 @@ mod tests {
             );
         }
     }
-
-    #[test]
-    fn change_custom_works() {
-        #[derive(Debug, PartialEq, Eq, Clone)]
-        struct Custom {
-            _a: i32,
-        }
-        let send = BankMsg::Send {
-            to_address: "you".to_string(),
-            amount: coins(1015, "earth"),
-        };
-        // Custom to Empty
-        let msg: CosmosMsg<Custom> = send.clone().into();
-        let msg2: CosmosMsg<Empty> = msg.change_custom().unwrap();
-        assert_eq!(msg2, CosmosMsg::Bank(send.clone()));
-        let custom = CosmosMsg::Custom(Custom { _a: 5 });
-        let converted = custom.change_custom::<Empty>();
-        assert_eq!(converted, None);
-
-        // Empty to Custom
-        let msg: CosmosMsg<Empty> = send.clone().into();
-        let msg2: CosmosMsg<Custom> = msg.change_custom().unwrap();
-        assert_eq!(msg2, CosmosMsg::Bank(send));
-        let empty = CosmosMsg::Custom(Empty {});
-        let converted = empty.change_custom::<Custom>();
-        assert_eq!(converted, None);
-    }
 }
diff --git a/packages/std/src/results/response.rs b/packages/std/src/results/response.rs
index 11bfcc1484..c8f7c65c4d 100644
--- a/packages/std/src/results/response.rs
+++ b/packages/std/src/results/response.rs
@@ -4,7 +4,7 @@ use serde::{Deserialize, Serialize};
 use crate::prelude::*;
 use crate::Binary;
 
-use super::{Attribute, CosmosMsg, Empty, Event, SubMsg};
+use super::{Attribute, CosmosMsg, Event, SubMsg};
 
 /// A response of a contract entry point, such as `instantiate`, `execute` or `migrate`.
 ///
@@ -62,13 +62,13 @@ use super::{Attribute, CosmosMsg, Empty, Event, SubMsg};
 /// ```
 #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
 #[non_exhaustive]
-pub struct Response<T = Empty> {
+pub struct Response {
     /// Optional list of messages to pass. These will be executed in order.
     /// If the ReplyOn variant matches the result (Always, Success on Ok, Error on Err),
     /// the runtime will invoke this contract's `reply` entry point
     /// after execution. Otherwise, they act like "fire and forget".
     /// Use `SubMsg::new` to create messages with the older "fire and forget" semantics.
-    pub messages: Vec<SubMsg<T>>,
+    pub messages: Vec<SubMsg>,
     /// The attributes that will be emitted as part of a "wasm" event.
     ///
     /// More info about events (and their attributes) can be found in [*Cosmos SDK* docs].
@@ -86,7 +86,7 @@ pub struct Response<T = Empty> {
     pub data: Option<Binary>,
 }
 
-impl<T> Default for Response<T> {
+impl Default for Response {
     fn default() -> Self {
         Response {
             messages: vec![],
@@ -97,7 +97,7 @@ impl<T> Default for Response<T> {
     }
 }
 
-impl<T> Response<T> {
+impl Response {
     pub fn new() -> Self {
         Self::default()
     }
@@ -112,14 +112,14 @@ impl<T> Response<T> {
 
     /// This creates a "fire and forget" message, by using `SubMsg::new()` to wrap it,
     /// and adds it to the list of messages to process.
-    pub fn add_message(mut self, msg: impl Into<CosmosMsg<T>>) -> Self {
+    pub fn add_message(mut self, msg: impl Into<CosmosMsg>) -> Self {
         self.messages.push(SubMsg::new(msg));
         self
     }
 
     /// This takes an explicit SubMsg (creates via eg. `reply_on_error`)
     /// and adds it to the list of messages to process.
-    pub fn add_submessage(mut self, msg: SubMsg<T>) -> Self {
+    pub fn add_submessage(mut self, msg: SubMsg) -> Self {
         self.messages.push(msg);
         self
     }
@@ -194,7 +194,7 @@ impl<T> Response<T> {
     ///     Response::new().add_messages(msgs)
     /// }
     /// ```
-    pub fn add_messages<M: Into<CosmosMsg<T>>>(self, msgs: impl IntoIterator<Item = M>) -> Self {
+    pub fn add_messages<M: Into<CosmosMsg>>(self, msgs: impl IntoIterator<Item = M>) -> Self {
         self.add_submessages(msgs.into_iter().map(SubMsg::new))
     }
 
@@ -209,7 +209,7 @@ impl<T> Response<T> {
     ///     Response::new().add_submessages(msgs)
     /// }
     /// ```
-    pub fn add_submessages(mut self, msgs: impl IntoIterator<Item = SubMsg<T>>) -> Self {
+    pub fn add_submessages(mut self, msgs: impl IntoIterator<Item = SubMsg>) -> Self {
         self.messages.extend(msgs);
         self
     }
@@ -232,23 +232,6 @@ impl<T> Response<T> {
         self.data = Some(data.into());
         self
     }
-
-    /// Convert this [`Response<T>`] to a [`Response<U>`] with a different custom message type.
-    /// This allows easier interactions between code written for a specific chain and
-    /// code written for multiple chains.
-    /// If this contains a [`CosmosMsg::Custom`] submessage, the function returns `None`.
-    pub fn change_custom<U>(self) -> Option<Response<U>> {
-        Some(Response {
-            messages: self
-                .messages
-                .into_iter()
-                .map(|msg| msg.change_custom())
-                .collect::<Option<Vec<_>>>()?,
-            attributes: self.attributes,
-            events: self.events,
-            data: self.data,
-        })
-    }
 }
 
 #[cfg(test)]
@@ -260,10 +243,10 @@ mod tests {
 
     #[test]
     fn response_add_attributes_works() {
-        let res = Response::<Empty>::new().add_attributes(core::iter::empty::<Attribute>());
+        let res = Response::new().add_attributes(core::iter::empty::<Attribute>());
         assert_eq!(res.attributes.len(), 0);
 
-        let res = Response::<Empty>::new().add_attributes([Attribute::new("test", "ing")]);
+        let res = Response::new().add_attributes([Attribute::new("test", "ing")]);
         assert_eq!(res.attributes.len(), 1);
         assert_eq!(
             res.attributes[0],
@@ -371,8 +354,8 @@ mod tests {
         let msg = "message".to_string();
         let our_event = OurEvent { msg };
         let event: Event = our_event.clone().into();
-        let actual = Response::<Empty>::new().add_event(our_event);
-        let expected = Response::<Empty>::new().add_event(event);
+        let actual = Response::new().add_event(our_event);
+        let expected = Response::new().add_event(event);
         assert_eq!(expected, actual);
     }
 
@@ -383,42 +366,8 @@ mod tests {
         let our_event1 = OurEvent { msg: msg1 };
         let our_event2 = OurEvent { msg: msg2 };
         let events: Vec<Event> = vec![our_event1.clone().into(), our_event2.clone().into()];
-        let actual = Response::<Empty>::new().add_events([our_event1, our_event2]);
-        let expected = Response::<Empty>::new().add_events(events);
+        let actual = Response::new().add_events([our_event1, our_event2]);
+        let expected = Response::new().add_events(events);
         assert_eq!(expected, actual);
     }
-
-    #[test]
-    fn change_custom_works() {
-        let response: Response<Empty> = Response {
-            messages: vec![SubMsg::new(BankMsg::Send {
-                to_address: "address".to_string(),
-                amount: coins(123, "earth"),
-            })],
-            attributes: vec![Attribute::new("foo", "bar")],
-            events: vec![Event::new("our_event").add_attribute("msg", "hello")],
-            data: None,
-        };
-        let converted_resp: Response<String> = response.clone().change_custom().unwrap();
-        assert_eq!(
-            converted_resp.messages,
-            vec![SubMsg::new(BankMsg::Send {
-                to_address: "address".to_string(),
-                amount: coins(123, "earth"),
-            })]
-        );
-        assert_eq!(converted_resp.attributes, response.attributes);
-        assert_eq!(converted_resp.events, response.events);
-        assert_eq!(converted_resp.data, response.data);
-
-        // response with custom message
-        let response = Response {
-            messages: vec![SubMsg::new(CosmosMsg::Custom(Empty {}))],
-            attributes: vec![Attribute::new("foo", "bar")],
-            events: vec![Event::new("our_event").add_attribute("msg", "hello")],
-            data: None,
-        };
-
-        assert_eq!(response.change_custom::<String>(), None);
-    }
 }
diff --git a/packages/std/src/results/submessages.rs b/packages/std/src/results/submessages.rs
index 8a1c5221c8..f8a7d31194 100644
--- a/packages/std/src/results/submessages.rs
+++ b/packages/std/src/results/submessages.rs
@@ -4,7 +4,7 @@ use serde::{Deserialize, Serialize};
 use crate::prelude::*;
 use crate::Binary;
 
-use super::{CosmosMsg, Empty, Event};
+use super::{CosmosMsg, Event};
 
 /// Use this to define when the contract gets a response callback.
 /// If you only need it for errors or success you can select just those in order
@@ -29,7 +29,7 @@ pub enum ReplyOn {
 /// but not revert any state changes in the calling contract. If this is required, it must be done
 /// manually in the `reply` entry point.
 #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
-pub struct SubMsg<T = Empty> {
+pub struct SubMsg {
     /// An arbitrary ID chosen by the contract.
     /// This is typically used to match `Reply`s in the `reply` entry point to the submessage.
     pub id: u64,
@@ -47,7 +47,7 @@ pub struct SubMsg<T = Empty> {
     /// On chains running CosmWasm 1.x this field will be ignored.
     #[serde(default)]
     pub payload: Binary,
-    pub msg: CosmosMsg<T>,
+    pub msg: CosmosMsg,
     /// Gas limit measured in [Cosmos SDK gas](https://github.com/CosmWasm/cosmwasm/blob/main/docs/GAS.md).
     ///
     /// Setting this to `None` means unlimited. Then the submessage execution can consume all gas of the
@@ -59,7 +59,7 @@ pub struct SubMsg<T = Empty> {
 /// This is used for cases when we use ReplyOn::Never and the id doesn't matter
 pub const UNUSED_MSG_ID: u64 = 0;
 
-impl<T> SubMsg<T> {
+impl SubMsg {
     /// Creates a "fire and forget" message with the pre-0.14 semantics.
     /// Since this is just an alias for [`SubMsg::reply_never`] it is somewhat recommended
     /// to use the latter in order to make the behaviour more explicit in the caller code.
@@ -67,7 +67,7 @@ impl<T> SubMsg<T> {
     ///
     /// By default, the submessage's gas limit will be unlimited. Use [`SubMsg::with_gas_limit`] to change it.
     /// Setting `payload` is not advised as this will never be used.
-    pub fn new(msg: impl Into<CosmosMsg<T>>) -> Self {
+    pub fn new(msg: impl Into<CosmosMsg>) -> Self {
         Self::reply_never(msg)
     }
 
@@ -75,7 +75,7 @@ impl<T> SubMsg<T> {
     ///
     /// By default, the submessage's `payload` will be empty and the gas limit will be unlimited. Use
     /// [`SubMsg::with_payload`] and [`SubMsg::with_gas_limit`] to change those.
-    pub fn reply_on_success(msg: impl Into<CosmosMsg<T>>, id: u64) -> Self {
+    pub fn reply_on_success(msg: impl Into<CosmosMsg>, id: u64) -> Self {
         Self::reply_on(msg.into(), id, ReplyOn::Success)
     }
 
@@ -83,7 +83,7 @@ impl<T> SubMsg<T> {
     ///
     /// By default, the submessage's `payload` will be empty and the gas limit will be unlimited. Use
     /// [`SubMsg::with_payload`] and [`SubMsg::with_gas_limit`] to change those.
-    pub fn reply_on_error(msg: impl Into<CosmosMsg<T>>, id: u64) -> Self {
+    pub fn reply_on_error(msg: impl Into<CosmosMsg>, id: u64) -> Self {
         Self::reply_on(msg.into(), id, ReplyOn::Error)
     }
 
@@ -91,7 +91,7 @@ impl<T> SubMsg<T> {
     ///
     /// By default, the submessage's `payload` will be empty and the gas limit will be unlimited. Use
     /// [`SubMsg::with_payload`] and [`SubMsg::with_gas_limit`] to change those.
-    pub fn reply_always(msg: impl Into<CosmosMsg<T>>, id: u64) -> Self {
+    pub fn reply_always(msg: impl Into<CosmosMsg>, id: u64) -> Self {
         Self::reply_on(msg.into(), id, ReplyOn::Always)
     }
 
@@ -99,7 +99,7 @@ impl<T> SubMsg<T> {
     ///
     /// By default, the submessage's gas limit will be unlimited. Use [`SubMsg::with_gas_limit`] to change it.
     /// Setting `payload` is not advised as this will never be used.
-    pub fn reply_never(msg: impl Into<CosmosMsg<T>>) -> Self {
+    pub fn reply_never(msg: impl Into<CosmosMsg>) -> Self {
         Self::reply_on(msg.into(), UNUSED_MSG_ID, ReplyOn::Never)
     }
 
@@ -139,7 +139,7 @@ impl<T> SubMsg<T> {
         self
     }
 
-    fn reply_on(msg: CosmosMsg<T>, id: u64, reply_on: ReplyOn) -> Self {
+    fn reply_on(msg: CosmosMsg, id: u64, reply_on: ReplyOn) -> Self {
         SubMsg {
             id,
             payload: Default::default(),
@@ -148,20 +148,6 @@ impl<T> SubMsg<T> {
             gas_limit: None,
         }
     }
-
-    /// Convert this [`SubMsg<T>`] to a [`SubMsg<U>`] with a different generic type.
-    /// This allows easier interactions between code written for a specific chain and
-    /// code written for multiple chains.
-    /// If this is a [`CosmosMsg::Custom`] submessage, the function returns `None`.
-    pub fn change_custom<U>(self) -> Option<SubMsg<U>> {
-        Some(SubMsg {
-            id: self.id,
-            payload: self.payload,
-            msg: self.msg.change_custom::<U>()?,
-            gas_limit: self.gas_limit,
-            reply_on: self.reply_on,
-        })
-    }
 }
 
 /// The result object returned to `reply`. We always get the ID from the submessage
diff --git a/packages/vm/benches/main.rs b/packages/vm/benches/main.rs
index f488c7280c..4af4c06159 100644
--- a/packages/vm/benches/main.rs
+++ b/packages/vm/benches/main.rs
@@ -71,7 +71,7 @@ fn bench_instance(c: &mut Criterion) {
             let verifier = instance.api().addr_make("verifies");
             let beneficiary = instance.api().addr_make("benefits");
             let msg = format!(r#"{{"verifier": "{verifier}", "beneficiary": "{beneficiary}"}}"#);
-            let contract_result = call_instantiate::<_, _, _, Empty>(
+            let contract_result = call_instantiate::<_, _, _>(
                 &mut instance,
                 &mock_env(),
                 &info,
@@ -95,7 +95,7 @@ fn bench_instance(c: &mut Criterion) {
         let beneficiary = instance.api().addr_make("benefits");
         let msg = format!(r#"{{"verifier": "{verifier}", "beneficiary": "{beneficiary}"}}"#);
         let contract_result =
-            call_instantiate::<_, _, _, Empty>(&mut instance, &mock_env(), &info, msg.as_bytes())
+            call_instantiate::<_, _, _>(&mut instance, &mock_env(), &info, msg.as_bytes())
                 .unwrap();
         assert!(contract_result.into_result().is_ok());
 
@@ -103,7 +103,7 @@ fn bench_instance(c: &mut Criterion) {
             let info = mock_info(&verifier, &coins(15, "earth"));
             let msg = br#"{"release":{"denom":"earth"}}"#;
             let contract_result =
-                call_execute::<_, _, _, Empty>(&mut instance, &mock_env(), &info, msg).unwrap();
+                call_execute::<_, _, _>(&mut instance, &mock_env(), &info, msg).unwrap();
             assert!(contract_result.into_result().is_ok());
         });
     });
@@ -118,7 +118,7 @@ fn bench_instance(c: &mut Criterion) {
 
         let info = mock_info("creator", &coins(1000, "earth"));
         let contract_result =
-            call_instantiate::<_, _, _, Empty>(&mut instance, &mock_env(), &info, b"{}").unwrap();
+            call_instantiate::<_, _, _>(&mut instance, &mock_env(), &info, b"{}").unwrap();
         assert!(contract_result.into_result().is_ok());
 
         let mut gas_used = 0;
@@ -127,7 +127,7 @@ fn bench_instance(c: &mut Criterion) {
             let info = mock_info("hasher", &[]);
             let msg = br#"{"argon2":{"mem_cost":256,"time_cost":3}}"#;
             let contract_result =
-                call_execute::<_, _, _, Empty>(&mut instance, &mock_env(), &info, msg).unwrap();
+                call_execute::<_, _, _>(&mut instance, &mock_env(), &info, msg).unwrap();
             assert!(contract_result.into_result().is_ok());
             gas_used = gas_before - instance.get_gas_left();
         });
@@ -145,7 +145,7 @@ fn bench_instance(c: &mut Criterion) {
 
         let info = mock_info("creator", &coins(1000, "earth"));
         let contract_result =
-            call_instantiate::<_, _, _, Empty>(&mut instance, &mock_env(), &info, b"{}").unwrap();
+            call_instantiate::<_, _, _>(&mut instance, &mock_env(), &info, b"{}").unwrap();
         assert!(contract_result.into_result().is_ok());
 
         let mut gas_used = 0;
@@ -165,8 +165,8 @@ fn bench_instance(c: &mut Criterion) {
                 let info = mock_info("hasher", &[]);
                 let msg = br#"{"cpu_loop":{}}"#;
 
-                let vm_result =
-                    call_execute::<_, _, _, Empty>(&mut instance, &mock_env(), &info, msg);
+                let vm_result: Result<cosmwasm_std::ContractResult<cosmwasm_std::Response>, VmError> =
+                    call_execute::<_, _, _>(&mut instance, &mock_env(), &info, msg);
 
                 assert!(matches!(vm_result, Err(VmError::GasDepletion { .. })));
                 gas_used = gas_before - instance.get_gas_left();
@@ -446,7 +446,7 @@ fn bench_combined(c: &mut Criterion) {
             let info = mock_info("guest", &[]);
             let msg = br#"{"noop":{}}"#;
             let contract_result =
-                call_execute::<_, _, _, Empty>(&mut instance, &mock_env(), &info, msg).unwrap();
+                call_execute::<_, _, _>(&mut instance, &mock_env(), &info, msg).unwrap();
             contract_result.into_result().unwrap();
         });
     });
@@ -473,7 +473,7 @@ fn bench_combined(c: &mut Criterion) {
             let info = mock_info("guest", &[]);
             let msg = br#"{"noop":{}}"#;
             let contract_result =
-                call_execute::<_, _, _, Empty>(&mut instance, &mock_env(), &info, msg).unwrap();
+                call_execute::<_, _, _>(&mut instance, &mock_env(), &info, msg).unwrap();
             contract_result.into_result().unwrap();
         });
     });
@@ -498,7 +498,7 @@ fn bench_combined(c: &mut Criterion) {
             let info = mock_info("guest", &[]);
             let msg = br#"{"noop":{}}"#;
             let contract_result =
-                call_execute::<_, _, _, Empty>(&mut instance, &mock_env(), &info, msg).unwrap();
+                call_execute::<_, _, _>(&mut instance, &mock_env(), &info, msg).unwrap();
             contract_result.into_result().unwrap();
         });
     });
diff --git a/packages/vm/examples/heap_profiling.rs b/packages/vm/examples/heap_profiling.rs
index 037b6794fd..1013d59a3c 100644
--- a/packages/vm/examples/heap_profiling.rs
+++ b/packages/vm/examples/heap_profiling.rs
@@ -5,7 +5,7 @@ use std::time::{Duration, SystemTime};
 use tempfile::TempDir;
 use time::{format_description::well_known::Rfc3339, OffsetDateTime};
 
-use cosmwasm_std::{coins, Checksum, Empty};
+use cosmwasm_std::{coins, Checksum};
 use cosmwasm_vm::testing::{mock_backend, mock_env, mock_info, MockApi, MockQuerier, MockStorage};
 use cosmwasm_vm::{
     call_execute, call_instantiate, capabilities_from_csv, Cache, CacheOptions, InstanceOptions,
@@ -154,7 +154,7 @@ fn app(runtime: u64) {
                 if let Some(msg) = &contracts[idx].instantiate_msg {
                     let info = mock_info("creator", &coins(1000, "earth"));
                     let contract_result =
-                        call_instantiate::<_, _, _, Empty>(&mut instance, &mock_env(), &info, msg)
+                        call_instantiate::<_, _, _>(&mut instance, &mock_env(), &info, msg)
                             .unwrap();
                     assert!(contract_result.into_result().is_ok());
                 }
@@ -163,7 +163,7 @@ fn app(runtime: u64) {
                     let info = mock_info("verifies", &coins(15, "earth"));
                     let msg = execute.msg;
                     let res =
-                        call_execute::<_, _, _, Empty>(&mut instance, &mock_env(), &info, msg);
+                        call_execute::<_, _, _>(&mut instance, &mock_env(), &info, msg);
 
                     if execute.expect_error {
                         if res.is_ok() {
diff --git a/packages/vm/examples/multi_threaded_cache.rs b/packages/vm/examples/multi_threaded_cache.rs
index 295627e0b1..17f90556ad 100644
--- a/packages/vm/examples/multi_threaded_cache.rs
+++ b/packages/vm/examples/multi_threaded_cache.rs
@@ -2,7 +2,7 @@ use std::sync::Arc;
 use std::thread;
 use tempfile::TempDir;
 
-use cosmwasm_std::{coins, Empty};
+use cosmwasm_std::coins;
 use cosmwasm_vm::testing::{mock_backend, mock_env, mock_info, MockApi, MockQuerier, MockStorage};
 use cosmwasm_vm::{
     call_execute, call_instantiate, capabilities_from_csv, Cache, CacheOptions, InstanceOptions,
@@ -59,7 +59,7 @@ pub fn main() {
             let verifier = instance.api().addr_make("verifies");
             let beneficiary = instance.api().addr_make("benefits");
             let msg = format!(r#"{{"verifier": "{verifier}", "beneficiary": "{beneficiary}"}}"#);
-            let contract_result = call_instantiate::<_, _, _, Empty>(
+            let contract_result = call_instantiate::<_, _, _>(
                 &mut instance,
                 &mock_env(),
                 &info,
@@ -71,7 +71,7 @@ pub fn main() {
             let info = mock_info(&verifier, &coins(15, "earth"));
             let msg = br#"{"release":{"denom":"earth"}}"#;
             let contract_result =
-                call_execute::<_, _, _, Empty>(&mut instance, &mock_env(), &info, msg).unwrap();
+                call_execute::<_, _, _>(&mut instance, &mock_env(), &info, msg).unwrap();
             assert!(contract_result.into_result().is_ok());
         }));
     }
diff --git a/packages/vm/src/cache.rs b/packages/vm/src/cache.rs
index c551047efe..785fcf0522 100644
--- a/packages/vm/src/cache.rs
+++ b/packages/vm/src/cache.rs
@@ -608,7 +608,7 @@ mod tests {
     use super::*;
     use crate::calls::{call_execute, call_instantiate};
     use crate::testing::{mock_backend, mock_env, mock_info, MockApi, MockQuerier, MockStorage};
-    use cosmwasm_std::{coins, Empty};
+    use cosmwasm_std::coins;
     use std::borrow::Cow;
     use std::fs::{create_dir_all, remove_dir_all};
     use tempfile::TempDir;
@@ -693,7 +693,7 @@ mod tests {
         let beneficiary = instance.api().addr_make("benefits");
         let msg = format!(r#"{{"verifier": "{verifier}", "beneficiary": "{beneficiary}"}}"#);
         let response =
-            call_instantiate::<_, _, _, Empty>(instance, &mock_env(), &info, msg.as_bytes())
+            call_instantiate::<_, _, _>(instance, &mock_env(), &info, msg.as_bytes())
                 .unwrap()
                 .unwrap();
         assert_eq!(response.messages.len(), 0);
@@ -701,7 +701,7 @@ mod tests {
         // execute
         let info = mock_info(&verifier, &coins(15, "earth"));
         let msg = br#"{"release":{"denom":"earth"}}"#;
-        let response = call_execute::<_, _, _, Empty>(instance, &mock_env(), &info, msg)
+        let response = call_execute::<_, _, _>(instance, &mock_env(), &info, msg)
             .unwrap()
             .unwrap();
         assert_eq!(response.messages.len(), 1);
@@ -1046,7 +1046,7 @@ mod tests {
             let verifier = instance.api().addr_make("verifies");
             let beneficiary = instance.api().addr_make("benefits");
             let msg = format!(r#"{{"verifier": "{verifier}", "beneficiary": "{beneficiary}"}}"#);
-            let res = call_instantiate::<_, _, _, Empty>(
+            let res = call_instantiate::<_, _, _>(
                 &mut instance,
                 &mock_env(),
                 &info,
@@ -1072,7 +1072,7 @@ mod tests {
             let verifier = instance.api().addr_make("verifies");
             let beneficiary = instance.api().addr_make("benefits");
             let msg = format!(r#"{{"verifier": "{verifier}", "beneficiary": "{beneficiary}"}}"#);
-            let res = call_instantiate::<_, _, _, Empty>(
+            let res = call_instantiate::<_, _, _>(
                 &mut instance,
                 &mock_env(),
                 &info,
@@ -1100,7 +1100,7 @@ mod tests {
             let verifier = instance.api().addr_make("verifies");
             let beneficiary = instance.api().addr_make("benefits");
             let msg = format!(r#"{{"verifier": "{verifier}", "beneficiary": "{beneficiary}"}}"#);
-            let res = call_instantiate::<_, _, _, Empty>(
+            let res = call_instantiate::<_, _, _>(
                 &mut instance,
                 &mock_env(),
                 &info,
@@ -1132,7 +1132,7 @@ mod tests {
             let verifier = instance.api().addr_make("verifies");
             let beneficiary = instance.api().addr_make("benefits");
             let msg = format!(r#"{{"verifier": "{verifier}", "beneficiary": "{beneficiary}"}}"#);
-            let response = call_instantiate::<_, _, _, Empty>(
+            let response = call_instantiate::<_, _, _>(
                 &mut instance,
                 &mock_env(),
                 &info,
@@ -1145,7 +1145,7 @@ mod tests {
             // execute
             let info = mock_info(&verifier, &coins(15, "earth"));
             let msg = br#"{"release":{"denom":"earth"}}"#;
-            let response = call_execute::<_, _, _, Empty>(&mut instance, &mock_env(), &info, msg)
+            let response = call_execute::<_, _, _>(&mut instance, &mock_env(), &info, msg)
                 .unwrap()
                 .unwrap();
             assert_eq!(response.messages.len(), 1);
@@ -1166,7 +1166,7 @@ mod tests {
             let verifier = instance.api().addr_make("verifies");
             let beneficiary = instance.api().addr_make("benefits");
             let msg = format!(r#"{{"verifier": "{verifier}", "beneficiary": "{beneficiary}"}}"#);
-            let response = call_instantiate::<_, _, _, Empty>(
+            let response = call_instantiate::<_, _, _>(
                 &mut instance,
                 &mock_env(),
                 &info,
@@ -1179,7 +1179,7 @@ mod tests {
             // execute
             let info = mock_info(&verifier, &coins(15, "earth"));
             let msg = br#"{"release":{"denom":"earth"}}"#;
-            let response = call_execute::<_, _, _, Empty>(&mut instance, &mock_env(), &info, msg)
+            let response = call_execute::<_, _, _>(&mut instance, &mock_env(), &info, msg)
                 .unwrap()
                 .unwrap();
             assert_eq!(response.messages.len(), 1);
@@ -1202,7 +1202,7 @@ mod tests {
             let verifier = instance.api().addr_make("verifies");
             let beneficiary = instance.api().addr_make("benefits");
             let msg = format!(r#"{{"verifier": "{verifier}", "beneficiary": "{beneficiary}"}}"#);
-            let response = call_instantiate::<_, _, _, Empty>(
+            let response = call_instantiate::<_, _, _>(
                 &mut instance,
                 &mock_env(),
                 &info,
@@ -1215,7 +1215,7 @@ mod tests {
             // execute
             let info = mock_info(&verifier, &coins(15, "earth"));
             let msg = br#"{"release":{"denom":"earth"}}"#;
-            let response = call_execute::<_, _, _, Empty>(&mut instance, &mock_env(), &info, msg)
+            let response = call_execute::<_, _, _>(&mut instance, &mock_env(), &info, msg)
                 .unwrap()
                 .unwrap();
             assert_eq!(response.messages.len(), 1);
@@ -1261,7 +1261,7 @@ mod tests {
         let mary = instance.api().addr_make("mary");
         let msg = format!(r#"{{"verifier": "{sue}", "beneficiary": "{mary}"}}"#);
         let res =
-            call_instantiate::<_, _, _, Empty>(&mut instance, &mock_env(), &info, msg.as_bytes())
+            call_instantiate::<_, _, _>(&mut instance, &mock_env(), &info, msg.as_bytes())
                 .unwrap();
         let msgs = res.unwrap().messages;
         assert_eq!(msgs.len(), 0);
@@ -1276,7 +1276,7 @@ mod tests {
         let john = instance.api().addr_make("john");
         let msg = format!(r#"{{"verifier": "{bob}", "beneficiary": "{john}"}}"#);
         let res =
-            call_instantiate::<_, _, _, Empty>(&mut instance, &mock_env(), &info, msg.as_bytes())
+            call_instantiate::<_, _, _>(&mut instance, &mock_env(), &info, msg.as_bytes())
                 .unwrap();
         let msgs = res.unwrap().messages;
         assert_eq!(msgs.len(), 0);
@@ -1288,7 +1288,7 @@ mod tests {
             .unwrap();
         let info = mock_info(&bob, &coins(15, "earth"));
         let msg = br#"{"release":{"denom":"earth"}}"#;
-        let res = call_execute::<_, _, _, Empty>(&mut instance, &mock_env(), &info, msg).unwrap();
+        let res = call_execute::<_, _, _>(&mut instance, &mock_env(), &info, msg).unwrap();
         let msgs = res.unwrap().messages;
         assert_eq!(1, msgs.len());
 
@@ -1298,7 +1298,7 @@ mod tests {
             .unwrap();
         let info = mock_info(&sue, &coins(15, "earth"));
         let msg = br#"{"release":{"denom":"earth"}}"#;
-        let res = call_execute::<_, _, _, Empty>(&mut instance, &mock_env(), &info, msg).unwrap();
+        let res = call_execute::<_, _, _>(&mut instance, &mock_env(), &info, msg).unwrap();
         let msgs = res.unwrap().messages;
         assert_eq!(1, msgs.len());
     }
@@ -1326,7 +1326,7 @@ mod tests {
         let sue = instance1.api().addr_make("sue");
         let mary = instance1.api().addr_make("mary");
         let msg = format!(r#"{{"verifier": "{sue}", "beneficiary": "{mary}"}}"#);
-        call_instantiate::<_, _, _, Empty>(&mut instance1, &mock_env(), &info, msg.as_bytes())
+        call_instantiate::<_, _, _>(&mut instance1, &mock_env(), &info, msg.as_bytes())
             .unwrap()
             .unwrap();
         assert!(instance1.get_gas_left() < original_gas);
@@ -1362,7 +1362,7 @@ mod tests {
         let mary = instance1.api().addr_make("mary");
         let msg1 = format!(r#"{{"verifier": "{sue}", "beneficiary": "{mary}"}}"#);
 
-        match call_instantiate::<_, _, _, Empty>(
+        match call_instantiate::<_, _, _>(
             &mut instance1,
             &mock_env(),
             &info1,
@@ -1391,7 +1391,7 @@ mod tests {
         let bob = instance2.api().addr_make("bob");
         let john = instance2.api().addr_make("john");
         let msg2 = format!(r#"{{"verifier": "{bob}", "beneficiary": "{john}"}}"#);
-        call_instantiate::<_, _, _, Empty>(&mut instance2, &mock_env(), &info2, msg2.as_bytes())
+        call_instantiate::<_, _, _>(&mut instance2, &mock_env(), &info2, msg2.as_bytes())
             .unwrap()
             .unwrap();
     }
diff --git a/packages/vm/src/calls.rs b/packages/vm/src/calls.rs
index 370c2d7032..4f12e5b348 100644
--- a/packages/vm/src/calls.rs
+++ b/packages/vm/src/calls.rs
@@ -1,8 +1,7 @@
-use serde::de::DeserializeOwned;
 use wasmer::Value;
 
 use cosmwasm_std::{
-    ContractResult, CustomMsg, Env, IbcBasicResponse, IbcDestinationCallbackMsg,
+    ContractResult, Env, IbcBasicResponse, IbcDestinationCallbackMsg,
     IbcSourceCallbackMsg, MessageInfo, MigrateInfo, QueryResponse, Reply, Response,
 };
 
@@ -112,117 +111,111 @@ mod deserialization_limits {
     pub const RESULT_IBC_DESTINATION_CALLBACK: usize = 256 * KI;
 }
 
-pub fn call_instantiate<A, S, Q, U>(
+pub fn call_instantiate<A, S, Q>(
     instance: &mut Instance<A, S, Q>,
     env: &Env,
     info: &MessageInfo,
     msg: &[u8],
-) -> VmResult<ContractResult<Response<U>>>
+) -> VmResult<ContractResult<Response>>
 where
     A: BackendApi + 'static,
     S: Storage + 'static,
     Q: Querier + 'static,
-    U: DeserializeOwned + CustomMsg,
 {
     let env = to_vec(env)?;
     let info = to_vec(info)?;
     let data = call_instantiate_raw(instance, &env, &info, msg)?;
-    let result: ContractResult<Response<U>> =
+    let result: ContractResult<Response> =
         from_slice(&data, deserialization_limits::RESULT_INSTANTIATE)?;
     Ok(result)
 }
 
-pub fn call_execute<A, S, Q, U>(
+pub fn call_execute<A, S, Q>(
     instance: &mut Instance<A, S, Q>,
     env: &Env,
     info: &MessageInfo,
     msg: &[u8],
-) -> VmResult<ContractResult<Response<U>>>
+) -> VmResult<ContractResult<Response>>
 where
     A: BackendApi + 'static,
     S: Storage + 'static,
     Q: Querier + 'static,
-    U: DeserializeOwned + CustomMsg,
 {
     let env = to_vec(env)?;
     let info = to_vec(info)?;
     let data = call_execute_raw(instance, &env, &info, msg)?;
-    let result: ContractResult<Response<U>> =
+    let result: ContractResult<Response> =
         from_slice(&data, deserialization_limits::RESULT_EXECUTE)?;
     Ok(result)
 }
 
-pub fn call_migrate<A, S, Q, U>(
+pub fn call_migrate<A, S, Q>(
     instance: &mut Instance<A, S, Q>,
     env: &Env,
     msg: &[u8],
-) -> VmResult<ContractResult<Response<U>>>
+) -> VmResult<ContractResult<Response>>
 where
     A: BackendApi + 'static,
     S: Storage + 'static,
     Q: Querier + 'static,
-    U: DeserializeOwned + CustomMsg,
 {
     let env = to_vec(env)?;
     let data = call_migrate_raw(instance, &env, msg)?;
-    let result: ContractResult<Response<U>> =
+    let result: ContractResult<Response> =
         from_slice(&data, deserialization_limits::RESULT_MIGRATE)?;
     Ok(result)
 }
 
-pub fn call_migrate_with_info<A, S, Q, U>(
+pub fn call_migrate_with_info<A, S, Q>(
     instance: &mut Instance<A, S, Q>,
     env: &Env,
     msg: &[u8],
     migrate_info: &MigrateInfo,
-) -> VmResult<ContractResult<Response<U>>>
+) -> VmResult<ContractResult<Response>>
 where
     A: BackendApi + 'static,
     S: Storage + 'static,
     Q: Querier + 'static,
-    U: DeserializeOwned + CustomMsg,
 {
     let env = to_vec(env)?;
     let migrate_info = to_vec(migrate_info)?;
     let data = call_migrate_with_info_raw(instance, &env, msg, &migrate_info)?;
-    let result: ContractResult<Response<U>> =
+    let result: ContractResult<Response> =
         from_slice(&data, deserialization_limits::RESULT_MIGRATE)?;
     Ok(result)
 }
 
-pub fn call_sudo<A, S, Q, U>(
+pub fn call_sudo<A, S, Q>(
     instance: &mut Instance<A, S, Q>,
     env: &Env,
     msg: &[u8],
-) -> VmResult<ContractResult<Response<U>>>
+) -> VmResult<ContractResult<Response>>
 where
     A: BackendApi + 'static,
     S: Storage + 'static,
     Q: Querier + 'static,
-    U: DeserializeOwned + CustomMsg,
 {
     let env = to_vec(env)?;
     let data = call_sudo_raw(instance, &env, msg)?;
-    let result: ContractResult<Response<U>> =
+    let result: ContractResult<Response> =
         from_slice(&data, deserialization_limits::RESULT_SUDO)?;
     Ok(result)
 }
 
-pub fn call_reply<A, S, Q, U>(
+pub fn call_reply<A, S, Q>(
     instance: &mut Instance<A, S, Q>,
     env: &Env,
     msg: &Reply,
-) -> VmResult<ContractResult<Response<U>>>
+) -> VmResult<ContractResult<Response>>
 where
     A: BackendApi + 'static,
     S: Storage + 'static,
     Q: Querier + 'static,
-    U: DeserializeOwned + CustomMsg,
 {
     let env = to_vec(env)?;
     let msg = to_vec(msg)?;
     let data = call_reply_raw(instance, &env, &msg)?;
-    let result: ContractResult<Response<U>> =
+    let result: ContractResult<Response> =
         from_slice(&data, deserialization_limits::RESULT_REPLY)?;
     Ok(result)
 }
@@ -270,16 +263,15 @@ where
 }
 
 #[cfg(feature = "stargate")]
-pub fn call_ibc_channel_connect<A, S, Q, U>(
+pub fn call_ibc_channel_connect<A, S, Q>(
     instance: &mut Instance<A, S, Q>,
     env: &Env,
     msg: &IbcChannelConnectMsg,
-) -> VmResult<ContractResult<IbcBasicResponse<U>>>
+) -> VmResult<ContractResult<IbcBasicResponse>>
 where
     A: BackendApi + 'static,
     S: Storage + 'static,
     Q: Querier + 'static,
-    U: DeserializeOwned + CustomMsg,
 {
     let env = to_vec(env)?;
     let msg = to_vec(msg)?;
@@ -289,16 +281,15 @@ where
 }
 
 #[cfg(feature = "stargate")]
-pub fn call_ibc_channel_close<A, S, Q, U>(
+pub fn call_ibc_channel_close<A, S, Q>(
     instance: &mut Instance<A, S, Q>,
     env: &Env,
     msg: &IbcChannelCloseMsg,
-) -> VmResult<ContractResult<IbcBasicResponse<U>>>
+) -> VmResult<ContractResult<IbcBasicResponse>>
 where
     A: BackendApi + 'static,
     S: Storage + 'static,
     Q: Querier + 'static,
-    U: DeserializeOwned + CustomMsg,
 {
     let env = to_vec(env)?;
     let msg = to_vec(msg)?;
@@ -308,16 +299,15 @@ where
 }
 
 #[cfg(feature = "stargate")]
-pub fn call_ibc_packet_receive<A, S, Q, U>(
+pub fn call_ibc_packet_receive<A, S, Q>(
     instance: &mut Instance<A, S, Q>,
     env: &Env,
     msg: &IbcPacketReceiveMsg,
-) -> VmResult<ContractResult<IbcReceiveResponse<U>>>
+) -> VmResult<ContractResult<IbcReceiveResponse>>
 where
     A: BackendApi + 'static,
     S: Storage + 'static,
     Q: Querier + 'static,
-    U: DeserializeOwned + CustomMsg,
 {
     let env = to_vec(env)?;
     let msg = to_vec(msg)?;
@@ -327,16 +317,15 @@ where
 }
 
 #[cfg(feature = "stargate")]
-pub fn call_ibc_packet_ack<A, S, Q, U>(
+pub fn call_ibc_packet_ack<A, S, Q>(
     instance: &mut Instance<A, S, Q>,
     env: &Env,
     msg: &IbcPacketAckMsg,
-) -> VmResult<ContractResult<IbcBasicResponse<U>>>
+) -> VmResult<ContractResult<IbcBasicResponse>>
 where
     A: BackendApi + 'static,
     S: Storage + 'static,
     Q: Querier + 'static,
-    U: DeserializeOwned + CustomMsg,
 {
     let env = to_vec(env)?;
     let msg = to_vec(msg)?;
@@ -346,16 +335,15 @@ where
 }
 
 #[cfg(feature = "stargate")]
-pub fn call_ibc_packet_timeout<A, S, Q, U>(
+pub fn call_ibc_packet_timeout<A, S, Q>(
     instance: &mut Instance<A, S, Q>,
     env: &Env,
     msg: &IbcPacketTimeoutMsg,
-) -> VmResult<ContractResult<IbcBasicResponse<U>>>
+) -> VmResult<ContractResult<IbcBasicResponse>>
 where
     A: BackendApi + 'static,
     S: Storage + 'static,
     Q: Querier + 'static,
-    U: DeserializeOwned + CustomMsg,
 {
     let env = to_vec(env)?;
     let msg = to_vec(msg)?;
@@ -364,16 +352,15 @@ where
     Ok(result)
 }
 
-pub fn call_ibc_source_callback<A, S, Q, U>(
+pub fn call_ibc_source_callback<A, S, Q>(
     instance: &mut Instance<A, S, Q>,
     env: &Env,
     msg: &IbcSourceCallbackMsg,
-) -> VmResult<ContractResult<IbcBasicResponse<U>>>
+) -> VmResult<ContractResult<IbcBasicResponse>>
 where
     A: BackendApi + 'static,
     S: Storage + 'static,
     Q: Querier + 'static,
-    U: DeserializeOwned + CustomMsg,
 {
     let env = to_vec(env)?;
     let msg = to_vec(msg)?;
@@ -382,16 +369,15 @@ where
     Ok(result)
 }
 
-pub fn call_ibc_destination_callback<A, S, Q, U>(
+pub fn call_ibc_destination_callback<A, S, Q>(
     instance: &mut Instance<A, S, Q>,
     env: &Env,
     msg: &IbcDestinationCallbackMsg,
-) -> VmResult<ContractResult<IbcBasicResponse<U>>>
+) -> VmResult<ContractResult<IbcBasicResponse>>
 where
     A: BackendApi + 'static,
     S: Storage + 'static,
     Q: Querier + 'static,
-    U: DeserializeOwned + CustomMsg,
 {
     let env = to_vec(env)?;
     let msg = to_vec(msg)?;
@@ -698,16 +684,15 @@ where
 }
 
 #[cfg(feature = "ibc2")]
-pub fn call_ibc2_packet_timeout<A, S, Q, U>(
+pub fn call_ibc2_packet_timeout<A, S, Q>(
     instance: &mut Instance<A, S, Q>,
     env: &Env,
     msg: &Ibc2PacketTimeoutMsg,
-) -> VmResult<ContractResult<IbcBasicResponse<U>>>
+) -> VmResult<ContractResult<IbcBasicResponse>>
 where
     A: BackendApi + 'static,
     S: Storage + 'static,
     Q: Querier + 'static,
-    U: DeserializeOwned + CustomMsg,
 {
     let env = to_vec(env)?;
     let msg = to_vec(msg)?;
@@ -802,16 +787,15 @@ where
 }
 
 #[cfg(feature = "ibc2")]
-pub fn call_ibc2_packet_receive<A, S, Q, U>(
+pub fn call_ibc2_packet_receive<A, S, Q>(
     instance: &mut Instance<A, S, Q>,
     env: &Env,
     msg: &Ibc2PacketReceiveMsg,
-) -> VmResult<ContractResult<IbcReceiveResponse<U>>>
+) -> VmResult<ContractResult<IbcReceiveResponse>>
 where
     A: BackendApi + 'static,
     S: Storage + 'static,
     Q: Querier + 'static,
-    U: DeserializeOwned + CustomMsg,
 {
     let env = to_vec(env)?;
     let msg = to_vec(msg)?;
@@ -844,7 +828,7 @@ mod tests {
         let verifier = instance.api().addr_make("verifies");
         let beneficiary = instance.api().addr_make("benefits");
         let msg = format!(r#"{{"verifier": "{verifier}", "beneficiary": "{beneficiary}"}}"#);
-        call_instantiate::<_, _, _, Empty>(&mut instance, &mock_env(), &info, msg.as_bytes())
+        call_instantiate::<_, _, _>(&mut instance, &mock_env(), &info, msg.as_bytes())
             .unwrap()
             .unwrap();
     }
@@ -858,7 +842,7 @@ mod tests {
 
         let serialized_msg = to_vec(&msg).unwrap();
         let err =
-            call_instantiate::<_, _, _, Empty>(&mut deps, &mock_env(), &info, &serialized_msg)
+            call_instantiate::<_, _, _>(&mut deps, &mock_env(), &info, &serialized_msg)
                 .unwrap_err();
 
         assert!(matches!(
@@ -880,14 +864,14 @@ mod tests {
         let verifier = instance.api().addr_make("verifies");
         let beneficiary = instance.api().addr_make("benefits");
         let msg = format!(r#"{{"verifier": "{verifier}", "beneficiary": "{beneficiary}"}}"#);
-        call_instantiate::<_, _, _, Empty>(&mut instance, &mock_env(), &info, msg.as_bytes())
+        call_instantiate::<_, _, _>(&mut instance, &mock_env(), &info, msg.as_bytes())
             .unwrap()
             .unwrap();
 
         // execute
         let info = mock_info(&verifier, &coins(15, "earth"));
         let msg = br#"{"release":{"denom":"earth"}}"#;
-        call_execute::<_, _, _, Empty>(&mut instance, &mock_env(), &info, msg)
+        call_execute::<_, _, _>(&mut instance, &mock_env(), &info, msg)
             .unwrap()
             .unwrap();
     }
@@ -898,7 +882,7 @@ mod tests {
 
         // init
         let info = mock_info("creator", &[]);
-        call_instantiate::<_, _, _, Empty>(&mut instance, &mock_env(), &info, br#"{}"#)
+        call_instantiate::<_, _, _>(&mut instance, &mock_env(), &info, br#"{}"#)
             .unwrap()
             .unwrap();
 
@@ -906,7 +890,7 @@ mod tests {
         let info = mock_info("looper", &[]);
         let msg = br#"{"cpu_loop":{}}"#;
         let err =
-            call_execute::<_, _, _, Empty>(&mut instance, &mock_env(), &info, msg).unwrap_err();
+            call_execute::<_, _, _>(&mut instance, &mock_env(), &info, msg).unwrap_err();
         assert!(matches!(err, VmError::GasDepletion { .. }));
     }
 
@@ -915,7 +899,7 @@ mod tests {
         let mut instance = mock_instance(CYBERPUNK, &[]);
 
         let info = mock_info("creator", &[]);
-        call_instantiate::<_, _, _, Empty>(&mut instance, &mock_env(), &info, br#"{}"#)
+        call_instantiate::<_, _, _>(&mut instance, &mock_env(), &info, br#"{}"#)
             .unwrap()
             .unwrap();
 
@@ -923,7 +907,7 @@ mod tests {
         let info = mock_info("troll", &[]);
         let msg = br#"{"panic":{}}"#;
         let err =
-            call_execute::<_, _, _, Empty>(&mut instance, &mock_env(), &info, msg).unwrap_err();
+            call_execute::<_, _, _>(&mut instance, &mock_env(), &info, msg).unwrap_err();
         match err {
             VmError::RuntimeErr { msg, .. } => {
                 assert!(
@@ -940,7 +924,7 @@ mod tests {
         let mut instance = mock_instance(CYBERPUNK, &[]);
 
         let info = mock_info("creator", &[]);
-        call_instantiate::<_, _, _, Empty>(&mut instance, &mock_env(), &info, br#"{}"#)
+        call_instantiate::<_, _, _>(&mut instance, &mock_env(), &info, br#"{}"#)
             .unwrap()
             .unwrap();
 
@@ -948,7 +932,7 @@ mod tests {
         let info = mock_info("troll", &[]);
         let msg = br#"{"unreachable":{}}"#;
         let err =
-            call_execute::<_, _, _, Empty>(&mut instance, &mock_env(), &info, msg).unwrap_err();
+            call_execute::<_, _, _>(&mut instance, &mock_env(), &info, msg).unwrap_err();
         match err {
             VmError::RuntimeErr { msg, .. } => {
                 assert!(msg.contains("RuntimeError: unreachable"))
@@ -969,14 +953,14 @@ mod tests {
         let verifier = instance.api().addr_make("verifies");
         let beneficiary = instance.api().addr_make("benefits");
         let msg = format!(r#"{{"verifier": "{verifier}", "beneficiary": "{beneficiary}"}}"#);
-        call_instantiate::<_, _, _, Empty>(&mut instance, &mock_env(), &info, msg.as_bytes())
+        call_instantiate::<_, _, _>(&mut instance, &mock_env(), &info, msg.as_bytes())
             .unwrap()
             .unwrap();
 
         // change the verifier via migrate
         let someone_else = instance.api().addr_make("someone else");
         let msg = format!(r#"{{"verifier": "{someone_else}"}}"#);
-        let _res = call_migrate::<_, _, _, Empty>(&mut instance, &mock_env(), msg.as_bytes())
+        let _res = call_migrate::<_, _, _>(&mut instance, &mock_env(), msg.as_bytes())
             .unwrap()
             .unwrap();
 
@@ -1002,7 +986,7 @@ mod tests {
         let verifier = instance.api().addr_make("verifies");
         let beneficiary = instance.api().addr_make("benefits");
         let msg = format!(r#"{{"verifier": "{verifier}", "beneficiary": "{beneficiary}"}}"#);
-        call_instantiate::<_, _, _, Empty>(&mut instance, &mock_env(), &info, msg.as_bytes())
+        call_instantiate::<_, _, _>(&mut instance, &mock_env(), &info, msg.as_bytes())
             .unwrap()
             .unwrap();
 
@@ -1013,7 +997,7 @@ mod tests {
             sender: Addr::unchecked(someone_else.clone()),
             old_migrate_version: Some(33),
         };
-        let _res = call_migrate_with_info::<_, _, _, Empty>(
+        let _res = call_migrate_with_info::<_, _, _>(
             &mut instance,
             &mock_env(),
             msg.as_bytes(),
@@ -1041,7 +1025,7 @@ mod tests {
         let verifier = instance.api().addr_make("verifies");
         let beneficiary = instance.api().addr_make("benefits");
         let msg = format!(r#"{{"verifier": "{verifier}", "beneficiary": "{beneficiary}"}}"#);
-        call_instantiate::<_, _, _, Empty>(&mut instance, &mock_env(), &info, msg.as_bytes())
+        call_instantiate::<_, _, _>(&mut instance, &mock_env(), &info, msg.as_bytes())
             .unwrap()
             .unwrap();
 
@@ -1077,7 +1061,7 @@ mod tests {
 
         // init
         let info = mock_info("creator", &[]);
-        call_instantiate::<_, _, _, Empty>(&mut instance, &mock_env(), &info, br#"{}"#)
+        call_instantiate::<_, _, _>(&mut instance, &mock_env(), &info, br#"{}"#)
             .unwrap()
             .unwrap();
 
@@ -1160,7 +1144,7 @@ mod tests {
             // init
             let info = mock_info("creator", &[]);
             let msg = br#"{"reflect_code_id":77}"#;
-            call_instantiate::<_, _, _, Empty>(instance, &mock_env(), &info, msg)
+            call_instantiate::<_, _, _>(instance, &mock_env(), &info, msg)
                 .unwrap()
                 .unwrap();
             // first we try to open with a valid handshake
@@ -1172,7 +1156,7 @@ mod tests {
             // then we connect (with counter-party version set)
             let handshake_connect =
                 mock_ibc_channel_connect_ack(channel_id, IbcOrder::Ordered, IBC_VERSION);
-            let res: IbcBasicResponse = call_ibc_channel_connect::<_, _, _, Empty>(
+            let res: IbcBasicResponse = call_ibc_channel_connect::<_, _, _>(
                 instance,
                 &mock_env(),
                 &handshake_connect,
@@ -1203,7 +1187,7 @@ mod tests {
                     data: None,
                 }),
             };
-            call_reply::<_, _, _, Empty>(instance, &mock_env(), &response).unwrap();
+            call_reply::<_, _, _>(instance, &mock_env(), &response).unwrap();
         }
 
         const CHANNEL_ID: &str = "channel-123";
@@ -1222,7 +1206,7 @@ mod tests {
             setup(&mut instance, CHANNEL_ID, &account);
             let handshake_close =
                 mock_ibc_channel_close_init(CHANNEL_ID, IbcOrder::Ordered, IBC_VERSION);
-            call_ibc_channel_close::<_, _, _, Empty>(&mut instance, &mock_env(), &handshake_close)
+            call_ibc_channel_close::<_, _, _>(&mut instance, &mock_env(), &handshake_close)
                 .unwrap()
                 .unwrap();
         }
@@ -1233,7 +1217,7 @@ mod tests {
             setup(&mut instance, CHANNEL_ID, ACCOUNT);
             let ack = IbcAcknowledgement::new(br#"{}"#);
             let msg = mock_ibc_packet_ack(CHANNEL_ID, br#"{}"#, ack).unwrap();
-            call_ibc_packet_ack::<_, _, _, Empty>(&mut instance, &mock_env(), &msg)
+            call_ibc_packet_ack::<_, _, _>(&mut instance, &mock_env(), &msg)
                 .unwrap()
                 .unwrap();
         }
@@ -1243,7 +1227,7 @@ mod tests {
             let mut instance = mock_instance(IBC_REFLECT, &[]);
             setup(&mut instance, CHANNEL_ID, ACCOUNT);
             let msg = mock_ibc_packet_timeout(CHANNEL_ID, br#"{}"#).unwrap();
-            call_ibc_packet_timeout::<_, _, _, Empty>(&mut instance, &mock_env(), &msg)
+            call_ibc_packet_timeout::<_, _, _>(&mut instance, &mock_env(), &msg)
                 .unwrap()
                 .unwrap();
         }
@@ -1254,7 +1238,7 @@ mod tests {
             setup(&mut instance, CHANNEL_ID, ACCOUNT);
             let who_am_i = br#"{"who_am_i":{}}"#;
             let msg = mock_ibc_packet_recv(CHANNEL_ID, who_am_i).unwrap();
-            call_ibc_packet_receive::<_, _, _, Empty>(&mut instance, &mock_env(), &msg)
+            call_ibc_packet_receive::<_, _, _>(&mut instance, &mock_env(), &msg)
                 .unwrap()
                 .unwrap();
         }
@@ -1266,7 +1250,7 @@ mod tests {
             // init
             let creator = instance.api().addr_make("creator");
             let info = mock_info(&creator, &[]);
-            call_instantiate::<_, _, _, Empty>(&mut instance, &mock_env(), &info, br#"{}"#)
+            call_instantiate::<_, _, _>(&mut instance, &mock_env(), &info, br#"{}"#)
                 .unwrap()
                 .unwrap();
 
@@ -1285,7 +1269,7 @@ mod tests {
                 ack.original_packet,
                 ack.relayer,
             ));
-            call_ibc_source_callback::<_, _, _, Empty>(&mut instance, &mock_env(), &msg)
+            call_ibc_source_callback::<_, _, _>(&mut instance, &mock_env(), &msg)
                 .unwrap()
                 .unwrap();
             // query the CallbackStats
@@ -1304,7 +1288,7 @@ mod tests {
                 timeout.packet,
                 timeout.relayer,
             ));
-            call_ibc_source_callback::<_, _, _, Empty>(&mut instance, &mock_env(), &msg)
+            call_ibc_source_callback::<_, _, _>(&mut instance, &mock_env(), &msg)
                 .unwrap()
                 .unwrap();
             // query the CallbackStats
@@ -1337,7 +1321,7 @@ mod tests {
             let mut instance = mock_instance(IBC2, &[]);
             let info = mock_info("creator", &[]);
             let instantiate_msg = br#"{}"#;
-            call_instantiate::<_, _, _, Empty>(&mut instance, &mock_env(), &info, instantiate_msg)
+            call_instantiate::<_, _, _>(&mut instance, &mock_env(), &info, instantiate_msg)
                 .unwrap()
                 .unwrap();
 
@@ -1346,7 +1330,7 @@ mod tests {
                 send_async_ack_for_prev_msg: false,
             };
             let ibc2_timeout = mock_ibc2_packet_recv(&ibc2_msg).unwrap();
-            call_ibc2_packet_receive::<_, _, _, Empty>(&mut instance, &mock_env(), &ibc2_timeout)
+            call_ibc2_packet_receive::<_, _, _>(&mut instance, &mock_env(), &ibc2_timeout)
                 .unwrap()
                 .unwrap();
         }
@@ -1357,13 +1341,13 @@ mod tests {
             let mut instance = mock_instance(IBC2, &[]);
             let info = mock_info("creator", &[]);
             let instantiate_msg = br#"{}"#;
-            call_instantiate::<_, _, _, Empty>(&mut instance, &mock_env(), &info, instantiate_msg)
+            call_instantiate::<_, _, _>(&mut instance, &mock_env(), &info, instantiate_msg)
                 .unwrap()
                 .unwrap();
 
             let ibc2_msg = br#"SomeRandomMsg"#;
             let ibc2_msg = mock_ibc2_packet_timeout(ibc2_msg).unwrap();
-            call_ibc2_packet_timeout::<_, _, _, Empty>(&mut instance, &mock_env(), &ibc2_msg)
+            call_ibc2_packet_timeout::<_, _, _>(&mut instance, &mock_env(), &ibc2_msg)
                 .unwrap()
                 .unwrap();
         }
diff --git a/packages/vm/src/instance.rs b/packages/vm/src/instance.rs
index 1713042033..460fa2cdf5 100644
--- a/packages/vm/src/instance.rs
+++ b/packages/vm/src/instance.rs
@@ -568,12 +568,12 @@ mod tests {
 
         // init contract
         let info = mock_info("creator", &coins(1000, "earth"));
-        call_instantiate::<_, _, _, Empty>(&mut instance, &mock_env(), &info, br#"{}"#)
+        call_instantiate::<_, _, _>(&mut instance, &mock_env(), &info, br#"{}"#)
             .unwrap()
             .unwrap();
 
         let info = mock_info("caller", &[]);
-        call_execute::<_, _, _, Empty>(&mut instance, &mock_env(), &info, br#"{"debug":{}}"#)
+        call_execute::<_, _, _>(&mut instance, &mock_env(), &info, br#"{"debug":{}}"#)
             .unwrap()
             .unwrap();
 
@@ -585,7 +585,7 @@ mod tests {
         });
 
         let info = mock_info("caller", &[]);
-        call_execute::<_, _, _, Empty>(&mut instance, &mock_env(), &info, br#"{"debug":{}}"#)
+        call_execute::<_, _, _>(&mut instance, &mock_env(), &info, br#"{"debug":{}}"#)
             .unwrap()
             .unwrap();
 
@@ -593,7 +593,7 @@ mod tests {
         instance.unset_debug_handler();
 
         let info = mock_info("caller", &[]);
-        call_execute::<_, _, _, Empty>(&mut instance, &mock_env(), &info, br#"{"debug":{}}"#)
+        call_execute::<_, _, _>(&mut instance, &mock_env(), &info, br#"{"debug":{}}"#)
             .unwrap()
             .unwrap();
     }
@@ -793,7 +793,7 @@ mod tests {
         // set up an instance that will experience an error in an import
         let error_message = "Api failed intentionally";
         let mut instance = mock_instance_with_failing_api(HACKATOM, &[], error_message);
-        let init_result = call_instantiate::<_, _, _, Empty>(
+        let init_result = call_instantiate::<_, _, _>(
             &mut instance,
             &mock_env(),
             &mock_info("someone", &[]),
@@ -915,7 +915,7 @@ mod tests {
         let verifier = instance.api().addr_make("verifies");
         let beneficiary = instance.api().addr_make("benefits");
         let msg = format!(r#"{{"verifier": "{verifier}", "beneficiary": "{beneficiary}"}}"#);
-        call_instantiate::<_, _, _, Empty>(&mut instance, &mock_env(), &info, msg.as_bytes())
+        call_instantiate::<_, _, _>(&mut instance, &mock_env(), &info, msg.as_bytes())
             .unwrap()
             .unwrap();
 
@@ -1083,7 +1083,7 @@ mod tests {
         let verifier = instance.api().addr_make("verifies");
         let beneficiary = instance.api().addr_make("benefits");
         let msg = format!(r#"{{"verifier": "{verifier}", "beneficiary": "{beneficiary}"}}"#);
-        call_instantiate::<_, _, _, Empty>(&mut instance, &mock_env(), &info, msg.as_bytes())
+        call_instantiate::<_, _, _>(&mut instance, &mock_env(), &info, msg.as_bytes())
             .unwrap()
             .unwrap();
 
@@ -1100,7 +1100,7 @@ mod tests {
         let verifier = instance.api().addr_make("verifies");
         let beneficiary = instance.api().addr_make("benefits");
         let msg = format!(r#"{{"verifier": "{verifier}", "beneficiary": "{beneficiary}"}}"#);
-        call_instantiate::<_, _, _, Empty>(&mut instance, &mock_env(), &info, msg.as_bytes())
+        call_instantiate::<_, _, _>(&mut instance, &mock_env(), &info, msg.as_bytes())
             .unwrap()
             .unwrap();
 
@@ -1108,7 +1108,7 @@ mod tests {
         let gas_before_execute = instance.get_gas_left();
         let info = mock_info(&verifier, &coins(15, "earth"));
         let msg = br#"{"release":{"denom":"earth"}}"#;
-        call_execute::<_, _, _, Empty>(&mut instance, &mock_env(), &info, msg)
+        call_execute::<_, _, _>(&mut instance, &mock_env(), &info, msg)
             .unwrap()
             .unwrap();
 
@@ -1126,7 +1126,7 @@ mod tests {
         let beneficiary = instance.api().addr_make("benefits");
         let msg = format!(r#"{{"verifier": "{verifier}", "beneficiary": "{beneficiary}"}}"#);
         let res =
-            call_instantiate::<_, _, _, Empty>(&mut instance, &mock_env(), &info, msg.as_bytes());
+            call_instantiate::<_, _, _>(&mut instance, &mock_env(), &info, msg.as_bytes());
         assert!(res.is_err());
     }
 
@@ -1140,7 +1140,7 @@ mod tests {
         let beneficiary = instance.api().addr_make("benefits");
         let msg = format!(r#"{{"verifier": "{verifier}", "beneficiary": "{beneficiary}"}}"#);
         let _res =
-            call_instantiate::<_, _, _, Empty>(&mut instance, &mock_env(), &info, msg.as_bytes())
+            call_instantiate::<_, _, _>(&mut instance, &mock_env(), &info, msg.as_bytes())
                 .unwrap()
                 .unwrap();
 
diff --git a/packages/vm/src/testing/calls.rs b/packages/vm/src/testing/calls.rs
index 8029c92ed0..ca37d083a0 100644
--- a/packages/vm/src/testing/calls.rs
+++ b/packages/vm/src/testing/calls.rs
@@ -29,18 +29,17 @@ use crate::{BackendApi, Querier, Storage};
 /// Mimics the call signature of the smart contracts.
 /// Thus it moves env and msg rather than take them as reference.
 /// This is inefficient here, but only used in test code.
-pub fn instantiate<A, S, Q, M, U>(
+pub fn instantiate<A, S, Q, M>(
     instance: &mut Instance<A, S, Q>,
     env: Env,
     info: MessageInfo,
     msg: M,
-) -> ContractResult<Response<U>>
+) -> ContractResult<Response>
 where
     A: BackendApi + 'static,
     S: Storage + 'static,
     Q: Querier + 'static,
     M: Serialize,
-    U: DeserializeOwned + CustomMsg,
 {
     let serialized_msg = to_vec(&msg).expect("Testing error: Could not serialize request message");
     call_instantiate(instance, &env, &info, &serialized_msg).expect("VM error")
@@ -49,18 +48,17 @@ where
 // execute mimics the call signature of the smart contracts.
 // thus it moves env and msg rather than take them as reference.
 // this is inefficient here, but only used in test code
-pub fn execute<A, S, Q, M, U>(
+pub fn execute<A, S, Q, M>(
     instance: &mut Instance<A, S, Q>,
     env: Env,
     info: MessageInfo,
     msg: M,
-) -> ContractResult<Response<U>>
+) -> ContractResult<Response>
 where
     A: BackendApi + 'static,
     S: Storage + 'static,
     Q: Querier + 'static,
     M: Serialize,
-    U: DeserializeOwned + CustomMsg,
 {
     let serialized_msg = to_vec(&msg).expect("Testing error: Could not serialize request message");
     call_execute(instance, &env, &info, &serialized_msg).expect("VM error")
@@ -69,17 +67,16 @@ where
 // migrate mimics the call signature of the smart contracts.
 // thus it moves env and msg rather than take them as reference.
 // this is inefficient here, but only used in test code
-pub fn migrate<A, S, Q, M, U>(
+pub fn migrate<A, S, Q, M>(
     instance: &mut Instance<A, S, Q>,
     env: Env,
     msg: M,
-) -> ContractResult<Response<U>>
+) -> ContractResult<Response>
 where
     A: BackendApi + 'static,
     S: Storage + 'static,
     Q: Querier + 'static,
     M: Serialize,
-    U: DeserializeOwned + CustomMsg,
 {
     let serialized_msg = to_vec(&msg).expect("Testing error: Could not serialize request message");
     call_migrate(instance, &env, &serialized_msg).expect("VM error")
@@ -88,18 +85,17 @@ where
 // migrate mimics the call signature of the smart contracts.
 // thus it moves env and msg rather than take them as reference.
 // this is inefficient here, but only used in test code
-pub fn migrate_with_info<A, S, Q, M, U>(
+pub fn migrate_with_info<A, S, Q, M>(
     instance: &mut Instance<A, S, Q>,
     env: Env,
     msg: M,
     migrate_info: MigrateInfo,
-) -> ContractResult<Response<U>>
+) -> ContractResult<Response>
 where
     A: BackendApi + 'static,
     S: Storage + 'static,
     Q: Querier + 'static,
     M: Serialize,
-    U: DeserializeOwned + CustomMsg,
 {
     let serialized_msg = to_vec(&msg).expect("Testing error: Could not serialize request message");
     call_migrate_with_info(instance, &env, &serialized_msg, &migrate_info).expect("VM error")
@@ -112,7 +108,7 @@ pub fn sudo<A, S, Q, M, U>(
     instance: &mut Instance<A, S, Q>,
     env: Env,
     msg: M,
-) -> ContractResult<Response<U>>
+) -> ContractResult<Response>
 where
     A: BackendApi + 'static,
     S: Storage + 'static,
@@ -131,7 +127,7 @@ pub fn reply<A, S, Q, U>(
     instance: &mut Instance<A, S, Q>,
     env: Env,
     msg: Reply,
-) -> ContractResult<Response<U>>
+) -> ContractResult<Response>
 where
     A: BackendApi + 'static,
     S: Storage + 'static,
@@ -180,16 +176,15 @@ where
 // thus it moves env and channel rather than take them as reference.
 // this is inefficient here, but only used in test code
 #[cfg(feature = "stargate")]
-pub fn ibc_channel_connect<A, S, Q, U>(
+pub fn ibc_channel_connect<A, S, Q>(
     instance: &mut Instance<A, S, Q>,
     env: Env,
     msg: IbcChannelConnectMsg,
-) -> ContractResult<IbcBasicResponse<U>>
+) -> ContractResult<IbcBasicResponse>
 where
     A: BackendApi + 'static,
     S: Storage + 'static,
     Q: Querier + 'static,
-    U: DeserializeOwned + CustomMsg,
 {
     call_ibc_channel_connect(instance, &env, &msg).expect("VM error")
 }
@@ -198,16 +193,15 @@ where
 // thus it moves env and channel rather than take them as reference.
 // this is inefficient here, but only used in test code
 #[cfg(feature = "stargate")]
-pub fn ibc_channel_close<A, S, Q, U>(
+pub fn ibc_channel_close<A, S, Q>(
     instance: &mut Instance<A, S, Q>,
     env: Env,
     msg: IbcChannelCloseMsg,
-) -> ContractResult<IbcBasicResponse<U>>
+) -> ContractResult<IbcBasicResponse>
 where
     A: BackendApi + 'static,
     S: Storage + 'static,
     Q: Querier + 'static,
-    U: DeserializeOwned + CustomMsg,
 {
     call_ibc_channel_close(instance, &env, &msg).expect("VM error")
 }
@@ -216,16 +210,15 @@ where
 // thus it moves env and packet rather than take them as reference.
 // this is inefficient here, but only used in test code
 #[cfg(feature = "stargate")]
-pub fn ibc_packet_receive<A, S, Q, U>(
+pub fn ibc_packet_receive<A, S, Q>(
     instance: &mut Instance<A, S, Q>,
     env: Env,
     msg: IbcPacketReceiveMsg,
-) -> ContractResult<IbcReceiveResponse<U>>
+) -> ContractResult<IbcReceiveResponse>
 where
     A: BackendApi + 'static,
     S: Storage + 'static,
     Q: Querier + 'static,
-    U: DeserializeOwned + CustomMsg,
 {
     call_ibc_packet_receive(instance, &env, &msg).expect("VM error")
 }
@@ -234,16 +227,15 @@ where
 // thus it moves env and acknowledgement rather than take them as reference.
 // this is inefficient here, but only used in test code
 #[cfg(feature = "stargate")]
-pub fn ibc_packet_ack<A, S, Q, U>(
+pub fn ibc_packet_ack<A, S, Q>(
     instance: &mut Instance<A, S, Q>,
     env: Env,
     msg: IbcPacketAckMsg,
-) -> ContractResult<IbcBasicResponse<U>>
+) -> ContractResult<IbcBasicResponse>
 where
     A: BackendApi + 'static,
     S: Storage + 'static,
     Q: Querier + 'static,
-    U: DeserializeOwned + CustomMsg,
 {
     call_ibc_packet_ack(instance, &env, &msg).expect("VM error")
 }
@@ -252,16 +244,15 @@ where
 // thus it moves env and packet rather than take them as reference.
 // this is inefficient here, but only used in test code
 #[cfg(feature = "stargate")]
-pub fn ibc_packet_timeout<A, S, Q, U>(
+pub fn ibc_packet_timeout<A, S, Q>(
     instance: &mut Instance<A, S, Q>,
     env: Env,
     msg: IbcPacketTimeoutMsg,
-) -> ContractResult<IbcBasicResponse<U>>
+) -> ContractResult<IbcBasicResponse>
 where
     A: BackendApi + 'static,
     S: Storage + 'static,
     Q: Querier + 'static,
-    U: DeserializeOwned + CustomMsg,
 {
     call_ibc_packet_timeout(instance, &env, &msg).expect("VM error")
 }