From 9efa1f38b39f9afc4a660cdd8294725fd225ce26 Mon Sep 17 00:00:00 2001 From: Kayanski Date: Fri, 16 Feb 2024 19:41:56 +0100 Subject: [PATCH 01/37] Started impl, first test creation --- .../native/ibc-client/src/commands.rs | 127 ++++++++++++++---- .../contracts/native/ibc-client/src/error.rs | 3 + .../contracts/native/ibc-client/src/ibc.rs | 15 +++ .../native/ibc-host/src/endpoints/execute.rs | 10 +- .../native/ibc-host/src/endpoints/packet.rs | 38 +++++- .../abstract-adapter/src/endpoints.rs | 1 + .../abstract-adapter/src/endpoints/execute.rs | 3 +- .../src/endpoints/module_ibc.rs | 33 +++++ .../packages/abstract-app/src/endpoints.rs | 1 + .../abstract-app/src/endpoints/execute.rs | 10 +- .../abstract-app/src/endpoints/module_ibc.rs | 29 ++++ framework/packages/abstract-app/src/lib.rs | 37 ++++- framework/packages/abstract-app/src/state.rs | 11 +- framework/packages/abstract-core/src/base.rs | 6 +- .../packages/abstract-core/src/native/ibc.rs | 17 ++- .../abstract-core/src/native/ibc_client.rs | 10 +- .../abstract-core/src/native/ibc_host.rs | 19 ++- .../abstract-sdk/src/base/contract_base.rs | 19 +++ .../abstract-sdk/src/base/endpoints.rs | 2 + .../src/base/endpoints/modules_ibc.rs | 40 ++++++ .../packages/abstract-sdk/src/base/handler.rs | 7 +- .../packages/abstract-sdk/src/base/mod.rs | 8 +- framework/packages/abstract-sdk/src/error.rs | 8 ++ 23 files changed, 399 insertions(+), 55 deletions(-) create mode 100644 framework/packages/abstract-adapter/src/endpoints/module_ibc.rs create mode 100644 framework/packages/abstract-app/src/endpoints/module_ibc.rs create mode 100644 framework/packages/abstract-sdk/src/base/endpoints/modules_ibc.rs diff --git a/framework/contracts/native/ibc-client/src/commands.rs b/framework/contracts/native/ibc-client/src/commands.rs index b42d6ef402..75289bf39a 100644 --- a/framework/contracts/native/ibc-client/src/commands.rs +++ b/framework/contracts/native/ibc-client/src/commands.rs @@ -6,9 +6,9 @@ use abstract_core::{ state::{IbcInfrastructure, IBC_INFRA, REVERSE_POLYTONE_NOTE}, IbcClientCallback, }, - ibc_host, manager, - manager::ModuleInstallConfig, - objects::{chain_name::ChainName, AccountId, AssetEntry}, + ibc_host, + manager::{self, ModuleInstallConfig}, + objects::{chain_name::ChainName, module::ModuleInfo, AccountId, AssetEntry}, version_control::AccountBase, }; use abstract_sdk::{ @@ -22,8 +22,8 @@ use abstract_sdk::{ Resolve, }; use cosmwasm_std::{ - to_json_binary, wasm_execute, Coin, CosmosMsg, Deps, DepsMut, Empty, Env, IbcMsg, MessageInfo, - QueryRequest, Storage, + to_json_binary, wasm_execute, Binary, Coin, CosmosMsg, Deps, DepsMut, Empty, Env, IbcMsg, + MessageInfo, QueryRequest, Storage, }; use polytone::callbacks::CallbackRequest; @@ -169,6 +169,44 @@ fn send_remote_host_action( Ok(note_message.into()) } +/// Send a message to a remote abstract-ibc-host. This message will be proxied through polytone. +fn send_remote_host_module_action( + deps: Deps, + host_chain: ChainName, + source_module: ModuleInfo, + target_module: ModuleInfo, + msg: Binary, + callback_request: Option, +) -> IbcClientResult> { + // Send this message via the Polytone implementation + let ibc_infra = IBC_INFRA.load(deps.storage, &host_chain)?; + let note_contract = ibc_infra.polytone_note; + let remote_ibc_host = ibc_infra.remote_abstract_host; + + // message that will be called on the local note contract + let note_message = wasm_execute( + note_contract.to_string(), + &polytone_note::msg::ExecuteMsg::Execute { + msgs: vec![wasm_execute( + // The note's remote proxy will call the ibc host + remote_ibc_host, + &ibc_host::ExecuteMsg::ModuleExecute { + msg, + source_module, + target_module, + }, + vec![], + )? + .into()], + callback: callback_request, + timeout_seconds: PACKET_LIFETIME.into(), + }, + vec![], + )?; + + Ok(note_message.into()) +} + /// Perform a ICQ on a remote chain fn send_remote_host_query( deps: Deps, @@ -206,32 +244,67 @@ pub fn execute_send_packet( let cfg = CONFIG.load(deps.storage)?; - // Verify that the sender is a proxy contract - let account_base = cfg - .version_control - .assert_proxy(&info.sender, &deps.querier)?; + // The packet we need to send depends on the action we want to execute - // get account_id - let account_id = account_base.account_id(deps.as_ref())?; + let note_message = match &action { + HostAction::Dispatch { .. } | HostAction::Helpers(_) => { + // Verify that the sender is a proxy contract + let account_base = cfg + .version_control + .assert_proxy(&info.sender, &deps.querier)?; - // Can only call non-internal actions - if let HostAction::Internal(_) = action { - return Err(IbcClientError::ForbiddenInternalCall {}); - } + // get account_id + let account_id = account_base.account_id(deps.as_ref())?; - let callback_request = callback_info.map(|c| CallbackRequest { - receiver: env.contract.address.to_string(), - msg: to_json_binary(&IbcClientCallback::UserRemoteAction(c)).unwrap(), - }); + let callback_request = callback_info.map(|c| CallbackRequest { + receiver: env.contract.address.to_string(), + msg: to_json_binary(&IbcClientCallback::UserRemoteAction(c)).unwrap(), + }); + + send_remote_host_action( + deps.as_ref(), + account_id, + account_base, + host_chain, + action, + callback_request, + )? + } + HostAction::Module { + msg, + source_module, + target_module, + } => { + // We make sure the source_module is indeed who they say they are + let registry = CONFIG + .load(deps.storage)? + .version_control + .query_module(source_module.clone(), &deps.querier)?; + + if registry.reference.unwrap_addr()? != info.sender { + return Err(IbcClientError::ForbiddenModuleCall {}); + } - let note_message = send_remote_host_action( - deps.as_ref(), - account_id, - account_base, - host_chain, - action, - callback_request, - )?; + let callback_request = callback_info.map(|c| CallbackRequest { + receiver: env.contract.address.to_string(), + msg: to_json_binary(&IbcClientCallback::UserRemoteAction(c)).unwrap(), + }); + send_remote_host_module_action( + deps.as_ref(), + host_chain, + source_module.clone(), + target_module.clone(), + msg.clone(), + callback_request, + )? + + // If they are, we send a message to the module on the remote chain + } + HostAction::Internal(_) => { + // Can only call non-internal actions + return Err(IbcClientError::ForbiddenInternalCall {}); + } + }; Ok(IbcClientResponse::action("handle_send_msgs").add_message(note_message)) } diff --git a/framework/contracts/native/ibc-client/src/error.rs b/framework/contracts/native/ibc-client/src/error.rs index b1ed2cc0f0..ea8cb24e31 100644 --- a/framework/contracts/native/ibc-client/src/error.rs +++ b/framework/contracts/native/ibc-client/src/error.rs @@ -36,6 +36,9 @@ pub enum IbcClientError { #[error("packages that contain internal calls are not allowed")] ForbiddenInternalCall {}, + #[error("A non-module package can execute an ibc module call")] + ForbiddenModuleCall {}, + #[error("The host you are trying to connect is already connected")] HostAlreadyExists {}, diff --git a/framework/contracts/native/ibc-client/src/ibc.rs b/framework/contracts/native/ibc-client/src/ibc.rs index 4fac7b4999..4eb4e4f026 100644 --- a/framework/contracts/native/ibc-client/src/ibc.rs +++ b/framework/contracts/native/ibc-client/src/ibc.rs @@ -100,5 +100,20 @@ pub fn receive_action_callback( .add_attribute("chain", host_chain.to_string()) .add_attribute("callback_id", callback_info.id)) } + // TODO, find a better structure (should we separate module and user callbacks ?) + IbcClientCallback::ModuleRemoteAction { + callback_info, + target_module, + } => { + let callback = IbcResponseMsg { + id: callback_info.id.clone(), + msg: callback_info.msg, + result: callback.result, + }; + Ok(IbcClientResponse::action("module_specific_callback") + .add_message(callback.into_cosmos_msg(callback_info.receiver)?) + .add_attribute("chain", host_chain.to_string()) + .add_attribute("callback_id", callback_info.id)) + } } } diff --git a/framework/contracts/native/ibc-host/src/endpoints/execute.rs b/framework/contracts/native/ibc-host/src/endpoints/execute.rs index 092707cbd3..6f8a3df67a 100644 --- a/framework/contracts/native/ibc-host/src/endpoints/execute.rs +++ b/framework/contracts/native/ibc-host/src/endpoints/execute.rs @@ -7,7 +7,7 @@ use abstract_core::{ use abstract_sdk::{core::ibc_host::ExecuteMsg, feature_objects::VersionControlContract}; use cosmwasm_std::{DepsMut, Env, MessageInfo}; -use super::packet::handle_host_action; +use super::packet::{handle_host_action, handle_host_module_action}; use crate::{ contract::{HostResponse, HostResult}, HostError, @@ -44,6 +44,14 @@ pub fn execute(deps: DepsMut, env: Env, info: MessageInfo, msg: ExecuteMsg) -> H cw_ownable::update_ownership(deps, &env.block, &info.sender, action)?; Ok(HostResponse::action("update_ownership")) } + ExecuteMsg::ModuleExecute { + msg, + source_module, + target_module, + } => { + let client_chain: ChainName = REVERSE_CHAIN_PROXIES.load(deps.storage, &info.sender)?; + handle_host_module_action(deps, env, client_chain, source_module, target_module, msg) + } } } diff --git a/framework/contracts/native/ibc-host/src/endpoints/packet.rs b/framework/contracts/native/ibc-host/src/endpoints/packet.rs index b60defc0cb..2fb0096f90 100644 --- a/framework/contracts/native/ibc-host/src/endpoints/packet.rs +++ b/framework/contracts/native/ibc-host/src/endpoints/packet.rs @@ -1,18 +1,21 @@ use abstract_core::{ + ibc::ModuleIbcMsg, ibc_host::{ - state::{ActionAfterCreationCache, TEMP_ACTION_AFTER_CREATION}, + state::{ActionAfterCreationCache, CONFIG, TEMP_ACTION_AFTER_CREATION}, HelperAction, }, - objects::{chain_name::ChainName, AccountId}, + objects::{chain_name::ChainName, module::ModuleInfo, AccountId}, }; use abstract_sdk::core::ibc_host::{HostAction, InternalAction}; -use cosmwasm_std::{DepsMut, Env}; +use cosmwasm_std::{wasm_execute, Binary, DepsMut, Empty, Env, Response}; use crate::{ account_commands::{self, receive_dispatch, receive_register, receive_send_all_back}, contract::HostResult, }; +use abstract_core::base::ExecuteMsg as MiddlewareExecMsg; + /// Handle actions that are passed to the IBC host contract /// This function is not permissioned and access control needs to be handled outside of it /// Usually the `client_chain` argument needs to be derived from the message sender @@ -105,3 +108,32 @@ pub fn handle_host_action( } .map_err(Into::into) } + +/// Handle actions that are passed to the IBC host contract and originate from a registered module +pub fn handle_host_module_action( + deps: DepsMut, + env: Env, + client_chain: ChainName, + source_module: ModuleInfo, + target_module: ModuleInfo, + msg: Binary, +) -> HostResult { + // We resolve the target module + let vc = CONFIG.load(deps.storage)?.version_control; + let target_module_resolved = vc.query_module(target_module, &deps.querier)?; + + // We pass the message on to the module + let msg = wasm_execute( + target_module_resolved.reference.unwrap_addr()?, + &MiddlewareExecMsg::ModuleIbc::(ModuleIbcMsg { + client_chain, + source_module, + msg, + }), + vec![], + )?; + + Ok(Response::new() + .add_attribute("action", "module-ibc-call") + .add_message(msg)) +} diff --git a/framework/packages/abstract-adapter/src/endpoints.rs b/framework/packages/abstract-adapter/src/endpoints.rs index 563c176587..3846d11af8 100644 --- a/framework/packages/abstract-adapter/src/endpoints.rs +++ b/framework/packages/abstract-adapter/src/endpoints.rs @@ -1,6 +1,7 @@ mod execute; mod ibc_callback; mod instantiate; +mod module_ibc; mod query; mod receive; mod reply; diff --git a/framework/packages/abstract-adapter/src/endpoints/execute.rs b/framework/packages/abstract-adapter/src/endpoints/execute.rs index e669a8e92f..80a4b7a019 100644 --- a/framework/packages/abstract-adapter/src/endpoints/execute.rs +++ b/framework/packages/abstract-adapter/src/endpoints/execute.rs @@ -4,7 +4,7 @@ use abstract_core::{ objects::nested_admin::query_top_level_owner, }; use abstract_sdk::{ - base::{ExecuteEndpoint, Handler, IbcCallbackEndpoint, ReceiveEndpoint}, + base::{ExecuteEndpoint, Handler, IbcCallbackEndpoint, ModuleIbcEndpoint, ReceiveEndpoint}, features::ModuleIdentification, AbstractResponse, AccountVerification, }; @@ -44,6 +44,7 @@ impl< .map_err(From::from), ExecuteMsg::IbcCallback(msg) => self.ibc_callback(deps, env, info, msg), ExecuteMsg::Receive(msg) => self.receive(deps, env, info, msg), + ExecuteMsg::ModuleIbc(msg) => self.module_ibc(deps, env, info, msg), } } } diff --git a/framework/packages/abstract-adapter/src/endpoints/module_ibc.rs b/framework/packages/abstract-adapter/src/endpoints/module_ibc.rs new file mode 100644 index 0000000000..0c9b4cd7e4 --- /dev/null +++ b/framework/packages/abstract-adapter/src/endpoints/module_ibc.rs @@ -0,0 +1,33 @@ +use abstract_core::IBC_HOST; +use abstract_core::{objects::module::ModuleInfo, AbstractError}; +use abstract_sdk::{base::ModuleIbcEndpoint, features::AbstractRegistryAccess}; +use crate::{state::ContractError, AdapterContract}; +use cosmwasm_std::Addr; +use abstract_sdk::AbstractSdkError; + +impl + ModuleIbcEndpoint + for AdapterContract +{ + fn ibc_host(&self, deps: cosmwasm_std::Deps) -> Result { + let vc_query_result = self + .abstract_registry(deps)? + .query_module( + ModuleInfo::from_id_latest(IBC_HOST).map_err(|err| { + let err: AbstractSdkError = err.into(); + err + })?, + &deps.querier, + ) + .map_err(|err| { + let err: AbstractError = err.into(); + let err: AbstractSdkError = err.into(); + err + })?; + + Ok(vc_query_result.reference.unwrap_native().map_err(|err| { + let err: AbstractSdkError = err.into(); + err + })?) + } +} diff --git a/framework/packages/abstract-app/src/endpoints.rs b/framework/packages/abstract-app/src/endpoints.rs index 9aaf20977e..7b9dbf00b9 100644 --- a/framework/packages/abstract-app/src/endpoints.rs +++ b/framework/packages/abstract-app/src/endpoints.rs @@ -2,6 +2,7 @@ mod execute; mod ibc_callback; pub mod instantiate; mod migrate; +mod module_ibc; mod query; mod receive; mod reply; diff --git a/framework/packages/abstract-app/src/endpoints/execute.rs b/framework/packages/abstract-app/src/endpoints/execute.rs index 8d6dd7fd87..532653bf0d 100644 --- a/framework/packages/abstract-app/src/endpoints/execute.rs +++ b/framework/packages/abstract-app/src/endpoints/execute.rs @@ -1,6 +1,9 @@ use abstract_core::app::{AppExecuteMsg, BaseExecuteMsg, ExecuteMsg}; -use abstract_sdk::{base::ReceiveEndpoint, features::AbstractResponse}; -use cosmwasm_std::{DepsMut, Env, MessageInfo, Response, StdError}; +use abstract_sdk::{ + base::{ModuleIbcEndpoint, ReceiveEndpoint}, + features::AbstractResponse, +}; +use cosmwasm_std::{DepsMut, Env, MessageInfo, Response}; use schemars::JsonSchema; use serde::Serialize; @@ -48,8 +51,7 @@ impl< .map_err(From::from), ExecuteMsg::IbcCallback(msg) => self.ibc_callback(deps, env, info, msg), ExecuteMsg::Receive(msg) => self.receive(deps, env, info, msg), - #[allow(unreachable_patterns)] - _ => Err(StdError::generic_err("Unsupported App execute message variant").into()), + ExecuteMsg::ModuleIbc(msg) => self.module_ibc(deps, env, info, msg), } } } diff --git a/framework/packages/abstract-app/src/endpoints/module_ibc.rs b/framework/packages/abstract-app/src/endpoints/module_ibc.rs new file mode 100644 index 0000000000..e7456122b7 --- /dev/null +++ b/framework/packages/abstract-app/src/endpoints/module_ibc.rs @@ -0,0 +1,29 @@ +use abstract_core::IBC_HOST; +use abstract_sdk::{base::ModuleIbcEndpoint, ModuleInterface}; + +use crate::{state::ContractError, AppContract}; + +impl< + Error: ContractError, + CustomInitMsg, + CustomExecMsg, + CustomQueryMsg, + CustomMigrateMsg, + ReceiveMsg, + SudoMsg, + > ModuleIbcEndpoint + for AppContract< + Error, + CustomInitMsg, + CustomExecMsg, + CustomQueryMsg, + CustomMigrateMsg, + ReceiveMsg, + SudoMsg, + > +{ + fn ibc_host(&self, deps: cosmwasm_std::Deps) -> Result { + let ibc_client = self.modules(deps).module_address(IBC_HOST)?; + Ok(ibc_client) + } +} diff --git a/framework/packages/abstract-app/src/lib.rs b/framework/packages/abstract-app/src/lib.rs index 0d768a4a4f..968390bb51 100644 --- a/framework/packages/abstract-app/src/lib.rs +++ b/framework/packages/abstract-app/src/lib.rs @@ -32,13 +32,16 @@ pub use abstract_testing; pub mod mock { pub use abstract_core::app; use abstract_core::{ + ibc::ModuleIbcMsg, + ibc_client, manager::ModuleInstallConfig, objects::{dependency::StaticDependency, module::ModuleInfo}, + IBC_CLIENT, }; use abstract_interface::{AppDeployer, DependencyCreation}; use cosmwasm_schema::QueryResponses; pub use cosmwasm_std::testing::*; - use cosmwasm_std::{to_json_binary, Response, StdError}; + use cosmwasm_std::{to_json_binary, wasm_execute, Response, StdError}; use cw_controllers::AdminError; use cw_orch::prelude::*; use cw_storage_plus::Item; @@ -56,6 +59,7 @@ pub mod mock { pub enum MockExecMsg { DoSomething {}, DoSomethingAdmin {}, + DoSomethingIbc {}, } #[cosmwasm_schema::cw_serde] @@ -87,7 +91,7 @@ pub mod mock { #[cosmwasm_schema::cw_serde] pub struct MockSudoMsg; - use abstract_sdk::{base::InstantiateEndpoint, AbstractSdkError}; + use abstract_sdk::{base::InstantiateEndpoint, AbstractSdkError, ModuleInterface}; use abstract_testing::{ addresses::{test_account_base, TEST_ANS_HOST, TEST_VERSION_CONTROL}, prelude::{ @@ -134,6 +138,8 @@ pub mod mock { // Easy way to see if an ibc-callback was actually received. pub const IBC_CALLBACK_RECEIVED: Item = Item::new("ibc_callback_received"); + // Easy way to see if an module ibc called was actually received. + pub const MODULE_IBC_RECEIVED: Item = Item::new("module_ibc_received"); pub const MOCK_APP_WITH_DEP: MockAppContract = MockAppContract::new(TEST_WITH_DEP_MODULE_ID, TEST_VERSION, None) @@ -141,7 +147,24 @@ pub mod mock { IBC_CALLBACK_RECEIVED.save(deps.storage, &false)?; Ok(Response::new().set_data("mock_init".as_bytes())) }) - .with_execute(|_, _, _, _, _| Ok(Response::new().set_data("mock_exec".as_bytes()))) + .with_execute(|deps, _, _, app, msg| match msg { + MockExecMsg::DoSomethingIbc {} => { + let ibc_client_addr = app.modules(deps.as_ref()).module_address(IBC_CLIENT)?; + // We send an IBC Client module message + let msg = wasm_execute( + ibc_client_addr, + &ibc_client::ExecuteMsg::RemoteAction { + host_chain: (), + action: (), + callback_info: (), + }, + vec![], + )?; + + Ok(Response::new().add_message(msg)) + } + _ => Ok(Response::new().set_data("mock_exec".as_bytes())), + }) .with_query(|deps, _, _, msg| match msg { MockQueryMsg::GetSomething {} => { to_json_binary(&MockQueryResponse {}).map_err(Into::into) @@ -163,7 +186,13 @@ pub mod mock { .with_replies(&[(1u64, |_, _, _, msg| { Ok(Response::new().set_data(msg.result.unwrap().data.unwrap())) })]) - .with_migrate(|_, _, _, _| Ok(Response::new().set_data("mock_migrate".as_bytes()))); + .with_migrate(|_, _, _, _| Ok(Response::new().set_data("mock_migrate".as_bytes()))) + .with_module_ibc(|deps, _, _, msg| { + let ModuleIbcMsg { source_module, .. } = msg; + // We save the module info status + MODULE_IBC_RECEIVED.save(deps.storage, &source_module)?; + Ok(Response::new()) + }); crate::cw_orch_interface!(MOCK_APP_WITH_DEP, MockAppContract, MockAppWithDepI); diff --git a/framework/packages/abstract-app/src/state.rs b/framework/packages/abstract-app/src/state.rs index 1b85431a9d..eb3def4b5d 100644 --- a/framework/packages/abstract-app/src/state.rs +++ b/framework/packages/abstract-app/src/state.rs @@ -3,7 +3,7 @@ use abstract_core::{ AbstractError, }; use abstract_sdk::{ - base::SudoHandlerFn, + base::{ModuleIbcHandlerFn, SudoHandlerFn}, feature_objects::{AnsHost, VersionControlContract}, namespaces::{ADMIN_NAMESPACE, BASE_STATE}, AbstractSdkError, @@ -176,6 +176,15 @@ impl< self.contract = self.contract.with_ibc_callbacks(callbacks); self } + + /// add Module IBC to contract + pub const fn with_module_ibc( + mut self, + module_handler: ModuleIbcHandlerFn, + ) -> Self { + self.contract = self.contract.with_module_ibc(module_handler); + self + } } #[cfg(test)] diff --git a/framework/packages/abstract-core/src/base.rs b/framework/packages/abstract-core/src/base.rs index 386df1e96f..7805d2f3c0 100644 --- a/framework/packages/abstract-core/src/base.rs +++ b/framework/packages/abstract-core/src/base.rs @@ -1,7 +1,7 @@ use cosmwasm_schema::QueryResponses; use cosmwasm_std::Empty; -use crate::ibc::IbcResponseMsg; +use crate::ibc::{IbcResponseMsg, ModuleIbcMsg}; // ANCHOR: exec /// Wrapper around all possible messages that can be sent to the module. @@ -14,6 +14,10 @@ pub enum ExecuteMsg { /// IbcReceive to process IBC callbacks /// In order to trust this, the apps and adapters verify this comes from the ibc-client contract. IbcCallback(IbcResponseMsg), + /// ModuleIbc endpoint to receive messages from this module on other chains + /// In order to trust this, the apps and adapters verify this comes from the ibc-host contract. + /// They should also trust the sending chain + ModuleIbc(ModuleIbcMsg), /// Receive endpoint for CW20 / external service integrations Receive(ReceiveMsg), } diff --git a/framework/packages/abstract-core/src/native/ibc.rs b/framework/packages/abstract-core/src/native/ibc.rs index b740ecc4ed..86944ad52c 100644 --- a/framework/packages/abstract-core/src/native/ibc.rs +++ b/framework/packages/abstract-core/src/native/ibc.rs @@ -1,7 +1,13 @@ -use cosmwasm_std::{to_json_binary, wasm_execute, Binary, CosmosMsg, StdResult}; +use cosmwasm_schema::cw_serde; +use cosmwasm_std::{to_json_binary, wasm_execute, Binary, CosmosMsg, Empty, StdResult}; use polytone::callbacks::Callback; use schemars::JsonSchema; +use crate::{ + base::ExecuteMsg, + objects::{chain_name::ChainName, module::ModuleInfo}, +}; + // CallbackInfo from modules, that is turned into an IbcResponseMsg by the ibc client #[cosmwasm_schema::cw_serde] pub struct CallbackInfo { @@ -39,7 +45,7 @@ impl IbcResponseMsg { { Ok(wasm_execute( contract_addr.into(), - &IbcCallbackMsg::IbcCallback(self), + &ExecuteMsg::IbcCallback::(self), vec![], )? .into()) @@ -52,3 +58,10 @@ impl IbcResponseMsg { enum IbcCallbackMsg { IbcCallback(IbcResponseMsg), } + +#[cw_serde] +pub struct ModuleIbcMsg { + pub client_chain: ChainName, + pub source_module: ModuleInfo, + pub msg: Binary, +} diff --git a/framework/packages/abstract-core/src/native/ibc_client.rs b/framework/packages/abstract-core/src/native/ibc_client.rs index 88e5643ad9..d73071d6cf 100644 --- a/framework/packages/abstract-core/src/native/ibc_client.rs +++ b/framework/packages/abstract-core/src/native/ibc_client.rs @@ -7,7 +7,7 @@ use crate::{ ibc::CallbackInfo, ibc_host::HostAction, manager::ModuleInstallConfig, - objects::{account::AccountId, chain_name::ChainName, AssetEntry}, + objects::{account::AccountId, chain_name::ChainName, module::ModuleInfo, AssetEntry}, }; pub mod state { @@ -133,7 +133,13 @@ pub enum ExecuteMsg { #[cosmwasm_schema::cw_serde] pub enum IbcClientCallback { UserRemoteAction(CallbackInfo), - CreateAccount { account_id: AccountId }, + ModuleRemoteAction { + callback_info: CallbackInfo, + target_module: ModuleInfo, + }, + CreateAccount { + account_id: AccountId, + }, WhoAmI {}, } diff --git a/framework/packages/abstract-core/src/native/ibc_host.rs b/framework/packages/abstract-core/src/native/ibc_host.rs index faa62ab902..2ec75ef925 100644 --- a/framework/packages/abstract-core/src/native/ibc_host.rs +++ b/framework/packages/abstract-core/src/native/ibc_host.rs @@ -8,12 +8,11 @@ //! The api structure is well-suited for implementing standard interfaces to external services like dexes, lending platforms, etc. use cosmwasm_schema::QueryResponses; -use cosmwasm_std::Addr; +use cosmwasm_std::{Addr, Binary}; use crate::{ - manager, - manager::ModuleInstallConfig, - objects::{account::AccountId, chain_name::ChainName, AssetEntry}, + manager::{self, ModuleInstallConfig}, + objects::{account::AccountId, chain_name::ChainName, module::ModuleInfo, AssetEntry}, }; pub mod state { @@ -92,6 +91,12 @@ pub enum HostAction { Dispatch { manager_msg: manager::ExecuteMsg, }, + /// Executes an action on the module with the corresponding module id on another chain + Module { + source_module: ModuleInfo, + target_module: ModuleInfo, + msg: Binary, + }, /// Can't be called by an account directly. These are permissioned messages that only the IBC Client is allowed to call by itself. Internal(InternalAction), /// Some helpers that allow calling dispatch messages faster (for actions that are called regularly) @@ -127,6 +132,12 @@ pub enum ExecuteMsg { proxy_address: String, action: HostAction, }, + /// Allows for remote execution from the Polytone implementation on a local module + ModuleExecute { + source_module: ModuleInfo, + target_module: ModuleInfo, + msg: Binary, + }, } /// Query Host message diff --git a/framework/packages/abstract-sdk/src/base/contract_base.rs b/framework/packages/abstract-sdk/src/base/contract_base.rs index d1d7edac56..1dbfbf93e3 100644 --- a/framework/packages/abstract-sdk/src/base/contract_base.rs +++ b/framework/packages/abstract-sdk/src/base/contract_base.rs @@ -1,3 +1,4 @@ +use abstract_core::ibc::ModuleIbcMsg; use cosmwasm_std::{Binary, Deps, DepsMut, Env, MessageInfo, Reply, Response, Storage}; use cw2::{ContractVersion, CONTRACT}; use cw_storage_plus::Item; @@ -52,6 +53,12 @@ pub type IbcCallbackHandlerFn = fn( ) -> Result; // ANCHOR_END: ibc +// ANCHOR: module_ibc +/// Function signature for an Module to Module IBC handler. +pub type ModuleIbcHandlerFn = + fn(DepsMut, Env, Module, ModuleIbcMsg) -> Result; +// ANCHOR_END: module_ibc + // ANCHOR: mig /// Function signature for a migrate handler. pub type MigrateHandlerFn = @@ -110,6 +117,8 @@ pub struct AbstractContract)], + /// Module IBC handler for passing messages between a module on different chains. + pub(crate) module_ibc_handler: Option>, } impl> AbstractContract @@ -130,6 +139,7 @@ where sudo_handler: None, instantiate_handler: None, query_handler: None, + module_ibc_handler: None, } } /// Gets the cw2 version of the contract. @@ -163,6 +173,15 @@ where self } + /// add IBC callback handler to contract + pub const fn with_module_ibc( + mut self, + module_handler: ModuleIbcHandlerFn, + ) -> Self { + self.module_ibc_handler = Some(module_handler); + self + } + /// Add instantiate handler to the contract. pub const fn with_instantiate( mut self, diff --git a/framework/packages/abstract-sdk/src/base/endpoints.rs b/framework/packages/abstract-sdk/src/base/endpoints.rs index fa9b447416..3995b939d6 100644 --- a/framework/packages/abstract-sdk/src/base/endpoints.rs +++ b/framework/packages/abstract-sdk/src/base/endpoints.rs @@ -130,6 +130,7 @@ mod execute; mod ibc_callback; mod instantiate; pub(crate) mod migrate; +mod modules_ibc; mod query; mod receive; mod reply; @@ -140,6 +141,7 @@ pub use execute::ExecuteEndpoint; pub use ibc_callback::IbcCallbackEndpoint; pub use instantiate::InstantiateEndpoint; pub use migrate::MigrateEndpoint; +pub use modules_ibc::ModuleIbcEndpoint; pub use query::QueryEndpoint; pub use receive::ReceiveEndpoint; pub use reply::ReplyEndpoint; diff --git a/framework/packages/abstract-sdk/src/base/endpoints/modules_ibc.rs b/framework/packages/abstract-sdk/src/base/endpoints/modules_ibc.rs new file mode 100644 index 0000000000..6c3b427006 --- /dev/null +++ b/framework/packages/abstract-sdk/src/base/endpoints/modules_ibc.rs @@ -0,0 +1,40 @@ +use abstract_core::ibc::ModuleIbcMsg; +use cosmwasm_std::{Addr, Deps, DepsMut, Env, MessageInfo, Response}; + +use crate::{base::Handler, AbstractSdkError}; + +/// Trait for a contract to call itself on an IBC counterpart. +pub trait ModuleIbcEndpoint: Handler { + /// Get the address of the ibc host associated with this module + fn ibc_host(&self, deps: Deps) -> Result; + + /// Handler for the `ExecuteMsg::IbcCallback()` variant. + fn module_ibc( + self, + deps: DepsMut, + env: Env, + info: MessageInfo, + msg: ModuleIbcMsg, + ) -> Result { + // Only an IBC host can call this endpoint + let ibc_host = self.ibc_host(deps.as_ref())?; + if info.sender.ne(&ibc_host) { + return Err(AbstractSdkError::ModuleIbcNotCalledByHost { + caller: info.sender, + host_addr: ibc_host, + module: self.info().0.to_string(), + } + .into()); + }; + + // Only a whitelisted chain can call this endpoint + /// TODO + /// + /// + let maybe_handler = self.maybe_module_ibc_handler(); + maybe_handler.map_or_else( + || Ok(Response::new()), + |handler| handler(deps, env, self, msg), + ) + } +} diff --git a/framework/packages/abstract-sdk/src/base/handler.rs b/framework/packages/abstract-sdk/src/base/handler.rs index 9df2799833..16ffa90519 100644 --- a/framework/packages/abstract-sdk/src/base/handler.rs +++ b/framework/packages/abstract-sdk/src/base/handler.rs @@ -4,7 +4,7 @@ use cw2::ContractVersion; use super::contract_base::{ AbstractContract, ExecuteHandlerFn, IbcCallbackHandlerFn, InstantiateHandlerFn, - MigrateHandlerFn, QueryHandlerFn, ReceiveHandlerFn, SudoHandlerFn, + MigrateHandlerFn, ModuleIbcHandlerFn, QueryHandlerFn, ReceiveHandlerFn, SudoHandlerFn, }; use crate::{ base::{ @@ -176,6 +176,11 @@ where } None } + /// Get an ibc callback handler if it exists. + fn maybe_module_ibc_handler(&self) -> Option> { + let contract = self.contract(); + contract.module_ibc_handler + } /// Get a reply handler if it exists. fn maybe_reply_handler(&self, id: u64) -> Option> { let contract = self.contract(); diff --git a/framework/packages/abstract-sdk/src/base/mod.rs b/framework/packages/abstract-sdk/src/base/mod.rs index 21aed52fd0..6bde48aa83 100644 --- a/framework/packages/abstract-sdk/src/base/mod.rs +++ b/framework/packages/abstract-sdk/src/base/mod.rs @@ -9,11 +9,11 @@ mod handler; pub use contract_base::{ AbstractContract, ExecuteHandlerFn, IbcCallbackHandlerFn, InstantiateHandlerFn, - MigrateHandlerFn, QueryHandlerFn, ReceiveHandlerFn, ReplyHandlerFn, SudoHandlerFn, - VersionString, + MigrateHandlerFn, ModuleIbcHandlerFn, QueryHandlerFn, ReceiveHandlerFn, ReplyHandlerFn, + SudoHandlerFn, VersionString, }; pub use endpoints::{ - ExecuteEndpoint, IbcCallbackEndpoint, InstantiateEndpoint, MigrateEndpoint, QueryEndpoint, - ReceiveEndpoint, ReplyEndpoint, SudoEndpoint, + ExecuteEndpoint, IbcCallbackEndpoint, InstantiateEndpoint, MigrateEndpoint, ModuleIbcEndpoint, + QueryEndpoint, ReceiveEndpoint, ReplyEndpoint, SudoEndpoint, }; pub use handler::Handler; diff --git a/framework/packages/abstract-sdk/src/error.rs b/framework/packages/abstract-sdk/src/error.rs index fc4617246a..e8bd4efb89 100644 --- a/framework/packages/abstract-sdk/src/error.rs +++ b/framework/packages/abstract-sdk/src/error.rs @@ -54,6 +54,14 @@ pub enum AbstractSdkError { module: String, }, + // callback not called by IBC host + #[error("Module {module} Ibc Endpoint called by {caller} instead of IBC host {host_addr}.")] + ModuleIbcNotCalledByHost { + caller: Addr, + host_addr: Addr, + module: String, + }, + // admin of proxy is not set #[error("Admin of proxy {proxy_addr} is not set.")] AdminNotSet { proxy_addr: Addr }, From 5393958f4ddffc7c8e0a7fa0434ce5ba3d54fdd5 Mon Sep 17 00:00:00 2001 From: Kayanski Date: Fri, 16 Feb 2024 19:42:06 +0100 Subject: [PATCH 02/37] formatting [skip ci] --- .../packages/abstract-adapter/src/endpoints/module_ibc.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/framework/packages/abstract-adapter/src/endpoints/module_ibc.rs b/framework/packages/abstract-adapter/src/endpoints/module_ibc.rs index 0c9b4cd7e4..ccb174e90c 100644 --- a/framework/packages/abstract-adapter/src/endpoints/module_ibc.rs +++ b/framework/packages/abstract-adapter/src/endpoints/module_ibc.rs @@ -1,9 +1,9 @@ +use crate::{state::ContractError, AdapterContract}; use abstract_core::IBC_HOST; use abstract_core::{objects::module::ModuleInfo, AbstractError}; +use abstract_sdk::AbstractSdkError; use abstract_sdk::{base::ModuleIbcEndpoint, features::AbstractRegistryAccess}; -use crate::{state::ContractError, AdapterContract}; use cosmwasm_std::Addr; -use abstract_sdk::AbstractSdkError; impl ModuleIbcEndpoint From f449ec1d0f165d89d7f4a0d41a7175d33c7e329e Mon Sep 17 00:00:00 2001 From: Kayanski Date: Wed, 6 Mar 2024 14:15:00 +0000 Subject: [PATCH 03/37] Restart impl --- framework/packages/abstract-app/src/lib.rs | 6 +++--- .../abstract-core/src/native/ibc_client.rs | 7 ++++++- .../packages/abstract-core/src/native/ibc_host.rs | 14 ++++++++------ .../abstract-sdk/src/base/endpoints/modules_ibc.rs | 4 ---- 4 files changed, 17 insertions(+), 14 deletions(-) diff --git a/framework/packages/abstract-app/src/lib.rs b/framework/packages/abstract-app/src/lib.rs index 968390bb51..2bb9827935 100644 --- a/framework/packages/abstract-app/src/lib.rs +++ b/framework/packages/abstract-app/src/lib.rs @@ -59,7 +59,7 @@ pub mod mock { pub enum MockExecMsg { DoSomething {}, DoSomethingAdmin {}, - DoSomethingIbc {}, + DoSomethingIbc { remote_chain: ChainName }, } #[cosmwasm_schema::cw_serde] @@ -148,13 +148,13 @@ pub mod mock { Ok(Response::new().set_data("mock_init".as_bytes())) }) .with_execute(|deps, _, _, app, msg| match msg { - MockExecMsg::DoSomethingIbc {} => { + MockExecMsg::DoSomethingIbc { remote_chain } => { let ibc_client_addr = app.modules(deps.as_ref()).module_address(IBC_CLIENT)?; // We send an IBC Client module message let msg = wasm_execute( ibc_client_addr, &ibc_client::ExecuteMsg::RemoteAction { - host_chain: (), + host_chain: remote_chain, action: (), callback_info: (), }, diff --git a/framework/packages/abstract-core/src/native/ibc_client.rs b/framework/packages/abstract-core/src/native/ibc_client.rs index d73071d6cf..62eef7e41e 100644 --- a/framework/packages/abstract-core/src/native/ibc_client.rs +++ b/framework/packages/abstract-core/src/native/ibc_client.rs @@ -5,7 +5,7 @@ use polytone::callbacks::CallbackMessage; use self::state::IbcInfrastructure; use crate::{ ibc::CallbackInfo, - ibc_host::HostAction, + ibc_host::{HostAction, HostModuleAction}, manager::ModuleInstallConfig, objects::{account::AccountId, chain_name::ChainName, module::ModuleInfo, AssetEntry}, }; @@ -100,6 +100,11 @@ pub enum ExecuteMsg { namespace: Option, install_modules: Vec, }, + ModuleIbcAction { + host_chain: String, + action: HostModuleAction, + callback_info: Option, + }, RemoteAction { // host chain to be executed on // Example: "osmosis" diff --git a/framework/packages/abstract-core/src/native/ibc_host.rs b/framework/packages/abstract-core/src/native/ibc_host.rs index 2ec75ef925..cae98d70fc 100644 --- a/framework/packages/abstract-core/src/native/ibc_host.rs +++ b/framework/packages/abstract-core/src/native/ibc_host.rs @@ -91,18 +91,20 @@ pub enum HostAction { Dispatch { manager_msg: manager::ExecuteMsg, }, - /// Executes an action on the module with the corresponding module id on another chain - Module { - source_module: ModuleInfo, - target_module: ModuleInfo, - msg: Binary, - }, /// Can't be called by an account directly. These are permissioned messages that only the IBC Client is allowed to call by itself. Internal(InternalAction), /// Some helpers that allow calling dispatch messages faster (for actions that are called regularly) Helpers(HelperAction), } +/// Executes an action on the module with the corresponding module id on another chain +#[cosmwasm_schema::cw_serde] +pub struct HostModuleAction { + source_module: ModuleInfo, + target_module: ModuleInfo, + msg: Binary, +} + /// Interface to the Host. #[cosmwasm_schema::cw_serde] #[cfg_attr(feature = "interface", derive(cw_orch::ExecuteFns))] diff --git a/framework/packages/abstract-sdk/src/base/endpoints/modules_ibc.rs b/framework/packages/abstract-sdk/src/base/endpoints/modules_ibc.rs index 6c3b427006..f498b13749 100644 --- a/framework/packages/abstract-sdk/src/base/endpoints/modules_ibc.rs +++ b/framework/packages/abstract-sdk/src/base/endpoints/modules_ibc.rs @@ -27,10 +27,6 @@ pub trait ModuleIbcEndpoint: Handler { .into()); }; - // Only a whitelisted chain can call this endpoint - /// TODO - /// - /// let maybe_handler = self.maybe_module_ibc_handler(); maybe_handler.map_or_else( || Ok(Response::new()), From 4554f420e4d07de069c46b39e9c216c58f7faafc Mon Sep 17 00:00:00 2001 From: Kayanski Date: Wed, 6 Mar 2024 14:47:55 +0000 Subject: [PATCH 04/37] Added verifiedsender to ibc-callback --- .../native/ibc-client/src/commands.rs | 25 +++++++++++-- .../native/ibc-client/src/contract.rs | 31 +++++++++++----- .../contracts/native/ibc-client/src/ibc.rs | 6 ++- .../packages/abstract-core/src/native/ibc.rs | 7 +++- .../abstract-core/src/native/ibc_client.rs | 37 +++++++++++-------- .../abstract-sdk/src/base/contract_base.rs | 4 +- .../src/base/endpoints/ibc_callback.rs | 3 +- 7 files changed, 78 insertions(+), 35 deletions(-) diff --git a/framework/contracts/native/ibc-client/src/commands.rs b/framework/contracts/native/ibc-client/src/commands.rs index b42d6ef402..0451b70636 100644 --- a/framework/contracts/native/ibc-client/src/commands.rs +++ b/framework/contracts/native/ibc-client/src/commands.rs @@ -6,8 +6,8 @@ use abstract_core::{ state::{IbcInfrastructure, IBC_INFRA, REVERSE_POLYTONE_NOTE}, IbcClientCallback, }, - ibc_host, manager, - manager::ModuleInstallConfig, + ibc_host, + manager::{self, ModuleInstallConfig}, objects::{chain_name::ChainName, AccountId, AssetEntry}, version_control::AccountBase, }; @@ -221,7 +221,11 @@ pub fn execute_send_packet( let callback_request = callback_info.map(|c| CallbackRequest { receiver: env.contract.address.to_string(), - msg: to_json_binary(&IbcClientCallback::UserRemoteAction(c)).unwrap(), + msg: to_json_binary(&IbcClientCallback::UserRemoteAction { + sender: account_id.clone(), + callback_info: c, + }) + .unwrap(), }); let note_message = send_remote_host_action( @@ -240,15 +244,28 @@ pub fn execute_send_packet( pub fn execute_send_query( deps: DepsMut, env: Env, + info: MessageInfo, host_chain: String, queries: Vec>, callback_info: CallbackInfo, ) -> IbcClientResult { let host_chain = ChainName::from_str(&host_chain)?; + let cfg = CONFIG.load(deps.storage)?; + + // Verify that the sender is a proxy contract + let account_base = cfg + .version_control + .assert_proxy(&info.sender, &deps.querier)?; + // get account_id + let account_id = account_base.account_id(deps.as_ref())?; let callback_request = CallbackRequest { receiver: env.contract.address.to_string(), - msg: to_json_binary(&IbcClientCallback::UserRemoteAction(callback_info)).unwrap(), + msg: to_json_binary(&IbcClientCallback::UserRemoteAction { + sender: account_id, + callback_info, + }) + .unwrap(), }; let note_message = diff --git a/framework/contracts/native/ibc-client/src/contract.rs b/framework/contracts/native/ibc-client/src/contract.rs index 3bfbcd7fb7..bdad8ee9b6 100644 --- a/framework/contracts/native/ibc-client/src/contract.rs +++ b/framework/contracts/native/ibc-client/src/contract.rs @@ -70,7 +70,7 @@ pub fn execute(deps: DepsMut, env: Env, info: MessageInfo, msg: ExecuteMsg) -> I host_chain, queries, callback_info, - } => commands::execute_send_query(deps, env, host_chain, queries, callback_info), + } => commands::execute_send_query(deps, env, info, host_chain, queries, callback_info), ExecuteMsg::RegisterInfrastructure { chain, note, host } => { commands::execute_register_infrastructure(deps, env, info, chain, host, note) } @@ -462,7 +462,7 @@ mod tests { manager, objects::{ account::TEST_ACCOUNT_ID, chain_name::ChainName, - version_control::VersionControlError, + version_control::VersionControlError, AccountId, }, }; use abstract_testing::prelude::{ @@ -632,7 +632,10 @@ mod tests { }; let callback_request = CallbackRequest { - msg: to_json_binary(&IbcClientCallback::UserRemoteAction(callback_info.clone()))?, + msg: to_json_binary(&IbcClientCallback::UserRemoteAction { + callback_info: callback_info.clone(), + sender: AccountId::local(1), + })?, receiver: mock_env().contract.address.to_string(), }; @@ -675,7 +678,10 @@ mod tests { mod remote_query { use std::str::FromStr; - use abstract_core::{ibc::CallbackInfo, objects::chain_name::ChainName}; + use abstract_core::{ + ibc::CallbackInfo, + objects::{account::TEST_ACCOUNT_ID, chain_name::ChainName}, + }; use cosmwasm_std::{wasm_execute, BankQuery, Binary, QueryRequest}; use polytone::callbacks::CallbackRequest; @@ -709,7 +715,10 @@ mod tests { }; let callback_request = CallbackRequest { - msg: to_json_binary(&IbcClientCallback::UserRemoteAction(callback_info.clone()))?, + msg: to_json_binary(&IbcClientCallback::UserRemoteAction { + sender: TEST_ACCOUNT_ID, + callback_info: callback_info.clone(), + })?, receiver: mock_env().contract.address.to_string(), }; @@ -723,7 +732,7 @@ mod tests { callback_info, }; - let res = execute_as(deps.as_mut(), "sender", msg)?; + let res = execute_as(deps.as_mut(), TEST_PROXY, msg)?; let note_message = wasm_execute( note_contract.to_string(), @@ -1132,7 +1141,7 @@ mod tests { use abstract_core::{ ibc::{CallbackInfo, IbcResponseMsg}, - objects::{account::TEST_ACCOUNT_ID, chain_name::ChainName}, + objects::{account::TEST_ACCOUNT_ID, chain_name::ChainName, AccountId}, }; use cosmwasm_std::{from_json, Binary, Event, SubMsgResponse}; use polytone::callbacks::{Callback, CallbackMessage, ExecutionResponse}; @@ -1525,13 +1534,14 @@ mod tests { let receiver = String::from("receiver"); let callback_msg = CallbackMessage { initiator: env.contract.address, - initiator_msg: to_json_binary(&IbcClientCallback::UserRemoteAction( - CallbackInfo { + initiator_msg: to_json_binary(&IbcClientCallback::UserRemoteAction { + callback_info: CallbackInfo { id: id.clone(), msg: Some(callback_info_msg.clone()), receiver: receiver.clone(), }, - ))?, + sender: AccountId::local(1), + })?, result: Callback::Execute(Ok(ExecutionResponse { executed_by: remote_proxy.clone(), result: vec![], @@ -1548,6 +1558,7 @@ mod tests { id: id.clone(), msg: Some(callback_info_msg), result: callback_msg.result, + sender: AccountId::local(1) } .into_cosmos_msg(receiver)? ) diff --git a/framework/contracts/native/ibc-client/src/ibc.rs b/framework/contracts/native/ibc-client/src/ibc.rs index 4fac7b4999..9e742dc5c1 100644 --- a/framework/contracts/native/ibc-client/src/ibc.rs +++ b/framework/contracts/native/ibc-client/src/ibc.rs @@ -88,12 +88,16 @@ pub fn receive_action_callback( .add_attribute("chain", host_chain.to_string()), ) } - IbcClientCallback::UserRemoteAction(callback_info) => { + IbcClientCallback::UserRemoteAction { + sender, + callback_info, + } => { // Here we transfer the callback back to the module that requested it let callback = IbcResponseMsg { id: callback_info.id.clone(), msg: callback_info.msg, result: callback.result, + sender, }; Ok(IbcClientResponse::action("user_specific_callback") .add_message(callback.into_cosmos_msg(callback_info.receiver)?) diff --git a/framework/packages/abstract-core/src/native/ibc.rs b/framework/packages/abstract-core/src/native/ibc.rs index b740ecc4ed..85fc9b3bf2 100644 --- a/framework/packages/abstract-core/src/native/ibc.rs +++ b/framework/packages/abstract-core/src/native/ibc.rs @@ -2,6 +2,8 @@ use cosmwasm_std::{to_json_binary, wasm_execute, Binary, CosmosMsg, StdResult}; use polytone::callbacks::Callback; use schemars::JsonSchema; +use crate::objects::AccountId; + // CallbackInfo from modules, that is turned into an IbcResponseMsg by the ibc client #[cosmwasm_schema::cw_serde] pub struct CallbackInfo { @@ -22,6 +24,9 @@ pub struct IbcResponseMsg { /// The msg sent with the callback request. /// This is usually used to provide information to the ibc callback function for context pub msg: Option, + /// The account id of the sender of the original IBC message + /// This is verified by the ibc-client and can be trusted inside applications + pub sender: AccountId, pub result: Callback, } @@ -49,6 +54,6 @@ impl IbcResponseMsg { /// This is just a helper to properly serialize the above message. /// The actual receiver should include this variant in the larger ExecuteMsg enum #[cosmwasm_schema::cw_serde] -enum IbcCallbackMsg { +pub(crate) enum IbcCallbackMsg { IbcCallback(IbcResponseMsg), } diff --git a/framework/packages/abstract-core/src/native/ibc_client.rs b/framework/packages/abstract-core/src/native/ibc_client.rs index 88e5643ad9..45726cdada 100644 --- a/framework/packages/abstract-core/src/native/ibc_client.rs +++ b/framework/packages/abstract-core/src/native/ibc_client.rs @@ -132,8 +132,13 @@ pub enum ExecuteMsg { /// This enum is used for sending callbacks to the note contract of the IBC client #[cosmwasm_schema::cw_serde] pub enum IbcClientCallback { - UserRemoteAction(CallbackInfo), - CreateAccount { account_id: AccountId }, + UserRemoteAction { + sender: AccountId, + callback_info: CallbackInfo, + }, + CreateAccount { + account_id: AccountId, + }, WhoAmI {}, } @@ -243,8 +248,9 @@ mod tests { use polytone::callbacks::Callback; use speculoos::prelude::*; + use crate::ibc::IbcCallbackMsg; use crate::ibc::IbcResponseMsg; - + use crate::objects::AccountId; // ... (other test functions) #[test] @@ -259,20 +265,19 @@ mod tests { id: callback_id, msg: Some(callback_msg), result, + sender: AccountId::local(1), }; - let actual: CosmosMsg = response_msg.into_cosmos_msg(receiver.clone()).unwrap(); - - assert_that!(actual).matches(|e| { - matches!( - e, - CosmosMsg::Wasm(cosmwasm_std::WasmMsg::Execute { - contract_addr: _receiver, - // we can't test the message because the fields in it are private - msg: _, - funds: _ - }) - ) - }); + let actual: CosmosMsg = response_msg + .clone() + .into_cosmos_msg(receiver.clone()) + .unwrap(); + + assert_that!(actual).is_equal_to(CosmosMsg::Wasm(cosmwasm_std::WasmMsg::Execute { + contract_addr: receiver, + // we can't test the message because the fields in it are private + msg: to_json_binary(&IbcCallbackMsg::IbcCallback(response_msg)).unwrap(), + funds: vec![], + })) } } diff --git a/framework/packages/abstract-sdk/src/base/contract_base.rs b/framework/packages/abstract-sdk/src/base/contract_base.rs index c7565fb07f..1df6a827ec 100644 --- a/framework/packages/abstract-sdk/src/base/contract_base.rs +++ b/framework/packages/abstract-sdk/src/base/contract_base.rs @@ -1,3 +1,4 @@ +use abstract_core::objects::AccountId; use cosmwasm_std::{Binary, Deps, DepsMut, Env, MessageInfo, Reply, Response, Storage}; use cw2::{ContractVersion, CONTRACT}; use cw_storage_plus::Item; @@ -29,7 +30,6 @@ pub type QueryHandlerFn = fn(Deps, Env, &Module, CustomQueryMsg) -> Result; // ANCHOR_END: query -type CallbackId = String; type CallbackMessage = Option; // ANCHOR: ibc /// Function signature for an IBC callback handler. @@ -38,7 +38,7 @@ pub type IbcCallbackHandlerFn = fn( Env, MessageInfo, Module, - CallbackId, + AccountId, CallbackMessage, Callback, ) -> Result; diff --git a/framework/packages/abstract-sdk/src/base/endpoints/ibc_callback.rs b/framework/packages/abstract-sdk/src/base/endpoints/ibc_callback.rs index f4a50cd77c..cdf3248c91 100644 --- a/framework/packages/abstract-sdk/src/base/endpoints/ibc_callback.rs +++ b/framework/packages/abstract-sdk/src/base/endpoints/ibc_callback.rs @@ -29,11 +29,12 @@ pub trait IbcCallbackEndpoint: Handler { id, msg: callback_msg, result, + sender, } = msg; let maybe_handler = self.maybe_ibc_callback_handler(&id); maybe_handler.map_or_else( || Ok(Response::new()), - |handler| handler(deps, env, info, self, id, callback_msg, result), + |handler| handler(deps, env, info, self, sender, callback_msg, result), ) } } From 81f1556eaaa7c4d1ce7dac3002b3b17e27f81c2f Mon Sep 17 00:00:00 2001 From: Kayanski Date: Wed, 6 Mar 2024 15:42:34 +0000 Subject: [PATCH 05/37] Modified implementation with InstalledModuleIdentification for all module types to send messages --- .../native/ibc-client/src/commands.rs | 178 +++++++++++------- .../native/ibc-client/src/contract.rs | 16 ++ .../contracts/native/ibc-client/src/ibc.rs | 4 +- .../native/ibc-host/src/endpoints/packet.rs | 46 ++++- .../contracts/native/ibc-host/src/error.rs | 8 + .../packages/abstract-core/src/native/ibc.rs | 3 +- .../abstract-core/src/native/ibc_client.rs | 19 +- .../abstract-core/src/native/ibc_host.rs | 13 +- 8 files changed, 193 insertions(+), 94 deletions(-) diff --git a/framework/contracts/native/ibc-client/src/commands.rs b/framework/contracts/native/ibc-client/src/commands.rs index 75289bf39a..008ea3db68 100644 --- a/framework/contracts/native/ibc-client/src/commands.rs +++ b/framework/contracts/native/ibc-client/src/commands.rs @@ -4,11 +4,11 @@ use abstract_core::{ ibc::CallbackInfo, ibc_client::{ state::{IbcInfrastructure, IBC_INFRA, REVERSE_POLYTONE_NOTE}, - IbcClientCallback, + IbcClientCallback, InstalledModuleIdentification, }, ibc_host, manager::{self, ModuleInstallConfig}, - objects::{chain_name::ChainName, module::ModuleInfo, AccountId, AssetEntry}, + objects::{chain_name::ChainName, module_reference::ModuleReference, AccountId, AssetEntry}, version_control::AccountBase, }; use abstract_sdk::{ @@ -22,8 +22,8 @@ use abstract_sdk::{ Resolve, }; use cosmwasm_std::{ - to_json_binary, wasm_execute, Binary, Coin, CosmosMsg, Deps, DepsMut, Empty, Env, IbcMsg, - MessageInfo, QueryRequest, Storage, + ensure_eq, to_json_binary, wasm_execute, Binary, Coin, CosmosMsg, Deps, DepsMut, Empty, Env, + IbcMsg, MessageInfo, QueryRequest, Storage, }; use polytone::callbacks::CallbackRequest; @@ -169,44 +169,6 @@ fn send_remote_host_action( Ok(note_message.into()) } -/// Send a message to a remote abstract-ibc-host. This message will be proxied through polytone. -fn send_remote_host_module_action( - deps: Deps, - host_chain: ChainName, - source_module: ModuleInfo, - target_module: ModuleInfo, - msg: Binary, - callback_request: Option, -) -> IbcClientResult> { - // Send this message via the Polytone implementation - let ibc_infra = IBC_INFRA.load(deps.storage, &host_chain)?; - let note_contract = ibc_infra.polytone_note; - let remote_ibc_host = ibc_infra.remote_abstract_host; - - // message that will be called on the local note contract - let note_message = wasm_execute( - note_contract.to_string(), - &polytone_note::msg::ExecuteMsg::Execute { - msgs: vec![wasm_execute( - // The note's remote proxy will call the ibc host - remote_ibc_host, - &ibc_host::ExecuteMsg::ModuleExecute { - msg, - source_module, - target_module, - }, - vec![], - )? - .into()], - callback: callback_request, - timeout_seconds: PACKET_LIFETIME.into(), - }, - vec![], - )?; - - Ok(note_message.into()) -} - /// Perform a ICQ on a remote chain fn send_remote_host_query( deps: Deps, @@ -270,36 +232,6 @@ pub fn execute_send_packet( callback_request, )? } - HostAction::Module { - msg, - source_module, - target_module, - } => { - // We make sure the source_module is indeed who they say they are - let registry = CONFIG - .load(deps.storage)? - .version_control - .query_module(source_module.clone(), &deps.querier)?; - - if registry.reference.unwrap_addr()? != info.sender { - return Err(IbcClientError::ForbiddenModuleCall {}); - } - - let callback_request = callback_info.map(|c| CallbackRequest { - receiver: env.contract.address.to_string(), - msg: to_json_binary(&IbcClientCallback::UserRemoteAction(c)).unwrap(), - }); - send_remote_host_module_action( - deps.as_ref(), - host_chain, - source_module.clone(), - target_module.clone(), - msg.clone(), - callback_request, - )? - - // If they are, we send a message to the module on the remote chain - } HostAction::Internal(_) => { // Can only call non-internal actions return Err(IbcClientError::ForbiddenInternalCall {}); @@ -330,6 +262,108 @@ pub fn execute_send_query( Ok(IbcClientResponse::action("handle_send_msgs").add_message(note_message)) } +/// Sends a packet with an optional callback. +/// This is the top-level function to do IBC related actions. +pub fn execute_send_module_to_module_packet( + deps: DepsMut, + env: Env, + info: MessageInfo, + host_chain: String, + source_module: InstalledModuleIdentification, + target_module: InstalledModuleIdentification, + msg: Binary, + callback_info: Option, +) -> IbcClientResult { + let host_chain = ChainName::from_str(&host_chain)?; + let cfg = CONFIG.load(deps.storage)?; + + // We make sure the source_module is indeed who they say they are + let registry = cfg + .version_control + .query_module(source_module.module_info.clone(), &deps.querier)?; + + match registry.reference { + ModuleReference::AccountBase(_) => return Err(IbcClientError::Unauthorized {}), + ModuleReference::Native(_) => return Err(IbcClientError::Unauthorized {}), + ModuleReference::Adapter(addr) => { + // For adapters, we just need to verify they have the right address + if addr != info.sender { + return Err(IbcClientError::ForbiddenModuleCall {}); + } + } + ModuleReference::App(code_id) | ModuleReference::Standalone(code_id) => { + // We verify the caller has indeed the right code id + let sender_code_id = deps + .querier + .query_wasm_contract_info(info.sender.clone())? + .code_id; + if code_id != sender_code_id { + return Err(IbcClientError::ForbiddenModuleCall {}); + } + // If it does have the right code id, we verify the specified account has the app installed + let account_base = cfg.version_control.account_base( + &source_module + .account_id + .clone() + .ok_or(IbcClientError::ForbiddenModuleCall {})?, + &deps.querier, + )?; + + let module_info: manager::ModuleAddressesResponse = deps.querier.query_wasm_smart( + account_base.manager, + &manager::QueryMsg::ModuleAddresses { + ids: vec![source_module.module_info.id()], + }, + )?; + ensure_eq!( + module_info.modules[0].1, + info.sender, + IbcClientError::ForbiddenModuleCall {} + ); + } + _ => unimplemented!( + "This module type didn't exist when implementing module-to-module interactions" + ), + } + + // We send a message to the target module on the remote chain + // Send this message via the Polytone implementation + + let callback_request = callback_info.map(|c| CallbackRequest { + receiver: env.contract.address.to_string(), + msg: to_json_binary(&IbcClientCallback::ModuleRemoteAction { + sender_module: source_module.clone(), + callback_info: c, + }) + .unwrap(), + }); + let ibc_infra = IBC_INFRA.load(deps.storage, &host_chain)?; + let note_contract = ibc_infra.polytone_note; + let remote_ibc_host = ibc_infra.remote_abstract_host; + + // message that will be called on the local note contract + let note_message = wasm_execute( + note_contract.to_string(), + &polytone_note::msg::ExecuteMsg::Execute { + msgs: vec![wasm_execute( + // The note's remote proxy will call the ibc host + remote_ibc_host, + &ibc_host::ExecuteMsg::ModuleExecute { + msg, + source_module, + target_module, + }, + vec![], + )? + .into()], + callback: callback_request, + timeout_seconds: PACKET_LIFETIME.into(), + }, + vec![], + )?; + Ok(IbcClientResponse::action("handle_send_module_to_module_packet").add_message(note_message)) +} + /// Registers an Abstract Account on a remote chain. pub fn execute_register_account( deps: DepsMut, diff --git a/framework/contracts/native/ibc-client/src/contract.rs b/framework/contracts/native/ibc-client/src/contract.rs index 3bfbcd7fb7..6a5dda9a57 100644 --- a/framework/contracts/native/ibc-client/src/contract.rs +++ b/framework/contracts/native/ibc-client/src/contract.rs @@ -97,6 +97,22 @@ pub fn execute(deps: DepsMut, env: Env, info: MessageInfo, msg: ExecuteMsg) -> I ExecuteMsg::Callback(c) => { ibc::receive_action_callback(deps, env, info, c).map_err(Into::into) } + ExecuteMsg::ModuleIbcAction { + host_chain, + source_module, + target_module, + msg, + callback_info, + } => commands::execute_send_module_to_module_packet( + deps, + env, + info, + host_chain, + source_module, + target_module, + msg, + callback_info, + ), } } diff --git a/framework/contracts/native/ibc-client/src/ibc.rs b/framework/contracts/native/ibc-client/src/ibc.rs index 4eb4e4f026..a2d947f42c 100644 --- a/framework/contracts/native/ibc-client/src/ibc.rs +++ b/framework/contracts/native/ibc-client/src/ibc.rs @@ -100,10 +100,10 @@ pub fn receive_action_callback( .add_attribute("chain", host_chain.to_string()) .add_attribute("callback_id", callback_info.id)) } - // TODO, find a better structure (should we separate module and user callbacks ?) IbcClientCallback::ModuleRemoteAction { callback_info, - target_module, + // TODO This will be used when the sender is part of the callback msg (https://github.com/AbstractSDK/abstract/pull/277) + sender_module, } => { let callback = IbcResponseMsg { id: callback_info.id.clone(), diff --git a/framework/contracts/native/ibc-host/src/endpoints/packet.rs b/framework/contracts/native/ibc-host/src/endpoints/packet.rs index 2fb0096f90..e9404aadd5 100644 --- a/framework/contracts/native/ibc-host/src/endpoints/packet.rs +++ b/framework/contracts/native/ibc-host/src/endpoints/packet.rs @@ -1,10 +1,14 @@ use abstract_core::{ ibc::ModuleIbcMsg, + ibc_client::InstalledModuleIdentification, ibc_host::{ state::{ActionAfterCreationCache, CONFIG, TEMP_ACTION_AFTER_CREATION}, HelperAction, }, - objects::{chain_name::ChainName, module::ModuleInfo, AccountId}, + manager, + objects::{ + chain_name::ChainName, module::ModuleInfo, module_reference::ModuleReference, AccountId, + }, }; use abstract_sdk::core::ibc_host::{HostAction, InternalAction}; use cosmwasm_std::{wasm_execute, Binary, DepsMut, Empty, Env, Response}; @@ -12,6 +16,7 @@ use cosmwasm_std::{wasm_execute, Binary, DepsMut, Empty, Env, Response}; use crate::{ account_commands::{self, receive_dispatch, receive_register, receive_send_all_back}, contract::HostResult, + HostError, }; use abstract_core::base::ExecuteMsg as MiddlewareExecMsg; @@ -114,17 +119,48 @@ pub fn handle_host_module_action( deps: DepsMut, env: Env, client_chain: ChainName, - source_module: ModuleInfo, - target_module: ModuleInfo, + source_module: InstalledModuleIdentification, + target_module: InstalledModuleIdentification, msg: Binary, ) -> HostResult { // We resolve the target module let vc = CONFIG.load(deps.storage)?.version_control; - let target_module_resolved = vc.query_module(target_module, &deps.querier)?; + let target_module_resolved = + vc.query_module(target_module.module_info.clone(), &deps.querier)?; + + let target_addr = match target_module_resolved.reference { + ModuleReference::AccountBase(_) => { + return Err(HostError::WrongModuleAction(target_module.module_info.id())) + } + ModuleReference::Native(_) => { + return Err(HostError::WrongModuleAction(target_module.module_info.id())) + } + ModuleReference::Adapter(addr) => addr, + ModuleReference::App(code_id) | ModuleReference::Standalone(code_id) => { + let account_base = vc.account_base( + &source_module + .account_id + .clone() + .ok_or(HostError::AccountIdNotSpecified {})?, + &deps.querier, + )?; + + let module_info: manager::ModuleAddressesResponse = deps.querier.query_wasm_smart( + account_base.manager, + &manager::QueryMsg::ModuleAddresses { + ids: vec![source_module.module_info.id()], + }, + )?; + module_info.modules[0].1.clone() + } + _ => unimplemented!( + "This module type didn't exist when implementing module-to-module interactions" + ), + }; // We pass the message on to the module let msg = wasm_execute( - target_module_resolved.reference.unwrap_addr()?, + target_addr, &MiddlewareExecMsg::ModuleIbc::(ModuleIbcMsg { client_chain, source_module, diff --git a/framework/contracts/native/ibc-host/src/error.rs b/framework/contracts/native/ibc-host/src/error.rs index 1192007c12..9047140e38 100644 --- a/framework/contracts/native/ibc-host/src/error.rs +++ b/framework/contracts/native/ibc-host/src/error.rs @@ -42,6 +42,14 @@ pub enum HostError { #[error("Chain or proxy address already registered.")] ProxyAddressExists {}, + + #[error("Can't send a module-to-module packet to {0}")] + WrongModuleAction(String), + + #[error( + "You need to specify an account id for an account-specific module (apps and standalone)" + )] + AccountIdNotSpecified {}, } impl From for HostError { diff --git a/framework/packages/abstract-core/src/native/ibc.rs b/framework/packages/abstract-core/src/native/ibc.rs index 86944ad52c..5e9409be53 100644 --- a/framework/packages/abstract-core/src/native/ibc.rs +++ b/framework/packages/abstract-core/src/native/ibc.rs @@ -5,6 +5,7 @@ use schemars::JsonSchema; use crate::{ base::ExecuteMsg, + ibc_client::InstalledModuleIdentification, objects::{chain_name::ChainName, module::ModuleInfo}, }; @@ -62,6 +63,6 @@ enum IbcCallbackMsg { #[cw_serde] pub struct ModuleIbcMsg { pub client_chain: ChainName, - pub source_module: ModuleInfo, + pub source_module: InstalledModuleIdentification, pub msg: Binary, } diff --git a/framework/packages/abstract-core/src/native/ibc_client.rs b/framework/packages/abstract-core/src/native/ibc_client.rs index 62eef7e41e..321bc45fc2 100644 --- a/framework/packages/abstract-core/src/native/ibc_client.rs +++ b/framework/packages/abstract-core/src/native/ibc_client.rs @@ -1,11 +1,11 @@ use cosmwasm_schema::QueryResponses; -use cosmwasm_std::{Addr, Coin, Empty, QueryRequest}; +use cosmwasm_std::{Addr, Binary, Coin, Empty, QueryRequest}; use polytone::callbacks::CallbackMessage; use self::state::IbcInfrastructure; use crate::{ ibc::CallbackInfo, - ibc_host::{HostAction, HostModuleAction}, + ibc_host::HostAction, manager::ModuleInstallConfig, objects::{account::AccountId, chain_name::ChainName, module::ModuleInfo, AssetEntry}, }; @@ -102,7 +102,9 @@ pub enum ExecuteMsg { }, ModuleIbcAction { host_chain: String, - action: HostModuleAction, + source_module: InstalledModuleIdentification, + target_module: InstalledModuleIdentification, + msg: Binary, callback_info: Option, }, RemoteAction { @@ -139,8 +141,8 @@ pub enum ExecuteMsg { pub enum IbcClientCallback { UserRemoteAction(CallbackInfo), ModuleRemoteAction { + sender_module: InstalledModuleIdentification, callback_info: CallbackInfo, - target_module: ModuleInfo, }, CreateAccount { account_id: AccountId, @@ -148,6 +150,15 @@ pub enum IbcClientCallback { WhoAmI {}, } +/// This is used for identifying calling modules +/// For adapters, we don't need the account id because it's independent of an account +/// For apps and standalone, the account id is used to identify the calling module +#[cosmwasm_schema::cw_serde] +pub struct InstalledModuleIdentification { + pub module_info: ModuleInfo, + pub account_id: Option, +} + #[cosmwasm_schema::cw_serde] #[cfg_attr(feature = "interface", derive(cw_orch::QueryFns))] #[derive(QueryResponses)] diff --git a/framework/packages/abstract-core/src/native/ibc_host.rs b/framework/packages/abstract-core/src/native/ibc_host.rs index cae98d70fc..98f48a9c06 100644 --- a/framework/packages/abstract-core/src/native/ibc_host.rs +++ b/framework/packages/abstract-core/src/native/ibc_host.rs @@ -11,6 +11,7 @@ use cosmwasm_schema::QueryResponses; use cosmwasm_std::{Addr, Binary}; use crate::{ + ibc_client::InstalledModuleIdentification, manager::{self, ModuleInstallConfig}, objects::{account::AccountId, chain_name::ChainName, module::ModuleInfo, AssetEntry}, }; @@ -97,14 +98,6 @@ pub enum HostAction { Helpers(HelperAction), } -/// Executes an action on the module with the corresponding module id on another chain -#[cosmwasm_schema::cw_serde] -pub struct HostModuleAction { - source_module: ModuleInfo, - target_module: ModuleInfo, - msg: Binary, -} - /// Interface to the Host. #[cosmwasm_schema::cw_serde] #[cfg_attr(feature = "interface", derive(cw_orch::ExecuteFns))] @@ -136,8 +129,8 @@ pub enum ExecuteMsg { }, /// Allows for remote execution from the Polytone implementation on a local module ModuleExecute { - source_module: ModuleInfo, - target_module: ModuleInfo, + source_module: InstalledModuleIdentification, + target_module: InstalledModuleIdentification, msg: Binary, }, } From 883a09a203d83d6767e82c48049ac51dc2a1f232 Mon Sep 17 00:00:00 2001 From: Kayanski Date: Thu, 7 Mar 2024 08:46:11 +0000 Subject: [PATCH 06/37] Added test --- framework/packages/abstract-app/src/lib.rs | 19 ++- interchain/tests/src/interchain_accounts.rs | 137 ++++++++++++++++++++ 2 files changed, 153 insertions(+), 3 deletions(-) diff --git a/framework/packages/abstract-app/src/lib.rs b/framework/packages/abstract-app/src/lib.rs index 9187de57c7..7fa6996a50 100644 --- a/framework/packages/abstract-app/src/lib.rs +++ b/framework/packages/abstract-app/src/lib.rs @@ -33,7 +33,7 @@ pub mod mock { pub use abstract_core::app; use abstract_core::{ manager::ModuleInstallConfig, - objects::{dependency::StaticDependency, module::ModuleInfo}, + objects::{dependency::StaticDependency, module::ModuleInfo, AccountId}, }; use abstract_interface::{AppDeployer, DependencyCreation}; use cosmwasm_schema::QueryResponses; @@ -41,7 +41,7 @@ pub mod mock { use cosmwasm_std::{to_json_binary, Response, StdError}; use cw_controllers::AdminError; use cw_orch::prelude::*; - use cw_storage_plus::Item; + use cw_storage_plus::{Item, Map}; pub type AppTestResult = Result<(), MockError>; @@ -68,6 +68,9 @@ pub mod mock { #[returns(ReceivedIbcCallbackStatus)] GetReceivedIbcCallbackStatus {}, + + #[returns(ReceivedIbcCallbackStatus)] + GetReceivedIbcCallbackSenderStatus { sender: AccountId }, } #[cosmwasm_schema::cw_serde] @@ -134,6 +137,7 @@ pub mod mock { // Easy way to see if an ibc-callback was actually received. pub const IBC_CALLBACK_RECEIVED: Item = Item::new("ibc_callback_received"); + pub const IBC_CALLBACK_SENDER: Map = Map::new("ibc_callback_sender"); pub const MOCK_APP_WITH_DEP: MockAppContract = MockAppContract::new(TEST_WITH_DEP_MODULE_ID, TEST_VERSION, None) @@ -152,11 +156,20 @@ pub mod mock { }) .map_err(Into::into) } + MockQueryMsg::GetReceivedIbcCallbackSenderStatus { sender } => { + to_json_binary(&ReceivedIbcCallbackStatus { + received: IBC_CALLBACK_SENDER.load(deps.storage, sender)?, + }) + .map_err(Into::into) + } }) .with_sudo(|_, _, _, _| Ok(Response::new().set_data("mock_sudo".as_bytes()))) .with_receive(|_, _, _, _, _| Ok(Response::new().set_data("mock_receive".as_bytes()))) - .with_ibc_callbacks(&[("c_id", |deps, _, _, _, _, _, _| { + .with_ibc_callbacks(&[("c_id", |deps, _, _, _, sender, _, _| { IBC_CALLBACK_RECEIVED.save(deps.storage, &true).unwrap(); + IBC_CALLBACK_SENDER + .save(deps.storage, sender, &true) + .unwrap(); Ok(Response::new().add_attribute("mock_callback", "executed")) })]) .with_dependencies(&[StaticDependency::new(TEST_MODULE_ID, &[TEST_VERSION])]) diff --git a/interchain/tests/src/interchain_accounts.rs b/interchain/tests/src/interchain_accounts.rs index 64e032d983..7b8b9b6095 100644 --- a/interchain/tests/src/interchain_accounts.rs +++ b/interchain/tests/src/interchain_accounts.rs @@ -278,6 +278,129 @@ mod test { Ok(()) } + #[test] + fn anyone_can_call_account_ibc_app_callback() -> AnyResult<()> { + logger_test_init(); + let mock_interchain = + MockBech32InterchainEnv::new(vec![(JUNO, "juno"), (STARGAZE, "stargaze")]); + + // We just verified all steps pass + let (abstr_origin, _abstr_remote) = ibc_abstract_setup(&mock_interchain, JUNO, STARGAZE)?; + + let remote_name = ChainName::from_chain_id(STARGAZE).to_string(); + + let (origin_account, _remote_account_id) = + create_test_remote_account(&abstr_origin, JUNO, STARGAZE, &mock_interchain, None)?; + + let app = MockAppWithDepI::new( + TEST_WITH_DEP_MODULE_ID, + abstr_origin.version_control.get_chain().clone(), + ); + + let app_dep = MockAppI::new( + TEST_MODULE_ID, + abstr_origin.version_control.get_chain().clone(), + ); + + let app_account = + abstr_origin + .account_factory + .create_default_account(GovernanceDetails::Monarchy { + monarch: abstr_origin + .version_control + .get_chain() + .sender() + .into_string(), + })?; + + let app_deps_account = + abstr_origin + .account_factory + .create_default_account(GovernanceDetails::Monarchy { + monarch: abstr_origin + .version_control + .get_chain() + .sender() + .into_string(), + })?; + + abstr_origin.version_control.claim_namespace( + app_account.manager.config()?.account_id, + TEST_WITH_DEP_NAMESPACE.to_owned(), + )?; + abstr_origin.version_control.claim_namespace( + app_deps_account.manager.config()?.account_id, + TEST_NAMESPACE.to_owned(), + )?; + + app.deploy(TEST_VERSION.parse()?, DeployStrategy::Try)?; + app_dep.deploy(TEST_VERSION.parse()?, DeployStrategy::Try)?; + + origin_account.install_app(&app_dep, &MockInitMsg {}, None)?; + origin_account.install_app(&app, &MockInitMsg {}, None)?; + let res: ModuleAddressesResponse = origin_account + .manager + .module_addresses(vec![TEST_WITH_DEP_MODULE_ID.to_owned()])?; + + assert_eq!(1, res.modules.len()); + + let module_address = res.modules[0].1.to_string(); + + let new_name = "Funky Crazy Name"; + let new_description = "Funky new account with wonderful capabilities"; + let new_link = "https://abstract.money"; + + // The user on origin chain wants to change the account description + let ibc_action_result = origin_account.manager.execute_on_remote( + &remote_name, + ManagerExecuteMsg::UpdateInfo { + name: Some(new_name.to_string()), + description: Some(new_description.to_string()), + link: Some(new_link.to_string()), + }, + Some(CallbackInfo { + id: String::from("c_id"), + msg: None, + receiver: module_address.clone(), + }), + )?; + + assert_callback_status(&app, false)?; + assert_callback_sender(&app, origin_account.id()?, false)?; + + mock_interchain.wait_ibc(JUNO, ibc_action_result)?; + + // Switched to true by the callback. + assert_callback_status(&app, true)?; + assert_callback_sender(&app, origin_account.id()?, true)?; + + // A new account sends an action with a callback on another account user on origin chain wants to change the account description + let (new_account, _) = + create_test_remote_account(&abstr_origin, JUNO, STARGAZE, &mock_interchain, None)?; + let ibc_action_result = new_account.manager.execute_on_remote( + &remote_name, + ManagerExecuteMsg::UpdateInfo { + name: Some(new_name.to_string()), + description: Some(new_description.to_string()), + link: Some(new_link.to_string()), + }, + Some(CallbackInfo { + id: String::from("c_id"), + msg: None, + receiver: module_address, + }), + )?; + + assert_callback_sender(&app, new_account.id()?, false)?; + + mock_interchain.wait_ibc(JUNO, ibc_action_result)?; + + // Switched to true by the callback. + assert_callback_sender(&app, new_account.id()?, true)?; + + Ok(()) + } + #[test] fn ibc_adapter_callback() -> AnyResult<()> { logger_test_init(); @@ -368,6 +491,20 @@ mod test { Ok(()) } + fn assert_callback_sender( + app: &MockAppWithDepI, + account_id: AccountId, + status: bool, + ) -> AnyResult<()> { + let get_received_ibc_callback_status_res = app + .get_received_ibc_callback_sender_status(account_id) + .map(|r| r.received) + .unwrap_or(false); + + assert_eq!(status, get_received_ibc_callback_status_res); + Ok(()) + } + fn assert_adapter_callback_status( app: &MockAdapterI, status: bool, From 151566563cbd71904f4a0da0d033d9f2ec739307 Mon Sep 17 00:00:00 2001 From: Kayanski Date: Thu, 7 Mar 2024 10:45:05 +0000 Subject: [PATCH 07/37] Module-to-module works --- .../native/ibc-host/src/endpoints/packet.rs | 30 +- .../contracts/native/ibc-host/src/error.rs | 8 +- .../src/endpoints/ibc_callback.rs | 16 +- .../src/endpoints/module_ibc.rs | 16 +- .../src/endpoints/ibc_callback.rs | 4 +- .../abstract-app/src/endpoints/module_ibc.rs | 23 +- framework/packages/abstract-app/src/lib.rs | 37 +- .../packages/abstract-core/src/native/ibc.rs | 4 +- .../abstract-core/src/native/ibc_host.rs | 2 +- .../abstract-interface/src/deployment.rs | 4 + .../src/base/endpoints/ibc_callback.rs | 2 +- .../src/base/endpoints/modules_ibc.rs | 2 +- interchain/tests/Cargo.toml | 1 + interchain/tests/src/lib.rs | 1 + .../src/module_to_module_interactions.rs | 600 ++++++++++++++++++ interchain/tests/src/setup.rs | 22 +- 16 files changed, 684 insertions(+), 88 deletions(-) create mode 100644 interchain/tests/src/module_to_module_interactions.rs diff --git a/framework/contracts/native/ibc-host/src/endpoints/packet.rs b/framework/contracts/native/ibc-host/src/endpoints/packet.rs index e9404aadd5..3597278922 100644 --- a/framework/contracts/native/ibc-host/src/endpoints/packet.rs +++ b/framework/contracts/native/ibc-host/src/endpoints/packet.rs @@ -6,9 +6,7 @@ use abstract_core::{ HelperAction, }, manager, - objects::{ - chain_name::ChainName, module::ModuleInfo, module_reference::ModuleReference, AccountId, - }, + objects::{chain_name::ChainName, module_reference::ModuleReference, AccountId}, }; use abstract_sdk::core::ibc_host::{HostAction, InternalAction}; use cosmwasm_std::{wasm_execute, Binary, DepsMut, Empty, Env, Response}; @@ -136,22 +134,28 @@ pub fn handle_host_module_action( return Err(HostError::WrongModuleAction(target_module.module_info.id())) } ModuleReference::Adapter(addr) => addr, - ModuleReference::App(code_id) | ModuleReference::Standalone(code_id) => { - let account_base = vc.account_base( - &source_module - .account_id - .clone() - .ok_or(HostError::AccountIdNotSpecified {})?, - &deps.querier, - )?; + ModuleReference::App(_) | ModuleReference::Standalone(_) => { + let target_account_id = target_module + .account_id + .clone() + .ok_or(HostError::AccountIdNotSpecified {})?; + let account_base = vc.account_base(&target_account_id, &deps.querier)?; let module_info: manager::ModuleAddressesResponse = deps.querier.query_wasm_smart( account_base.manager, &manager::QueryMsg::ModuleAddresses { - ids: vec![source_module.module_info.id()], + ids: vec![target_module.module_info.id()], }, )?; - module_info.modules[0].1.clone() + module_info + .modules + .first() + .ok_or(HostError::MissingModule { + module_info: target_module.module_info.to_string(), + account_id: target_account_id, + })? + .1 + .clone() } _ => unimplemented!( "This module type didn't exist when implementing module-to-module interactions" diff --git a/framework/contracts/native/ibc-host/src/error.rs b/framework/contracts/native/ibc-host/src/error.rs index c2a317ce04..26c780cabc 100644 --- a/framework/contracts/native/ibc-host/src/error.rs +++ b/framework/contracts/native/ibc-host/src/error.rs @@ -1,5 +1,5 @@ use abstract_core::{ - objects::{ans_host::AnsHostError, version_control::VersionControlError}, + objects::{ans_host::AnsHostError, version_control::VersionControlError, AccountId}, AbstractError, }; use abstract_sdk::AbstractSdkError; @@ -46,6 +46,12 @@ pub enum HostError { #[error("Can't send a module-to-module packet to {0}")] WrongModuleAction(String), + #[error("Missing module {module_info} on account {account_id}")] + MissingModule { + module_info: String, + account_id: AccountId, + }, + #[error( "You need to specify an account id for an account-specific module (apps and standalone)" )] diff --git a/framework/packages/abstract-adapter/src/endpoints/ibc_callback.rs b/framework/packages/abstract-adapter/src/endpoints/ibc_callback.rs index d8e3dd234b..7259e43491 100644 --- a/framework/packages/abstract-adapter/src/endpoints/ibc_callback.rs +++ b/framework/packages/abstract-adapter/src/endpoints/ibc_callback.rs @@ -8,25 +8,15 @@ impl { - fn ibc_client(&self, deps: Deps) -> Result { + fn ibc_client(&self, deps: Deps) -> Result { let vc_query_result = self .abstract_registry(deps)? - .query_module( - ModuleInfo::from_id_latest(IBC_CLIENT).map_err(|err| { - let err: AbstractSdkError = err.into(); - err - })?, - &deps.querier, - ) + .query_module(ModuleInfo::from_id_latest(IBC_CLIENT)?, &deps.querier) .map_err(|err| { let err: AbstractError = err.into(); - let err: AbstractSdkError = err.into(); err })?; - Ok(vc_query_result.reference.unwrap_native().map_err(|err| { - let err: AbstractSdkError = err.into(); - err - })?) + Ok(vc_query_result.reference.unwrap_native()?) } } diff --git a/framework/packages/abstract-adapter/src/endpoints/module_ibc.rs b/framework/packages/abstract-adapter/src/endpoints/module_ibc.rs index ccb174e90c..552820f092 100644 --- a/framework/packages/abstract-adapter/src/endpoints/module_ibc.rs +++ b/framework/packages/abstract-adapter/src/endpoints/module_ibc.rs @@ -9,25 +9,15 @@ impl { - fn ibc_host(&self, deps: cosmwasm_std::Deps) -> Result { + fn ibc_host(&self, deps: cosmwasm_std::Deps) -> Result { let vc_query_result = self .abstract_registry(deps)? - .query_module( - ModuleInfo::from_id_latest(IBC_HOST).map_err(|err| { - let err: AbstractSdkError = err.into(); - err - })?, - &deps.querier, - ) + .query_module(ModuleInfo::from_id_latest(IBC_HOST)?, &deps.querier) .map_err(|err| { let err: AbstractError = err.into(); - let err: AbstractSdkError = err.into(); err })?; - Ok(vc_query_result.reference.unwrap_native().map_err(|err| { - let err: AbstractSdkError = err.into(); - err - })?) + Ok(vc_query_result.reference.unwrap_native()?) } } diff --git a/framework/packages/abstract-app/src/endpoints/ibc_callback.rs b/framework/packages/abstract-app/src/endpoints/ibc_callback.rs index 73c435cb05..52d0a1784f 100644 --- a/framework/packages/abstract-app/src/endpoints/ibc_callback.rs +++ b/framework/packages/abstract-app/src/endpoints/ibc_callback.rs @@ -1,5 +1,5 @@ use abstract_core::IBC_CLIENT; -use abstract_sdk::ModuleInterface; +use abstract_sdk::{AbstractSdkError, ModuleInterface}; use cosmwasm_std::Addr; use crate::{state::ContractError, AppContract, IbcCallbackEndpoint}; @@ -23,7 +23,7 @@ impl< SudoMsg, > { - fn ibc_client(&self, deps: cosmwasm_std::Deps) -> Result { + fn ibc_client(&self, deps: cosmwasm_std::Deps) -> Result { let ibc_client = self.modules(deps).module_address(IBC_CLIENT)?; Ok(ibc_client) } diff --git a/framework/packages/abstract-app/src/endpoints/module_ibc.rs b/framework/packages/abstract-app/src/endpoints/module_ibc.rs index e7456122b7..f35c84c23d 100644 --- a/framework/packages/abstract-app/src/endpoints/module_ibc.rs +++ b/framework/packages/abstract-app/src/endpoints/module_ibc.rs @@ -1,5 +1,6 @@ -use abstract_core::IBC_HOST; -use abstract_sdk::{base::ModuleIbcEndpoint, ModuleInterface}; +use abstract_core::{objects::module::ModuleInfo, AbstractError, IBC_HOST}; +use abstract_sdk::{base::ModuleIbcEndpoint, features::AbstractRegistryAccess, AbstractSdkError}; +use cosmwasm_std::Addr; use crate::{state::ContractError, AppContract}; @@ -22,8 +23,20 @@ impl< SudoMsg, > { - fn ibc_host(&self, deps: cosmwasm_std::Deps) -> Result { - let ibc_client = self.modules(deps).module_address(IBC_HOST)?; - Ok(ibc_client) + // This can't be used because accounts don't install the ibc_host on their accounts so this is never available + // fn ibc_host(&self, deps: cosmwasm_std::Deps) -> Result { + // let ibc_client = self.modules(deps).module_address(IBC_HOST)?; + // Ok(ibc_client) + // } + fn ibc_host(&self, deps: cosmwasm_std::Deps) -> Result { + let vc_query_result = self + .abstract_registry(deps)? + .query_module(ModuleInfo::from_id_latest(IBC_HOST)?, &deps.querier) + .map_err(|err| { + let err: AbstractError = err.into(); + err + })?; + + Ok(vc_query_result.reference.unwrap_native()?) } } diff --git a/framework/packages/abstract-app/src/lib.rs b/framework/packages/abstract-app/src/lib.rs index 1098dbd17e..9187de57c7 100644 --- a/framework/packages/abstract-app/src/lib.rs +++ b/framework/packages/abstract-app/src/lib.rs @@ -32,16 +32,13 @@ pub use abstract_testing; pub mod mock { pub use abstract_core::app; use abstract_core::{ - ibc::ModuleIbcMsg, - ibc_client, manager::ModuleInstallConfig, objects::{dependency::StaticDependency, module::ModuleInfo}, - IBC_CLIENT, }; use abstract_interface::{AppDeployer, DependencyCreation}; use cosmwasm_schema::QueryResponses; pub use cosmwasm_std::testing::{mock_dependencies, mock_env, mock_info}; - use cosmwasm_std::{to_json_binary, wasm_execute, Response, StdError}; + use cosmwasm_std::{to_json_binary, Response, StdError}; use cw_controllers::AdminError; use cw_orch::prelude::*; use cw_storage_plus::Item; @@ -59,7 +56,6 @@ pub mod mock { pub enum MockExecMsg { DoSomething {}, DoSomethingAdmin {}, - DoSomethingIbc { remote_chain: ChainName }, } #[cosmwasm_schema::cw_serde] @@ -91,7 +87,7 @@ pub mod mock { #[cosmwasm_schema::cw_serde] pub struct MockSudoMsg; - use abstract_sdk::{base::InstantiateEndpoint, AbstractSdkError, ModuleInterface}; + use abstract_sdk::{base::InstantiateEndpoint, AbstractSdkError}; use abstract_testing::{ addresses::{test_account_base, TEST_ANS_HOST, TEST_VERSION_CONTROL}, prelude::{ @@ -138,8 +134,6 @@ pub mod mock { // Easy way to see if an ibc-callback was actually received. pub const IBC_CALLBACK_RECEIVED: Item = Item::new("ibc_callback_received"); - // Easy way to see if an module ibc called was actually received. - pub const MODULE_IBC_RECEIVED: Item = Item::new("module_ibc_received"); pub const MOCK_APP_WITH_DEP: MockAppContract = MockAppContract::new(TEST_WITH_DEP_MODULE_ID, TEST_VERSION, None) @@ -147,24 +141,7 @@ pub mod mock { IBC_CALLBACK_RECEIVED.save(deps.storage, &false)?; Ok(Response::new().set_data("mock_init".as_bytes())) }) - .with_execute(|deps, _, _, app, msg| match msg { - MockExecMsg::DoSomethingIbc { remote_chain } => { - let ibc_client_addr = app.modules(deps.as_ref()).module_address(IBC_CLIENT)?; - // We send an IBC Client module message - let msg = wasm_execute( - ibc_client_addr, - &ibc_client::ExecuteMsg::RemoteAction { - host_chain: remote_chain, - action: (), - callback_info: (), - }, - vec![], - )?; - - Ok(Response::new().add_message(msg)) - } - _ => Ok(Response::new().set_data("mock_exec".as_bytes())), - }) + .with_execute(|_, _, _, _, _| Ok(Response::new().set_data("mock_exec".as_bytes()))) .with_query(|deps, _, _, msg| match msg { MockQueryMsg::GetSomething {} => { to_json_binary(&MockQueryResponse {}).map_err(Into::into) @@ -186,13 +163,7 @@ pub mod mock { .with_replies(&[(1u64, |_, _, _, msg| { Ok(Response::new().set_data(msg.result.unwrap().data.unwrap())) })]) - .with_migrate(|_, _, _, _| Ok(Response::new().set_data("mock_migrate".as_bytes()))) - .with_module_ibc(|deps, _, _, msg| { - let ModuleIbcMsg { source_module, .. } = msg; - // We save the module info status - MODULE_IBC_RECEIVED.save(deps.storage, &source_module)?; - Ok(Response::new()) - }); + .with_migrate(|_, _, _, _| Ok(Response::new().set_data("mock_migrate".as_bytes()))); crate::cw_orch_interface!(MOCK_APP_WITH_DEP, MockAppContract, MockAppWithDepI); diff --git a/framework/packages/abstract-core/src/native/ibc.rs b/framework/packages/abstract-core/src/native/ibc.rs index 5e9409be53..977c405386 100644 --- a/framework/packages/abstract-core/src/native/ibc.rs +++ b/framework/packages/abstract-core/src/native/ibc.rs @@ -4,9 +4,7 @@ use polytone::callbacks::Callback; use schemars::JsonSchema; use crate::{ - base::ExecuteMsg, - ibc_client::InstalledModuleIdentification, - objects::{chain_name::ChainName, module::ModuleInfo}, + base::ExecuteMsg, ibc_client::InstalledModuleIdentification, objects::chain_name::ChainName, }; // CallbackInfo from modules, that is turned into an IbcResponseMsg by the ibc client diff --git a/framework/packages/abstract-core/src/native/ibc_host.rs b/framework/packages/abstract-core/src/native/ibc_host.rs index 98f48a9c06..5c0cb0c540 100644 --- a/framework/packages/abstract-core/src/native/ibc_host.rs +++ b/framework/packages/abstract-core/src/native/ibc_host.rs @@ -13,7 +13,7 @@ use cosmwasm_std::{Addr, Binary}; use crate::{ ibc_client::InstalledModuleIdentification, manager::{self, ModuleInstallConfig}, - objects::{account::AccountId, chain_name::ChainName, module::ModuleInfo, AssetEntry}, + objects::{account::AccountId, chain_name::ChainName, AssetEntry}, }; pub mod state { diff --git a/framework/packages/abstract-interface/src/deployment.rs b/framework/packages/abstract-interface/src/deployment.rs index 07d32e229e..9ed5987036 100644 --- a/framework/packages/abstract-interface/src/deployment.rs +++ b/framework/packages/abstract-interface/src/deployment.rs @@ -256,6 +256,10 @@ impl Abstract { self.ibc.client.as_instance(), ibc_client::contract::CONTRACT_VERSION.to_string(), ), + ( + self.ibc.host.as_instance(), + ibc_host::contract::CONTRACT_VERSION.to_string(), + ), ] } } diff --git a/framework/packages/abstract-sdk/src/base/endpoints/ibc_callback.rs b/framework/packages/abstract-sdk/src/base/endpoints/ibc_callback.rs index f4a50cd77c..b4fddc41bd 100644 --- a/framework/packages/abstract-sdk/src/base/endpoints/ibc_callback.rs +++ b/framework/packages/abstract-sdk/src/base/endpoints/ibc_callback.rs @@ -5,7 +5,7 @@ use cosmwasm_std::{Addr, Deps, DepsMut, Env, MessageInfo, Response}; /// Trait for a contract's IBC callback ExecuteMsg variant. pub trait IbcCallbackEndpoint: Handler { /// Queries the IBC Client address. - fn ibc_client(&self, deps: Deps) -> Result; + fn ibc_client(&self, deps: Deps) -> Result; /// Handler for the `ExecuteMsg::IbcCallback()` variant. fn ibc_callback( diff --git a/framework/packages/abstract-sdk/src/base/endpoints/modules_ibc.rs b/framework/packages/abstract-sdk/src/base/endpoints/modules_ibc.rs index f498b13749..a1457dd513 100644 --- a/framework/packages/abstract-sdk/src/base/endpoints/modules_ibc.rs +++ b/framework/packages/abstract-sdk/src/base/endpoints/modules_ibc.rs @@ -6,7 +6,7 @@ use crate::{base::Handler, AbstractSdkError}; /// Trait for a contract to call itself on an IBC counterpart. pub trait ModuleIbcEndpoint: Handler { /// Get the address of the ibc host associated with this module - fn ibc_host(&self, deps: Deps) -> Result; + fn ibc_host(&self, deps: Deps) -> Result; /// Handler for the `ExecuteMsg::IbcCallback()` variant. fn module_ibc( diff --git a/interchain/tests/Cargo.toml b/interchain/tests/Cargo.toml index 020f393b9c..c43ab2961f 100644 --- a/interchain/tests/Cargo.toml +++ b/interchain/tests/Cargo.toml @@ -58,3 +58,4 @@ abstract-scripts = { path = "../scripts" } abstract-integration-tests = { path = "../../framework/packages/abstract-integration-tests" } lazy_static = "1.4.0" abstract-client = { version = "0.21.0", path = "../../framework/packages/abstract-client" } +cw-storage-plus = "1.2.0" diff --git a/interchain/tests/src/lib.rs b/interchain/tests/src/lib.rs index 9994ab2e65..422932fae5 100644 --- a/interchain/tests/src/lib.rs +++ b/interchain/tests/src/lib.rs @@ -3,6 +3,7 @@ pub const STARGAZE: &str = "stargaze-1"; pub const OSMOSIS: &str = "osmosis-1"; pub mod interchain_accounts; +pub mod module_to_module_interactions; pub mod setup; #[cfg(test)] diff --git a/interchain/tests/src/module_to_module_interactions.rs b/interchain/tests/src/module_to_module_interactions.rs new file mode 100644 index 0000000000..ead7423364 --- /dev/null +++ b/interchain/tests/src/module_to_module_interactions.rs @@ -0,0 +1,600 @@ +pub use abstract_core::app; +use abstract_core::{ + ibc::{CallbackInfo, ModuleIbcMsg}, + ibc_client::{self, InstalledModuleIdentification}, + manager::ModuleInstallConfig, + objects::{dependency::StaticDependency, module::ModuleInfo}, + IBC_CLIENT, +}; +use abstract_interface::{AppDeployer, DependencyCreation}; +use cosmwasm_schema::{cw_serde, QueryResponses}; +pub use cosmwasm_std::testing::{mock_dependencies, mock_env, mock_info}; +use cosmwasm_std::{to_json_binary, wasm_execute, Response, StdError}; +use cw_controllers::AdminError; +use cw_orch::prelude::*; +use cw_storage_plus::Item; + +pub type AppTestResult = Result<(), MockError>; + +abstract_app::app_msg_types!(MockAppContract, MockExecMsg, MockQueryMsg); + +#[cosmwasm_schema::cw_serde] +pub struct MockInitMsg {} + +#[cosmwasm_schema::cw_serde] +#[derive(cw_orch::ExecuteFns)] +#[impl_into(ExecuteMsg)] +pub enum MockExecMsg { + DoSomething {}, + DoSomethingAdmin {}, + DoSomethingIbc { + remote_chain: String, + target_module: InstalledModuleIdentification, + }, +} + +#[cosmwasm_schema::cw_serde] +#[derive(cw_orch::QueryFns)] +#[impl_into(QueryMsg)] +#[derive(QueryResponses)] +pub enum MockQueryMsg { + #[returns(ReceivedIbcCallbackStatus)] + GetReceivedIbcCallbackStatus {}, + + #[returns(ReceivedIbcModuleStatus)] + GetReceivedIbcModuleStatus {}, +} + +#[cosmwasm_schema::cw_serde] +pub struct ReceivedIbcCallbackStatus { + pub received: bool, +} + +#[cosmwasm_schema::cw_serde] +pub struct ReceivedIbcModuleStatus { + pub received: InstalledModuleIdentification, +} + +#[cosmwasm_schema::cw_serde] +pub struct MockMigrateMsg; + +#[cosmwasm_schema::cw_serde] +pub struct MockReceiveMsg; + +#[cosmwasm_schema::cw_serde] +pub struct MockSudoMsg; + +use abstract_sdk::{ + base::InstantiateEndpoint, features::AccountIdentification, AbstractSdkError, ModuleInterface, +}; +use abstract_testing::{ + addresses::{test_account_base, TEST_ANS_HOST, TEST_VERSION_CONTROL}, + prelude::{ + MockDeps, MockQuerierBuilder, TEST_MODULE_FACTORY, TEST_MODULE_ID, TEST_VERSION, + TEST_WITH_DEP_MODULE_ID, + }, +}; +use thiserror::Error; + +use abstract_app::{AppContract, AppError}; + +#[derive(Error, Debug, PartialEq)] +pub enum MockError { + #[error("{0}")] + Std(#[from] StdError), + + #[error("{0}")] + DappError(#[from] AppError), + + #[error("{0}")] + Abstract(#[from] abstract_core::AbstractError), + + #[error("{0}")] + AbstractSdk(#[from] AbstractSdkError), + + #[error("{0}")] + Admin(#[from] AdminError), +} + +pub type MockAppContract = AppContract< + // MockModule, + MockError, + MockInitMsg, + MockExecMsg, + MockQueryMsg, + MockMigrateMsg, + MockReceiveMsg, + MockSudoMsg, +>; + +#[cw_serde] +pub struct IbcModuleToModuleMsg { + ibc_msg: String, +} + +// Easy way to see if an ibc-callback was actually received. +pub const IBC_CALLBACK_RECEIVED: Item = Item::new("ibc_callback_received"); +// Easy way to see if an module ibc called was actually received. +pub const MODULE_IBC_RECEIVED: Item = + Item::new("module_ibc_received"); + +pub const fn mock_app(id: &'static str, version: &'static str) -> MockAppContract { + MockAppContract::new(id, version, None) + .with_instantiate(|deps, _, _, _, _| { + IBC_CALLBACK_RECEIVED.save(deps.storage, &false)?; + Ok(Response::new().set_data("mock_init".as_bytes())) + }) + .with_execute(|deps, env, _, app, msg| match msg { + MockExecMsg::DoSomethingIbc { + remote_chain, + target_module, + } => { + let ibc_client_addr = app.modules(deps.as_ref()).module_address(IBC_CLIENT)?; + // We send an IBC Client module message + let msg = wasm_execute( + ibc_client_addr, + &ibc_client::ExecuteMsg::ModuleIbcAction { + host_chain: remote_chain, + source_module: InstalledModuleIdentification { + module_info: ModuleInfo::from_id(app.module_id(), app.version().into()) + .unwrap(), + account_id: Some(app.account_id(deps.as_ref())?), + }, + target_module, + msg: to_json_binary(&IbcModuleToModuleMsg { + ibc_msg: "module_to_module:msg".to_string(), + }) + .unwrap(), + callback_info: Some(CallbackInfo { + id: "c_id".to_string(), + msg: None, + receiver: env.contract.address.to_string(), + }), + }, + vec![], + )?; + + Ok(Response::new().add_message(msg)) + } + _ => Ok(Response::new().set_data("mock_exec".as_bytes())), + }) + .with_query(|deps, _, _, msg| match msg { + MockQueryMsg::GetReceivedIbcCallbackStatus {} => { + to_json_binary(&ReceivedIbcCallbackStatus { + received: IBC_CALLBACK_RECEIVED.load(deps.storage)?, + }) + .map_err(Into::into) + } + MockQueryMsg::GetReceivedIbcModuleStatus {} => { + to_json_binary(&ReceivedIbcModuleStatus { + received: MODULE_IBC_RECEIVED.load(deps.storage)?, + }) + .map_err(Into::into) + } + }) + .with_sudo(|_, _, _, _| Ok(Response::new().set_data("mock_sudo".as_bytes()))) + .with_receive(|_, _, _, _, _| Ok(Response::new().set_data("mock_receive".as_bytes()))) + .with_ibc_callbacks(&[("c_id", |deps, _, _, _, _, _, _| { + IBC_CALLBACK_RECEIVED.save(deps.storage, &true).unwrap(); + Ok(Response::new().add_attribute("mock_callback", "executed")) + })]) + .with_replies(&[(1u64, |_, _, _, msg| { + Ok(Response::new().set_data(msg.result.unwrap().data.unwrap())) + })]) + .with_migrate(|_, _, _, _| Ok(Response::new().set_data("mock_migrate".as_bytes()))) + .with_module_ibc(|deps, _, _, msg| { + let ModuleIbcMsg { source_module, .. } = msg; + // We save the module info status + MODULE_IBC_RECEIVED.save(deps.storage, &source_module)?; + Ok(Response::new()) + }) +} + +pub mod origin_app { + use abstract_testing::addresses::{TEST_MODULE_ID, TEST_VERSION}; + + use super::{mock_app, MockAppContract}; + pub const MOCK_APP_ORIGIN: MockAppContract = mock_app(TEST_MODULE_ID, TEST_VERSION); + abstract_app::cw_orch_interface!(MOCK_APP_ORIGIN, MockAppContract, MockAppOriginI); +} + +pub mod remote_app { + use super::{mock_app, MockAppContract}; + + pub const TEST_MODULE_ID_REMOTE: &str = "tester:test-module-id-remote"; + pub const TEST_VERSION_REMOTE: &str = "0.45.7"; + pub const MOCK_APP_REMOTE: MockAppContract = + mock_app(TEST_MODULE_ID_REMOTE, TEST_VERSION_REMOTE); + abstract_app::cw_orch_interface!(MOCK_APP_REMOTE, MockAppContract, MockAppRemoteI); +} + +#[cfg(test)] +pub mod test { + + fn assert_remote_module_call_status( + app: &MockAppRemoteI, + source_module_expected: Option, + ) -> AnyResult<()> { + let source_module = app + .get_received_ibc_module_status() + .map(|s| s.received) + .ok(); + + assert_eq!(source_module, source_module_expected); + Ok(()) + } + + fn assert_callback_status(app: &MockAppOriginI, status: bool) -> AnyResult<()> { + let get_received_ibc_callback_status_res: ReceivedIbcCallbackStatus = + app.get_received_ibc_callback_status()?; + + assert_eq!( + ReceivedIbcCallbackStatus { received: status }, + get_received_ibc_callback_status_res + ); + Ok(()) + } + use crate::{ + interchain_accounts::create_test_remote_account, + module_to_module_interactions::{ + origin_app::interface::MockAppOriginI, + remote_app::{interface::MockAppRemoteI, TEST_MODULE_ID_REMOTE, TEST_VERSION_REMOTE}, + MockExecMsgFns, MockInitMsg, MockQueryMsgFns, ReceivedIbcCallbackStatus, + }, + setup::{ + ibc_abstract_setup, ibc_connect_polytone_and_abstract, mock_test::logger_test_init, + }, + JUNO, STARGAZE, + }; + use abstract_app::objects::{chain_name::ChainName, module::ModuleInfo, AccountId}; + use abstract_core::{ + ibc_client::InstalledModuleIdentification, manager::ModuleAddressesResponse, + }; + use abstract_interface::{AppDeployer, DeployStrategy, ManagerQueryFns, VCExecFns}; + use abstract_testing::addresses::{TEST_MODULE_ID, TEST_NAMESPACE, TEST_VERSION}; + use anyhow::Result as AnyResult; + use base64::{engine::general_purpose, Engine}; + use cw_orch::interchain::MockBech32InterchainEnv; + use cw_orch::prelude::*; + + #[test] + fn target_module_must_exist() -> AnyResult<()> { + logger_test_init(); + let mock_interchain = + MockBech32InterchainEnv::new(vec![(JUNO, "juno"), (STARGAZE, "stargaze")]); + + // We just verified all steps pass + let (abstr_origin, abstr_remote) = ibc_abstract_setup(&mock_interchain, JUNO, STARGAZE)?; + ibc_connect_polytone_and_abstract(&mock_interchain, STARGAZE, JUNO)?; + + let remote_name = ChainName::from_chain_id(STARGAZE).to_string(); + + let (origin_account, _remote_account_id) = + create_test_remote_account(&abstr_origin, JUNO, STARGAZE, &mock_interchain, None)?; + + let (remote_account, _remote_account_id) = + create_test_remote_account(&abstr_remote, STARGAZE, JUNO, &mock_interchain, None)?; + + let app = MockAppOriginI::new( + TEST_MODULE_ID, + abstr_origin.version_control.get_chain().clone(), + ); + + abstr_origin.version_control.claim_namespace( + origin_account.manager.config()?.account_id, + TEST_NAMESPACE.to_owned(), + )?; + + app.deploy(TEST_VERSION.parse()?, DeployStrategy::Try)?; + + origin_account.install_app(&app, &MockInitMsg {}, None)?; + let res: ModuleAddressesResponse = origin_account + .manager + .module_addresses(vec![TEST_MODULE_ID.to_owned()])?; + + assert_eq!(1, res.modules.len()); + + // The user on origin chain wants to change the account description + let target_module_info = + ModuleInfo::from_id(TEST_MODULE_ID_REMOTE, TEST_VERSION_REMOTE.into())?; + let ibc_action_result = app.do_something_ibc( + remote_name, + InstalledModuleIdentification { + module_info: target_module_info.clone(), + account_id: Some(remote_account.id()?), + }, + )?; + + let ibc_result = mock_interchain.wait_ibc(JUNO, ibc_action_result)?; + + let expected_error_outcome = format!( + "Module {} does not have a stored module reference", + target_module_info + ); + match &ibc_result.packets[0].outcome { + cw_orch::interchain::types::IbcPacketOutcome::Timeout { .. } => { + panic!("Expected a failed ack not a timeout !") + } + cw_orch::interchain::types::IbcPacketOutcome::Success { ack, .. } => match ack { + cw_orch::interchain::types::IbcPacketAckDecode::Error(e) => { + assert!(e.contains(&expected_error_outcome)); + } + cw_orch::interchain::types::IbcPacketAckDecode::Success(_) => { + panic!("Expected a error ack") + } + cw_orch::interchain::types::IbcPacketAckDecode::NotParsed(original_ack) => { + let error_str = + String::from_utf8_lossy(&general_purpose::STANDARD.decode(original_ack)?) + .to_string(); + assert!(error_str.contains(&expected_error_outcome)); + } + }, + } + + Ok(()) + } + + #[test] + fn target_account_must_exist() -> AnyResult<()> { + logger_test_init(); + let mock_interchain = + MockBech32InterchainEnv::new(vec![(JUNO, "juno"), (STARGAZE, "stargaze")]); + + // We just verified all steps pass + let (abstr_origin, abstr_remote) = ibc_abstract_setup(&mock_interchain, JUNO, STARGAZE)?; + ibc_connect_polytone_and_abstract(&mock_interchain, STARGAZE, JUNO)?; + + let remote_name = ChainName::from_chain_id(STARGAZE).to_string(); + + let (origin_account, _remote_account_id) = + create_test_remote_account(&abstr_origin, JUNO, STARGAZE, &mock_interchain, None)?; + + let (remote_account, _remote_account_id) = + create_test_remote_account(&abstr_remote, STARGAZE, JUNO, &mock_interchain, None)?; + + // Install local app + let app = MockAppOriginI::new( + TEST_MODULE_ID, + abstr_origin.version_control.get_chain().clone(), + ); + + abstr_origin + .version_control + .claim_namespace(origin_account.id()?, TEST_NAMESPACE.to_owned())?; + + app.deploy(TEST_VERSION.parse()?, DeployStrategy::Try)?; + + origin_account.install_app(&app, &MockInitMsg {}, None)?; + let res: ModuleAddressesResponse = origin_account + .manager + .module_addresses(vec![TEST_MODULE_ID.to_owned()])?; + + assert_eq!(1, res.modules.len()); + + // Install remote app + let app_remote = MockAppRemoteI::new( + TEST_MODULE_ID_REMOTE, + abstr_remote.version_control.get_chain().clone(), + ); + + abstr_remote + .version_control + .claim_namespace(remote_account.id()?, TEST_NAMESPACE.to_owned())?; + + app_remote.deploy(TEST_VERSION_REMOTE.parse()?, DeployStrategy::Try)?; + + remote_account.install_app(&app_remote, &MockInitMsg {}, None)?; + + // The user on origin chain wants to change the account description + let unknown_account_id = AccountId::local(remote_account.id()?.seq() + 80); + let target_module_info = + ModuleInfo::from_id(TEST_MODULE_ID_REMOTE, TEST_VERSION_REMOTE.into())?; + let ibc_action_result = app.do_something_ibc( + remote_name, + InstalledModuleIdentification { + module_info: target_module_info.clone(), + // This account is not supposed to exist on the remote chain + account_id: Some(unknown_account_id.clone()), + }, + )?; + + let ibc_result = mock_interchain.wait_ibc(JUNO, ibc_action_result)?; + + let expected_error_outcome = format!("Unknown Account id {}", unknown_account_id); + match &ibc_result.packets[0].outcome { + cw_orch::interchain::types::IbcPacketOutcome::Timeout { .. } => { + panic!("Expected a failed ack not a timeout !") + } + cw_orch::interchain::types::IbcPacketOutcome::Success { ack, .. } => match ack { + cw_orch::interchain::types::IbcPacketAckDecode::Error(e) => { + assert!(e.contains(&expected_error_outcome)); + } + cw_orch::interchain::types::IbcPacketAckDecode::Success(_) => { + panic!("Expected a error ack") + } + cw_orch::interchain::types::IbcPacketAckDecode::NotParsed(original_ack) => { + let error_str = + String::from_utf8_lossy(&general_purpose::STANDARD.decode(original_ack)?) + .to_string(); + assert!(error_str.contains(&expected_error_outcome)); + } + }, + } + Ok(()) + } + + #[test] + fn target_account_must_have_module_installed() -> AnyResult<()> { + logger_test_init(); + let mock_interchain = + MockBech32InterchainEnv::new(vec![(JUNO, "juno"), (STARGAZE, "stargaze")]); + + // We just verified all steps pass + let (abstr_origin, abstr_remote) = ibc_abstract_setup(&mock_interchain, JUNO, STARGAZE)?; + ibc_connect_polytone_and_abstract(&mock_interchain, STARGAZE, JUNO)?; + + let remote_name = ChainName::from_chain_id(STARGAZE).to_string(); + + let (origin_account, _remote_account_id) = + create_test_remote_account(&abstr_origin, JUNO, STARGAZE, &mock_interchain, None)?; + + let (remote_account, _remote_account_id) = + create_test_remote_account(&abstr_remote, STARGAZE, JUNO, &mock_interchain, None)?; + + // Install local app + let app = MockAppOriginI::new( + TEST_MODULE_ID, + abstr_origin.version_control.get_chain().clone(), + ); + + abstr_origin + .version_control + .claim_namespace(origin_account.id()?, TEST_NAMESPACE.to_owned())?; + + app.deploy(TEST_VERSION.parse()?, DeployStrategy::Try)?; + + origin_account.install_app(&app, &MockInitMsg {}, None)?; + let res: ModuleAddressesResponse = origin_account + .manager + .module_addresses(vec![TEST_MODULE_ID.to_owned()])?; + + assert_eq!(1, res.modules.len()); + + let local_module_address = res.modules[0].1.to_string(); + + // Install remote app + let app_remote = MockAppRemoteI::new( + TEST_MODULE_ID_REMOTE, + abstr_remote.version_control.get_chain().clone(), + ); + + abstr_remote + .version_control + .claim_namespace(remote_account.id()?, TEST_NAMESPACE.to_owned())?; + + app_remote.deploy(TEST_VERSION_REMOTE.parse()?, DeployStrategy::Try)?; + + // The user on origin chain wants to change the account description + let target_module_info = + ModuleInfo::from_id(TEST_MODULE_ID_REMOTE, TEST_VERSION_REMOTE.into())?; + let ibc_action_result = app.do_something_ibc( + remote_name, + InstalledModuleIdentification { + module_info: target_module_info.clone(), + // This account is not supposed to exist on the remote chain + account_id: Some(remote_account.id()?), + }, + )?; + + let ibc_result = mock_interchain.wait_ibc(JUNO, ibc_action_result)?; + + let expected_error_outcome = format!( + "Missing module {} on account {}", + target_module_info, + remote_account.id()? + ); + match &ibc_result.packets[0].outcome { + cw_orch::interchain::types::IbcPacketOutcome::Timeout { timeout_tx } => { + panic!("Expected a failed ack not a timeout !") + } + cw_orch::interchain::types::IbcPacketOutcome::Success { + receive_tx, + ack_tx, + ack, + } => match ack { + cw_orch::interchain::types::IbcPacketAckDecode::Error(e) => { + assert!(e.contains(&expected_error_outcome)); + } + cw_orch::interchain::types::IbcPacketAckDecode::Success(_) => { + panic!("Expected a error ack") + } + cw_orch::interchain::types::IbcPacketAckDecode::NotParsed(original_ack) => { + let error_str = + String::from_utf8_lossy(&general_purpose::STANDARD.decode(original_ack)?) + .to_string(); + assert!(error_str.contains(&expected_error_outcome)); + } + }, + } + + Ok(()) + } + #[test] + fn works() -> AnyResult<()> { + logger_test_init(); + let mock_interchain = + MockBech32InterchainEnv::new(vec![(JUNO, "juno"), (STARGAZE, "stargaze")]); + + // We just verified all steps pass + let (abstr_origin, abstr_remote) = ibc_abstract_setup(&mock_interchain, JUNO, STARGAZE)?; + ibc_connect_polytone_and_abstract(&mock_interchain, STARGAZE, JUNO)?; + + let remote_name = ChainName::from_chain_id(STARGAZE).to_string(); + + let (origin_account, _remote_account_id) = + create_test_remote_account(&abstr_origin, JUNO, STARGAZE, &mock_interchain, None)?; + + let (remote_account, _remote_account_id) = + create_test_remote_account(&abstr_remote, STARGAZE, JUNO, &mock_interchain, None)?; + + // Install local app + let app = MockAppOriginI::new( + TEST_MODULE_ID, + abstr_origin.version_control.get_chain().clone(), + ); + + abstr_origin + .version_control + .claim_namespace(origin_account.id()?, TEST_NAMESPACE.to_owned())?; + + app.deploy(TEST_VERSION.parse()?, DeployStrategy::Try)?; + + origin_account.install_app(&app, &MockInitMsg {}, None)?; + let res: ModuleAddressesResponse = origin_account + .manager + .module_addresses(vec![TEST_MODULE_ID.to_owned()])?; + + assert_eq!(1, res.modules.len()); + + // Install remote app + let app_remote = MockAppRemoteI::new( + TEST_MODULE_ID_REMOTE, + abstr_remote.version_control.get_chain().clone(), + ); + + abstr_remote + .version_control + .claim_namespace(remote_account.id()?, TEST_NAMESPACE.to_owned())?; + + app_remote.deploy(TEST_VERSION_REMOTE.parse()?, DeployStrategy::Try)?; + remote_account.install_app(&app_remote, &MockInitMsg {}, None)?; + + // The user on origin chain wants to change the account description + let target_module_info = + ModuleInfo::from_id(TEST_MODULE_ID_REMOTE, TEST_VERSION_REMOTE.into())?; + let ibc_action_result = app.do_something_ibc( + remote_name, + InstalledModuleIdentification { + module_info: target_module_info.clone(), + // This account is not supposed to exist on the remote chain + account_id: Some(remote_account.id()?), + }, + )?; + + assert_remote_module_call_status(&app_remote, None)?; + assert_callback_status(&app, false)?; + + mock_interchain.wait_ibc(JUNO, ibc_action_result)?; + + assert_remote_module_call_status( + &app_remote, + Some(InstalledModuleIdentification { + module_info: ModuleInfo::from_id(TEST_MODULE_ID, TEST_VERSION.into())?, + account_id: Some(origin_account.id()?), + }), + )?; + assert_callback_status(&app, true)?; + + Ok(()) + } +} diff --git a/interchain/tests/src/setup.rs b/interchain/tests/src/setup.rs index 19a70a3fa2..7e69493bc5 100644 --- a/interchain/tests/src/setup.rs +++ b/interchain/tests/src/setup.rs @@ -23,6 +23,25 @@ pub fn ibc_abstract_setup>( let origin_polytone = Polytone::deploy_on(origin_chain.clone(), None)?; let remote_polytone = Polytone::deploy_on(remote_chain.clone(), None)?; + ibc_connect_polytone_and_abstract(interchain, origin_chain_id, remote_chain_id)?; + + Ok((abstr_origin, abstr_remote)) +} + +pub fn ibc_connect_polytone_and_abstract>( + interchain: &IBC, + origin_chain_id: &str, + remote_chain_id: &str, +) -> AnyResult<()> { + let origin_chain = interchain.chain(origin_chain_id).unwrap(); + let remote_chain = interchain.chain(remote_chain_id).unwrap(); + + let abstr_origin = Abstract::load_from(origin_chain.clone())?; + let abstr_remote = Abstract::load_from(remote_chain.clone())?; + + let origin_polytone = Polytone::load_from(origin_chain.clone())?; + let remote_polytone = Polytone::load_from(remote_chain.clone())?; + // Creating a connection between 2 polytone deployments interchain.create_contract_channel( &origin_polytone.note, @@ -33,8 +52,7 @@ pub fn ibc_abstract_setup>( // Create the connection between client and host abstract_ibc_connection_with(&abstr_origin, interchain, &abstr_remote, &origin_polytone)?; - - Ok((abstr_origin, abstr_remote)) + Ok(()) } #[cfg(test)] From 658907b605606b96f9463e970b6218376fd9c91c Mon Sep 17 00:00:00 2001 From: Kayanski Date: Thu, 7 Mar 2024 11:06:53 +0000 Subject: [PATCH 08/37] Fixed tests and clippy --- .../contracts/native/ibc-client/src/ibc.rs | 9 ++- .../native/ibc-host/src/endpoints/execute.rs | 2 +- .../native/ibc-host/src/endpoints/packet.rs | 44 +++---------- .../contracts/native/ibc-host/src/error.rs | 2 +- .../abstract-core/src/native/ibc_client.rs | 64 ++++++++++++++++++- .../src/module_to_module_interactions.rs | 50 ++------------- interchain/tests/src/setup.rs | 4 +- 7 files changed, 86 insertions(+), 89 deletions(-) diff --git a/framework/contracts/native/ibc-client/src/ibc.rs b/framework/contracts/native/ibc-client/src/ibc.rs index a2d947f42c..3e638acb18 100644 --- a/framework/contracts/native/ibc-client/src/ibc.rs +++ b/framework/contracts/native/ibc-client/src/ibc.rs @@ -1,7 +1,7 @@ use abstract_core::{ ibc::IbcResponseMsg, ibc_client::{ - state::{IBC_INFRA, REVERSE_POLYTONE_NOTE}, + state::{CONFIG, IBC_INFRA, REVERSE_POLYTONE_NOTE}, IbcClientCallback, }, objects::chain_name::ChainName, @@ -102,9 +102,14 @@ pub fn receive_action_callback( } IbcClientCallback::ModuleRemoteAction { callback_info, - // TODO This will be used when the sender is part of the callback msg (https://github.com/AbstractSDK/abstract/pull/277) sender_module, } => { + // resolve the address for that sender module + let vc = CONFIG.load(deps.storage)?.version_control; + + // TODO This will be used when the sender is part of the callback msg (https://github.com/AbstractSDK/abstract/pull/277) + let addr = sender_module.addr(deps.as_ref(), vc)?; + let callback = IbcResponseMsg { id: callback_info.id.clone(), msg: callback_info.msg, diff --git a/framework/contracts/native/ibc-host/src/endpoints/execute.rs b/framework/contracts/native/ibc-host/src/endpoints/execute.rs index 6f8a3df67a..52fa225f70 100644 --- a/framework/contracts/native/ibc-host/src/endpoints/execute.rs +++ b/framework/contracts/native/ibc-host/src/endpoints/execute.rs @@ -50,7 +50,7 @@ pub fn execute(deps: DepsMut, env: Env, info: MessageInfo, msg: ExecuteMsg) -> H target_module, } => { let client_chain: ChainName = REVERSE_CHAIN_PROXIES.load(deps.storage, &info.sender)?; - handle_host_module_action(deps, env, client_chain, source_module, target_module, msg) + handle_host_module_action(deps, client_chain, source_module, target_module, msg) } } } diff --git a/framework/contracts/native/ibc-host/src/endpoints/packet.rs b/framework/contracts/native/ibc-host/src/endpoints/packet.rs index 3597278922..e83fb8230e 100644 --- a/framework/contracts/native/ibc-host/src/endpoints/packet.rs +++ b/framework/contracts/native/ibc-host/src/endpoints/packet.rs @@ -5,7 +5,6 @@ use abstract_core::{ state::{ActionAfterCreationCache, CONFIG, TEMP_ACTION_AFTER_CREATION}, HelperAction, }, - manager, objects::{chain_name::ChainName, module_reference::ModuleReference, AccountId}, }; use abstract_sdk::core::ibc_host::{HostAction, InternalAction}; @@ -115,7 +114,6 @@ pub fn handle_host_action( /// Handle actions that are passed to the IBC host contract and originate from a registered module pub fn handle_host_module_action( deps: DepsMut, - env: Env, client_chain: ChainName, source_module: InstalledModuleIdentification, target_module: InstalledModuleIdentification, @@ -126,41 +124,17 @@ pub fn handle_host_module_action( let target_module_resolved = vc.query_module(target_module.module_info.clone(), &deps.querier)?; - let target_addr = match target_module_resolved.reference { - ModuleReference::AccountBase(_) => { - return Err(HostError::WrongModuleAction(target_module.module_info.id())) - } - ModuleReference::Native(_) => { - return Err(HostError::WrongModuleAction(target_module.module_info.id())) + // We can't send module actions to accounts base and native apps + match target_module_resolved.reference { + ModuleReference::AccountBase(_) | ModuleReference::Native(_) => { + return Err(HostError::WrongModuleAction( + target_module.module_info.to_string(), + )) } - ModuleReference::Adapter(addr) => addr, - ModuleReference::App(_) | ModuleReference::Standalone(_) => { - let target_account_id = target_module - .account_id - .clone() - .ok_or(HostError::AccountIdNotSpecified {})?; - let account_base = vc.account_base(&target_account_id, &deps.querier)?; + _ => (), + } - let module_info: manager::ModuleAddressesResponse = deps.querier.query_wasm_smart( - account_base.manager, - &manager::QueryMsg::ModuleAddresses { - ids: vec![target_module.module_info.id()], - }, - )?; - module_info - .modules - .first() - .ok_or(HostError::MissingModule { - module_info: target_module.module_info.to_string(), - account_id: target_account_id, - })? - .1 - .clone() - } - _ => unimplemented!( - "This module type didn't exist when implementing module-to-module interactions" - ), - }; + let target_addr = target_module.addr(deps.as_ref(), vc)?; // We pass the message on to the module let msg = wasm_execute( diff --git a/framework/contracts/native/ibc-host/src/error.rs b/framework/contracts/native/ibc-host/src/error.rs index 26c780cabc..d3d11f7d43 100644 --- a/framework/contracts/native/ibc-host/src/error.rs +++ b/framework/contracts/native/ibc-host/src/error.rs @@ -43,7 +43,7 @@ pub enum HostError { #[error("Chain or proxy address already registered.")] ProxyAddressExists {}, - #[error("Can't send a module-to-module packet to {0}")] + #[error("Can't send a module-to-module packet to {0}, wrong module type")] WrongModuleAction(String), #[error("Missing module {module_info} on account {account_id}")] diff --git a/framework/packages/abstract-core/src/native/ibc_client.rs b/framework/packages/abstract-core/src/native/ibc_client.rs index 321bc45fc2..e9c9f2f3db 100644 --- a/framework/packages/abstract-core/src/native/ibc_client.rs +++ b/framework/packages/abstract-core/src/native/ibc_client.rs @@ -1,13 +1,17 @@ use cosmwasm_schema::QueryResponses; -use cosmwasm_std::{Addr, Binary, Coin, Empty, QueryRequest}; +use cosmwasm_std::{Addr, Binary, Coin, Deps, Empty, QueryRequest, StdError}; use polytone::callbacks::CallbackMessage; use self::state::IbcInfrastructure; use crate::{ ibc::CallbackInfo, ibc_host::HostAction, - manager::ModuleInstallConfig, - objects::{account::AccountId, chain_name::ChainName, module::ModuleInfo, AssetEntry}, + manager::{self, ModuleInstallConfig}, + objects::{ + account::AccountId, chain_name::ChainName, module::ModuleInfo, + module_reference::ModuleReference, version_control::VersionControlContract, AssetEntry, + }, + AbstractError, }; pub mod state { @@ -159,6 +163,60 @@ pub struct InstalledModuleIdentification { pub account_id: Option, } +impl InstalledModuleIdentification { + pub fn addr(&self, deps: Deps, vc: VersionControlContract) -> Result { + let target_module_resolved = vc.query_module(self.module_info.clone(), &deps.querier)?; + + let no_account_id_error = + StdError::generic_err("Account id not specified in installed module definition"); + + let target_addr = match target_module_resolved.reference { + ModuleReference::AccountBase(code_id) => { + let target_account_id = self + .account_id + .clone() + .ok_or(no_account_id_error)?; + let account_base = vc.account_base(&target_account_id, &deps.querier)?; + + if deps.querier.query_wasm_contract_info(&account_base.proxy)?.code_id == code_id{ + account_base.proxy + }else if deps.querier.query_wasm_contract_info(&account_base.manager)?.code_id == code_id{ + account_base.manager + }else{ + Err(StdError::generic_err("Account base contract doesn't correspond to any of the proxy or manager"))? + } + } + ModuleReference::Native(addr) => addr, + ModuleReference::Adapter(addr) => addr, + ModuleReference::App(_) | ModuleReference::Standalone(_) => { + let target_account_id = self + .account_id + .clone() + .ok_or(no_account_id_error)?; + let account_base = vc.account_base(&target_account_id, &deps.querier)?; + + let module_info: manager::ModuleAddressesResponse = deps.querier.query_wasm_smart( + account_base.manager, + &manager::QueryMsg::ModuleAddresses { + ids: vec![self.module_info.id()], + }, + )?; + module_info + .modules + .first() + .ok_or(AbstractError::AppNotInstalled( + self.module_info.to_string()))? + .1 + .clone() + } + _ => unimplemented!( + "This module type didn't exist when implementing installed module address resolution" + ), + }; + Ok(target_addr) + } +} + #[cosmwasm_schema::cw_serde] #[cfg_attr(feature = "interface", derive(cw_orch::QueryFns))] #[derive(QueryResponses)] diff --git a/interchain/tests/src/module_to_module_interactions.rs b/interchain/tests/src/module_to_module_interactions.rs index ead7423364..3b40234370 100644 --- a/interchain/tests/src/module_to_module_interactions.rs +++ b/interchain/tests/src/module_to_module_interactions.rs @@ -2,16 +2,13 @@ pub use abstract_core::app; use abstract_core::{ ibc::{CallbackInfo, ModuleIbcMsg}, ibc_client::{self, InstalledModuleIdentification}, - manager::ModuleInstallConfig, - objects::{dependency::StaticDependency, module::ModuleInfo}, + objects::module::ModuleInfo, IBC_CLIENT, }; -use abstract_interface::{AppDeployer, DependencyCreation}; use cosmwasm_schema::{cw_serde, QueryResponses}; pub use cosmwasm_std::testing::{mock_dependencies, mock_env, mock_info}; use cosmwasm_std::{to_json_binary, wasm_execute, Response, StdError}; use cw_controllers::AdminError; -use cw_orch::prelude::*; use cw_storage_plus::Item; pub type AppTestResult = Result<(), MockError>; @@ -64,16 +61,7 @@ pub struct MockReceiveMsg; #[cosmwasm_schema::cw_serde] pub struct MockSudoMsg; -use abstract_sdk::{ - base::InstantiateEndpoint, features::AccountIdentification, AbstractSdkError, ModuleInterface, -}; -use abstract_testing::{ - addresses::{test_account_base, TEST_ANS_HOST, TEST_VERSION_CONTROL}, - prelude::{ - MockDeps, MockQuerierBuilder, TEST_MODULE_FACTORY, TEST_MODULE_ID, TEST_VERSION, - TEST_WITH_DEP_MODULE_ID, - }, -}; +use abstract_sdk::{features::AccountIdentification, AbstractSdkError, ModuleInterface}; use thiserror::Error; use abstract_app::{AppContract, AppError}; @@ -247,9 +235,7 @@ pub mod test { JUNO, STARGAZE, }; use abstract_app::objects::{chain_name::ChainName, module::ModuleInfo, AccountId}; - use abstract_core::{ - ibc_client::InstalledModuleIdentification, manager::ModuleAddressesResponse, - }; + use abstract_core::ibc_client::InstalledModuleIdentification; use abstract_interface::{AppDeployer, DeployStrategy, ManagerQueryFns, VCExecFns}; use abstract_testing::addresses::{TEST_MODULE_ID, TEST_NAMESPACE, TEST_VERSION}; use anyhow::Result as AnyResult; @@ -288,11 +274,6 @@ pub mod test { app.deploy(TEST_VERSION.parse()?, DeployStrategy::Try)?; origin_account.install_app(&app, &MockInitMsg {}, None)?; - let res: ModuleAddressesResponse = origin_account - .manager - .module_addresses(vec![TEST_MODULE_ID.to_owned()])?; - - assert_eq!(1, res.modules.len()); // The user on origin chain wants to change the account description let target_module_info = @@ -365,11 +346,6 @@ pub mod test { app.deploy(TEST_VERSION.parse()?, DeployStrategy::Try)?; origin_account.install_app(&app, &MockInitMsg {}, None)?; - let res: ModuleAddressesResponse = origin_account - .manager - .module_addresses(vec![TEST_MODULE_ID.to_owned()])?; - - assert_eq!(1, res.modules.len()); // Install remote app let app_remote = MockAppRemoteI::new( @@ -454,13 +430,6 @@ pub mod test { app.deploy(TEST_VERSION.parse()?, DeployStrategy::Try)?; origin_account.install_app(&app, &MockInitMsg {}, None)?; - let res: ModuleAddressesResponse = origin_account - .manager - .module_addresses(vec![TEST_MODULE_ID.to_owned()])?; - - assert_eq!(1, res.modules.len()); - - let local_module_address = res.modules[0].1.to_string(); // Install remote app let app_remote = MockAppRemoteI::new( @@ -494,14 +463,10 @@ pub mod test { remote_account.id()? ); match &ibc_result.packets[0].outcome { - cw_orch::interchain::types::IbcPacketOutcome::Timeout { timeout_tx } => { + cw_orch::interchain::types::IbcPacketOutcome::Timeout { .. } => { panic!("Expected a failed ack not a timeout !") } - cw_orch::interchain::types::IbcPacketOutcome::Success { - receive_tx, - ack_tx, - ack, - } => match ack { + cw_orch::interchain::types::IbcPacketOutcome::Success { ack, .. } => match ack { cw_orch::interchain::types::IbcPacketAckDecode::Error(e) => { assert!(e.contains(&expected_error_outcome)); } @@ -550,11 +515,6 @@ pub mod test { app.deploy(TEST_VERSION.parse()?, DeployStrategy::Try)?; origin_account.install_app(&app, &MockInitMsg {}, None)?; - let res: ModuleAddressesResponse = origin_account - .manager - .module_addresses(vec![TEST_MODULE_ID.to_owned()])?; - - assert_eq!(1, res.modules.len()); // Install remote app let app_remote = MockAppRemoteI::new( diff --git a/interchain/tests/src/setup.rs b/interchain/tests/src/setup.rs index 7e69493bc5..7ac31a8787 100644 --- a/interchain/tests/src/setup.rs +++ b/interchain/tests/src/setup.rs @@ -20,8 +20,8 @@ pub fn ibc_abstract_setup>( Abstract::deploy_on(remote_chain.clone(), remote_chain.sender().to_string())?; // Deploying polytone on both chains - let origin_polytone = Polytone::deploy_on(origin_chain.clone(), None)?; - let remote_polytone = Polytone::deploy_on(remote_chain.clone(), None)?; + Polytone::deploy_on(origin_chain.clone(), None)?; + Polytone::deploy_on(remote_chain.clone(), None)?; ibc_connect_polytone_and_abstract(interchain, origin_chain_id, remote_chain_id)?; From c9c466a0ab2345319da11d65ed24370cef8a2584 Mon Sep 17 00:00:00 2001 From: Kayanski Date: Thu, 7 Mar 2024 11:08:52 +0000 Subject: [PATCH 09/37] Clippy --- .../abstract-core/src/native/ibc_client.rs | 36 ++++++++++--------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/framework/packages/abstract-core/src/native/ibc_client.rs b/framework/packages/abstract-core/src/native/ibc_client.rs index e9c9f2f3db..f7f9ef454b 100644 --- a/framework/packages/abstract-core/src/native/ibc_client.rs +++ b/framework/packages/abstract-core/src/native/ibc_client.rs @@ -172,27 +172,33 @@ impl InstalledModuleIdentification { let target_addr = match target_module_resolved.reference { ModuleReference::AccountBase(code_id) => { - let target_account_id = self - .account_id - .clone() - .ok_or(no_account_id_error)?; + let target_account_id = self.account_id.clone().ok_or(no_account_id_error)?; let account_base = vc.account_base(&target_account_id, &deps.querier)?; - if deps.querier.query_wasm_contract_info(&account_base.proxy)?.code_id == code_id{ + if deps + .querier + .query_wasm_contract_info(&account_base.proxy)? + .code_id + == code_id + { account_base.proxy - }else if deps.querier.query_wasm_contract_info(&account_base.manager)?.code_id == code_id{ + } else if deps + .querier + .query_wasm_contract_info(&account_base.manager)? + .code_id + == code_id + { account_base.manager - }else{ - Err(StdError::generic_err("Account base contract doesn't correspond to any of the proxy or manager"))? + } else { + Err(StdError::generic_err( + "Account base contract doesn't correspond to any of the proxy or manager", + ))? } } ModuleReference::Native(addr) => addr, ModuleReference::Adapter(addr) => addr, ModuleReference::App(_) | ModuleReference::Standalone(_) => { - let target_account_id = self - .account_id - .clone() - .ok_or(no_account_id_error)?; + let target_account_id = self.account_id.clone().ok_or(no_account_id_error)?; let account_base = vc.account_base(&target_account_id, &deps.querier)?; let module_info: manager::ModuleAddressesResponse = deps.querier.query_wasm_smart( @@ -204,14 +210,10 @@ impl InstalledModuleIdentification { module_info .modules .first() - .ok_or(AbstractError::AppNotInstalled( - self.module_info.to_string()))? + .ok_or(AbstractError::AppNotInstalled(self.module_info.to_string()))? .1 .clone() } - _ => unimplemented!( - "This module type didn't exist when implementing installed module address resolution" - ), }; Ok(target_addr) } From 301c373ddee92231e64ac8fe26e4796901f1e19c Mon Sep 17 00:00:00 2001 From: Kayanski Date: Thu, 7 Mar 2024 14:13:40 +0000 Subject: [PATCH 10/37] Fixed test after error change --- interchain/tests/src/module_to_module_interactions.rs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/interchain/tests/src/module_to_module_interactions.rs b/interchain/tests/src/module_to_module_interactions.rs index 3b40234370..45050b26eb 100644 --- a/interchain/tests/src/module_to_module_interactions.rs +++ b/interchain/tests/src/module_to_module_interactions.rs @@ -457,11 +457,8 @@ pub mod test { let ibc_result = mock_interchain.wait_ibc(JUNO, ibc_action_result)?; - let expected_error_outcome = format!( - "Missing module {} on account {}", - target_module_info, - remote_account.id()? - ); + let expected_error_outcome = + format!("App {} not installed on Account", target_module_info,); match &ibc_result.packets[0].outcome { cw_orch::interchain::types::IbcPacketOutcome::Timeout { .. } => { panic!("Expected a failed ack not a timeout !") From de6a62eaf530a6e8bf8d00efaeda63de85188e49 Mon Sep 17 00:00:00 2001 From: Kayanski Date: Mon, 11 Mar 2024 10:09:50 +0000 Subject: [PATCH 11/37] Fixed error --- .../abstract-adapter/src/endpoints/ibc_callback.rs | 9 +++------ .../abstract-adapter/src/endpoints/module_ibc.rs | 8 ++------ framework/packages/abstract-adapter/src/schema.rs | 1 + framework/packages/abstract-adapter/src/state.rs | 14 +++++++++++--- .../abstract-app/src/endpoints/ibc_callback.rs | 4 ++-- .../abstract-app/src/endpoints/module_ibc.rs | 9 +++------ .../src/base/endpoints/ibc_callback.rs | 2 +- .../abstract-sdk/src/base/endpoints/modules_ibc.rs | 2 +- 8 files changed, 24 insertions(+), 25 deletions(-) diff --git a/framework/packages/abstract-adapter/src/endpoints/ibc_callback.rs b/framework/packages/abstract-adapter/src/endpoints/ibc_callback.rs index 7259e43491..ebc2ef0735 100644 --- a/framework/packages/abstract-adapter/src/endpoints/ibc_callback.rs +++ b/framework/packages/abstract-adapter/src/endpoints/ibc_callback.rs @@ -1,5 +1,5 @@ use abstract_core::{objects::module::ModuleInfo, AbstractError, IBC_CLIENT}; -use abstract_sdk::{base::IbcCallbackEndpoint, features::AbstractRegistryAccess, AbstractSdkError}; +use abstract_sdk::{base::IbcCallbackEndpoint, features::AbstractRegistryAccess}; use cosmwasm_std::{Addr, Deps}; use crate::{state::ContractError, AdapterContract}; @@ -8,14 +8,11 @@ impl { - fn ibc_client(&self, deps: Deps) -> Result { + fn ibc_client(&self, deps: Deps) -> Result { let vc_query_result = self .abstract_registry(deps)? .query_module(ModuleInfo::from_id_latest(IBC_CLIENT)?, &deps.querier) - .map_err(|err| { - let err: AbstractError = err.into(); - err - })?; + .map_err(Into::::into)?; Ok(vc_query_result.reference.unwrap_native()?) } diff --git a/framework/packages/abstract-adapter/src/endpoints/module_ibc.rs b/framework/packages/abstract-adapter/src/endpoints/module_ibc.rs index 552820f092..bd605b9951 100644 --- a/framework/packages/abstract-adapter/src/endpoints/module_ibc.rs +++ b/framework/packages/abstract-adapter/src/endpoints/module_ibc.rs @@ -1,7 +1,6 @@ use crate::{state::ContractError, AdapterContract}; use abstract_core::IBC_HOST; use abstract_core::{objects::module::ModuleInfo, AbstractError}; -use abstract_sdk::AbstractSdkError; use abstract_sdk::{base::ModuleIbcEndpoint, features::AbstractRegistryAccess}; use cosmwasm_std::Addr; @@ -9,14 +8,11 @@ impl { - fn ibc_host(&self, deps: cosmwasm_std::Deps) -> Result { + fn ibc_host(&self, deps: cosmwasm_std::Deps) -> Result { let vc_query_result = self .abstract_registry(deps)? .query_module(ModuleInfo::from_id_latest(IBC_HOST)?, &deps.querier) - .map_err(|err| { - let err: AbstractError = err.into(); - err - })?; + .map_err(Into::::into)?; Ok(vc_query_result.reference.unwrap_native()?) } diff --git a/framework/packages/abstract-adapter/src/schema.rs b/framework/packages/abstract-adapter/src/schema.rs index c63e770f95..1c6f0d05bb 100644 --- a/framework/packages/abstract-adapter/src/schema.rs +++ b/framework/packages/abstract-adapter/src/schema.rs @@ -16,6 +16,7 @@ impl< Error: From + From + From + + From + 'static, CustomExecMsg: Serialize + JsonSchema + AdapterExecuteMsg, CustomInitMsg: Serialize + JsonSchema, diff --git a/framework/packages/abstract-adapter/src/state.rs b/framework/packages/abstract-adapter/src/state.rs index e9400f231d..9ca9412d09 100644 --- a/framework/packages/abstract-adapter/src/state.rs +++ b/framework/packages/abstract-adapter/src/state.rs @@ -1,6 +1,6 @@ use std::fmt::Debug; -use abstract_core::objects::dependency::StaticDependency; +use abstract_core::{objects::dependency::StaticDependency, AbstractError}; use abstract_sdk::{ base::{ AbstractContract, ExecuteHandlerFn, Handler, IbcCallbackHandlerFn, InstantiateHandlerFn, @@ -22,11 +22,19 @@ pub const AUTHORIZED_ADDRESSES_NAMESPACE: &str = "authorized_addresses"; pub const MAXIMUM_AUTHORIZED_ADDRESSES: u32 = 15; pub trait ContractError: - From + From + From + 'static + From + + From + + From + + From + + 'static { } impl ContractError for T where - T: From + From + From + 'static + T: From + + From + + From + + From + + 'static { } diff --git a/framework/packages/abstract-app/src/endpoints/ibc_callback.rs b/framework/packages/abstract-app/src/endpoints/ibc_callback.rs index 52d0a1784f..73c435cb05 100644 --- a/framework/packages/abstract-app/src/endpoints/ibc_callback.rs +++ b/framework/packages/abstract-app/src/endpoints/ibc_callback.rs @@ -1,5 +1,5 @@ use abstract_core::IBC_CLIENT; -use abstract_sdk::{AbstractSdkError, ModuleInterface}; +use abstract_sdk::ModuleInterface; use cosmwasm_std::Addr; use crate::{state::ContractError, AppContract, IbcCallbackEndpoint}; @@ -23,7 +23,7 @@ impl< SudoMsg, > { - fn ibc_client(&self, deps: cosmwasm_std::Deps) -> Result { + fn ibc_client(&self, deps: cosmwasm_std::Deps) -> Result { let ibc_client = self.modules(deps).module_address(IBC_CLIENT)?; Ok(ibc_client) } diff --git a/framework/packages/abstract-app/src/endpoints/module_ibc.rs b/framework/packages/abstract-app/src/endpoints/module_ibc.rs index f35c84c23d..05c2e572a7 100644 --- a/framework/packages/abstract-app/src/endpoints/module_ibc.rs +++ b/framework/packages/abstract-app/src/endpoints/module_ibc.rs @@ -1,5 +1,5 @@ use abstract_core::{objects::module::ModuleInfo, AbstractError, IBC_HOST}; -use abstract_sdk::{base::ModuleIbcEndpoint, features::AbstractRegistryAccess, AbstractSdkError}; +use abstract_sdk::{base::ModuleIbcEndpoint, features::AbstractRegistryAccess}; use cosmwasm_std::Addr; use crate::{state::ContractError, AppContract}; @@ -28,14 +28,11 @@ impl< // let ibc_client = self.modules(deps).module_address(IBC_HOST)?; // Ok(ibc_client) // } - fn ibc_host(&self, deps: cosmwasm_std::Deps) -> Result { + fn ibc_host(&self, deps: cosmwasm_std::Deps) -> Result { let vc_query_result = self .abstract_registry(deps)? .query_module(ModuleInfo::from_id_latest(IBC_HOST)?, &deps.querier) - .map_err(|err| { - let err: AbstractError = err.into(); - err - })?; + .map_err(Into::::into)?; Ok(vc_query_result.reference.unwrap_native()?) } diff --git a/framework/packages/abstract-sdk/src/base/endpoints/ibc_callback.rs b/framework/packages/abstract-sdk/src/base/endpoints/ibc_callback.rs index b4fddc41bd..f4a50cd77c 100644 --- a/framework/packages/abstract-sdk/src/base/endpoints/ibc_callback.rs +++ b/framework/packages/abstract-sdk/src/base/endpoints/ibc_callback.rs @@ -5,7 +5,7 @@ use cosmwasm_std::{Addr, Deps, DepsMut, Env, MessageInfo, Response}; /// Trait for a contract's IBC callback ExecuteMsg variant. pub trait IbcCallbackEndpoint: Handler { /// Queries the IBC Client address. - fn ibc_client(&self, deps: Deps) -> Result; + fn ibc_client(&self, deps: Deps) -> Result; /// Handler for the `ExecuteMsg::IbcCallback()` variant. fn ibc_callback( diff --git a/framework/packages/abstract-sdk/src/base/endpoints/modules_ibc.rs b/framework/packages/abstract-sdk/src/base/endpoints/modules_ibc.rs index a1457dd513..f498b13749 100644 --- a/framework/packages/abstract-sdk/src/base/endpoints/modules_ibc.rs +++ b/framework/packages/abstract-sdk/src/base/endpoints/modules_ibc.rs @@ -6,7 +6,7 @@ use crate::{base::Handler, AbstractSdkError}; /// Trait for a contract to call itself on an IBC counterpart. pub trait ModuleIbcEndpoint: Handler { /// Get the address of the ibc host associated with this module - fn ibc_host(&self, deps: Deps) -> Result; + fn ibc_host(&self, deps: Deps) -> Result; /// Handler for the `ExecuteMsg::IbcCallback()` variant. fn module_ibc( From 46d2920503afd468a30dcf910ff01f78ea3755b8 Mon Sep 17 00:00:00 2001 From: Kayanski Date: Mon, 11 Mar 2024 10:42:10 +0000 Subject: [PATCH 12/37] Removed user initiated callbacks --- .../native/ibc-client/src/commands.rs | 74 +--- .../native/ibc-client/src/contract.rs | 234 +----------- .../contracts/native/ibc-client/src/ibc.rs | 17 - .../packages/abstract-adapter/src/lib.rs | 2 +- .../packages/abstract-adapter/src/state.rs | 2 +- framework/packages/abstract-app/src/lib.rs | 20 +- framework/packages/abstract-app/src/state.rs | 2 +- .../packages/abstract-core/src/native/ibc.rs | 5 - .../abstract-core/src/native/ibc_client.rs | 29 +- .../abstract-interface/src/account/manager.rs | 7 - .../packages/abstract-sdk/src/apis/ibc.rs | 58 +-- .../abstract-sdk/src/base/contract_base.rs | 14 +- .../src/base/endpoints/ibc_callback.rs | 3 +- interchain/tests/src/interchain_accounts.rs | 356 +----------------- .../cw-staking/src/handlers/execute.rs | 4 +- .../adapters/dex/src/handlers/execute.rs | 4 +- 16 files changed, 30 insertions(+), 801 deletions(-) diff --git a/framework/contracts/native/ibc-client/src/commands.rs b/framework/contracts/native/ibc-client/src/commands.rs index 0451b70636..82297f7d33 100644 --- a/framework/contracts/native/ibc-client/src/commands.rs +++ b/framework/contracts/native/ibc-client/src/commands.rs @@ -1,7 +1,6 @@ use std::str::FromStr; use abstract_core::{ - ibc::CallbackInfo, ibc_client::{ state::{IbcInfrastructure, IBC_INFRA, REVERSE_POLYTONE_NOTE}, IbcClientCallback, @@ -23,7 +22,7 @@ use abstract_sdk::{ }; use cosmwasm_std::{ to_json_binary, wasm_execute, Coin, CosmosMsg, Deps, DepsMut, Empty, Env, IbcMsg, MessageInfo, - QueryRequest, Storage, + Storage, }; use polytone::callbacks::CallbackRequest; @@ -169,38 +168,14 @@ fn send_remote_host_action( Ok(note_message.into()) } -/// Perform a ICQ on a remote chain -fn send_remote_host_query( - deps: Deps, - host_chain: ChainName, - queries: Vec>, - callback_request: CallbackRequest, -) -> IbcClientResult> { - // Send this message via the Polytone infra - let note_contract = IBC_INFRA.load(deps.storage, &host_chain)?.polytone_note; - - let note_message = wasm_execute( - note_contract.to_string(), - &polytone_note::msg::ExecuteMsg::Query { - msgs: queries, - callback: callback_request, - timeout_seconds: PACKET_LIFETIME.into(), - }, - vec![], - )?; - - Ok(note_message.into()) -} - /// Sends a packet with an optional callback. /// This is the top-level function to do IBC related actions. pub fn execute_send_packet( deps: DepsMut, - env: Env, + _env: Env, info: MessageInfo, host_chain: String, action: HostAction, - callback_info: Option, ) -> IbcClientResult { let host_chain = ChainName::from_str(&host_chain)?; @@ -219,61 +194,18 @@ pub fn execute_send_packet( return Err(IbcClientError::ForbiddenInternalCall {}); } - let callback_request = callback_info.map(|c| CallbackRequest { - receiver: env.contract.address.to_string(), - msg: to_json_binary(&IbcClientCallback::UserRemoteAction { - sender: account_id.clone(), - callback_info: c, - }) - .unwrap(), - }); - let note_message = send_remote_host_action( deps.as_ref(), account_id, account_base, host_chain, action, - callback_request, + None, )?; Ok(IbcClientResponse::action("handle_send_msgs").add_message(note_message)) } -// Top-level function for performing queries. -pub fn execute_send_query( - deps: DepsMut, - env: Env, - info: MessageInfo, - host_chain: String, - queries: Vec>, - callback_info: CallbackInfo, -) -> IbcClientResult { - let host_chain = ChainName::from_str(&host_chain)?; - let cfg = CONFIG.load(deps.storage)?; - - // Verify that the sender is a proxy contract - let account_base = cfg - .version_control - .assert_proxy(&info.sender, &deps.querier)?; - // get account_id - let account_id = account_base.account_id(deps.as_ref())?; - - let callback_request = CallbackRequest { - receiver: env.contract.address.to_string(), - msg: to_json_binary(&IbcClientCallback::UserRemoteAction { - sender: account_id, - callback_info, - }) - .unwrap(), - }; - - let note_message = - send_remote_host_query(deps.as_ref(), host_chain, queries, callback_request)?; - - Ok(IbcClientResponse::action("handle_send_msgs").add_message(note_message)) -} - /// Registers an Abstract Account on a remote chain. pub fn execute_register_account( deps: DepsMut, diff --git a/framework/contracts/native/ibc-client/src/contract.rs b/framework/contracts/native/ibc-client/src/contract.rs index bdad8ee9b6..8b170aec76 100644 --- a/framework/contracts/native/ibc-client/src/contract.rs +++ b/framework/contracts/native/ibc-client/src/contract.rs @@ -61,16 +61,9 @@ pub fn execute(deps: DepsMut, env: Env, info: MessageInfo, msg: ExecuteMsg) -> I version_control, } => commands::execute_update_config(deps, info, ans_host, version_control) .map_err(Into::into), - ExecuteMsg::RemoteAction { - host_chain, - action, - callback_info, - } => commands::execute_send_packet(deps, env, info, host_chain, action, callback_info), - ExecuteMsg::RemoteQueries { - host_chain, - queries, - callback_info, - } => commands::execute_send_query(deps, env, info, host_chain, queries, callback_info), + ExecuteMsg::RemoteAction { host_chain, action } => { + commands::execute_send_packet(deps, env, info, host_chain, action) + } ExecuteMsg::RegisterInfrastructure { chain, note, host } => { commands::execute_register_infrastructure(deps, env, info, chain, host, note) } @@ -457,19 +450,17 @@ mod tests { use std::str::FromStr; use abstract_core::{ - ibc::CallbackInfo, ibc_host::{self, HostAction, InternalAction}, manager, objects::{ account::TEST_ACCOUNT_ID, chain_name::ChainName, - version_control::VersionControlError, AccountId, + version_control::VersionControlError, }, }; use abstract_testing::prelude::{ mocked_account_querier_builder, TEST_CHAIN, TEST_MANAGER, TEST_PROXY, }; - use cosmwasm_std::{wasm_execute, Binary}; - use polytone::callbacks::CallbackRequest; + use cosmwasm_std::wasm_execute; use super::*; use crate::commands::PACKET_LIFETIME; @@ -491,7 +482,6 @@ mod tests { link: None, }, }, - callback_info: None, }; let res = execute_as(deps.as_mut(), TEST_MANAGER, msg); @@ -523,7 +513,6 @@ mod tests { namespace: None, install_modules: vec![], }), - callback_info: None, }; let res = execute_as(deps.as_mut(), TEST_PROXY, msg); @@ -565,7 +554,6 @@ mod tests { let msg = ExecuteMsg::RemoteAction { host_chain: chain_name.to_string(), action: action.clone(), - callback_info: None, }; let res = execute_as(deps.as_mut(), TEST_PROXY, msg)?; @@ -596,161 +584,6 @@ mod tests { ); Ok(()) } - - #[test] - fn send_packet_with_callback() -> IbcClientTestResult { - let mut deps = mock_dependencies(); - deps.querier = mocked_account_querier_builder().build(); - mock_init(deps.as_mut())?; - - let chain_name = ChainName::from_str(TEST_CHAIN)?; - let note_contract = Addr::unchecked("note"); - let remote_ibc_host = String::from("test_remote_host"); - - IBC_INFRA.save( - deps.as_mut().storage, - &chain_name, - &IbcInfrastructure { - polytone_note: note_contract.clone(), - remote_abstract_host: remote_ibc_host.clone(), - remote_proxy: None, - }, - )?; - - let action = HostAction::Dispatch { - manager_msg: manager::ExecuteMsg::UpdateInfo { - name: None, - description: None, - link: None, - }, - }; - - let callback_info = CallbackInfo { - id: String::from("id"), - receiver: String::from("receiver"), - msg: Some(Binary(vec![])), - }; - - let callback_request = CallbackRequest { - msg: to_json_binary(&IbcClientCallback::UserRemoteAction { - callback_info: callback_info.clone(), - sender: AccountId::local(1), - })?, - receiver: mock_env().contract.address.to_string(), - }; - - let msg = ExecuteMsg::RemoteAction { - host_chain: chain_name.to_string(), - action: action.clone(), - callback_info: Some(callback_info), - }; - - let res = execute_as(deps.as_mut(), TEST_PROXY, msg)?; - - let note_message = wasm_execute( - note_contract.to_string(), - &polytone_note::msg::ExecuteMsg::Execute { - msgs: vec![wasm_execute( - // The note's remote proxy will call the ibc host - remote_ibc_host, - &ibc_host::ExecuteMsg::Execute { - proxy_address: TEST_PROXY.to_owned(), - account_id: TEST_ACCOUNT_ID, - action, - }, - vec![], - )? - .into()], - callback: Some(callback_request), - timeout_seconds: PACKET_LIFETIME.into(), - }, - vec![], - )?; - - assert_eq!( - IbcClientResponse::action("handle_send_msgs").add_message(note_message), - res - ); - Ok(()) - } - } - - mod remote_query { - use std::str::FromStr; - - use abstract_core::{ - ibc::CallbackInfo, - objects::{account::TEST_ACCOUNT_ID, chain_name::ChainName}, - }; - use cosmwasm_std::{wasm_execute, BankQuery, Binary, QueryRequest}; - use polytone::callbacks::CallbackRequest; - - use super::*; - use crate::commands::PACKET_LIFETIME; - - #[test] - fn works() -> IbcClientTestResult { - let mut deps = mock_dependencies(); - deps.querier = mocked_account_querier_builder().build(); - mock_init(deps.as_mut())?; - - let chain_name = ChainName::from_str(TEST_CHAIN)?; - let note_contract = Addr::unchecked("note"); - let remote_ibc_host = String::from("test_remote_host"); - - IBC_INFRA.save( - deps.as_mut().storage, - &chain_name, - &IbcInfrastructure { - polytone_note: note_contract.clone(), - remote_abstract_host: remote_ibc_host.clone(), - remote_proxy: None, - }, - )?; - - let callback_info = CallbackInfo { - id: String::from("id"), - receiver: String::from("receiver"), - msg: Some(Binary(vec![])), - }; - - let callback_request = CallbackRequest { - msg: to_json_binary(&IbcClientCallback::UserRemoteAction { - sender: TEST_ACCOUNT_ID, - callback_info: callback_info.clone(), - })?, - receiver: mock_env().contract.address.to_string(), - }; - - let queries = vec![QueryRequest::Bank(BankQuery::AllBalances { - address: String::from("addr"), - })]; - - let msg = ExecuteMsg::RemoteQueries { - host_chain: chain_name.to_string(), - queries: queries.clone(), - callback_info, - }; - - let res = execute_as(deps.as_mut(), TEST_PROXY, msg)?; - - let note_message = wasm_execute( - note_contract.to_string(), - &polytone_note::msg::ExecuteMsg::Query { - msgs: queries, - callback: callback_request, - timeout_seconds: PACKET_LIFETIME.into(), - }, - vec![], - )?; - - assert_eq!( - IbcClientResponse::action("handle_send_msgs").add_message(note_message), - res - ); - - Ok(()) - } } mod send_funds { @@ -1139,10 +972,7 @@ mod tests { mod callback { use std::str::FromStr; - use abstract_core::{ - ibc::{CallbackInfo, IbcResponseMsg}, - objects::{account::TEST_ACCOUNT_ID, chain_name::ChainName, AccountId}, - }; + use abstract_core::objects::{account::TEST_ACCOUNT_ID, chain_name::ChainName}; use cosmwasm_std::{from_json, Binary, Event, SubMsgResponse}; use polytone::callbacks::{Callback, CallbackMessage, ExecutionResponse}; @@ -1517,58 +1347,6 @@ mod tests { Ok(()) } - - #[test] - fn user_remote_action() -> IbcClientTestResult { - let mut deps = mock_dependencies(); - mock_init(deps.as_mut())?; - let env = mock_env(); - - let chain_name = ChainName::from_str(TEST_CHAIN)?; - let note = Addr::unchecked("note"); - let remote_proxy = String::from("remote_proxy"); - - REVERSE_POLYTONE_NOTE.save(deps.as_mut().storage, ¬e, &chain_name)?; - let id = String::from("id"); - let callback_info_msg = Binary(vec![]); - let receiver = String::from("receiver"); - let callback_msg = CallbackMessage { - initiator: env.contract.address, - initiator_msg: to_json_binary(&IbcClientCallback::UserRemoteAction { - callback_info: CallbackInfo { - id: id.clone(), - msg: Some(callback_info_msg.clone()), - receiver: receiver.clone(), - }, - sender: AccountId::local(1), - })?, - result: Callback::Execute(Ok(ExecutionResponse { - executed_by: remote_proxy.clone(), - result: vec![], - })), - }; - let msg = ExecuteMsg::Callback(callback_msg.clone()); - - let res = execute_as(deps.as_mut(), note.as_ref(), msg)?; - - assert_eq!( - IbcClientResponse::action("user_specific_callback") - .add_message( - IbcResponseMsg { - id: id.clone(), - msg: Some(callback_info_msg), - result: callback_msg.result, - sender: AccountId::local(1) - } - .into_cosmos_msg(receiver)? - ) - .add_attribute("chain", chain_name.to_string()) - .add_attribute("callback_id", id), - res - ); - - Ok(()) - } } mod list_proxies_by_account_id { use std::str::FromStr; diff --git a/framework/contracts/native/ibc-client/src/ibc.rs b/framework/contracts/native/ibc-client/src/ibc.rs index 9e742dc5c1..014f0576d5 100644 --- a/framework/contracts/native/ibc-client/src/ibc.rs +++ b/framework/contracts/native/ibc-client/src/ibc.rs @@ -1,5 +1,4 @@ use abstract_core::{ - ibc::IbcResponseMsg, ibc_client::{ state::{IBC_INFRA, REVERSE_POLYTONE_NOTE}, IbcClientCallback, @@ -88,21 +87,5 @@ pub fn receive_action_callback( .add_attribute("chain", host_chain.to_string()), ) } - IbcClientCallback::UserRemoteAction { - sender, - callback_info, - } => { - // Here we transfer the callback back to the module that requested it - let callback = IbcResponseMsg { - id: callback_info.id.clone(), - msg: callback_info.msg, - result: callback.result, - sender, - }; - Ok(IbcClientResponse::action("user_specific_callback") - .add_message(callback.into_cosmos_msg(callback_info.receiver)?) - .add_attribute("chain", host_chain.to_string()) - .add_attribute("callback_id", callback_info.id)) - } } } diff --git a/framework/packages/abstract-adapter/src/lib.rs b/framework/packages/abstract-adapter/src/lib.rs index aa33191167..b3f51aadc3 100644 --- a/framework/packages/abstract-adapter/src/lib.rs +++ b/framework/packages/abstract-adapter/src/lib.rs @@ -124,7 +124,7 @@ pub mod mock { }) .with_sudo(|_, _, _, _| Ok(Response::new().set_data("mock_sudo".as_bytes()))) .with_receive(|_, _, _, _, _| Ok(Response::new().set_data("mock_receive".as_bytes()))) - .with_ibc_callbacks(&[("c_id", |deps, _, _, _, _, _, _| { + .with_ibc_callbacks(&[("c_id", |deps, _, _, _, _, _| { IBC_CALLBACK_RECEIVED.save(deps.storage, &true).unwrap(); Ok(Response::new().set_data("mock_callback".as_bytes())) })]) diff --git a/framework/packages/abstract-adapter/src/state.rs b/framework/packages/abstract-adapter/src/state.rs index e9400f231d..40e1379ca9 100644 --- a/framework/packages/abstract-adapter/src/state.rs +++ b/framework/packages/abstract-adapter/src/state.rs @@ -183,7 +183,7 @@ mod tests { .with_query(|_, _, _, _| cosmwasm_std::to_json_binary("mock_query").map_err(Into::into)) .with_sudo(|_, _, _, _| Ok(Response::new().set_data("mock_sudo".as_bytes()))) .with_receive(|_, _, _, _, _| Ok(Response::new().set_data("mock_receive".as_bytes()))) - .with_ibc_callbacks(&[("c_id", |_, _, _, _, _, _, _| { + .with_ibc_callbacks(&[("c_id", |_, _, _, _, _, _| { Ok(Response::new().set_data("mock_callback".as_bytes())) })]) .with_replies(&[(1u64, |_, _, _, msg| { diff --git a/framework/packages/abstract-app/src/lib.rs b/framework/packages/abstract-app/src/lib.rs index 7fa6996a50..30f1d46bf8 100644 --- a/framework/packages/abstract-app/src/lib.rs +++ b/framework/packages/abstract-app/src/lib.rs @@ -33,7 +33,7 @@ pub mod mock { pub use abstract_core::app; use abstract_core::{ manager::ModuleInstallConfig, - objects::{dependency::StaticDependency, module::ModuleInfo, AccountId}, + objects::{dependency::StaticDependency, module::ModuleInfo}, }; use abstract_interface::{AppDeployer, DependencyCreation}; use cosmwasm_schema::QueryResponses; @@ -41,7 +41,7 @@ pub mod mock { use cosmwasm_std::{to_json_binary, Response, StdError}; use cw_controllers::AdminError; use cw_orch::prelude::*; - use cw_storage_plus::{Item, Map}; + use cw_storage_plus::Item; pub type AppTestResult = Result<(), MockError>; @@ -68,9 +68,6 @@ pub mod mock { #[returns(ReceivedIbcCallbackStatus)] GetReceivedIbcCallbackStatus {}, - - #[returns(ReceivedIbcCallbackStatus)] - GetReceivedIbcCallbackSenderStatus { sender: AccountId }, } #[cosmwasm_schema::cw_serde] @@ -137,7 +134,6 @@ pub mod mock { // Easy way to see if an ibc-callback was actually received. pub const IBC_CALLBACK_RECEIVED: Item = Item::new("ibc_callback_received"); - pub const IBC_CALLBACK_SENDER: Map = Map::new("ibc_callback_sender"); pub const MOCK_APP_WITH_DEP: MockAppContract = MockAppContract::new(TEST_WITH_DEP_MODULE_ID, TEST_VERSION, None) @@ -156,20 +152,12 @@ pub mod mock { }) .map_err(Into::into) } - MockQueryMsg::GetReceivedIbcCallbackSenderStatus { sender } => { - to_json_binary(&ReceivedIbcCallbackStatus { - received: IBC_CALLBACK_SENDER.load(deps.storage, sender)?, - }) - .map_err(Into::into) - } }) .with_sudo(|_, _, _, _| Ok(Response::new().set_data("mock_sudo".as_bytes()))) .with_receive(|_, _, _, _, _| Ok(Response::new().set_data("mock_receive".as_bytes()))) - .with_ibc_callbacks(&[("c_id", |deps, _, _, _, sender, _, _| { + .with_ibc_callbacks(&[("c_id", |deps, _, _, _, _, _| { IBC_CALLBACK_RECEIVED.save(deps.storage, &true).unwrap(); - IBC_CALLBACK_SENDER - .save(deps.storage, sender, &true) - .unwrap(); + Ok(Response::new().add_attribute("mock_callback", "executed")) })]) .with_dependencies(&[StaticDependency::new(TEST_MODULE_ID, &[TEST_VERSION])]) diff --git a/framework/packages/abstract-app/src/state.rs b/framework/packages/abstract-app/src/state.rs index 1b85431a9d..e0651a835a 100644 --- a/framework/packages/abstract-app/src/state.rs +++ b/framework/packages/abstract-app/src/state.rs @@ -193,7 +193,7 @@ mod tests { .with_query(|_, _, _, _| cosmwasm_std::to_json_binary("mock_query").map_err(Into::into)) .with_sudo(|_, _, _, _| Ok(Response::new().set_data("mock_sudo".as_bytes()))) .with_receive(|_, _, _, _, _| Ok(Response::new().set_data("mock_receive".as_bytes()))) - .with_ibc_callbacks(&[("c_id", |_, _, _, _, _, _, _| { + .with_ibc_callbacks(&[("c_id", |_, _, _, _, _, _| { Ok(Response::new().set_data("mock_callback".as_bytes())) })]) .with_replies(&[(1u64, |_, _, _, msg| { diff --git a/framework/packages/abstract-core/src/native/ibc.rs b/framework/packages/abstract-core/src/native/ibc.rs index 85fc9b3bf2..65b62bf881 100644 --- a/framework/packages/abstract-core/src/native/ibc.rs +++ b/framework/packages/abstract-core/src/native/ibc.rs @@ -2,8 +2,6 @@ use cosmwasm_std::{to_json_binary, wasm_execute, Binary, CosmosMsg, StdResult}; use polytone::callbacks::Callback; use schemars::JsonSchema; -use crate::objects::AccountId; - // CallbackInfo from modules, that is turned into an IbcResponseMsg by the ibc client #[cosmwasm_schema::cw_serde] pub struct CallbackInfo { @@ -24,9 +22,6 @@ pub struct IbcResponseMsg { /// The msg sent with the callback request. /// This is usually used to provide information to the ibc callback function for context pub msg: Option, - /// The account id of the sender of the original IBC message - /// This is verified by the ibc-client and can be trusted inside applications - pub sender: AccountId, pub result: Callback, } diff --git a/framework/packages/abstract-core/src/native/ibc_client.rs b/framework/packages/abstract-core/src/native/ibc_client.rs index 45726cdada..150ece3b1c 100644 --- a/framework/packages/abstract-core/src/native/ibc_client.rs +++ b/framework/packages/abstract-core/src/native/ibc_client.rs @@ -1,10 +1,9 @@ use cosmwasm_schema::QueryResponses; -use cosmwasm_std::{Addr, Coin, Empty, QueryRequest}; +use cosmwasm_std::{Addr, Coin}; use polytone::callbacks::CallbackMessage; use self::state::IbcInfrastructure; use crate::{ - ibc::CallbackInfo, ibc_host::HostAction, manager::ModuleInstallConfig, objects::{account::AccountId, chain_name::ChainName, AssetEntry}, @@ -106,39 +105,19 @@ pub enum ExecuteMsg { host_chain: String, // execute the custom host function action: HostAction, - // optional callback info - callback_info: Option, - }, - /// Allows to query something on a remote contract and act on that query result - /// This has to be an Execute variant for IBC queries - RemoteQueries { - // host chain to be executed on - // Example: "osmosis" - host_chain: String, - // execute following queries - queries: Vec>, - // mandatory callback info - callback_info: CallbackInfo, }, RemoveHost { host_chain: String, }, - /// Callback from the Polytone implementation - /// This is only triggered when a contract execution is succesful + /// This is NOT ONLY triggered when a contract execution is successful Callback(CallbackMessage), } /// This enum is used for sending callbacks to the note contract of the IBC client #[cosmwasm_schema::cw_serde] pub enum IbcClientCallback { - UserRemoteAction { - sender: AccountId, - callback_info: CallbackInfo, - }, - CreateAccount { - account_id: AccountId, - }, + CreateAccount { account_id: AccountId }, WhoAmI {}, } @@ -250,7 +229,6 @@ mod tests { use crate::ibc::IbcCallbackMsg; use crate::ibc::IbcResponseMsg; - use crate::objects::AccountId; // ... (other test functions) #[test] @@ -265,7 +243,6 @@ mod tests { id: callback_id, msg: Some(callback_msg), result, - sender: AccountId::local(1), }; let actual: CosmosMsg = response_msg diff --git a/framework/packages/abstract-interface/src/account/manager.rs b/framework/packages/abstract-interface/src/account/manager.rs index ef5e65adec..cd3c7d5bad 100644 --- a/framework/packages/abstract-interface/src/account/manager.rs +++ b/framework/packages/abstract-interface/src/account/manager.rs @@ -1,7 +1,6 @@ pub use abstract_core::manager::{ExecuteMsgFns as ManagerExecFns, QueryMsgFns as ManagerQueryFns}; use abstract_core::{ adapter::{self, AdapterBaseMsg}, - ibc::CallbackInfo, ibc_host::{HelperAction, HostAction}, manager::*, module_factory::SimulateInstallModulesResponse, @@ -208,14 +207,12 @@ impl Manager { &self, host_chain: &str, msg: ExecuteMsg, - callback_info: Option, ) -> Result<::Response, crate::AbstractInterfaceError> { let msg = abstract_core::proxy::ExecuteMsg::IbcAction { msgs: vec![abstract_core::ibc_client::ExecuteMsg::RemoteAction { host_chain: host_chain.into(), action: HostAction::Dispatch { manager_msg: msg }, - callback_info, }], }; @@ -227,7 +224,6 @@ impl Manager { host_chain: &str, module_id: &str, msg: Binary, - callback_info: Option, ) -> Result<::Response, crate::AbstractInterfaceError> { let msg = abstract_core::proxy::ExecuteMsg::IbcAction { @@ -239,7 +235,6 @@ impl Manager { exec_msg: msg, }, }, - callback_info, }], }; @@ -249,14 +244,12 @@ impl Manager { pub fn send_all_funds_back( &self, host_chain: &str, - callback_info: Option, ) -> Result<::Response, crate::AbstractInterfaceError> { let msg = abstract_core::proxy::ExecuteMsg::IbcAction { msgs: vec![abstract_core::ibc_client::ExecuteMsg::RemoteAction { host_chain: host_chain.into(), action: HostAction::Helpers(HelperAction::SendAllBack), - callback_info, }], }; diff --git a/framework/packages/abstract-sdk/src/apis/ibc.rs b/framework/packages/abstract-sdk/src/apis/ibc.rs index 1c17a55afc..424851c8fd 100644 --- a/framework/packages/abstract-sdk/src/apis/ibc.rs +++ b/framework/packages/abstract-sdk/src/apis/ibc.rs @@ -3,7 +3,6 @@ //! use abstract_core::{ - ibc::CallbackInfo, ibc_client::ExecuteMsg as IbcClientMsg, ibc_host::HostAction, manager::ModuleInstallConfig, @@ -131,7 +130,6 @@ impl<'a, T: IbcInterface> IbcClient<'a, T> { )], }, }, - None, ) } @@ -148,7 +146,6 @@ impl<'a, T: IbcInterface> IbcClient<'a, T> { modules: vec![ModuleInstallConfig::new(module, None)], }, }, - None, ) } @@ -167,7 +164,6 @@ impl<'a, T: IbcInterface> IbcClient<'a, T> { exec_msg: to_json_binary(exec_msg)?, }, }, - None, ) } /// Call a [`HostAction`] on the host of the provided `host_chain`. @@ -175,16 +171,11 @@ impl<'a, T: IbcInterface> IbcClient<'a, T> { &self, host_chain: String, action: HostAction, - callback: Option, ) -> AbstractSdkResult { Ok(wasm_execute( self.base.proxy_address(self.deps)?.to_string(), &ExecuteMsg::IbcAction { - msgs: vec![IbcClientMsg::RemoteAction { - host_chain, - action, - callback_info: callback, - }], + msgs: vec![IbcClientMsg::RemoteAction { host_chain, action }], }, vec![], )? @@ -233,7 +224,6 @@ mod test { is_suspended: None, }, }, - None, ); assert_that!(msg).is_ok(); @@ -247,7 +237,6 @@ mod test { is_suspended: None, }, }, - callback_info: None, }], }) .unwrap(), @@ -256,51 +245,6 @@ mod test { assert_that!(msg.unwrap()).is_equal_to::(expected); } - /// Tests that a host_action can be built with a callback with more retries - #[test] - fn test_host_action_with_callback() { - let deps = mock_dependencies(); - let stub = MockModule::new(); - let client = stub.ibc_client(deps.as_ref()); - - let expected_callback = CallbackInfo { - receiver: "callback_receiver".to_string(), - id: "callback_id".to_string(), - msg: None, - }; - - let actual = client.host_action( - TEST_HOST_CHAIN.into(), - HostAction::Dispatch { - manager_msg: abstract_core::manager::ExecuteMsg::UpdateStatus { - is_suspended: None, - }, - }, - Some(expected_callback.clone()), - ); - - assert_that!(actual).is_ok(); - - let expected = CosmosMsg::Wasm(WasmMsg::Execute { - contract_addr: TEST_PROXY.to_string(), - msg: to_json_binary(&ExecuteMsg::IbcAction { - msgs: vec![IbcClientMsg::RemoteAction { - host_chain: TEST_HOST_CHAIN.into(), - action: HostAction::Dispatch { - manager_msg: abstract_core::manager::ExecuteMsg::UpdateStatus { - is_suspended: None, - }, - }, - callback_info: Some(expected_callback), - }], - }) - .unwrap(), - funds: vec![], - }); - - assert_that!(actual.unwrap()).is_equal_to::(expected); - } - /// Tests that the ics_20 transfer can be built and that the funds are passed into the sendFunds message not the execute message #[test] fn test_ics20_transfer() { diff --git a/framework/packages/abstract-sdk/src/base/contract_base.rs b/framework/packages/abstract-sdk/src/base/contract_base.rs index 1df6a827ec..65955c26c2 100644 --- a/framework/packages/abstract-sdk/src/base/contract_base.rs +++ b/framework/packages/abstract-sdk/src/base/contract_base.rs @@ -1,4 +1,3 @@ -use abstract_core::objects::AccountId; use cosmwasm_std::{Binary, Deps, DepsMut, Env, MessageInfo, Reply, Response, Storage}; use cw2::{ContractVersion, CONTRACT}; use cw_storage_plus::Item; @@ -33,15 +32,8 @@ pub type QueryHandlerFn = type CallbackMessage = Option; // ANCHOR: ibc /// Function signature for an IBC callback handler. -pub type IbcCallbackHandlerFn = fn( - DepsMut, - Env, - MessageInfo, - Module, - AccountId, - CallbackMessage, - Callback, -) -> Result; +pub type IbcCallbackHandlerFn = + fn(DepsMut, Env, MessageInfo, Module, CallbackMessage, Callback) -> Result; // ANCHOR_END: ibc // ANCHOR: mig @@ -368,7 +360,7 @@ mod test { fn test_with_ibc_callback_handlers() { const IBC_ID: &str = "aoeu"; const HANDLER: IbcCallbackHandlerFn = - |_, _, _, _, _, _, _| Ok(Response::default().add_attribute("test", "ibc")); + |_, _, _, _, _, _| Ok(Response::default().add_attribute("test", "ibc")); let contract = MockAppContract::new("test_contract", "0.1.0", ModuleMetadata::default()) .with_ibc_callbacks(&[(IBC_ID, HANDLER)]); diff --git a/framework/packages/abstract-sdk/src/base/endpoints/ibc_callback.rs b/framework/packages/abstract-sdk/src/base/endpoints/ibc_callback.rs index cdf3248c91..6e11c4c6a0 100644 --- a/framework/packages/abstract-sdk/src/base/endpoints/ibc_callback.rs +++ b/framework/packages/abstract-sdk/src/base/endpoints/ibc_callback.rs @@ -29,12 +29,11 @@ pub trait IbcCallbackEndpoint: Handler { id, msg: callback_msg, result, - sender, } = msg; let maybe_handler = self.maybe_ibc_callback_handler(&id); maybe_handler.map_or_else( || Ok(Response::new()), - |handler| handler(deps, env, info, self, sender, callback_msg, result), + |handler| handler(deps, env, info, self, callback_msg, result), ) } } diff --git a/interchain/tests/src/interchain_accounts.rs b/interchain/tests/src/interchain_accounts.rs index 7b8b9b6095..0edc782ea9 100644 --- a/interchain/tests/src/interchain_accounts.rs +++ b/interchain/tests/src/interchain_accounts.rs @@ -74,35 +74,24 @@ pub fn create_test_remote_account AnyResult<()> { - logger_test_init(); - let mock_interchain = - MockBech32InterchainEnv::new(vec![(JUNO, "juno"), (STARGAZE, "stargaze")]); - - // We just verified all steps pass - let (abstr_origin, _abstr_remote) = ibc_abstract_setup(&mock_interchain, JUNO, STARGAZE)?; - - let remote_name = ChainName::from_chain_id(STARGAZE).to_string(); - - let (origin_account, _remote_account_id) = - create_test_remote_account(&abstr_origin, JUNO, STARGAZE, &mock_interchain, None)?; - - let app = MockAppWithDepI::new( - TEST_WITH_DEP_MODULE_ID, - abstr_origin.version_control.get_chain().clone(), - ); - - let app_dep = MockAppI::new( - TEST_MODULE_ID, - abstr_origin.version_control.get_chain().clone(), - ); - - let app_account = - abstr_origin - .account_factory - .create_default_account(GovernanceDetails::Monarchy { - monarch: abstr_origin - .version_control - .get_chain() - .sender() - .into_string(), - })?; - - let app_deps_account = - abstr_origin - .account_factory - .create_default_account(GovernanceDetails::Monarchy { - monarch: abstr_origin - .version_control - .get_chain() - .sender() - .into_string(), - })?; - - abstr_origin.version_control.claim_namespace( - app_account.manager.config()?.account_id, - TEST_WITH_DEP_NAMESPACE.to_owned(), - )?; - abstr_origin.version_control.claim_namespace( - app_deps_account.manager.config()?.account_id, - TEST_NAMESPACE.to_owned(), - )?; - - app.deploy(TEST_VERSION.parse()?, DeployStrategy::Try)?; - app_dep.deploy(TEST_VERSION.parse()?, DeployStrategy::Try)?; - - origin_account.install_app(&app_dep, &MockInitMsg {}, None)?; - origin_account.install_app(&app, &MockInitMsg {}, None)?; - let res: ModuleAddressesResponse = origin_account - .manager - .module_addresses(vec![TEST_WITH_DEP_MODULE_ID.to_owned()])?; - - assert_eq!(1, res.modules.len()); - - let module_address = res.modules[0].1.to_string(); - - let new_name = "Funky Crazy Name"; - let new_description = "Funky new account with wonderful capabilities"; - let new_link = "https://abstract.money"; - - // The user on origin chain wants to change the account description - let ibc_action_result = origin_account.manager.execute_on_remote( - &remote_name, - ManagerExecuteMsg::UpdateInfo { - name: Some(new_name.to_string()), - description: Some(new_description.to_string()), - link: Some(new_link.to_string()), - }, - Some(CallbackInfo { - id: String::from("c_id"), - msg: None, - receiver: module_address, - }), - )?; - - assert_callback_status(&app, false)?; - - mock_interchain.wait_ibc(JUNO, ibc_action_result)?; - - // Switched to true by the callback. - assert_callback_status(&app, true)?; - - Ok(()) - } - - #[test] - fn anyone_can_call_account_ibc_app_callback() -> AnyResult<()> { - logger_test_init(); - let mock_interchain = - MockBech32InterchainEnv::new(vec![(JUNO, "juno"), (STARGAZE, "stargaze")]); - - // We just verified all steps pass - let (abstr_origin, _abstr_remote) = ibc_abstract_setup(&mock_interchain, JUNO, STARGAZE)?; - - let remote_name = ChainName::from_chain_id(STARGAZE).to_string(); - - let (origin_account, _remote_account_id) = - create_test_remote_account(&abstr_origin, JUNO, STARGAZE, &mock_interchain, None)?; - - let app = MockAppWithDepI::new( - TEST_WITH_DEP_MODULE_ID, - abstr_origin.version_control.get_chain().clone(), - ); - - let app_dep = MockAppI::new( - TEST_MODULE_ID, - abstr_origin.version_control.get_chain().clone(), - ); - - let app_account = - abstr_origin - .account_factory - .create_default_account(GovernanceDetails::Monarchy { - monarch: abstr_origin - .version_control - .get_chain() - .sender() - .into_string(), - })?; - - let app_deps_account = - abstr_origin - .account_factory - .create_default_account(GovernanceDetails::Monarchy { - monarch: abstr_origin - .version_control - .get_chain() - .sender() - .into_string(), - })?; - - abstr_origin.version_control.claim_namespace( - app_account.manager.config()?.account_id, - TEST_WITH_DEP_NAMESPACE.to_owned(), - )?; - abstr_origin.version_control.claim_namespace( - app_deps_account.manager.config()?.account_id, - TEST_NAMESPACE.to_owned(), - )?; - - app.deploy(TEST_VERSION.parse()?, DeployStrategy::Try)?; - app_dep.deploy(TEST_VERSION.parse()?, DeployStrategy::Try)?; - - origin_account.install_app(&app_dep, &MockInitMsg {}, None)?; - origin_account.install_app(&app, &MockInitMsg {}, None)?; - let res: ModuleAddressesResponse = origin_account - .manager - .module_addresses(vec![TEST_WITH_DEP_MODULE_ID.to_owned()])?; - - assert_eq!(1, res.modules.len()); - - let module_address = res.modules[0].1.to_string(); - - let new_name = "Funky Crazy Name"; - let new_description = "Funky new account with wonderful capabilities"; - let new_link = "https://abstract.money"; - - // The user on origin chain wants to change the account description - let ibc_action_result = origin_account.manager.execute_on_remote( - &remote_name, - ManagerExecuteMsg::UpdateInfo { - name: Some(new_name.to_string()), - description: Some(new_description.to_string()), - link: Some(new_link.to_string()), - }, - Some(CallbackInfo { - id: String::from("c_id"), - msg: None, - receiver: module_address.clone(), - }), - )?; - - assert_callback_status(&app, false)?; - assert_callback_sender(&app, origin_account.id()?, false)?; - - mock_interchain.wait_ibc(JUNO, ibc_action_result)?; - - // Switched to true by the callback. - assert_callback_status(&app, true)?; - assert_callback_sender(&app, origin_account.id()?, true)?; - - // A new account sends an action with a callback on another account user on origin chain wants to change the account description - let (new_account, _) = - create_test_remote_account(&abstr_origin, JUNO, STARGAZE, &mock_interchain, None)?; - let ibc_action_result = new_account.manager.execute_on_remote( - &remote_name, - ManagerExecuteMsg::UpdateInfo { - name: Some(new_name.to_string()), - description: Some(new_description.to_string()), - link: Some(new_link.to_string()), - }, - Some(CallbackInfo { - id: String::from("c_id"), - msg: None, - receiver: module_address, - }), - )?; - - assert_callback_sender(&app, new_account.id()?, false)?; - - mock_interchain.wait_ibc(JUNO, ibc_action_result)?; - - // Switched to true by the callback. - assert_callback_sender(&app, new_account.id()?, true)?; - - Ok(()) - } - - #[test] - fn ibc_adapter_callback() -> AnyResult<()> { - logger_test_init(); - let mock_interchain = - MockBech32InterchainEnv::new(vec![(JUNO, "juno"), (STARGAZE, "stargaze")]); - - // We just verified all steps pass - let (abstr_origin, _abstr_remote) = ibc_abstract_setup(&mock_interchain, JUNO, STARGAZE)?; - - let remote_name = ChainName::from_chain_id(STARGAZE).to_string(); - - let (origin_account, _remote_account_id) = - create_test_remote_account(&abstr_origin, JUNO, STARGAZE, &mock_interchain, None)?; - - let adapter = MockAdapterI::new( - TEST_MODULE_ID, - abstr_origin.version_control.get_chain().clone(), - ); - - let adapter_account = - abstr_origin - .account_factory - .create_default_account(GovernanceDetails::Monarchy { - monarch: abstr_origin - .version_control - .get_chain() - .sender() - .into_string(), - })?; - - abstr_origin.version_control.claim_namespace( - adapter_account.manager.config()?.account_id, - TEST_NAMESPACE.to_owned(), - )?; - - adapter.deploy( - TEST_VERSION.parse()?, - abstract_adapter::mock::MockInitMsg {}, - DeployStrategy::Try, - )?; - - origin_account.install_adapter(&adapter, None)?; - let res: ModuleAddressesResponse = origin_account - .manager - .module_addresses(vec![TEST_MODULE_ID.to_owned()])?; - - assert_eq!(1, res.modules.len()); - - let module_address = res.modules[0].1.to_string(); - - let new_name = "Funky Crazy Name"; - let new_description = "Funky new account with wonderful capabilities"; - let new_link = "https://abstract.money"; - - // The user on origin chain wants to change the account description - let ibc_action_result = origin_account.manager.execute_on_remote( - &remote_name, - ManagerExecuteMsg::UpdateInfo { - name: Some(new_name.to_string()), - description: Some(new_description.to_string()), - link: Some(new_link.to_string()), - }, - Some(CallbackInfo { - id: String::from("c_id"), - msg: None, - receiver: module_address, - }), - )?; - - assert_adapter_callback_status(&adapter, false)?; - - mock_interchain.wait_ibc(JUNO, ibc_action_result)?; - - // Switched to true by the callback. - assert_adapter_callback_status(&adapter, true)?; - - Ok(()) - } - - fn assert_callback_status(app: &MockAppWithDepI, status: bool) -> AnyResult<()> { - let get_received_ibc_callback_status_res: ReceivedIbcCallbackStatus = - app.get_received_ibc_callback_status()?; - - assert_eq!( - ReceivedIbcCallbackStatus { received: status }, - get_received_ibc_callback_status_res - ); - Ok(()) - } - - fn assert_callback_sender( - app: &MockAppWithDepI, - account_id: AccountId, - status: bool, - ) -> AnyResult<()> { - let get_received_ibc_callback_status_res = app - .get_received_ibc_callback_sender_status(account_id) - .map(|r| r.received) - .unwrap_or(false); - - assert_eq!(status, get_received_ibc_callback_status_res); - Ok(()) - } - - fn assert_adapter_callback_status( - app: &MockAdapterI, - status: bool, - ) -> AnyResult<()> { - let get_received_ibc_callback_status_res = app.get_received_ibc_callback_status()?; - - assert_eq!( - abstract_adapter::mock::ReceivedIbcCallbackStatus { received: status }, - get_received_ibc_callback_status_res - ); - Ok(()) - } - #[test] fn test_multi_hop_account_creation() -> AnyResult<()> { logger_test_init(); @@ -616,7 +267,6 @@ mod test { ManagerExecuteMsg::UpdateSettings { ibc_enabled: Some(true), }, - None, )?; mock_interchain.wait_ibc(JUNO, enable_ibc_tx)?; @@ -633,7 +283,6 @@ mod test { install_modules: vec![], }], })?, - None, )?; mock_interchain.wait_ibc(JUNO, create_account_remote_tx)?; @@ -740,7 +389,6 @@ mod test { )? .into()], })?, - None, )?; // The create remote account tx is passed ? @@ -1086,7 +734,7 @@ mod test { // Send all back. let send_funds_back_tx = origin_account .manager - .send_all_funds_back(&ChainName::from_chain_id(STARGAZE).to_string(), None)?; + .send_all_funds_back(&ChainName::from_chain_id(STARGAZE).to_string())?; mock_interchain.wait_ibc(JUNO, send_funds_back_tx)?; diff --git a/modules/contracts/adapters/cw-staking/src/handlers/execute.rs b/modules/contracts/adapters/cw-staking/src/handlers/execute.rs index 0f9c25231d..59fe6985b0 100644 --- a/modules/contracts/adapters/cw-staking/src/handlers/execute.rs +++ b/modules/contracts/adapters/cw-staking/src/handlers/execute.rs @@ -92,7 +92,7 @@ fn handle_ibc_request( // If the calling entity is a contract, we provide a callback on successful cross-chain-staking let maybe_contract_info = deps.querier.query_wasm_contract_info(info.sender.clone()); - let callback = if maybe_contract_info.is_err() { + let _callback = if maybe_contract_info.is_err() { None } else { Some(CallbackInfo { @@ -104,7 +104,7 @@ fn handle_ibc_request( receiver: info.sender.into_string(), }) }; - let ibc_action_msg = ibc_client.host_action(host_chain.to_string(), host_action, callback)?; + let ibc_action_msg = ibc_client.host_action(host_chain.to_string(), host_action)?; Ok(adapter .custom_response("handle_ibc_request", vec![("provider", provider_name)]) diff --git a/modules/contracts/adapters/dex/src/handlers/execute.rs b/modules/contracts/adapters/dex/src/handlers/execute.rs index 73285b18e0..ca4b72c217 100644 --- a/modules/contracts/adapters/dex/src/handlers/execute.rs +++ b/modules/contracts/adapters/dex/src/handlers/execute.rs @@ -167,7 +167,7 @@ fn handle_ibc_request( // If the calling entity is a contract, we provide a callback on successful swap let maybe_contract_info = deps.querier.query_wasm_contract_info(info.sender.clone()); - let callback = if maybe_contract_info.is_err() { + let _callback = if maybe_contract_info.is_err() { None } else { Some(CallbackInfo { @@ -179,7 +179,7 @@ fn handle_ibc_request( receiver: info.sender.into_string(), }) }; - let ibc_action_msg = ibc_client.host_action(host_chain.to_string(), host_action, callback)?; + let ibc_action_msg = ibc_client.host_action(host_chain.to_string(), host_action)?; // call both messages on the proxy Ok(Response::new().add_messages(vec![ics20_transfer_msg, ibc_action_msg])) From 1eac1f8cc2ef81be2c40ef115bf690ba66178f6f Mon Sep 17 00:00:00 2001 From: Kayanski Date: Mon, 11 Mar 2024 12:41:51 +0000 Subject: [PATCH 13/37] Add source module in callback --- framework/contracts/native/ibc-client/src/ibc.rs | 7 +------ framework/packages/abstract-core/src/native/ibc.rs | 3 +++ 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/framework/contracts/native/ibc-client/src/ibc.rs b/framework/contracts/native/ibc-client/src/ibc.rs index 3e638acb18..1fd4947217 100644 --- a/framework/contracts/native/ibc-client/src/ibc.rs +++ b/framework/contracts/native/ibc-client/src/ibc.rs @@ -104,16 +104,11 @@ pub fn receive_action_callback( callback_info, sender_module, } => { - // resolve the address for that sender module - let vc = CONFIG.load(deps.storage)?.version_control; - - // TODO This will be used when the sender is part of the callback msg (https://github.com/AbstractSDK/abstract/pull/277) - let addr = sender_module.addr(deps.as_ref(), vc)?; - let callback = IbcResponseMsg { id: callback_info.id.clone(), msg: callback_info.msg, result: callback.result, + source_module, }; Ok(IbcClientResponse::action("module_specific_callback") .add_message(callback.into_cosmos_msg(callback_info.receiver)?) diff --git a/framework/packages/abstract-core/src/native/ibc.rs b/framework/packages/abstract-core/src/native/ibc.rs index 977c405386..e3ea370f52 100644 --- a/framework/packages/abstract-core/src/native/ibc.rs +++ b/framework/packages/abstract-core/src/native/ibc.rs @@ -27,6 +27,9 @@ pub struct IbcResponseMsg { /// The msg sent with the callback request. /// This is usually used to provide information to the ibc callback function for context pub msg: Option, + /// This identifies the module that called the action initially + /// This SHOULD be used by the callback function to identify the callback source + pub source_module: InstalledModuleIdentification, pub result: Callback, } From 285073307c112d143f94839e2cbdfc9a5816e5ca Mon Sep 17 00:00:00 2001 From: Kayanski Date: Mon, 11 Mar 2024 12:56:17 +0000 Subject: [PATCH 14/37] Fixed tests --- framework/packages/abstract-adapter/src/state.rs | 2 +- framework/packages/abstract-app/src/lib.rs | 14 +++++++++----- framework/packages/abstract-app/src/state.rs | 2 +- .../abstract-core/src/native/ibc_client.rs | 3 ++- .../abstract-sdk/src/base/contract_base.rs | 2 +- 5 files changed, 14 insertions(+), 9 deletions(-) diff --git a/framework/packages/abstract-adapter/src/state.rs b/framework/packages/abstract-adapter/src/state.rs index b5ca25a215..9ca9412d09 100644 --- a/framework/packages/abstract-adapter/src/state.rs +++ b/framework/packages/abstract-adapter/src/state.rs @@ -191,7 +191,7 @@ mod tests { .with_query(|_, _, _, _| cosmwasm_std::to_json_binary("mock_query").map_err(Into::into)) .with_sudo(|_, _, _, _| Ok(Response::new().set_data("mock_sudo".as_bytes()))) .with_receive(|_, _, _, _, _| Ok(Response::new().set_data("mock_receive".as_bytes()))) - .with_ibc_callbacks(&[("c_id", |_, _, _, _, _, _| { + .with_ibc_callbacks(&[("c_id", |_, _, _, _, _, _, _| { Ok(Response::new().set_data("mock_callback".as_bytes())) })]) .with_replies(&[(1u64, |_, _, _, msg| { diff --git a/framework/packages/abstract-app/src/lib.rs b/framework/packages/abstract-app/src/lib.rs index 061f76174a..508ddab440 100644 --- a/framework/packages/abstract-app/src/lib.rs +++ b/framework/packages/abstract-app/src/lib.rs @@ -32,6 +32,7 @@ pub use abstract_testing; pub mod mock { pub use abstract_core::app; use abstract_core::{ + ibc_client::InstalledModuleIdentification, manager::ModuleInstallConfig, objects::{dependency::StaticDependency, module::ModuleInfo}, }; @@ -75,7 +76,7 @@ pub mod mock { #[cosmwasm_schema::cw_serde] pub struct ReceivedIbcCallbackStatus { - pub received: bool, + pub received: Option, } #[cosmwasm_schema::cw_serde] @@ -133,12 +134,13 @@ pub mod mock { MockAppContract::new(TEST_MODULE_ID, TEST_VERSION, None); // Easy way to see if an ibc-callback was actually received. - pub const IBC_CALLBACK_RECEIVED: Item = Item::new("ibc_callback_received"); + pub const IBC_CALLBACK_RECEIVED: Item> = + Item::new("ibc_callback_received"); pub const MOCK_APP_WITH_DEP: MockAppContract = MockAppContract::new(TEST_WITH_DEP_MODULE_ID, TEST_VERSION, None) .with_instantiate(|deps, _, _, _, _| { - IBC_CALLBACK_RECEIVED.save(deps.storage, &false)?; + IBC_CALLBACK_RECEIVED.save(deps.storage, &None)?; Ok(Response::new().set_data("mock_init".as_bytes())) }) .with_execute(|_, _, _, _, _| Ok(Response::new().set_data("mock_exec".as_bytes()))) @@ -155,8 +157,10 @@ pub mod mock { }) .with_sudo(|_, _, _, _| Ok(Response::new().set_data("mock_sudo".as_bytes()))) .with_receive(|_, _, _, _, _| Ok(Response::new().set_data("mock_receive".as_bytes()))) - .with_ibc_callbacks(&[("c_id", |deps, _, _, _, _, _, _| { - IBC_CALLBACK_RECEIVED.save(deps.storage, &true).unwrap(); + .with_ibc_callbacks(&[("c_id", |deps, _, _, _, module, _, _| { + IBC_CALLBACK_RECEIVED + .save(deps.storage, &Some(module)) + .unwrap(); Ok(Response::new().add_attribute("mock_callback", "executed")) })]) diff --git a/framework/packages/abstract-app/src/state.rs b/framework/packages/abstract-app/src/state.rs index d8b2b5cdae..eb3def4b5d 100644 --- a/framework/packages/abstract-app/src/state.rs +++ b/framework/packages/abstract-app/src/state.rs @@ -202,7 +202,7 @@ mod tests { .with_query(|_, _, _, _| cosmwasm_std::to_json_binary("mock_query").map_err(Into::into)) .with_sudo(|_, _, _, _| Ok(Response::new().set_data("mock_sudo".as_bytes()))) .with_receive(|_, _, _, _, _| Ok(Response::new().set_data("mock_receive".as_bytes()))) - .with_ibc_callbacks(&[("c_id", |_, _, _, _, _, _| { + .with_ibc_callbacks(&[("c_id", |_, _, _, _, _, _, _| { Ok(Response::new().set_data("mock_callback".as_bytes())) })]) .with_replies(&[(1u64, |_, _, _, msg| { diff --git a/framework/packages/abstract-core/src/native/ibc_client.rs b/framework/packages/abstract-core/src/native/ibc_client.rs index 45cf00e3fe..17f82650ef 100644 --- a/framework/packages/abstract-core/src/native/ibc_client.rs +++ b/framework/packages/abstract-core/src/native/ibc_client.rs @@ -313,6 +313,7 @@ mod tests { use crate::ibc::IbcCallbackMsg; use crate::ibc::IbcResponseMsg; use crate::objects::module::ModuleInfo; + use crate::objects::AccountId; use super::InstalledModuleIdentification; // ... (other test functions) @@ -331,7 +332,7 @@ mod tests { result, sender_module: InstalledModuleIdentification { module_info: ModuleInfo::from_id_latest("tester:test-module").unwrap(), - account_id: AccountId::local(1), + account_id: Some(AccountId::local(1)), }, }; diff --git a/framework/packages/abstract-sdk/src/base/contract_base.rs b/framework/packages/abstract-sdk/src/base/contract_base.rs index 62c1e191b5..e9c417e8e9 100644 --- a/framework/packages/abstract-sdk/src/base/contract_base.rs +++ b/framework/packages/abstract-sdk/src/base/contract_base.rs @@ -386,7 +386,7 @@ mod test { fn test_with_ibc_callback_handlers() { const IBC_ID: &str = "aoeu"; const HANDLER: IbcCallbackHandlerFn = - |_, _, _, _, _, _| Ok(Response::default().add_attribute("test", "ibc")); + |_, _, _, _, _, _, _| Ok(Response::default().add_attribute("test", "ibc")); let contract = MockAppContract::new("test_contract", "0.1.0", ModuleMetadata::default()) .with_ibc_callbacks(&[(IBC_ID, HANDLER)]); From 4b9bcf916d24135ab8ab427cceea2e3484c979c4 Mon Sep 17 00:00:00 2001 From: Kayanski Date: Mon, 11 Mar 2024 13:07:03 +0000 Subject: [PATCH 15/37] Fixed tests --- .../tests/snapshots/adapters__account_install_adapter.snap | 3 ++- .../tests/snapshots/adapters__install_one_adapter.snap | 3 ++- .../snapshots/adapters__install_one_adapter_with_fee.snap | 3 ++- ...__installing_specific_version_should_install_expected.snap | 3 ++- .../adapters__reinstalling_adapter_should_be_allowed.snap | 3 ++- ...pters__reinstalling_new_version_should_install_latest.snap | 3 ++- .../manager/tests/snapshots/apps__account_install_app.snap | 3 ++- .../snapshots/apps__execute_on_proxy_through_manager.snap | 3 ++- .../install_modules__adds_module_to_account_modules.snap | 3 ++- .../tests/snapshots/proxy__default_without_response_data.snap | 3 ++- .../manager/tests/snapshots/proxy__exec_through_manager.snap | 3 ++- .../manager/tests/snapshots/proxy__instantiate_proxy.snap | 3 ++- .../snapshots/proxy__proxy_install_multiple_modules.snap | 3 ++- .../snapshots/proxy__proxy_install_standalone_modules.snap | 3 ++- .../tests/snapshots/proxy__proxy_with_response_data.snap | 3 ++- ...baccount__account_move_ownership_to_falsy_sub_account.snap | 3 ++- .../subaccount__creating_on_subaccount_should_succeed.snap | 3 ++- ...__installed_app_updating_on_subaccount_should_succeed.snap | 3 ++- ...baccount__proxy_updating_on_subaccount_should_succeed.snap | 3 ++- ...ount__recursive_updating_on_subaccount_should_succeed.snap | 3 ++- .../snapshots/subaccount__sub_account_move_ownership.snap | 3 ++- ...subaccount__sub_account_move_ownership_to_sub_account.snap | 3 ++- .../subaccount__updating_on_subaccount_should_succeed.snap | 3 ++- modules/contracts/adapters/tendermint-staking/src/error.rs | 4 ++++ 24 files changed, 50 insertions(+), 23 deletions(-) diff --git a/framework/contracts/account/manager/tests/snapshots/adapters__account_install_adapter.snap b/framework/contracts/account/manager/tests/snapshots/adapters__account_install_adapter.snap index 747a78c51a..ddfd9ddc2f 100644 --- a/framework/contracts/account/manager/tests/snapshots/adapters__account_install_adapter.snap +++ b/framework/contracts/account/manager/tests/snapshots/adapters__account_install_adapter.snap @@ -112,6 +112,8 @@ expression: all_storage - "{\"account_base\":5}" - - "\u0000\u0003lib\u0000\babstract\u0000\bans-host0.21.0" - "{\"native\":\"mock1mzdhwvvh22wrt07w59wxyd58822qavwkx5lcej7aqfkpqqlhaqfsetqc4t\"}" + - - "\u0000\u0003lib\u0000\babstract\u0000\bibc-host0.21.0" + - "{\"native\":\"mock14ejqjyq8um4p3xfqj74yld5waqljf88fz25yxnma0cngspxe3les6xzvf5\"}" - - "\u0000\u0003lib\u0000\babstract\u0000\nibc-client0.21.0" - "{\"native\":\"mock1aaf9r6s7nxhysuegqrxv0wpm27ypyv4886medd3mrkrw6t4yfcns7ctvz5\"}" - - "\u0000\u0003lib\u0000\babstract\u0000\u000emodule-factory0.21.0" @@ -145,4 +147,3 @@ expression: all_storage - "{\"contract\":\"tester:mock-adapter1\",\"version\":\"1.0.0\"}" - - module_data - "{\"module\":\"tester:mock-adapter1\",\"version\":\"1.0.0\",\"dependencies\":[],\"metadata\":null}" - diff --git a/framework/contracts/account/manager/tests/snapshots/adapters__install_one_adapter.snap b/framework/contracts/account/manager/tests/snapshots/adapters__install_one_adapter.snap index 13d8f6f064..098620e40f 100644 --- a/framework/contracts/account/manager/tests/snapshots/adapters__install_one_adapter.snap +++ b/framework/contracts/account/manager/tests/snapshots/adapters__install_one_adapter.snap @@ -112,6 +112,8 @@ expression: all_storage - "{\"account_base\":5}" - - "\u0000\u0003lib\u0000\babstract\u0000\bans-host0.21.0" - "{\"native\":\"mock1mzdhwvvh22wrt07w59wxyd58822qavwkx5lcej7aqfkpqqlhaqfsetqc4t\"}" + - - "\u0000\u0003lib\u0000\babstract\u0000\bibc-host0.21.0" + - "{\"native\":\"mock14ejqjyq8um4p3xfqj74yld5waqljf88fz25yxnma0cngspxe3les6xzvf5\"}" - - "\u0000\u0003lib\u0000\babstract\u0000\nibc-client0.21.0" - "{\"native\":\"mock1aaf9r6s7nxhysuegqrxv0wpm27ypyv4886medd3mrkrw6t4yfcns7ctvz5\"}" - - "\u0000\u0003lib\u0000\babstract\u0000\u000emodule-factory0.21.0" @@ -147,4 +149,3 @@ expression: all_storage - "false" - - module_data - "{\"module\":\"tester:test-module-id\",\"version\":\"0.21.0\",\"dependencies\":[],\"metadata\":\"test_metadata\"}" - diff --git a/framework/contracts/account/manager/tests/snapshots/adapters__install_one_adapter_with_fee.snap b/framework/contracts/account/manager/tests/snapshots/adapters__install_one_adapter_with_fee.snap index 5563bbffa1..18f9e38434 100644 --- a/framework/contracts/account/manager/tests/snapshots/adapters__install_one_adapter_with_fee.snap +++ b/framework/contracts/account/manager/tests/snapshots/adapters__install_one_adapter_with_fee.snap @@ -114,6 +114,8 @@ expression: all_storage - "{\"account_base\":5}" - - "\u0000\u0003lib\u0000\babstract\u0000\bans-host0.21.0" - "{\"native\":\"mock1mzdhwvvh22wrt07w59wxyd58822qavwkx5lcej7aqfkpqqlhaqfsetqc4t\"}" + - - "\u0000\u0003lib\u0000\babstract\u0000\bibc-host0.21.0" + - "{\"native\":\"mock14ejqjyq8um4p3xfqj74yld5waqljf88fz25yxnma0cngspxe3les6xzvf5\"}" - - "\u0000\u0003lib\u0000\babstract\u0000\nibc-client0.21.0" - "{\"native\":\"mock1aaf9r6s7nxhysuegqrxv0wpm27ypyv4886medd3mrkrw6t4yfcns7ctvz5\"}" - - "\u0000\u0003lib\u0000\babstract\u0000\u000emodule-factory0.21.0" @@ -149,4 +151,3 @@ expression: all_storage - "false" - - module_data - "{\"module\":\"tester:test-module-id\",\"version\":\"0.21.0\",\"dependencies\":[],\"metadata\":\"test_metadata\"}" - diff --git a/framework/contracts/account/manager/tests/snapshots/adapters__installing_specific_version_should_install_expected.snap b/framework/contracts/account/manager/tests/snapshots/adapters__installing_specific_version_should_install_expected.snap index da8371e14e..6913f78c7e 100644 --- a/framework/contracts/account/manager/tests/snapshots/adapters__installing_specific_version_should_install_expected.snap +++ b/framework/contracts/account/manager/tests/snapshots/adapters__installing_specific_version_should_install_expected.snap @@ -114,6 +114,8 @@ expression: all_storage - "{\"account_base\":5}" - - "\u0000\u0003lib\u0000\babstract\u0000\bans-host0.21.0" - "{\"native\":\"mock1mzdhwvvh22wrt07w59wxyd58822qavwkx5lcej7aqfkpqqlhaqfsetqc4t\"}" + - - "\u0000\u0003lib\u0000\babstract\u0000\bibc-host0.21.0" + - "{\"native\":\"mock14ejqjyq8um4p3xfqj74yld5waqljf88fz25yxnma0cngspxe3les6xzvf5\"}" - - "\u0000\u0003lib\u0000\babstract\u0000\nibc-client0.21.0" - "{\"native\":\"mock1aaf9r6s7nxhysuegqrxv0wpm27ypyv4886medd3mrkrw6t4yfcns7ctvz5\"}" - - "\u0000\u0003lib\u0000\babstract\u0000\u000emodule-factory0.21.0" @@ -147,4 +149,3 @@ expression: all_storage - "{\"contract\":\"tester:mock-adapter1\",\"version\":\"2.0.0\"}" - - module_data - "{\"module\":\"tester:mock-adapter1\",\"version\":\"2.0.0\",\"dependencies\":[],\"metadata\":null}" - diff --git a/framework/contracts/account/manager/tests/snapshots/adapters__reinstalling_adapter_should_be_allowed.snap b/framework/contracts/account/manager/tests/snapshots/adapters__reinstalling_adapter_should_be_allowed.snap index 13d8f6f064..098620e40f 100644 --- a/framework/contracts/account/manager/tests/snapshots/adapters__reinstalling_adapter_should_be_allowed.snap +++ b/framework/contracts/account/manager/tests/snapshots/adapters__reinstalling_adapter_should_be_allowed.snap @@ -112,6 +112,8 @@ expression: all_storage - "{\"account_base\":5}" - - "\u0000\u0003lib\u0000\babstract\u0000\bans-host0.21.0" - "{\"native\":\"mock1mzdhwvvh22wrt07w59wxyd58822qavwkx5lcej7aqfkpqqlhaqfsetqc4t\"}" + - - "\u0000\u0003lib\u0000\babstract\u0000\bibc-host0.21.0" + - "{\"native\":\"mock14ejqjyq8um4p3xfqj74yld5waqljf88fz25yxnma0cngspxe3les6xzvf5\"}" - - "\u0000\u0003lib\u0000\babstract\u0000\nibc-client0.21.0" - "{\"native\":\"mock1aaf9r6s7nxhysuegqrxv0wpm27ypyv4886medd3mrkrw6t4yfcns7ctvz5\"}" - - "\u0000\u0003lib\u0000\babstract\u0000\u000emodule-factory0.21.0" @@ -147,4 +149,3 @@ expression: all_storage - "false" - - module_data - "{\"module\":\"tester:test-module-id\",\"version\":\"0.21.0\",\"dependencies\":[],\"metadata\":\"test_metadata\"}" - diff --git a/framework/contracts/account/manager/tests/snapshots/adapters__reinstalling_new_version_should_install_latest.snap b/framework/contracts/account/manager/tests/snapshots/adapters__reinstalling_new_version_should_install_latest.snap index 97502ba5e2..fbff30e492 100644 --- a/framework/contracts/account/manager/tests/snapshots/adapters__reinstalling_new_version_should_install_latest.snap +++ b/framework/contracts/account/manager/tests/snapshots/adapters__reinstalling_new_version_should_install_latest.snap @@ -114,6 +114,8 @@ expression: all_storage - "{\"account_base\":5}" - - "\u0000\u0003lib\u0000\babstract\u0000\bans-host0.21.0" - "{\"native\":\"mock1mzdhwvvh22wrt07w59wxyd58822qavwkx5lcej7aqfkpqqlhaqfsetqc4t\"}" + - - "\u0000\u0003lib\u0000\babstract\u0000\bibc-host0.21.0" + - "{\"native\":\"mock14ejqjyq8um4p3xfqj74yld5waqljf88fz25yxnma0cngspxe3les6xzvf5\"}" - - "\u0000\u0003lib\u0000\babstract\u0000\nibc-client0.21.0" - "{\"native\":\"mock1aaf9r6s7nxhysuegqrxv0wpm27ypyv4886medd3mrkrw6t4yfcns7ctvz5\"}" - - "\u0000\u0003lib\u0000\babstract\u0000\u000emodule-factory0.21.0" @@ -147,4 +149,3 @@ expression: all_storage - "{\"contract\":\"tester:mock-adapter1\",\"version\":\"2.0.0\"}" - - module_data - "{\"module\":\"tester:mock-adapter1\",\"version\":\"2.0.0\",\"dependencies\":[],\"metadata\":null}" - diff --git a/framework/contracts/account/manager/tests/snapshots/apps__account_install_app.snap b/framework/contracts/account/manager/tests/snapshots/apps__account_install_app.snap index 2451d21413..d7d2858dbf 100644 --- a/framework/contracts/account/manager/tests/snapshots/apps__account_install_app.snap +++ b/framework/contracts/account/manager/tests/snapshots/apps__account_install_app.snap @@ -112,6 +112,8 @@ expression: all_storage - "{\"account_base\":5}" - - "\u0000\u0003lib\u0000\babstract\u0000\bans-host0.21.0" - "{\"native\":\"mock1mzdhwvvh22wrt07w59wxyd58822qavwkx5lcej7aqfkpqqlhaqfsetqc4t\"}" + - - "\u0000\u0003lib\u0000\babstract\u0000\bibc-host0.21.0" + - "{\"native\":\"mock14ejqjyq8um4p3xfqj74yld5waqljf88fz25yxnma0cngspxe3les6xzvf5\"}" - - "\u0000\u0003lib\u0000\babstract\u0000\nibc-client0.21.0" - "{\"native\":\"mock1aaf9r6s7nxhysuegqrxv0wpm27ypyv4886medd3mrkrw6t4yfcns7ctvz5\"}" - - "\u0000\u0003lib\u0000\babstract\u0000\u000emodule-factory0.21.0" @@ -147,4 +149,3 @@ expression: all_storage - "{\"contract\":\"tester:app\",\"version\":\"1.0.0\"}" - - module_data - "{\"module\":\"tester:app\",\"version\":\"1.0.0\",\"dependencies\":[],\"metadata\":null}" - diff --git a/framework/contracts/account/manager/tests/snapshots/apps__execute_on_proxy_through_manager.snap b/framework/contracts/account/manager/tests/snapshots/apps__execute_on_proxy_through_manager.snap index b7a3d42289..9a80b86ae4 100644 --- a/framework/contracts/account/manager/tests/snapshots/apps__execute_on_proxy_through_manager.snap +++ b/framework/contracts/account/manager/tests/snapshots/apps__execute_on_proxy_through_manager.snap @@ -106,6 +106,8 @@ expression: all_storage - "{\"account_base\":5}" - - "\u0000\u0003lib\u0000\babstract\u0000\bans-host0.21.0" - "{\"native\":\"mock1mzdhwvvh22wrt07w59wxyd58822qavwkx5lcej7aqfkpqqlhaqfsetqc4t\"}" + - - "\u0000\u0003lib\u0000\babstract\u0000\bibc-host0.21.0" + - "{\"native\":\"mock14ejqjyq8um4p3xfqj74yld5waqljf88fz25yxnma0cngspxe3les6xzvf5\"}" - - "\u0000\u0003lib\u0000\babstract\u0000\nibc-client0.21.0" - "{\"native\":\"mock1aaf9r6s7nxhysuegqrxv0wpm27ypyv4886medd3mrkrw6t4yfcns7ctvz5\"}" - - "\u0000\u0003lib\u0000\babstract\u0000\u000emodule-factory0.21.0" @@ -128,4 +130,3 @@ expression: all_storage - "{\"contract\":\"abstract:version-control\",\"version\":\"0.21.0\"}" - - ownership - "{\"owner\":\"mock1pgm8hyk0pvphmlvfjc8wsvk4daluz5tgrw6pu5mfpemk74uxnx9qwrtv4f\",\"pending_owner\":null,\"pending_expiry\":null}" - diff --git a/framework/contracts/account/manager/tests/snapshots/install_modules__adds_module_to_account_modules.snap b/framework/contracts/account/manager/tests/snapshots/install_modules__adds_module_to_account_modules.snap index 114a351208..591042bc5e 100644 --- a/framework/contracts/account/manager/tests/snapshots/install_modules__adds_module_to_account_modules.snap +++ b/framework/contracts/account/manager/tests/snapshots/install_modules__adds_module_to_account_modules.snap @@ -122,6 +122,8 @@ expression: all_storage - "{\"account_base\":5}" - - "\u0000\u0003lib\u0000\babstract\u0000\bans-host0.21.0" - "{\"native\":\"mock1mzdhwvvh22wrt07w59wxyd58822qavwkx5lcej7aqfkpqqlhaqfsetqc4t\"}" + - - "\u0000\u0003lib\u0000\babstract\u0000\bibc-host0.21.0" + - "{\"native\":\"mock14ejqjyq8um4p3xfqj74yld5waqljf88fz25yxnma0cngspxe3les6xzvf5\"}" - - "\u0000\u0003lib\u0000\babstract\u0000\nibc-client0.21.0" - "{\"native\":\"mock1aaf9r6s7nxhysuegqrxv0wpm27ypyv4886medd3mrkrw6t4yfcns7ctvz5\"}" - - "\u0000\u0003lib\u0000\babstract\u0000\u000emodule-factory0.21.0" @@ -162,4 +164,3 @@ expression: all_storage - "{\"contract\":\"tester:mock-adapter2\",\"version\":\"2.0.0\"}" - - module_data - "{\"module\":\"tester:mock-adapter2\",\"version\":\"2.0.0\",\"dependencies\":[],\"metadata\":null}" - diff --git a/framework/contracts/account/manager/tests/snapshots/proxy__default_without_response_data.snap b/framework/contracts/account/manager/tests/snapshots/proxy__default_without_response_data.snap index 8da83f82ae..870c71d880 100644 --- a/framework/contracts/account/manager/tests/snapshots/proxy__default_without_response_data.snap +++ b/framework/contracts/account/manager/tests/snapshots/proxy__default_without_response_data.snap @@ -112,6 +112,8 @@ expression: all_storage - "{\"account_base\":5}" - - "\u0000\u0003lib\u0000\babstract\u0000\bans-host0.21.0" - "{\"native\":\"mock1mzdhwvvh22wrt07w59wxyd58822qavwkx5lcej7aqfkpqqlhaqfsetqc4t\"}" + - - "\u0000\u0003lib\u0000\babstract\u0000\bibc-host0.21.0" + - "{\"native\":\"mock14ejqjyq8um4p3xfqj74yld5waqljf88fz25yxnma0cngspxe3les6xzvf5\"}" - - "\u0000\u0003lib\u0000\babstract\u0000\nibc-client0.21.0" - "{\"native\":\"mock1aaf9r6s7nxhysuegqrxv0wpm27ypyv4886medd3mrkrw6t4yfcns7ctvz5\"}" - - "\u0000\u0003lib\u0000\babstract\u0000\u000emodule-factory0.21.0" @@ -147,4 +149,3 @@ expression: all_storage - "false" - - module_data - "{\"module\":\"tester:test-module-id\",\"version\":\"0.21.0\",\"dependencies\":[],\"metadata\":\"test_metadata\"}" - diff --git a/framework/contracts/account/manager/tests/snapshots/proxy__exec_through_manager.snap b/framework/contracts/account/manager/tests/snapshots/proxy__exec_through_manager.snap index 11d15e975f..3e83028ed2 100644 --- a/framework/contracts/account/manager/tests/snapshots/proxy__exec_through_manager.snap +++ b/framework/contracts/account/manager/tests/snapshots/proxy__exec_through_manager.snap @@ -106,6 +106,8 @@ expression: all_storage - "{\"account_base\":5}" - - "\u0000\u0003lib\u0000\babstract\u0000\bans-host0.21.0" - "{\"native\":\"mock1mzdhwvvh22wrt07w59wxyd58822qavwkx5lcej7aqfkpqqlhaqfsetqc4t\"}" + - - "\u0000\u0003lib\u0000\babstract\u0000\bibc-host0.21.0" + - "{\"native\":\"mock14ejqjyq8um4p3xfqj74yld5waqljf88fz25yxnma0cngspxe3les6xzvf5\"}" - - "\u0000\u0003lib\u0000\babstract\u0000\nibc-client0.21.0" - "{\"native\":\"mock1aaf9r6s7nxhysuegqrxv0wpm27ypyv4886medd3mrkrw6t4yfcns7ctvz5\"}" - - "\u0000\u0003lib\u0000\babstract\u0000\u000emodule-factory0.21.0" @@ -128,4 +130,3 @@ expression: all_storage - "{\"contract\":\"abstract:version-control\",\"version\":\"0.21.0\"}" - - ownership - "{\"owner\":\"mock1pgm8hyk0pvphmlvfjc8wsvk4daluz5tgrw6pu5mfpemk74uxnx9qwrtv4f\",\"pending_owner\":null,\"pending_expiry\":null}" - diff --git a/framework/contracts/account/manager/tests/snapshots/proxy__instantiate_proxy.snap b/framework/contracts/account/manager/tests/snapshots/proxy__instantiate_proxy.snap index 11d15e975f..3e83028ed2 100644 --- a/framework/contracts/account/manager/tests/snapshots/proxy__instantiate_proxy.snap +++ b/framework/contracts/account/manager/tests/snapshots/proxy__instantiate_proxy.snap @@ -106,6 +106,8 @@ expression: all_storage - "{\"account_base\":5}" - - "\u0000\u0003lib\u0000\babstract\u0000\bans-host0.21.0" - "{\"native\":\"mock1mzdhwvvh22wrt07w59wxyd58822qavwkx5lcej7aqfkpqqlhaqfsetqc4t\"}" + - - "\u0000\u0003lib\u0000\babstract\u0000\bibc-host0.21.0" + - "{\"native\":\"mock14ejqjyq8um4p3xfqj74yld5waqljf88fz25yxnma0cngspxe3les6xzvf5\"}" - - "\u0000\u0003lib\u0000\babstract\u0000\nibc-client0.21.0" - "{\"native\":\"mock1aaf9r6s7nxhysuegqrxv0wpm27ypyv4886medd3mrkrw6t4yfcns7ctvz5\"}" - - "\u0000\u0003lib\u0000\babstract\u0000\u000emodule-factory0.21.0" @@ -128,4 +130,3 @@ expression: all_storage - "{\"contract\":\"abstract:version-control\",\"version\":\"0.21.0\"}" - - ownership - "{\"owner\":\"mock1pgm8hyk0pvphmlvfjc8wsvk4daluz5tgrw6pu5mfpemk74uxnx9qwrtv4f\",\"pending_owner\":null,\"pending_expiry\":null}" - diff --git a/framework/contracts/account/manager/tests/snapshots/proxy__proxy_install_multiple_modules.snap b/framework/contracts/account/manager/tests/snapshots/proxy__proxy_install_multiple_modules.snap index fc765238f6..56852870d6 100644 --- a/framework/contracts/account/manager/tests/snapshots/proxy__proxy_install_multiple_modules.snap +++ b/framework/contracts/account/manager/tests/snapshots/proxy__proxy_install_multiple_modules.snap @@ -88,6 +88,8 @@ expression: all_storage - "{\"account_base\":5}" - - "\u0000\u0003lib\u0000\babstract\u0000\bans-host0.21.0" - "{\"native\":\"mock1mzdhwvvh22wrt07w59wxyd58822qavwkx5lcej7aqfkpqqlhaqfsetqc4t\"}" + - - "\u0000\u0003lib\u0000\babstract\u0000\bibc-host0.21.0" + - "{\"native\":\"mock14ejqjyq8um4p3xfqj74yld5waqljf88fz25yxnma0cngspxe3les6xzvf5\"}" - - "\u0000\u0003lib\u0000\babstract\u0000\nibc-client0.21.0" - "{\"native\":\"mock1aaf9r6s7nxhysuegqrxv0wpm27ypyv4886medd3mrkrw6t4yfcns7ctvz5\"}" - - "\u0000\u0003lib\u0000\babstract\u0000\u000bstandalone11.0.0" @@ -116,4 +118,3 @@ expression: all_storage - "{\"contract\":\"abstract:version-control\",\"version\":\"0.21.0\"}" - - ownership - "{\"owner\":\"mock1pgm8hyk0pvphmlvfjc8wsvk4daluz5tgrw6pu5mfpemk74uxnx9qwrtv4f\",\"pending_owner\":null,\"pending_expiry\":null}" - diff --git a/framework/contracts/account/manager/tests/snapshots/proxy__proxy_install_standalone_modules.snap b/framework/contracts/account/manager/tests/snapshots/proxy__proxy_install_standalone_modules.snap index 7acc594db4..a341757ae5 100644 --- a/framework/contracts/account/manager/tests/snapshots/proxy__proxy_install_standalone_modules.snap +++ b/framework/contracts/account/manager/tests/snapshots/proxy__proxy_install_standalone_modules.snap @@ -84,6 +84,8 @@ expression: all_storage - "{\"account_base\":5}" - - "\u0000\u0003lib\u0000\babstract\u0000\bans-host0.21.0" - "{\"native\":\"mock1mzdhwvvh22wrt07w59wxyd58822qavwkx5lcej7aqfkpqqlhaqfsetqc4t\"}" + - - "\u0000\u0003lib\u0000\babstract\u0000\bibc-host0.21.0" + - "{\"native\":\"mock14ejqjyq8um4p3xfqj74yld5waqljf88fz25yxnma0cngspxe3les6xzvf5\"}" - - "\u0000\u0003lib\u0000\babstract\u0000\nibc-client0.21.0" - "{\"native\":\"mock1aaf9r6s7nxhysuegqrxv0wpm27ypyv4886medd3mrkrw6t4yfcns7ctvz5\"}" - - "\u0000\u0003lib\u0000\babstract\u0000\u000bstandalone11.0.0" @@ -112,4 +114,3 @@ expression: all_storage - "{\"contract\":\"abstract:version-control\",\"version\":\"0.21.0\"}" - - ownership - "{\"owner\":\"mock1pgm8hyk0pvphmlvfjc8wsvk4daluz5tgrw6pu5mfpemk74uxnx9qwrtv4f\",\"pending_owner\":null,\"pending_expiry\":null}" - diff --git a/framework/contracts/account/manager/tests/snapshots/proxy__proxy_with_response_data.snap b/framework/contracts/account/manager/tests/snapshots/proxy__proxy_with_response_data.snap index e83c999962..7b8339a96c 100644 --- a/framework/contracts/account/manager/tests/snapshots/proxy__proxy_with_response_data.snap +++ b/framework/contracts/account/manager/tests/snapshots/proxy__proxy_with_response_data.snap @@ -112,6 +112,8 @@ expression: all_storage - "{\"account_base\":5}" - - "\u0000\u0003lib\u0000\babstract\u0000\bans-host0.21.0" - "{\"native\":\"mock1mzdhwvvh22wrt07w59wxyd58822qavwkx5lcej7aqfkpqqlhaqfsetqc4t\"}" + - - "\u0000\u0003lib\u0000\babstract\u0000\bibc-host0.21.0" + - "{\"native\":\"mock14ejqjyq8um4p3xfqj74yld5waqljf88fz25yxnma0cngspxe3les6xzvf5\"}" - - "\u0000\u0003lib\u0000\babstract\u0000\nibc-client0.21.0" - "{\"native\":\"mock1aaf9r6s7nxhysuegqrxv0wpm27ypyv4886medd3mrkrw6t4yfcns7ctvz5\"}" - - "\u0000\u0003lib\u0000\babstract\u0000\u000emodule-factory0.21.0" @@ -149,4 +151,3 @@ expression: all_storage - "false" - - module_data - "{\"module\":\"tester:test-module-id\",\"version\":\"0.21.0\",\"dependencies\":[],\"metadata\":\"test_metadata\"}" - diff --git a/framework/contracts/account/manager/tests/snapshots/subaccount__account_move_ownership_to_falsy_sub_account.snap b/framework/contracts/account/manager/tests/snapshots/subaccount__account_move_ownership_to_falsy_sub_account.snap index 96e4697dda..4e68223daf 100644 --- a/framework/contracts/account/manager/tests/snapshots/subaccount__account_move_ownership_to_falsy_sub_account.snap +++ b/framework/contracts/account/manager/tests/snapshots/subaccount__account_move_ownership_to_falsy_sub_account.snap @@ -164,6 +164,8 @@ expression: all_storage - "{\"account_base\":5}" - - "\u0000\u0003lib\u0000\babstract\u0000\bans-host0.21.0" - "{\"native\":\"mock1mzdhwvvh22wrt07w59wxyd58822qavwkx5lcej7aqfkpqqlhaqfsetqc4t\"}" + - - "\u0000\u0003lib\u0000\babstract\u0000\bibc-host0.21.0" + - "{\"native\":\"mock14ejqjyq8um4p3xfqj74yld5waqljf88fz25yxnma0cngspxe3les6xzvf5\"}" - - "\u0000\u0003lib\u0000\babstract\u0000\nibc-client0.21.0" - "{\"native\":\"mock1aaf9r6s7nxhysuegqrxv0wpm27ypyv4886medd3mrkrw6t4yfcns7ctvz5\"}" - - "\u0000\u0003lib\u0000\babstract\u0000\u000emodule-factory0.21.0" @@ -190,4 +192,3 @@ expression: all_storage - "{\"contract\":\"abstract:version-control\",\"version\":\"0.21.0\"}" - - ownership - "{\"owner\":\"mock1pgm8hyk0pvphmlvfjc8wsvk4daluz5tgrw6pu5mfpemk74uxnx9qwrtv4f\",\"pending_owner\":null,\"pending_expiry\":null}" - diff --git a/framework/contracts/account/manager/tests/snapshots/subaccount__creating_on_subaccount_should_succeed.snap b/framework/contracts/account/manager/tests/snapshots/subaccount__creating_on_subaccount_should_succeed.snap index c79b9c3cec..a79720ead1 100644 --- a/framework/contracts/account/manager/tests/snapshots/subaccount__creating_on_subaccount_should_succeed.snap +++ b/framework/contracts/account/manager/tests/snapshots/subaccount__creating_on_subaccount_should_succeed.snap @@ -108,6 +108,8 @@ expression: all_storage - "{\"account_base\":5}" - - "\u0000\u0003lib\u0000\babstract\u0000\bans-host0.21.0" - "{\"native\":\"mock1mzdhwvvh22wrt07w59wxyd58822qavwkx5lcej7aqfkpqqlhaqfsetqc4t\"}" + - - "\u0000\u0003lib\u0000\babstract\u0000\bibc-host0.21.0" + - "{\"native\":\"mock14ejqjyq8um4p3xfqj74yld5waqljf88fz25yxnma0cngspxe3les6xzvf5\"}" - - "\u0000\u0003lib\u0000\babstract\u0000\nibc-client0.21.0" - "{\"native\":\"mock1aaf9r6s7nxhysuegqrxv0wpm27ypyv4886medd3mrkrw6t4yfcns7ctvz5\"}" - - "\u0000\u0003lib\u0000\babstract\u0000\u000emodule-factory0.21.0" @@ -132,4 +134,3 @@ expression: all_storage - "{\"contract\":\"abstract:version-control\",\"version\":\"0.21.0\"}" - - ownership - "{\"owner\":\"mock1pgm8hyk0pvphmlvfjc8wsvk4daluz5tgrw6pu5mfpemk74uxnx9qwrtv4f\",\"pending_owner\":null,\"pending_expiry\":null}" - diff --git a/framework/contracts/account/manager/tests/snapshots/subaccount__installed_app_updating_on_subaccount_should_succeed.snap b/framework/contracts/account/manager/tests/snapshots/subaccount__installed_app_updating_on_subaccount_should_succeed.snap index 000de0f7a8..a3ac046d09 100644 --- a/framework/contracts/account/manager/tests/snapshots/subaccount__installed_app_updating_on_subaccount_should_succeed.snap +++ b/framework/contracts/account/manager/tests/snapshots/subaccount__installed_app_updating_on_subaccount_should_succeed.snap @@ -136,6 +136,8 @@ expression: all_storage - "{\"account_base\":5}" - - "\u0000\u0003lib\u0000\babstract\u0000\bans-host0.21.0" - "{\"native\":\"mock1mzdhwvvh22wrt07w59wxyd58822qavwkx5lcej7aqfkpqqlhaqfsetqc4t\"}" + - - "\u0000\u0003lib\u0000\babstract\u0000\bibc-host0.21.0" + - "{\"native\":\"mock14ejqjyq8um4p3xfqj74yld5waqljf88fz25yxnma0cngspxe3les6xzvf5\"}" - - "\u0000\u0003lib\u0000\babstract\u0000\nibc-client0.21.0" - "{\"native\":\"mock1aaf9r6s7nxhysuegqrxv0wpm27ypyv4886medd3mrkrw6t4yfcns7ctvz5\"}" - - "\u0000\u0003lib\u0000\babstract\u0000\u000emodule-factory0.21.0" @@ -160,4 +162,3 @@ expression: all_storage - "{\"contract\":\"abstract:version-control\",\"version\":\"0.21.0\"}" - - ownership - "{\"owner\":\"mock1pgm8hyk0pvphmlvfjc8wsvk4daluz5tgrw6pu5mfpemk74uxnx9qwrtv4f\",\"pending_owner\":null,\"pending_expiry\":null}" - diff --git a/framework/contracts/account/manager/tests/snapshots/subaccount__proxy_updating_on_subaccount_should_succeed.snap b/framework/contracts/account/manager/tests/snapshots/subaccount__proxy_updating_on_subaccount_should_succeed.snap index a6783d3f4f..83195619aa 100644 --- a/framework/contracts/account/manager/tests/snapshots/subaccount__proxy_updating_on_subaccount_should_succeed.snap +++ b/framework/contracts/account/manager/tests/snapshots/subaccount__proxy_updating_on_subaccount_should_succeed.snap @@ -136,6 +136,8 @@ expression: all_storage - "{\"account_base\":5}" - - "\u0000\u0003lib\u0000\babstract\u0000\bans-host0.21.0" - "{\"native\":\"mock1mzdhwvvh22wrt07w59wxyd58822qavwkx5lcej7aqfkpqqlhaqfsetqc4t\"}" + - - "\u0000\u0003lib\u0000\babstract\u0000\bibc-host0.21.0" + - "{\"native\":\"mock14ejqjyq8um4p3xfqj74yld5waqljf88fz25yxnma0cngspxe3les6xzvf5\"}" - - "\u0000\u0003lib\u0000\babstract\u0000\nibc-client0.21.0" - "{\"native\":\"mock1aaf9r6s7nxhysuegqrxv0wpm27ypyv4886medd3mrkrw6t4yfcns7ctvz5\"}" - - "\u0000\u0003lib\u0000\babstract\u0000\u000emodule-factory0.21.0" @@ -160,4 +162,3 @@ expression: all_storage - "{\"contract\":\"abstract:version-control\",\"version\":\"0.21.0\"}" - - ownership - "{\"owner\":\"mock1pgm8hyk0pvphmlvfjc8wsvk4daluz5tgrw6pu5mfpemk74uxnx9qwrtv4f\",\"pending_owner\":null,\"pending_expiry\":null}" - diff --git a/framework/contracts/account/manager/tests/snapshots/subaccount__recursive_updating_on_subaccount_should_succeed.snap b/framework/contracts/account/manager/tests/snapshots/subaccount__recursive_updating_on_subaccount_should_succeed.snap index 5bcf441f3d..a3424e0894 100644 --- a/framework/contracts/account/manager/tests/snapshots/subaccount__recursive_updating_on_subaccount_should_succeed.snap +++ b/framework/contracts/account/manager/tests/snapshots/subaccount__recursive_updating_on_subaccount_should_succeed.snap @@ -166,6 +166,8 @@ expression: all_storage - "{\"account_base\":5}" - - "\u0000\u0003lib\u0000\babstract\u0000\bans-host0.21.0" - "{\"native\":\"mock1mzdhwvvh22wrt07w59wxyd58822qavwkx5lcej7aqfkpqqlhaqfsetqc4t\"}" + - - "\u0000\u0003lib\u0000\babstract\u0000\bibc-host0.21.0" + - "{\"native\":\"mock14ejqjyq8um4p3xfqj74yld5waqljf88fz25yxnma0cngspxe3les6xzvf5\"}" - - "\u0000\u0003lib\u0000\babstract\u0000\nibc-client0.21.0" - "{\"native\":\"mock1aaf9r6s7nxhysuegqrxv0wpm27ypyv4886medd3mrkrw6t4yfcns7ctvz5\"}" - - "\u0000\u0003lib\u0000\babstract\u0000\u000emodule-factory0.21.0" @@ -192,4 +194,3 @@ expression: all_storage - "{\"contract\":\"abstract:version-control\",\"version\":\"0.21.0\"}" - - ownership - "{\"owner\":\"mock1pgm8hyk0pvphmlvfjc8wsvk4daluz5tgrw6pu5mfpemk74uxnx9qwrtv4f\",\"pending_owner\":null,\"pending_expiry\":null}" - diff --git a/framework/contracts/account/manager/tests/snapshots/subaccount__sub_account_move_ownership.snap b/framework/contracts/account/manager/tests/snapshots/subaccount__sub_account_move_ownership.snap index 2edb5e3299..e3f613ce1a 100644 --- a/framework/contracts/account/manager/tests/snapshots/subaccount__sub_account_move_ownership.snap +++ b/framework/contracts/account/manager/tests/snapshots/subaccount__sub_account_move_ownership.snap @@ -134,6 +134,8 @@ expression: all_storage - "{\"account_base\":5}" - - "\u0000\u0003lib\u0000\babstract\u0000\bans-host0.21.0" - "{\"native\":\"mock1mzdhwvvh22wrt07w59wxyd58822qavwkx5lcej7aqfkpqqlhaqfsetqc4t\"}" + - - "\u0000\u0003lib\u0000\babstract\u0000\bibc-host0.21.0" + - "{\"native\":\"mock14ejqjyq8um4p3xfqj74yld5waqljf88fz25yxnma0cngspxe3les6xzvf5\"}" - - "\u0000\u0003lib\u0000\babstract\u0000\nibc-client0.21.0" - "{\"native\":\"mock1aaf9r6s7nxhysuegqrxv0wpm27ypyv4886medd3mrkrw6t4yfcns7ctvz5\"}" - - "\u0000\u0003lib\u0000\babstract\u0000\u000emodule-factory0.21.0" @@ -158,4 +160,3 @@ expression: all_storage - "{\"contract\":\"abstract:version-control\",\"version\":\"0.21.0\"}" - - ownership - "{\"owner\":\"mock1pgm8hyk0pvphmlvfjc8wsvk4daluz5tgrw6pu5mfpemk74uxnx9qwrtv4f\",\"pending_owner\":null,\"pending_expiry\":null}" - diff --git a/framework/contracts/account/manager/tests/snapshots/subaccount__sub_account_move_ownership_to_sub_account.snap b/framework/contracts/account/manager/tests/snapshots/subaccount__sub_account_move_ownership_to_sub_account.snap index 746d3fae12..534b56d8cb 100644 --- a/framework/contracts/account/manager/tests/snapshots/subaccount__sub_account_move_ownership_to_sub_account.snap +++ b/framework/contracts/account/manager/tests/snapshots/subaccount__sub_account_move_ownership_to_sub_account.snap @@ -194,6 +194,8 @@ expression: all_storage - "{\"account_base\":5}" - - "\u0000\u0003lib\u0000\babstract\u0000\bans-host0.21.0" - "{\"native\":\"mock1mzdhwvvh22wrt07w59wxyd58822qavwkx5lcej7aqfkpqqlhaqfsetqc4t\"}" + - - "\u0000\u0003lib\u0000\babstract\u0000\bibc-host0.21.0" + - "{\"native\":\"mock14ejqjyq8um4p3xfqj74yld5waqljf88fz25yxnma0cngspxe3les6xzvf5\"}" - - "\u0000\u0003lib\u0000\babstract\u0000\nibc-client0.21.0" - "{\"native\":\"mock1aaf9r6s7nxhysuegqrxv0wpm27ypyv4886medd3mrkrw6t4yfcns7ctvz5\"}" - - "\u0000\u0003lib\u0000\babstract\u0000\u000emodule-factory0.21.0" @@ -222,4 +224,3 @@ expression: all_storage - "{\"contract\":\"abstract:version-control\",\"version\":\"0.21.0\"}" - - ownership - "{\"owner\":\"mock1pgm8hyk0pvphmlvfjc8wsvk4daluz5tgrw6pu5mfpemk74uxnx9qwrtv4f\",\"pending_owner\":null,\"pending_expiry\":null}" - diff --git a/framework/contracts/account/manager/tests/snapshots/subaccount__updating_on_subaccount_should_succeed.snap b/framework/contracts/account/manager/tests/snapshots/subaccount__updating_on_subaccount_should_succeed.snap index a6783d3f4f..83195619aa 100644 --- a/framework/contracts/account/manager/tests/snapshots/subaccount__updating_on_subaccount_should_succeed.snap +++ b/framework/contracts/account/manager/tests/snapshots/subaccount__updating_on_subaccount_should_succeed.snap @@ -136,6 +136,8 @@ expression: all_storage - "{\"account_base\":5}" - - "\u0000\u0003lib\u0000\babstract\u0000\bans-host0.21.0" - "{\"native\":\"mock1mzdhwvvh22wrt07w59wxyd58822qavwkx5lcej7aqfkpqqlhaqfsetqc4t\"}" + - - "\u0000\u0003lib\u0000\babstract\u0000\bibc-host0.21.0" + - "{\"native\":\"mock14ejqjyq8um4p3xfqj74yld5waqljf88fz25yxnma0cngspxe3les6xzvf5\"}" - - "\u0000\u0003lib\u0000\babstract\u0000\nibc-client0.21.0" - "{\"native\":\"mock1aaf9r6s7nxhysuegqrxv0wpm27ypyv4886medd3mrkrw6t4yfcns7ctvz5\"}" - - "\u0000\u0003lib\u0000\babstract\u0000\u000emodule-factory0.21.0" @@ -160,4 +162,3 @@ expression: all_storage - "{\"contract\":\"abstract:version-control\",\"version\":\"0.21.0\"}" - - ownership - "{\"owner\":\"mock1pgm8hyk0pvphmlvfjc8wsvk4daluz5tgrw6pu5mfpemk74uxnx9qwrtv4f\",\"pending_owner\":null,\"pending_expiry\":null}" - diff --git a/modules/contracts/adapters/tendermint-staking/src/error.rs b/modules/contracts/adapters/tendermint-staking/src/error.rs index b7401ae918..70d75f7212 100644 --- a/modules/contracts/adapters/tendermint-staking/src/error.rs +++ b/modules/contracts/adapters/tendermint-staking/src/error.rs @@ -1,4 +1,5 @@ use abstract_adapter::AdapterError; +use abstract_core::AbstractError; use abstract_sdk::AbstractSdkError; use cosmwasm_std::StdError; use thiserror::Error; @@ -11,6 +12,9 @@ pub enum TendermintStakeError { #[error("{0}")] AbstractSdk(#[from] AbstractSdkError), + #[error("{0}")] + Abstract(#[from] AbstractError), + #[error("{0}")] AdapterError(#[from] AdapterError), } From 62e836dff944378081f44032cac375b923fed4b9 Mon Sep 17 00:00:00 2001 From: Kayanski Date: Mon, 11 Mar 2024 15:24:49 +0000 Subject: [PATCH 16/37] not use latest but current version for client and host verification --- framework/packages/abstract-adapter/Cargo.toml | 2 ++ .../src/endpoints/ibc_callback.rs | 13 +++++++++++-- .../src/endpoints/module_ibc.rs | 9 ++++++++- framework/packages/abstract-app/Cargo.toml | 1 + .../abstract-app/src/endpoints/module_ibc.rs | 18 +++++++++++------- 5 files changed, 33 insertions(+), 10 deletions(-) diff --git a/framework/packages/abstract-adapter/Cargo.toml b/framework/packages/abstract-adapter/Cargo.toml index 46def1c5c0..67a0192b96 100644 --- a/framework/packages/abstract-adapter/Cargo.toml +++ b/framework/packages/abstract-adapter/Cargo.toml @@ -29,6 +29,8 @@ abstract-testing = { workspace = true, optional = true } cw-orch = { workspace = true, optional = true } # Keep this as a version and update when publishing new versions abstract-interface = { path = "../../packages/abstract-interface", version = "0.21.0", optional = true } +abstract-ibc-client = { version = "0.21.0", path = "../../contracts/native/ibc-client" } +abstract-ibc-host = { version = "0.21.0", path = "../../contracts/native/ibc-host" } [dev-dependencies] speculoos = { workspace = true } diff --git a/framework/packages/abstract-adapter/src/endpoints/ibc_callback.rs b/framework/packages/abstract-adapter/src/endpoints/ibc_callback.rs index ebc2ef0735..487f9a1a55 100644 --- a/framework/packages/abstract-adapter/src/endpoints/ibc_callback.rs +++ b/framework/packages/abstract-adapter/src/endpoints/ibc_callback.rs @@ -1,4 +1,7 @@ -use abstract_core::{objects::module::ModuleInfo, AbstractError, IBC_CLIENT}; +use abstract_core::{ + objects::module::{ModuleInfo, ModuleVersion}, + AbstractError, IBC_CLIENT, +}; use abstract_sdk::{base::IbcCallbackEndpoint, features::AbstractRegistryAccess}; use cosmwasm_std::{Addr, Deps}; @@ -11,7 +14,13 @@ impl Result { let vc_query_result = self .abstract_registry(deps)? - .query_module(ModuleInfo::from_id_latest(IBC_CLIENT)?, &deps.querier) + .query_module( + ModuleInfo::from_id( + IBC_CLIENT, + ModuleVersion::from(abstract_ibc_client::contract::CONTRACT_VERSION), + )?, + &deps.querier, + ) .map_err(Into::::into)?; Ok(vc_query_result.reference.unwrap_native()?) diff --git a/framework/packages/abstract-adapter/src/endpoints/module_ibc.rs b/framework/packages/abstract-adapter/src/endpoints/module_ibc.rs index bd605b9951..2acd4ccac3 100644 --- a/framework/packages/abstract-adapter/src/endpoints/module_ibc.rs +++ b/framework/packages/abstract-adapter/src/endpoints/module_ibc.rs @@ -1,4 +1,5 @@ use crate::{state::ContractError, AdapterContract}; +use abstract_core::objects::module::ModuleVersion; use abstract_core::IBC_HOST; use abstract_core::{objects::module::ModuleInfo, AbstractError}; use abstract_sdk::{base::ModuleIbcEndpoint, features::AbstractRegistryAccess}; @@ -11,7 +12,13 @@ impl Result { let vc_query_result = self .abstract_registry(deps)? - .query_module(ModuleInfo::from_id_latest(IBC_HOST)?, &deps.querier) + .query_module( + ModuleInfo::from_id( + IBC_HOST, + ModuleVersion::from(abstract_ibc_host::contract::CONTRACT_VERSION), + )?, + &deps.querier, + ) .map_err(Into::::into)?; Ok(vc_query_result.reference.unwrap_native()?) diff --git a/framework/packages/abstract-app/Cargo.toml b/framework/packages/abstract-app/Cargo.toml index 3ccb45e720..1f67523b14 100644 --- a/framework/packages/abstract-app/Cargo.toml +++ b/framework/packages/abstract-app/Cargo.toml @@ -36,6 +36,7 @@ abstract-testing = { workspace = true, optional = true } cw-orch = { workspace = true, optional = true } abstract-interface = { path = "../../packages/abstract-interface", version = "0.21.0", optional = true } +abstract-ibc-host = { version = "0.21.0", path = "../../contracts/native/ibc-host" } [dev-dependencies] cosmwasm-schema = { workspace = true } diff --git a/framework/packages/abstract-app/src/endpoints/module_ibc.rs b/framework/packages/abstract-app/src/endpoints/module_ibc.rs index 05c2e572a7..c9cc7d8d20 100644 --- a/framework/packages/abstract-app/src/endpoints/module_ibc.rs +++ b/framework/packages/abstract-app/src/endpoints/module_ibc.rs @@ -1,4 +1,7 @@ -use abstract_core::{objects::module::ModuleInfo, AbstractError, IBC_HOST}; +use abstract_core::{ + objects::module::{ModuleInfo, ModuleVersion}, + AbstractError, IBC_HOST, +}; use abstract_sdk::{base::ModuleIbcEndpoint, features::AbstractRegistryAccess}; use cosmwasm_std::Addr; @@ -23,15 +26,16 @@ impl< SudoMsg, > { - // This can't be used because accounts don't install the ibc_host on their accounts so this is never available - // fn ibc_host(&self, deps: cosmwasm_std::Deps) -> Result { - // let ibc_client = self.modules(deps).module_address(IBC_HOST)?; - // Ok(ibc_client) - // } fn ibc_host(&self, deps: cosmwasm_std::Deps) -> Result { let vc_query_result = self .abstract_registry(deps)? - .query_module(ModuleInfo::from_id_latest(IBC_HOST)?, &deps.querier) + .query_module( + ModuleInfo::from_id( + IBC_HOST, + ModuleVersion::from(abstract_ibc_host::contract::CONTRACT_VERSION), + )?, + &deps.querier, + ) .map_err(Into::::into)?; Ok(vc_query_result.reference.unwrap_native()?) From 6869f929c46f2fa2c391eaf5b17bc5bc900fa1ff Mon Sep 17 00:00:00 2001 From: Kayanski Date: Mon, 11 Mar 2024 15:47:36 +0000 Subject: [PATCH 17/37] Removed cross-account calls --- .../native/ibc-client/src/commands.rs | 7 ++- .../native/ibc-host/src/endpoints/packet.rs | 43 +++++++++++++------ .../abstract-core/src/native/ibc_client.rs | 2 +- .../abstract-core/src/native/ibc_host.rs | 4 +- 4 files changed, 37 insertions(+), 19 deletions(-) diff --git a/framework/contracts/native/ibc-client/src/commands.rs b/framework/contracts/native/ibc-client/src/commands.rs index d345f7a156..c3a1e99138 100644 --- a/framework/contracts/native/ibc-client/src/commands.rs +++ b/framework/contracts/native/ibc-client/src/commands.rs @@ -8,7 +8,10 @@ use abstract_core::{ }, ibc_host, manager::{self, ModuleInstallConfig}, - objects::{chain_name::ChainName, module_reference::ModuleReference, AccountId, AssetEntry}, + objects::{ + chain_name::ChainName, module::ModuleInfo, module_reference::ModuleReference, AccountId, + AssetEntry, + }, version_control::AccountBase, }; use abstract_sdk::{ @@ -220,7 +223,7 @@ pub fn execute_send_module_to_module_packet( info: MessageInfo, host_chain: String, source_module: InstalledModuleIdentification, - target_module: InstalledModuleIdentification, + target_module: ModuleInfo, msg: Binary, callback_info: Option, ) -> IbcClientResult { diff --git a/framework/contracts/native/ibc-host/src/endpoints/packet.rs b/framework/contracts/native/ibc-host/src/endpoints/packet.rs index e83fb8230e..e5b7c4a601 100644 --- a/framework/contracts/native/ibc-host/src/endpoints/packet.rs +++ b/framework/contracts/native/ibc-host/src/endpoints/packet.rs @@ -5,7 +5,9 @@ use abstract_core::{ state::{ActionAfterCreationCache, CONFIG, TEMP_ACTION_AFTER_CREATION}, HelperAction, }, - objects::{chain_name::ChainName, module_reference::ModuleReference, AccountId}, + objects::{ + chain_name::ChainName, module::ModuleInfo, module_reference::ModuleReference, AccountId, + }, }; use abstract_sdk::core::ibc_host::{HostAction, InternalAction}; use cosmwasm_std::{wasm_execute, Binary, DepsMut, Empty, Env, Response}; @@ -18,6 +20,13 @@ use crate::{ use abstract_core::base::ExecuteMsg as MiddlewareExecMsg; +pub fn remote_account_id(remote_chain: ChainName, account_id: AccountId) -> HostResult { + let mut account_id = account_id.clone(); + account_id.trace_mut().push_chain(remote_chain.clone()); + + Ok(account_id) +} + /// Handle actions that are passed to the IBC host contract /// This function is not permissioned and access control needs to be handled outside of it /// Usually the `client_chain` argument needs to be derived from the message sender @@ -30,8 +39,7 @@ pub fn handle_host_action( host_action: HostAction, ) -> HostResult { // Push the client chain to the account trace - let mut account_id = received_account_id.clone(); - account_id.trace_mut().push_chain(client_chain.clone()); + let account_id = remote_account_id(client_chain.clone(), received_account_id.clone())?; // get the local account information match host_action { @@ -116,25 +124,32 @@ pub fn handle_host_module_action( deps: DepsMut, client_chain: ChainName, source_module: InstalledModuleIdentification, - target_module: InstalledModuleIdentification, + target_module: ModuleInfo, msg: Binary, ) -> HostResult { // We resolve the target module let vc = CONFIG.load(deps.storage)?.version_control; - let target_module_resolved = - vc.query_module(target_module.module_info.clone(), &deps.querier)?; + let target_module_resolved = vc.query_module(target_module.clone(), &deps.querier)?; // We can't send module actions to accounts base and native apps - match target_module_resolved.reference { + let target_addr = match target_module_resolved.reference { ModuleReference::AccountBase(_) | ModuleReference::Native(_) => { - return Err(HostError::WrongModuleAction( - target_module.module_info.to_string(), - )) + return Err(HostError::WrongModuleAction(target_module.to_string())) } - _ => (), - } - - let target_addr = target_module.addr(deps.as_ref(), vc)?; + ModuleReference::Adapter(addr) => addr, + ModuleReference::App(_) | ModuleReference::Standalone(_) => { + let installed_module = InstalledModuleIdentification { + module_info: target_module, + account_id: source_module + .account_id + .clone() + .map(|a| remote_account_id(client_chain.clone(), a)) + .transpose()?, + }; + installed_module.addr(deps.as_ref(), vc)? + } + _ => unimplemented!(), + }; // We pass the message on to the module let msg = wasm_execute( diff --git a/framework/packages/abstract-core/src/native/ibc_client.rs b/framework/packages/abstract-core/src/native/ibc_client.rs index 17f82650ef..30245d41e9 100644 --- a/framework/packages/abstract-core/src/native/ibc_client.rs +++ b/framework/packages/abstract-core/src/native/ibc_client.rs @@ -107,7 +107,7 @@ pub enum ExecuteMsg { ModuleIbcAction { host_chain: String, source_module: InstalledModuleIdentification, - target_module: InstalledModuleIdentification, + target_module: ModuleInfo, msg: Binary, callback_info: Option, }, diff --git a/framework/packages/abstract-core/src/native/ibc_host.rs b/framework/packages/abstract-core/src/native/ibc_host.rs index 5c0cb0c540..b3b8feb9e5 100644 --- a/framework/packages/abstract-core/src/native/ibc_host.rs +++ b/framework/packages/abstract-core/src/native/ibc_host.rs @@ -13,7 +13,7 @@ use cosmwasm_std::{Addr, Binary}; use crate::{ ibc_client::InstalledModuleIdentification, manager::{self, ModuleInstallConfig}, - objects::{account::AccountId, chain_name::ChainName, AssetEntry}, + objects::{account::AccountId, chain_name::ChainName, module::ModuleInfo, AssetEntry}, }; pub mod state { @@ -130,7 +130,7 @@ pub enum ExecuteMsg { /// Allows for remote execution from the Polytone implementation on a local module ModuleExecute { source_module: InstalledModuleIdentification, - target_module: InstalledModuleIdentification, + target_module: ModuleInfo, msg: Binary, }, } From 43174c96d8cba72e5696edfe7c76bb3dc11de072 Mon Sep 17 00:00:00 2001 From: Kayanski Date: Mon, 11 Mar 2024 16:41:36 +0000 Subject: [PATCH 18/37] Fixed test --- .../contracts/native/ibc-client/src/ibc.rs | 4 +- .../native/ibc-host/src/endpoints/packet.rs | 2 +- framework/packages/abstract-app/src/lib.rs | 6 +- framework/packages/abstract-core/src/base.rs | 6 +- .../packages/abstract-core/src/native/ibc.rs | 16 +- .../abstract-core/src/native/ibc_client.rs | 5 +- .../abstract-sdk/src/base/contract_base.rs | 4 +- .../src/base/endpoints/ibc_callback.rs | 18 +- .../src/module_to_module_interactions.rs | 176 +++++------------- 9 files changed, 86 insertions(+), 151 deletions(-) diff --git a/framework/contracts/native/ibc-client/src/ibc.rs b/framework/contracts/native/ibc-client/src/ibc.rs index 0bd172e5f5..6022283994 100644 --- a/framework/contracts/native/ibc-client/src/ibc.rs +++ b/framework/contracts/native/ibc-client/src/ibc.rs @@ -1,5 +1,5 @@ use abstract_core::{ - ibc::IbcResponseMsg, + ibc::IbcCallbackMsg, ibc_client::{ state::{IBC_INFRA, REVERSE_POLYTONE_NOTE}, IbcClientCallback, @@ -92,7 +92,7 @@ pub fn receive_action_callback( callback_info, sender_module, } => { - let callback = IbcResponseMsg { + let callback = IbcCallbackMsg { id: callback_info.id.clone(), msg: callback_info.msg, result: callback.result, diff --git a/framework/contracts/native/ibc-host/src/endpoints/packet.rs b/framework/contracts/native/ibc-host/src/endpoints/packet.rs index e5b7c4a601..4d6ee4fe41 100644 --- a/framework/contracts/native/ibc-host/src/endpoints/packet.rs +++ b/framework/contracts/native/ibc-host/src/endpoints/packet.rs @@ -156,7 +156,7 @@ pub fn handle_host_module_action( target_addr, &MiddlewareExecMsg::ModuleIbc::(ModuleIbcMsg { client_chain, - source_module, + source_module: source_module.module_info, msg, }), vec![], diff --git a/framework/packages/abstract-app/src/lib.rs b/framework/packages/abstract-app/src/lib.rs index 508ddab440..bc1a4c693f 100644 --- a/framework/packages/abstract-app/src/lib.rs +++ b/framework/packages/abstract-app/src/lib.rs @@ -32,7 +32,6 @@ pub use abstract_testing; pub mod mock { pub use abstract_core::app; use abstract_core::{ - ibc_client::InstalledModuleIdentification, manager::ModuleInstallConfig, objects::{dependency::StaticDependency, module::ModuleInfo}, }; @@ -76,7 +75,7 @@ pub mod mock { #[cosmwasm_schema::cw_serde] pub struct ReceivedIbcCallbackStatus { - pub received: Option, + pub received: Option, } #[cosmwasm_schema::cw_serde] @@ -134,8 +133,7 @@ pub mod mock { MockAppContract::new(TEST_MODULE_ID, TEST_VERSION, None); // Easy way to see if an ibc-callback was actually received. - pub const IBC_CALLBACK_RECEIVED: Item> = - Item::new("ibc_callback_received"); + pub const IBC_CALLBACK_RECEIVED: Item> = Item::new("ibc_callback_received"); pub const MOCK_APP_WITH_DEP: MockAppContract = MockAppContract::new(TEST_WITH_DEP_MODULE_ID, TEST_VERSION, None) diff --git a/framework/packages/abstract-core/src/base.rs b/framework/packages/abstract-core/src/base.rs index 7805d2f3c0..d5e4ed3752 100644 --- a/framework/packages/abstract-core/src/base.rs +++ b/framework/packages/abstract-core/src/base.rs @@ -1,7 +1,7 @@ use cosmwasm_schema::QueryResponses; use cosmwasm_std::Empty; -use crate::ibc::{IbcResponseMsg, ModuleIbcMsg}; +use crate::ibc::{IbcCallbackMsg, ModuleIbcMsg}; // ANCHOR: exec /// Wrapper around all possible messages that can be sent to the module. @@ -13,8 +13,8 @@ pub enum ExecuteMsg { Module(CustomExecMsg), /// IbcReceive to process IBC callbacks /// In order to trust this, the apps and adapters verify this comes from the ibc-client contract. - IbcCallback(IbcResponseMsg), - /// ModuleIbc endpoint to receive messages from this module on other chains + IbcCallback(IbcCallbackMsg), + /// ModuleIbc endpoint to receive messages from modules on other chains /// In order to trust this, the apps and adapters verify this comes from the ibc-host contract. /// They should also trust the sending chain ModuleIbc(ModuleIbcMsg), diff --git a/framework/packages/abstract-core/src/native/ibc.rs b/framework/packages/abstract-core/src/native/ibc.rs index bed0659ebd..420fcd0011 100644 --- a/framework/packages/abstract-core/src/native/ibc.rs +++ b/framework/packages/abstract-core/src/native/ibc.rs @@ -4,7 +4,9 @@ use polytone::callbacks::Callback; use schemars::JsonSchema; use crate::{ - base::ExecuteMsg, ibc_client::InstalledModuleIdentification, objects::chain_name::ChainName, + base::ExecuteMsg, + ibc_client::InstalledModuleIdentification, + objects::{chain_name::ChainName, module::ModuleInfo}, }; // CallbackInfo from modules, that is turned into an IbcResponseMsg by the ibc client @@ -21,7 +23,7 @@ pub struct CallbackInfo { /// IbcResponseMsg should be de/serialized under `IbcCallback()` variant in a ExecuteMsg #[cosmwasm_schema::cw_serde] -pub struct IbcResponseMsg { +pub struct IbcCallbackMsg { /// The ID chosen by the caller in the `callback_info.id` pub id: String, /// The msg sent with the callback request. @@ -33,10 +35,10 @@ pub struct IbcResponseMsg { pub result: Callback, } -impl IbcResponseMsg { +impl IbcCallbackMsg { /// serializes the message pub fn into_json_binary(self) -> StdResult { - let msg = IbcCallbackMsg::IbcCallback(self); + let msg = IbcCallbackMsgSerializeHelper::IbcCallback(self); to_json_binary(&msg) } @@ -57,13 +59,13 @@ impl IbcResponseMsg { /// This is just a helper to properly serialize the above message. /// The actual receiver should include this variant in the larger ExecuteMsg enum #[cosmwasm_schema::cw_serde] -pub(crate) enum IbcCallbackMsg { - IbcCallback(IbcResponseMsg), +pub(crate) enum IbcCallbackMsgSerializeHelper { + IbcCallback(IbcCallbackMsg), } #[cw_serde] pub struct ModuleIbcMsg { pub client_chain: ChainName, - pub source_module: InstalledModuleIdentification, + pub source_module: ModuleInfo, pub msg: Binary, } diff --git a/framework/packages/abstract-core/src/native/ibc_client.rs b/framework/packages/abstract-core/src/native/ibc_client.rs index 30245d41e9..936eb8706e 100644 --- a/framework/packages/abstract-core/src/native/ibc_client.rs +++ b/framework/packages/abstract-core/src/native/ibc_client.rs @@ -310,8 +310,7 @@ mod tests { use polytone::callbacks::Callback; use speculoos::prelude::*; - use crate::ibc::IbcCallbackMsg; - use crate::ibc::IbcResponseMsg; + use crate::ibc::{IbcCallbackMsg, IbcCallbackMsgSerializeHelper}; use crate::objects::module::ModuleInfo; use crate::objects::AccountId; @@ -344,7 +343,7 @@ mod tests { assert_that!(actual).is_equal_to(CosmosMsg::Wasm(cosmwasm_std::WasmMsg::Execute { contract_addr: receiver, // we can't test the message because the fields in it are private - msg: to_json_binary(&IbcCallbackMsg::IbcCallback(response_msg)).unwrap(), + msg: to_json_binary(&IbcCallbackMsgSerializeHelper::IbcCallback(response_msg)).unwrap(), funds: vec![], })) } diff --git a/framework/packages/abstract-sdk/src/base/contract_base.rs b/framework/packages/abstract-sdk/src/base/contract_base.rs index e9c417e8e9..2e2848ebb4 100644 --- a/framework/packages/abstract-sdk/src/base/contract_base.rs +++ b/framework/packages/abstract-sdk/src/base/contract_base.rs @@ -1,4 +1,4 @@ -use abstract_core::{ibc::ModuleIbcMsg, ibc_client::InstalledModuleIdentification}; +use abstract_core::{ibc::ModuleIbcMsg, objects::module::ModuleInfo}; use cosmwasm_std::{Binary, Deps, DepsMut, Env, MessageInfo, Reply, Response, Storage}; use cw2::{ContractVersion, CONTRACT}; use cw_storage_plus::Item; @@ -38,7 +38,7 @@ pub type IbcCallbackHandlerFn = fn( Env, MessageInfo, Module, - InstalledModuleIdentification, + ModuleInfo, CallbackMessage, Callback, ) -> Result; diff --git a/framework/packages/abstract-sdk/src/base/endpoints/ibc_callback.rs b/framework/packages/abstract-sdk/src/base/endpoints/ibc_callback.rs index 9fd6a19af4..0bd66ab3f6 100644 --- a/framework/packages/abstract-sdk/src/base/endpoints/ibc_callback.rs +++ b/framework/packages/abstract-sdk/src/base/endpoints/ibc_callback.rs @@ -1,5 +1,5 @@ use crate::{base::Handler, AbstractSdkError}; -use abstract_core::ibc::IbcResponseMsg; +use abstract_core::ibc::IbcCallbackMsg; use cosmwasm_std::{Addr, Deps, DepsMut, Env, MessageInfo, Response}; /// Trait for a contract's IBC callback ExecuteMsg variant. @@ -13,7 +13,7 @@ pub trait IbcCallbackEndpoint: Handler { deps: DepsMut, env: Env, info: MessageInfo, - msg: IbcResponseMsg, + msg: IbcCallbackMsg, ) -> Result { let ibc_client = self.ibc_client(deps.as_ref())?; @@ -25,7 +25,7 @@ pub trait IbcCallbackEndpoint: Handler { } .into()); }; - let IbcResponseMsg { + let IbcCallbackMsg { id, msg: callback_msg, result, @@ -34,7 +34,17 @@ pub trait IbcCallbackEndpoint: Handler { let maybe_handler = self.maybe_ibc_callback_handler(&id); maybe_handler.map_or_else( || Ok(Response::new()), - |handler| handler(deps, env, info, self, sender_module, callback_msg, result), + |handler| { + handler( + deps, + env, + info, + self, + sender_module.module_info, + callback_msg, + result, + ) + }, ) } } diff --git a/interchain/tests/src/module_to_module_interactions.rs b/interchain/tests/src/module_to_module_interactions.rs index 45050b26eb..a6021bdd83 100644 --- a/interchain/tests/src/module_to_module_interactions.rs +++ b/interchain/tests/src/module_to_module_interactions.rs @@ -26,7 +26,7 @@ pub enum MockExecMsg { DoSomethingAdmin {}, DoSomethingIbc { remote_chain: String, - target_module: InstalledModuleIdentification, + target_module: ModuleInfo, }, } @@ -49,7 +49,7 @@ pub struct ReceivedIbcCallbackStatus { #[cosmwasm_schema::cw_serde] pub struct ReceivedIbcModuleStatus { - pub received: InstalledModuleIdentification, + pub received: ModuleInfo, } #[cosmwasm_schema::cw_serde] @@ -103,8 +103,7 @@ pub struct IbcModuleToModuleMsg { // Easy way to see if an ibc-callback was actually received. pub const IBC_CALLBACK_RECEIVED: Item = Item::new("ibc_callback_received"); // Easy way to see if an module ibc called was actually received. -pub const MODULE_IBC_RECEIVED: Item = - Item::new("module_ibc_received"); +pub const MODULE_IBC_RECEIVED: Item = Item::new("module_ibc_received"); pub const fn mock_app(id: &'static str, version: &'static str) -> MockAppContract { MockAppContract::new(id, version, None) @@ -174,7 +173,7 @@ pub const fn mock_app(id: &'static str, version: &'static str) -> MockAppContrac let ModuleIbcMsg { source_module, .. } = msg; // We save the module info status MODULE_IBC_RECEIVED.save(deps.storage, &source_module)?; - Ok(Response::new()) + Ok(Response::new().add_attribute("mock_module_ibc", "executed")) }) } @@ -201,7 +200,7 @@ pub mod test { fn assert_remote_module_call_status( app: &MockAppRemoteI, - source_module_expected: Option, + source_module_expected: Option, ) -> AnyResult<()> { let source_module = app .get_received_ibc_module_status() @@ -235,11 +234,19 @@ pub mod test { JUNO, STARGAZE, }; use abstract_app::objects::{chain_name::ChainName, module::ModuleInfo, AccountId}; - use abstract_core::ibc_client::InstalledModuleIdentification; - use abstract_interface::{AppDeployer, DeployStrategy, ManagerQueryFns, VCExecFns}; + use abstract_core::{ + ibc_client::InstalledModuleIdentification, + manager::{self, ModuleInstallConfig}, + proxy, + }; + use abstract_interface::{ + AbstractAccount, AppDeployer, DeployStrategy, Manager, ManagerQueryFns, VCExecFns, + VCQueryFns, + }; use abstract_testing::addresses::{TEST_MODULE_ID, TEST_NAMESPACE, TEST_VERSION}; use anyhow::Result as AnyResult; use base64::{engine::general_purpose, Engine}; + use cosmwasm_std::to_json_binary; use cw_orch::interchain::MockBech32InterchainEnv; use cw_orch::prelude::*; @@ -258,9 +265,6 @@ pub mod test { let (origin_account, _remote_account_id) = create_test_remote_account(&abstr_origin, JUNO, STARGAZE, &mock_interchain, None)?; - let (remote_account, _remote_account_id) = - create_test_remote_account(&abstr_remote, STARGAZE, JUNO, &mock_interchain, None)?; - let app = MockAppOriginI::new( TEST_MODULE_ID, abstr_origin.version_control.get_chain().clone(), @@ -278,13 +282,7 @@ pub mod test { // The user on origin chain wants to change the account description let target_module_info = ModuleInfo::from_id(TEST_MODULE_ID_REMOTE, TEST_VERSION_REMOTE.into())?; - let ibc_action_result = app.do_something_ibc( - remote_name, - InstalledModuleIdentification { - module_info: target_module_info.clone(), - account_id: Some(remote_account.id()?), - }, - )?; + let ibc_action_result = app.do_something_ibc(remote_name, target_module_info.clone())?; let ibc_result = mock_interchain.wait_ibc(JUNO, ibc_action_result)?; @@ -316,7 +314,7 @@ pub mod test { } #[test] - fn target_account_must_exist() -> AnyResult<()> { + fn target_account_must_have_module_installed() -> AnyResult<()> { logger_test_init(); let mock_interchain = MockBech32InterchainEnv::new(vec![(JUNO, "juno"), (STARGAZE, "stargaze")]); @@ -359,24 +357,15 @@ pub mod test { app_remote.deploy(TEST_VERSION_REMOTE.parse()?, DeployStrategy::Try)?; - remote_account.install_app(&app_remote, &MockInitMsg {}, None)?; - // The user on origin chain wants to change the account description - let unknown_account_id = AccountId::local(remote_account.id()?.seq() + 80); let target_module_info = ModuleInfo::from_id(TEST_MODULE_ID_REMOTE, TEST_VERSION_REMOTE.into())?; - let ibc_action_result = app.do_something_ibc( - remote_name, - InstalledModuleIdentification { - module_info: target_module_info.clone(), - // This account is not supposed to exist on the remote chain - account_id: Some(unknown_account_id.clone()), - }, - )?; + let ibc_action_result = app.do_something_ibc(remote_name, target_module_info.clone())?; let ibc_result = mock_interchain.wait_ibc(JUNO, ibc_action_result)?; - let expected_error_outcome = format!("Unknown Account id {}", unknown_account_id); + let expected_error_outcome = + format!("App {} not installed on Account", target_module_info,); match &ibc_result.packets[0].outcome { cw_orch::interchain::types::IbcPacketOutcome::Timeout { .. } => { panic!("Expected a failed ack not a timeout !") @@ -396,11 +385,11 @@ pub mod test { } }, } + Ok(()) } - #[test] - fn target_account_must_have_module_installed() -> AnyResult<()> { + fn works() -> AnyResult<()> { logger_test_init(); let mock_interchain = MockBech32InterchainEnv::new(vec![(JUNO, "juno"), (STARGAZE, "stargaze")]); @@ -411,10 +400,10 @@ pub mod test { let remote_name = ChainName::from_chain_id(STARGAZE).to_string(); - let (origin_account, _remote_account_id) = + let (origin_account, remote_account_id) = create_test_remote_account(&abstr_origin, JUNO, STARGAZE, &mock_interchain, None)?; - let (remote_account, _remote_account_id) = + let (remote_account, _) = create_test_remote_account(&abstr_remote, STARGAZE, JUNO, &mock_interchain, None)?; // Install local app @@ -443,112 +432,49 @@ pub mod test { app_remote.deploy(TEST_VERSION_REMOTE.parse()?, DeployStrategy::Try)?; - // The user on origin chain wants to change the account description - let target_module_info = - ModuleInfo::from_id(TEST_MODULE_ID_REMOTE, TEST_VERSION_REMOTE.into())?; - let ibc_action_result = app.do_something_ibc( - remote_name, - InstalledModuleIdentification { - module_info: target_module_info.clone(), - // This account is not supposed to exist on the remote chain - account_id: Some(remote_account.id()?), + let remote_install_response = origin_account.manager.execute_on_remote( + &remote_name, + manager::ExecuteMsg::InstallModules { + modules: vec![ModuleInstallConfig::new( + ModuleInfo::from_id_latest(TEST_MODULE_ID_REMOTE)?, + Some(to_json_binary(&MockInitMsg {})?), + )], }, )?; - let ibc_result = mock_interchain.wait_ibc(JUNO, ibc_action_result)?; - - let expected_error_outcome = - format!("App {} not installed on Account", target_module_info,); - match &ibc_result.packets[0].outcome { - cw_orch::interchain::types::IbcPacketOutcome::Timeout { .. } => { - panic!("Expected a failed ack not a timeout !") - } - cw_orch::interchain::types::IbcPacketOutcome::Success { ack, .. } => match ack { - cw_orch::interchain::types::IbcPacketAckDecode::Error(e) => { - assert!(e.contains(&expected_error_outcome)); - } - cw_orch::interchain::types::IbcPacketAckDecode::Success(_) => { - panic!("Expected a error ack") - } - cw_orch::interchain::types::IbcPacketAckDecode::NotParsed(original_ack) => { - let error_str = - String::from_utf8_lossy(&general_purpose::STANDARD.decode(original_ack)?) - .to_string(); - assert!(error_str.contains(&expected_error_outcome)); - } - }, - } - - Ok(()) - } - #[test] - fn works() -> AnyResult<()> { - logger_test_init(); - let mock_interchain = - MockBech32InterchainEnv::new(vec![(JUNO, "juno"), (STARGAZE, "stargaze")]); - - // We just verified all steps pass - let (abstr_origin, abstr_remote) = ibc_abstract_setup(&mock_interchain, JUNO, STARGAZE)?; - ibc_connect_polytone_and_abstract(&mock_interchain, STARGAZE, JUNO)?; - - let remote_name = ChainName::from_chain_id(STARGAZE).to_string(); - - let (origin_account, _remote_account_id) = - create_test_remote_account(&abstr_origin, JUNO, STARGAZE, &mock_interchain, None)?; - - let (remote_account, _remote_account_id) = - create_test_remote_account(&abstr_remote, STARGAZE, JUNO, &mock_interchain, None)?; - - // Install local app - let app = MockAppOriginI::new( - TEST_MODULE_ID, - abstr_origin.version_control.get_chain().clone(), - ); + mock_interchain.wait_ibc(JUNO, remote_install_response)?; - abstr_origin + // We get the object for handling the actual module on the remote account + let remote_manager = abstr_remote .version_control - .claim_namespace(origin_account.id()?, TEST_NAMESPACE.to_owned())?; - - app.deploy(TEST_VERSION.parse()?, DeployStrategy::Try)?; - - origin_account.install_app(&app, &MockInitMsg {}, None)?; - - // Install remote app - let app_remote = MockAppRemoteI::new( - TEST_MODULE_ID_REMOTE, + .account_base(remote_account_id)? + .account_base + .manager; + let manager = Manager::new( + "remote-account-manager", abstr_remote.version_control.get_chain().clone(), ); + manager.set_address(&remote_manager); + let module_address = manager.module_info(TEST_MODULE_ID_REMOTE)?.unwrap().address; + let remote_account_app = MockAppRemoteI::new( + "remote-account-app", + abstr_remote.version_control.get_chain().clone(), + ); + remote_account_app.set_address(&module_address); - abstr_remote - .version_control - .claim_namespace(remote_account.id()?, TEST_NAMESPACE.to_owned())?; - - app_remote.deploy(TEST_VERSION_REMOTE.parse()?, DeployStrategy::Try)?; - remote_account.install_app(&app_remote, &MockInitMsg {}, None)?; - - // The user on origin chain wants to change the account description + // The user on origin chain triggers a module-to-module interaction let target_module_info = ModuleInfo::from_id(TEST_MODULE_ID_REMOTE, TEST_VERSION_REMOTE.into())?; - let ibc_action_result = app.do_something_ibc( - remote_name, - InstalledModuleIdentification { - module_info: target_module_info.clone(), - // This account is not supposed to exist on the remote chain - account_id: Some(remote_account.id()?), - }, - )?; + let ibc_action_result = app.do_something_ibc(remote_name, target_module_info.clone())?; - assert_remote_module_call_status(&app_remote, None)?; + assert_remote_module_call_status(&remote_account_app, None)?; assert_callback_status(&app, false)?; mock_interchain.wait_ibc(JUNO, ibc_action_result)?; assert_remote_module_call_status( - &app_remote, - Some(InstalledModuleIdentification { - module_info: ModuleInfo::from_id(TEST_MODULE_ID, TEST_VERSION.into())?, - account_id: Some(origin_account.id()?), - }), + &remote_account_app, + Some(ModuleInfo::from_id(TEST_MODULE_ID, TEST_VERSION.into())?), )?; assert_callback_status(&app, true)?; From 502e4ef6aff0ea586b17e1612f5c9677199224e0 Mon Sep 17 00:00:00 2001 From: Kayanski Date: Mon, 11 Mar 2024 17:43:03 +0000 Subject: [PATCH 19/37] Better addr getter for installed module --- .../native/ibc-host/src/endpoints/packet.rs | 35 ++++++------------- .../abstract-core/src/native/ibc_client.rs | 29 ++++++++++----- .../src/base/endpoints/modules_ibc.rs | 2 +- integrations/astrovault-adapter/src/dex.rs | 2 +- .../src/module_to_module_interactions.rs | 13 +++---- 5 files changed, 37 insertions(+), 44 deletions(-) diff --git a/framework/contracts/native/ibc-host/src/endpoints/packet.rs b/framework/contracts/native/ibc-host/src/endpoints/packet.rs index 4d6ee4fe41..ffa9b7e05e 100644 --- a/framework/contracts/native/ibc-host/src/endpoints/packet.rs +++ b/framework/contracts/native/ibc-host/src/endpoints/packet.rs @@ -5,9 +5,7 @@ use abstract_core::{ state::{ActionAfterCreationCache, CONFIG, TEMP_ACTION_AFTER_CREATION}, HelperAction, }, - objects::{ - chain_name::ChainName, module::ModuleInfo, module_reference::ModuleReference, AccountId, - }, + objects::{chain_name::ChainName, module::ModuleInfo, AccountId}, }; use abstract_sdk::core::ibc_host::{HostAction, InternalAction}; use cosmwasm_std::{wasm_execute, Binary, DepsMut, Empty, Env, Response}; @@ -15,7 +13,6 @@ use cosmwasm_std::{wasm_execute, Binary, DepsMut, Empty, Env, Response}; use crate::{ account_commands::{self, receive_dispatch, receive_register, receive_send_all_back}, contract::HostResult, - HostError, }; use abstract_core::base::ExecuteMsg as MiddlewareExecMsg; @@ -129,31 +126,19 @@ pub fn handle_host_module_action( ) -> HostResult { // We resolve the target module let vc = CONFIG.load(deps.storage)?.version_control; - let target_module_resolved = vc.query_module(target_module.clone(), &deps.querier)?; - - // We can't send module actions to accounts base and native apps - let target_addr = match target_module_resolved.reference { - ModuleReference::AccountBase(_) | ModuleReference::Native(_) => { - return Err(HostError::WrongModuleAction(target_module.to_string())) - } - ModuleReference::Adapter(addr) => addr, - ModuleReference::App(_) | ModuleReference::Standalone(_) => { - let installed_module = InstalledModuleIdentification { - module_info: target_module, - account_id: source_module - .account_id - .clone() - .map(|a| remote_account_id(client_chain.clone(), a)) - .transpose()?, - }; - installed_module.addr(deps.as_ref(), vc)? - } - _ => unimplemented!(), + let target_module = InstalledModuleIdentification { + module_info: target_module, + account_id: source_module + .account_id + .map(|a| remote_account_id(client_chain.clone(), a)) + .transpose()?, }; + let target_module_resolved = target_module.addr(deps.as_ref(), vc)?; + // We pass the message on to the module let msg = wasm_execute( - target_addr, + target_module_resolved.address, &MiddlewareExecMsg::ModuleIbc::(ModuleIbcMsg { client_chain, source_module: source_module.module_info, diff --git a/framework/packages/abstract-core/src/native/ibc_client.rs b/framework/packages/abstract-core/src/native/ibc_client.rs index 936eb8706e..a7095ff073 100644 --- a/framework/packages/abstract-core/src/native/ibc_client.rs +++ b/framework/packages/abstract-core/src/native/ibc_client.rs @@ -148,14 +148,24 @@ pub struct InstalledModuleIdentification { pub account_id: Option, } +#[cosmwasm_schema::cw_serde] +pub struct ModuleAddr { + pub reference: ModuleReference, + pub address: Addr, +} + impl InstalledModuleIdentification { - pub fn addr(&self, deps: Deps, vc: VersionControlContract) -> Result { + pub fn addr( + &self, + deps: Deps, + vc: VersionControlContract, + ) -> Result { let target_module_resolved = vc.query_module(self.module_info.clone(), &deps.querier)?; let no_account_id_error = StdError::generic_err("Account id not specified in installed module definition"); - let target_addr = match target_module_resolved.reference { + let target_addr = match &target_module_resolved.reference { ModuleReference::AccountBase(code_id) => { let target_account_id = self.account_id.clone().ok_or(no_account_id_error)?; let account_base = vc.account_base(&target_account_id, &deps.querier)?; @@ -164,14 +174,14 @@ impl InstalledModuleIdentification { .querier .query_wasm_contract_info(&account_base.proxy)? .code_id - == code_id + == *code_id { account_base.proxy } else if deps .querier .query_wasm_contract_info(&account_base.manager)? .code_id - == code_id + == *code_id { account_base.manager } else { @@ -180,8 +190,8 @@ impl InstalledModuleIdentification { ))? } } - ModuleReference::Native(addr) => addr, - ModuleReference::Adapter(addr) => addr, + ModuleReference::Native(addr) => addr.clone(), + ModuleReference::Adapter(addr) => addr.clone(), ModuleReference::App(_) | ModuleReference::Standalone(_) => { let target_account_id = self.account_id.clone().ok_or(no_account_id_error)?; let account_base = vc.account_base(&target_account_id, &deps.querier)?; @@ -200,7 +210,10 @@ impl InstalledModuleIdentification { .clone() } }; - Ok(target_addr) + Ok(ModuleAddr { + reference: target_module_resolved.reference, + address: target_addr, + }) } } @@ -325,7 +338,7 @@ mod tests { let result = Callback::FatalError("ibc execution error".to_string()); - let response_msg = IbcResponseMsg { + let response_msg = IbcCallbackMsg { id: callback_id, msg: Some(callback_msg), result, diff --git a/framework/packages/abstract-sdk/src/base/endpoints/modules_ibc.rs b/framework/packages/abstract-sdk/src/base/endpoints/modules_ibc.rs index f498b13749..ac7971aa17 100644 --- a/framework/packages/abstract-sdk/src/base/endpoints/modules_ibc.rs +++ b/framework/packages/abstract-sdk/src/base/endpoints/modules_ibc.rs @@ -8,7 +8,7 @@ pub trait ModuleIbcEndpoint: Handler { /// Get the address of the ibc host associated with this module fn ibc_host(&self, deps: Deps) -> Result; - /// Handler for the `ExecuteMsg::IbcCallback()` variant. + /// Handler for the `ExecuteMsg::ModuleIbc(ModuleIbcMsg)` variant. fn module_ibc( self, deps: DepsMut, diff --git a/integrations/astrovault-adapter/src/dex.rs b/integrations/astrovault-adapter/src/dex.rs index 47219ea1eb..9b15770f30 100644 --- a/integrations/astrovault-adapter/src/dex.rs +++ b/integrations/astrovault-adapter/src/dex.rs @@ -740,7 +740,7 @@ mod tests { use std::{assert_eq, str::FromStr}; use abstract_dex_standard::tests::{expect_eq, DexCommandTester}; - use abstract_sdk::core::objects::{PoolAddress, PoolType}; + use abstract_sdk::core::objects::PoolAddress; use cosmwasm_schema::serde::Deserialize; use cosmwasm_std::{ coin, coins, from_json, to_json_binary, wasm_execute, Addr, Coin, CosmosMsg, Decimal, diff --git a/interchain/tests/src/module_to_module_interactions.rs b/interchain/tests/src/module_to_module_interactions.rs index a6021bdd83..f293354b3d 100644 --- a/interchain/tests/src/module_to_module_interactions.rs +++ b/interchain/tests/src/module_to_module_interactions.rs @@ -233,15 +233,10 @@ pub mod test { }, JUNO, STARGAZE, }; - use abstract_app::objects::{chain_name::ChainName, module::ModuleInfo, AccountId}; - use abstract_core::{ - ibc_client::InstalledModuleIdentification, - manager::{self, ModuleInstallConfig}, - proxy, - }; + use abstract_app::objects::{chain_name::ChainName, module::ModuleInfo}; + use abstract_core::manager::{self, ModuleInstallConfig}; use abstract_interface::{ - AbstractAccount, AppDeployer, DeployStrategy, Manager, ManagerQueryFns, VCExecFns, - VCQueryFns, + AppDeployer, DeployStrategy, Manager, ManagerQueryFns, VCExecFns, VCQueryFns, }; use abstract_testing::addresses::{TEST_MODULE_ID, TEST_NAMESPACE, TEST_VERSION}; use anyhow::Result as AnyResult; @@ -257,7 +252,7 @@ pub mod test { MockBech32InterchainEnv::new(vec![(JUNO, "juno"), (STARGAZE, "stargaze")]); // We just verified all steps pass - let (abstr_origin, abstr_remote) = ibc_abstract_setup(&mock_interchain, JUNO, STARGAZE)?; + let (abstr_origin, _abstr_remote) = ibc_abstract_setup(&mock_interchain, JUNO, STARGAZE)?; ibc_connect_polytone_and_abstract(&mock_interchain, STARGAZE, JUNO)?; let remote_name = ChainName::from_chain_id(STARGAZE).to_string(); From ed19f5e36d7a2d900f2a5fadee4d8c552ac9bf57 Mon Sep 17 00:00:00 2001 From: Kayanski Date: Tue, 12 Mar 2024 08:06:07 +0000 Subject: [PATCH 20/37] Added account + native module error --- .../native/ibc-host/src/endpoints/packet.rs | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/framework/contracts/native/ibc-host/src/endpoints/packet.rs b/framework/contracts/native/ibc-host/src/endpoints/packet.rs index ffa9b7e05e..91567109e0 100644 --- a/framework/contracts/native/ibc-host/src/endpoints/packet.rs +++ b/framework/contracts/native/ibc-host/src/endpoints/packet.rs @@ -5,7 +5,9 @@ use abstract_core::{ state::{ActionAfterCreationCache, CONFIG, TEMP_ACTION_AFTER_CREATION}, HelperAction, }, - objects::{chain_name::ChainName, module::ModuleInfo, AccountId}, + objects::{ + chain_name::ChainName, module::ModuleInfo, module_reference::ModuleReference, AccountId, + }, }; use abstract_sdk::core::ibc_host::{HostAction, InternalAction}; use cosmwasm_std::{wasm_execute, Binary, DepsMut, Empty, Env, Response}; @@ -13,6 +15,7 @@ use cosmwasm_std::{wasm_execute, Binary, DepsMut, Empty, Env, Response}; use crate::{ account_commands::{self, receive_dispatch, receive_register, receive_send_all_back}, contract::HostResult, + HostError, }; use abstract_core::base::ExecuteMsg as MiddlewareExecMsg; @@ -136,6 +139,15 @@ pub fn handle_host_module_action( let target_module_resolved = target_module.addr(deps.as_ref(), vc)?; + match target_module_resolved.reference { + ModuleReference::AccountBase(_) | ModuleReference::Native(_) => { + return Err(HostError::WrongModuleAction( + "Can't send module-to-module message to an account or a native module".to_string(), + )) + } + _ => {} + } + // We pass the message on to the module let msg = wasm_execute( target_module_resolved.address, From d561c1c7665a99717070c6ef9d4d5a700747fdf4 Mon Sep 17 00:00:00 2001 From: cyberhoward Date: Tue, 12 Mar 2024 16:13:19 +0100 Subject: [PATCH 21/37] rm unneeded clone --- framework/contracts/native/ibc-client/src/commands.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/framework/contracts/native/ibc-client/src/commands.rs b/framework/contracts/native/ibc-client/src/commands.rs index c3a1e99138..46672643c7 100644 --- a/framework/contracts/native/ibc-client/src/commands.rs +++ b/framework/contracts/native/ibc-client/src/commands.rs @@ -255,9 +255,9 @@ pub fn execute_send_module_to_module_packet( } // If it does have the right code id, we verify the specified account has the app installed let account_base = cfg.version_control.account_base( - &source_module + source_module .account_id - .clone() + .as_ref() .ok_or(IbcClientError::ForbiddenModuleCall {})?, &deps.querier, )?; From 2085a47113590693b00e0ebe5dc550f57d80a2c8 Mon Sep 17 00:00:00 2001 From: cyberhoward Date: Tue, 12 Mar 2024 16:20:07 +0100 Subject: [PATCH 22/37] use raw query for module install verification --- framework/contracts/native/ibc-client/src/commands.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/framework/contracts/native/ibc-client/src/commands.rs b/framework/contracts/native/ibc-client/src/commands.rs index 46672643c7..beddd873db 100644 --- a/framework/contracts/native/ibc-client/src/commands.rs +++ b/framework/contracts/native/ibc-client/src/commands.rs @@ -262,14 +262,14 @@ pub fn execute_send_module_to_module_packet( &deps.querier, )?; - let module_info: manager::ModuleAddressesResponse = deps.querier.query_wasm_smart( + let maybe_module_addr = manager::state::ACCOUNT_MODULES.query( + &deps.querier, account_base.manager, - &manager::QueryMsg::ModuleAddresses { - ids: vec![source_module.module_info.id()], - }, + &source_module.module_info.id(), )?; + let module_addr = maybe_module_addr.ok_or(IbcClientError::ForbiddenModuleCall {})?; ensure_eq!( - module_info.modules[0].1, + module_addr, info.sender, IbcClientError::ForbiddenModuleCall {} ); From e8230314eaa54b6d384f96f49763c839e33b677d Mon Sep 17 00:00:00 2001 From: cyberhoward Date: Tue, 12 Mar 2024 16:40:49 +0100 Subject: [PATCH 23/37] update error msg --- framework/contracts/native/ibc-client/src/error.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/contracts/native/ibc-client/src/error.rs b/framework/contracts/native/ibc-client/src/error.rs index ea8cb24e31..dd1a3f4e2b 100644 --- a/framework/contracts/native/ibc-client/src/error.rs +++ b/framework/contracts/native/ibc-client/src/error.rs @@ -33,7 +33,7 @@ pub enum IbcClientError { #[error("remote account changed from {old} to {addr}")] RemoteAccountChanged { addr: String, old: String }, - #[error("packages that contain internal calls are not allowed")] + #[error("Calling internal actions externally is not allowed")] ForbiddenInternalCall {}, #[error("A non-module package can execute an ibc module call")] From 642a161268204335326e8397ba18d1fe55912d99 Mon Sep 17 00:00:00 2001 From: cyberhoward Date: Tue, 12 Mar 2024 16:48:19 +0100 Subject: [PATCH 24/37] rm redundant type --- framework/packages/abstract-core/src/native/ibc.rs | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/framework/packages/abstract-core/src/native/ibc.rs b/framework/packages/abstract-core/src/native/ibc.rs index 420fcd0011..40cfbdc2aa 100644 --- a/framework/packages/abstract-core/src/native/ibc.rs +++ b/framework/packages/abstract-core/src/native/ibc.rs @@ -38,7 +38,7 @@ pub struct IbcCallbackMsg { impl IbcCallbackMsg { /// serializes the message pub fn into_json_binary(self) -> StdResult { - let msg = IbcCallbackMsgSerializeHelper::IbcCallback(self); + let msg = ExecuteMsg::IbcCallback::(self); to_json_binary(&msg) } @@ -56,13 +56,6 @@ impl IbcCallbackMsg { } } -/// This is just a helper to properly serialize the above message. -/// The actual receiver should include this variant in the larger ExecuteMsg enum -#[cosmwasm_schema::cw_serde] -pub(crate) enum IbcCallbackMsgSerializeHelper { - IbcCallback(IbcCallbackMsg), -} - #[cw_serde] pub struct ModuleIbcMsg { pub client_chain: ChainName, From 1a686b5225cebad0188bafc10a7dbee950656d96 Mon Sep 17 00:00:00 2001 From: Kayanski Date: Wed, 13 Mar 2024 11:02:28 +0000 Subject: [PATCH 25/37] Added docs --- .../src/4_get_started/3_module_builder.md | 34 +++++++++++++++++++ .../packages/abstract-adapter/src/state.rs | 11 +++++- .../packages/abstract-core/src/native/ibc.rs | 2 ++ .../packages/abstract-sdk/src/base/handler.rs | 2 +- 4 files changed, 47 insertions(+), 2 deletions(-) diff --git a/framework/docs/src/4_get_started/3_module_builder.md b/framework/docs/src/4_get_started/3_module_builder.md index da020426a7..baa07a5feb 100644 --- a/framework/docs/src/4_get_started/3_module_builder.md +++ b/framework/docs/src/4_get_started/3_module_builder.md @@ -93,6 +93,7 @@ The available handlers are: - `with_receive`: Called when the App's `ExecuteMsg::Receive` variant is called on the execute entry point. - `with_ibc_callbacks`: Called when the App's `ExecuteMsg::IbcCallback` is called on the execute entry point. Matches the callback's callback ID to its associated function. +- `with_module_ibc`: Called when a Module wants to call another module over IBC. In the case of adapters, the handlers are the same, except for `with_migrate` and `with_sudo` that are missing for reasons we explain in the [adapter section](../3_framework/6_module_types.md#adapters). @@ -325,6 +326,39 @@ customizable but contains the IBC action acknowledgment. + +### Module Ibc + +The module ibc handler is a mutable entry point of the contract. It is similar to the `execute` handler but is +specifically geared towards handling module-to-module IBC calls. On this endpoint, the sender is a module on a remote chain. Module developers should test the `client_chain` AND `source_module` variables against their local storage. Without it, any module could execute the logic inside this functio + + + +
+ +#### Function Signature + +```rust,ignore +{{#include ../../../packages/abstract-sdk/src/base/contract_base.rs:module_ibc}} +``` + +#### Message + +Called when the App's `ExecuteMsg::ModuleIbc` variant is called on the execute entry point. The receiving type is not +customizable. It contains : + +- `client_chain` the remote chain identification +- `source_module` the sending module on the remote chain +- `msg` the message sent by the module. This is usually deserialized by the module's developer to trigger actions. + +```rust,ignore +{{#include ../../../packages/abstract-core/src/base.rs:exec}} + +{{#include ../../../packages/abstract-core/src/native/ibc.rs:module_ibc_msg}} +``` + +
+ ## Dependencies There is another method accessible on the module builder, which is the `with_dependencies` function. As it states it diff --git a/framework/packages/abstract-adapter/src/state.rs b/framework/packages/abstract-adapter/src/state.rs index 9ca9412d09..c510fe0ea1 100644 --- a/framework/packages/abstract-adapter/src/state.rs +++ b/framework/packages/abstract-adapter/src/state.rs @@ -4,7 +4,7 @@ use abstract_core::{objects::dependency::StaticDependency, AbstractError}; use abstract_sdk::{ base::{ AbstractContract, ExecuteHandlerFn, Handler, IbcCallbackHandlerFn, InstantiateHandlerFn, - QueryHandlerFn, ReceiveHandlerFn, ReplyHandlerFn, SudoHandlerFn, + ModuleIbcHandlerFn, QueryHandlerFn, ReceiveHandlerFn, ReplyHandlerFn, SudoHandlerFn, }, core::version_control::AccountBase, feature_objects::{AnsHost, VersionControlContract}, @@ -160,6 +160,15 @@ impl, + ) -> Self { + self.contract = self.contract.with_module_ibc(module_handler); + self + } } #[cfg(test)] diff --git a/framework/packages/abstract-core/src/native/ibc.rs b/framework/packages/abstract-core/src/native/ibc.rs index 420fcd0011..396b44d33d 100644 --- a/framework/packages/abstract-core/src/native/ibc.rs +++ b/framework/packages/abstract-core/src/native/ibc.rs @@ -63,9 +63,11 @@ pub(crate) enum IbcCallbackMsgSerializeHelper { IbcCallback(IbcCallbackMsg), } +// ANCHOR: module_ibc_msg #[cw_serde] pub struct ModuleIbcMsg { pub client_chain: ChainName, pub source_module: ModuleInfo, pub msg: Binary, } +// ANCHOR_END: module_ibc_msg diff --git a/framework/packages/abstract-sdk/src/base/handler.rs b/framework/packages/abstract-sdk/src/base/handler.rs index 16ffa90519..ec223d4e84 100644 --- a/framework/packages/abstract-sdk/src/base/handler.rs +++ b/framework/packages/abstract-sdk/src/base/handler.rs @@ -176,7 +176,7 @@ where } None } - /// Get an ibc callback handler if it exists. + /// Get an IBC module call handler if it exists. fn maybe_module_ibc_handler(&self) -> Option> { let contract = self.contract(); contract.module_ibc_handler From a7ea538f302fba4c864197d20aabee959288f372 Mon Sep 17 00:00:00 2001 From: Kayanski Date: Wed, 13 Mar 2024 11:26:52 +0000 Subject: [PATCH 26/37] Some nits --- .../native/ibc-client/src/commands.rs | 3 ++- .../contracts/native/ibc-client/src/error.rs | 2 +- .../contracts/native/ibc-client/src/ibc.rs | 2 ++ .../native/ibc-host/src/endpoints/packet.rs | 14 +++++++------ .../packages/abstract-adapter/src/lib.rs | 2 +- .../packages/abstract-adapter/src/state.rs | 2 +- framework/packages/abstract-app/src/lib.rs | 4 ++-- framework/packages/abstract-app/src/state.rs | 2 +- .../packages/abstract-core/src/native/ibc.rs | 5 +++-- .../abstract-core/src/native/ibc_client.rs | 18 ++++++++--------- .../abstract-sdk/src/base/contract_base.rs | 17 ++++------------ .../src/base/endpoints/ibc_callback.rs | 20 ++----------------- 12 files changed, 35 insertions(+), 56 deletions(-) diff --git a/framework/contracts/native/ibc-client/src/commands.rs b/framework/contracts/native/ibc-client/src/commands.rs index beddd873db..46fc936781 100644 --- a/framework/contracts/native/ibc-client/src/commands.rs +++ b/framework/contracts/native/ibc-client/src/commands.rs @@ -285,8 +285,9 @@ pub fn execute_send_module_to_module_packet( let callback_request = callback_info.map(|c| CallbackRequest { receiver: env.contract.address.to_string(), msg: to_json_binary(&IbcClientCallback::ModuleRemoteAction { - sender_module: source_module.clone(), + sender_module: source_module.module_info.clone(), callback_info: c, + initiator_msg: msg.clone(), }) .unwrap(), }); diff --git a/framework/contracts/native/ibc-client/src/error.rs b/framework/contracts/native/ibc-client/src/error.rs index dd1a3f4e2b..f4793b628c 100644 --- a/framework/contracts/native/ibc-client/src/error.rs +++ b/framework/contracts/native/ibc-client/src/error.rs @@ -36,7 +36,7 @@ pub enum IbcClientError { #[error("Calling internal actions externally is not allowed")] ForbiddenInternalCall {}, - #[error("A non-module package can execute an ibc module call")] + #[error("A non-module package (native or accounts) cannot execute an ibc module call")] ForbiddenModuleCall {}, #[error("The host you are trying to connect is already connected")] diff --git a/framework/contracts/native/ibc-client/src/ibc.rs b/framework/contracts/native/ibc-client/src/ibc.rs index 6022283994..4e09b641a4 100644 --- a/framework/contracts/native/ibc-client/src/ibc.rs +++ b/framework/contracts/native/ibc-client/src/ibc.rs @@ -91,10 +91,12 @@ pub fn receive_action_callback( IbcClientCallback::ModuleRemoteAction { callback_info, sender_module, + initiator_msg, } => { let callback = IbcCallbackMsg { id: callback_info.id.clone(), msg: callback_info.msg, + initiator_msg, result: callback.result, sender_module, }; diff --git a/framework/contracts/native/ibc-host/src/endpoints/packet.rs b/framework/contracts/native/ibc-host/src/endpoints/packet.rs index 91567109e0..a517350c12 100644 --- a/framework/contracts/native/ibc-host/src/endpoints/packet.rs +++ b/framework/contracts/native/ibc-host/src/endpoints/packet.rs @@ -20,11 +20,14 @@ use crate::{ use abstract_core::base::ExecuteMsg as MiddlewareExecMsg; -pub fn remote_account_id(remote_chain: ChainName, account_id: AccountId) -> HostResult { +pub fn client_to_host_account_id( + remote_chain: ChainName, + account_id: AccountId, +) -> AccountId { let mut account_id = account_id.clone(); - account_id.trace_mut().push_chain(remote_chain.clone()); + account_id.trace_mut().push_chain(remote_chain); - Ok(account_id) + account_id } /// Handle actions that are passed to the IBC host contract @@ -39,7 +42,7 @@ pub fn handle_host_action( host_action: HostAction, ) -> HostResult { // Push the client chain to the account trace - let account_id = remote_account_id(client_chain.clone(), received_account_id.clone())?; + let account_id = client_to_host_account_id(client_chain.clone(), received_account_id.clone()); // get the local account information match host_action { @@ -133,8 +136,7 @@ pub fn handle_host_module_action( module_info: target_module, account_id: source_module .account_id - .map(|a| remote_account_id(client_chain.clone(), a)) - .transpose()?, + .map(|a| client_to_host_account_id(client_chain.clone(), a)), }; let target_module_resolved = target_module.addr(deps.as_ref(), vc)?; diff --git a/framework/packages/abstract-adapter/src/lib.rs b/framework/packages/abstract-adapter/src/lib.rs index aa33191167..b4ec6dbdfb 100644 --- a/framework/packages/abstract-adapter/src/lib.rs +++ b/framework/packages/abstract-adapter/src/lib.rs @@ -124,7 +124,7 @@ pub mod mock { }) .with_sudo(|_, _, _, _| Ok(Response::new().set_data("mock_sudo".as_bytes()))) .with_receive(|_, _, _, _, _| Ok(Response::new().set_data("mock_receive".as_bytes()))) - .with_ibc_callbacks(&[("c_id", |deps, _, _, _, _, _, _| { + .with_ibc_callbacks(&[("c_id", |deps, _, _, _, _| { IBC_CALLBACK_RECEIVED.save(deps.storage, &true).unwrap(); Ok(Response::new().set_data("mock_callback".as_bytes())) })]) diff --git a/framework/packages/abstract-adapter/src/state.rs b/framework/packages/abstract-adapter/src/state.rs index c510fe0ea1..5a1816e9c2 100644 --- a/framework/packages/abstract-adapter/src/state.rs +++ b/framework/packages/abstract-adapter/src/state.rs @@ -200,7 +200,7 @@ mod tests { .with_query(|_, _, _, _| cosmwasm_std::to_json_binary("mock_query").map_err(Into::into)) .with_sudo(|_, _, _, _| Ok(Response::new().set_data("mock_sudo".as_bytes()))) .with_receive(|_, _, _, _, _| Ok(Response::new().set_data("mock_receive".as_bytes()))) - .with_ibc_callbacks(&[("c_id", |_, _, _, _, _, _, _| { + .with_ibc_callbacks(&[("c_id", |_, _, _, _, _| { Ok(Response::new().set_data("mock_callback".as_bytes())) })]) .with_replies(&[(1u64, |_, _, _, msg| { diff --git a/framework/packages/abstract-app/src/lib.rs b/framework/packages/abstract-app/src/lib.rs index bc1a4c693f..092e629f40 100644 --- a/framework/packages/abstract-app/src/lib.rs +++ b/framework/packages/abstract-app/src/lib.rs @@ -155,9 +155,9 @@ pub mod mock { }) .with_sudo(|_, _, _, _| Ok(Response::new().set_data("mock_sudo".as_bytes()))) .with_receive(|_, _, _, _, _| Ok(Response::new().set_data("mock_receive".as_bytes()))) - .with_ibc_callbacks(&[("c_id", |deps, _, _, _, module, _, _| { + .with_ibc_callbacks(&[("c_id", |deps, _, _, _, msg| { IBC_CALLBACK_RECEIVED - .save(deps.storage, &Some(module)) + .save(deps.storage, &Some(msg.sender_module)) .unwrap(); Ok(Response::new().add_attribute("mock_callback", "executed")) diff --git a/framework/packages/abstract-app/src/state.rs b/framework/packages/abstract-app/src/state.rs index eb3def4b5d..73277b2317 100644 --- a/framework/packages/abstract-app/src/state.rs +++ b/framework/packages/abstract-app/src/state.rs @@ -202,7 +202,7 @@ mod tests { .with_query(|_, _, _, _| cosmwasm_std::to_json_binary("mock_query").map_err(Into::into)) .with_sudo(|_, _, _, _| Ok(Response::new().set_data("mock_sudo".as_bytes()))) .with_receive(|_, _, _, _, _| Ok(Response::new().set_data("mock_receive".as_bytes()))) - .with_ibc_callbacks(&[("c_id", |_, _, _, _, _, _, _| { + .with_ibc_callbacks(&[("c_id", |_, _, _, _, _| { Ok(Response::new().set_data("mock_callback".as_bytes())) })]) .with_replies(&[(1u64, |_, _, _, msg| { diff --git a/framework/packages/abstract-core/src/native/ibc.rs b/framework/packages/abstract-core/src/native/ibc.rs index 80a7c4d224..a5d9a001c0 100644 --- a/framework/packages/abstract-core/src/native/ibc.rs +++ b/framework/packages/abstract-core/src/native/ibc.rs @@ -5,7 +5,6 @@ use schemars::JsonSchema; use crate::{ base::ExecuteMsg, - ibc_client::InstalledModuleIdentification, objects::{chain_name::ChainName, module::ModuleInfo}, }; @@ -29,9 +28,11 @@ pub struct IbcCallbackMsg { /// The msg sent with the callback request. /// This is usually used to provide information to the ibc callback function for context pub msg: Option, + /// The msg that initiated the ibc callback + pub initiator_msg: Binary, /// This identifies the module that called the action initially /// This SHOULD be used by the callback function to identify the callback sender - pub sender_module: InstalledModuleIdentification, + pub sender_module: ModuleInfo, pub result: Callback, } diff --git a/framework/packages/abstract-core/src/native/ibc_client.rs b/framework/packages/abstract-core/src/native/ibc_client.rs index a7095ff073..276db0edd0 100644 --- a/framework/packages/abstract-core/src/native/ibc_client.rs +++ b/framework/packages/abstract-core/src/native/ibc_client.rs @@ -130,8 +130,9 @@ pub enum ExecuteMsg { #[cosmwasm_schema::cw_serde] pub enum IbcClientCallback { ModuleRemoteAction { - sender_module: InstalledModuleIdentification, + sender_module: ModuleInfo, callback_info: CallbackInfo, + initiator_msg: Binary, }, CreateAccount { account_id: AccountId, @@ -319,15 +320,14 @@ pub struct RemoteProxyResponse { #[cfg(test)] mod tests { - use cosmwasm_std::{to_json_binary, CosmosMsg, Empty}; + use cosmwasm_std::{to_json_binary, Binary, CosmosMsg, Empty}; use polytone::callbacks::Callback; use speculoos::prelude::*; - use crate::ibc::{IbcCallbackMsg, IbcCallbackMsgSerializeHelper}; + use crate::app::ExecuteMsg; + use crate::ibc::IbcCallbackMsg; use crate::objects::module::ModuleInfo; - use crate::objects::AccountId; - use super::InstalledModuleIdentification; // ... (other test functions) #[test] @@ -342,10 +342,8 @@ mod tests { id: callback_id, msg: Some(callback_msg), result, - sender_module: InstalledModuleIdentification { - module_info: ModuleInfo::from_id_latest("tester:test-module").unwrap(), - account_id: Some(AccountId::local(1)), - }, + sender_module: ModuleInfo::from_id_latest("tester:test-module").unwrap(), + initiator_msg: Binary::from(vec![9u8, 7u8]), }; let actual: CosmosMsg = response_msg @@ -356,7 +354,7 @@ mod tests { assert_that!(actual).is_equal_to(CosmosMsg::Wasm(cosmwasm_std::WasmMsg::Execute { contract_addr: receiver, // we can't test the message because the fields in it are private - msg: to_json_binary(&IbcCallbackMsgSerializeHelper::IbcCallback(response_msg)).unwrap(), + msg: to_json_binary(&ExecuteMsg::::IbcCallback(response_msg)).unwrap(), funds: vec![], })) } diff --git a/framework/packages/abstract-sdk/src/base/contract_base.rs b/framework/packages/abstract-sdk/src/base/contract_base.rs index 2e2848ebb4..4609e14d84 100644 --- a/framework/packages/abstract-sdk/src/base/contract_base.rs +++ b/framework/packages/abstract-sdk/src/base/contract_base.rs @@ -1,8 +1,7 @@ -use abstract_core::{ibc::ModuleIbcMsg, objects::module::ModuleInfo}; +use abstract_core::ibc::{IbcCallbackMsg, ModuleIbcMsg}; use cosmwasm_std::{Binary, Deps, DepsMut, Env, MessageInfo, Reply, Response, Storage}; use cw2::{ContractVersion, CONTRACT}; use cw_storage_plus::Item; -use polytone::callbacks::Callback; use super::handler::Handler; use crate::{core::objects::dependency::StaticDependency, AbstractSdkError, AbstractSdkResult}; @@ -30,18 +29,10 @@ pub type QueryHandlerFn = fn(Deps, Env, &Module, CustomQueryMsg) -> Result; // ANCHOR_END: query -type CallbackMessage = Option; // ANCHOR: ibc /// Function signature for an IBC callback handler. -pub type IbcCallbackHandlerFn = fn( - DepsMut, - Env, - MessageInfo, - Module, - ModuleInfo, - CallbackMessage, - Callback, -) -> Result; +pub type IbcCallbackHandlerFn = + fn(DepsMut, Env, MessageInfo, Module, IbcCallbackMsg) -> Result; // ANCHOR_END: ibc // ANCHOR: module_ibc @@ -386,7 +377,7 @@ mod test { fn test_with_ibc_callback_handlers() { const IBC_ID: &str = "aoeu"; const HANDLER: IbcCallbackHandlerFn = - |_, _, _, _, _, _, _| Ok(Response::default().add_attribute("test", "ibc")); + |_, _, _, _, _| Ok(Response::default().add_attribute("test", "ibc")); let contract = MockAppContract::new("test_contract", "0.1.0", ModuleMetadata::default()) .with_ibc_callbacks(&[(IBC_ID, HANDLER)]); diff --git a/framework/packages/abstract-sdk/src/base/endpoints/ibc_callback.rs b/framework/packages/abstract-sdk/src/base/endpoints/ibc_callback.rs index 0bd66ab3f6..017338bce5 100644 --- a/framework/packages/abstract-sdk/src/base/endpoints/ibc_callback.rs +++ b/framework/packages/abstract-sdk/src/base/endpoints/ibc_callback.rs @@ -25,26 +25,10 @@ pub trait IbcCallbackEndpoint: Handler { } .into()); }; - let IbcCallbackMsg { - id, - msg: callback_msg, - result, - sender_module, - } = msg; - let maybe_handler = self.maybe_ibc_callback_handler(&id); + let maybe_handler = self.maybe_ibc_callback_handler(&msg.id); maybe_handler.map_or_else( || Ok(Response::new()), - |handler| { - handler( - deps, - env, - info, - self, - sender_module.module_info, - callback_msg, - result, - ) - }, + |handler| handler(deps, env, info, self, msg), ) } } From 389706e47aeed1b19b472d956591b51933d71134 Mon Sep 17 00:00:00 2001 From: Kayanski Date: Wed, 13 Mar 2024 11:26:57 +0000 Subject: [PATCH 27/37] formatting [skip ci] --- framework/contracts/native/ibc-host/src/endpoints/packet.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/framework/contracts/native/ibc-host/src/endpoints/packet.rs b/framework/contracts/native/ibc-host/src/endpoints/packet.rs index a517350c12..57fddc0af6 100644 --- a/framework/contracts/native/ibc-host/src/endpoints/packet.rs +++ b/framework/contracts/native/ibc-host/src/endpoints/packet.rs @@ -20,10 +20,7 @@ use crate::{ use abstract_core::base::ExecuteMsg as MiddlewareExecMsg; -pub fn client_to_host_account_id( - remote_chain: ChainName, - account_id: AccountId, -) -> AccountId { +pub fn client_to_host_account_id(remote_chain: ChainName, account_id: AccountId) -> AccountId { let mut account_id = account_id.clone(); account_id.trace_mut().push_chain(remote_chain); From 6962d1eb50ddafd36d465293853cc45aafe0329e Mon Sep 17 00:00:00 2001 From: Kayanski Date: Tue, 19 Mar 2024 13:50:35 +0000 Subject: [PATCH 28/37] Added error on no module ibc endpoint --- .../src/base/endpoints/modules_ibc.rs | 16 +++++++++------- framework/packages/abstract-sdk/src/error.rs | 4 ++++ 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/framework/packages/abstract-sdk/src/base/endpoints/modules_ibc.rs b/framework/packages/abstract-sdk/src/base/endpoints/modules_ibc.rs index ac7971aa17..408334e250 100644 --- a/framework/packages/abstract-sdk/src/base/endpoints/modules_ibc.rs +++ b/framework/packages/abstract-sdk/src/base/endpoints/modules_ibc.rs @@ -1,8 +1,8 @@ +use crate::features::ModuleIdentification; +use crate::{base::Handler, AbstractSdkError}; use abstract_core::ibc::ModuleIbcMsg; use cosmwasm_std::{Addr, Deps, DepsMut, Env, MessageInfo, Response}; -use crate::{base::Handler, AbstractSdkError}; - /// Trait for a contract to call itself on an IBC counterpart. pub trait ModuleIbcEndpoint: Handler { /// Get the address of the ibc host associated with this module @@ -27,10 +27,12 @@ pub trait ModuleIbcEndpoint: Handler { .into()); }; - let maybe_handler = self.maybe_module_ibc_handler(); - maybe_handler.map_or_else( - || Ok(Response::new()), - |handler| handler(deps, env, self, msg), - ) + // If there is no handler and this endpoint is called we need to error + let handler = + self.maybe_module_ibc_handler() + .ok_or(AbstractSdkError::NoModuleIbcHandler( + self.module_id().to_string(), + ))?; + handler(deps, env, self, msg) } } diff --git a/framework/packages/abstract-sdk/src/error.rs b/framework/packages/abstract-sdk/src/error.rs index e8bd4efb89..5bf140e872 100644 --- a/framework/packages/abstract-sdk/src/error.rs +++ b/framework/packages/abstract-sdk/src/error.rs @@ -62,6 +62,10 @@ pub enum AbstractSdkError { module: String, }, + // callback not called by IBC host + #[error("Called an IBC module action on {0}, when no endpoint was registered.")] + NoModuleIbcHandler(String), + // admin of proxy is not set #[error("Admin of proxy {proxy_addr} is not set.")] AdminNotSet { proxy_addr: Addr }, From 84f95e8baaefbcf836aeb862776d92b155d75c46 Mon Sep 17 00:00:00 2001 From: Kayanski Date: Tue, 19 Mar 2024 15:09:04 +0000 Subject: [PATCH 29/37] Fixed module queries and added calbackresult --- .../native/ibc-client/src/commands.rs | 40 +++++- .../native/ibc-client/src/contract.rs | 5 + .../contracts/native/ibc-client/src/ibc.rs | 27 +++- framework/packages/abstract-app/src/lib.rs | 6 +- .../packages/abstract-core/src/native/ibc.rs | 63 ++++++++- .../abstract-core/src/native/ibc_client.rs | 24 ++-- .../src/module_to_module_interactions.rs | 133 +++++++++++++++++- 7 files changed, 265 insertions(+), 33 deletions(-) diff --git a/framework/contracts/native/ibc-client/src/commands.rs b/framework/contracts/native/ibc-client/src/commands.rs index 46fc936781..5eb3463be2 100644 --- a/framework/contracts/native/ibc-client/src/commands.rs +++ b/framework/contracts/native/ibc-client/src/commands.rs @@ -26,7 +26,7 @@ use abstract_sdk::{ }; use cosmwasm_std::{ ensure_eq, to_json_binary, wasm_execute, Binary, Coin, CosmosMsg, Deps, DepsMut, Empty, Env, - IbcMsg, MessageInfo, Storage, + IbcMsg, MessageInfo, QueryRequest, Storage, }; use polytone::callbacks::CallbackRequest; @@ -285,7 +285,7 @@ pub fn execute_send_module_to_module_packet( let callback_request = callback_info.map(|c| CallbackRequest { receiver: env.contract.address.to_string(), msg: to_json_binary(&IbcClientCallback::ModuleRemoteAction { - sender_module: source_module.module_info.clone(), + sender_address: info.sender.to_string(), callback_info: c, initiator_msg: msg.clone(), }) @@ -318,6 +318,42 @@ pub fn execute_send_module_to_module_packet( Ok(IbcClientResponse::action("handle_send_module_to_module_packet").add_message(note_message)) } +/// Sends a packet with an optional callback. +/// This is the top-level function to do IBC related actions. +pub fn execute_send_query( + deps: DepsMut, + env: Env, + info: MessageInfo, + host_chain: String, + query: QueryRequest, + callback_info: CallbackInfo, +) -> IbcClientResult { + let host_chain = ChainName::from_str(&host_chain)?; + + let callback_request = CallbackRequest { + receiver: env.contract.address.to_string(), + msg: to_json_binary(&IbcClientCallback::ModuleRemoteQuery { + callback_info, + sender_address: info.sender.to_string(), + query: query.clone(), + }) + .unwrap(), + }; + + let ibc_infra = IBC_INFRA.load(deps.storage, &host_chain)?; + let note_contract = ibc_infra.polytone_note; + let note_message = wasm_execute( + note_contract.to_string(), + &polytone_note::msg::ExecuteMsg::Query { + msgs: vec![query], + callback: callback_request, + timeout_seconds: PACKET_LIFETIME.into(), + }, + vec![], + )?; + + Ok(IbcClientResponse::action("handle_send_msgs").add_message(note_message)) +} /// Registers an Abstract Account on a remote chain. pub fn execute_register_account( deps: DepsMut, diff --git a/framework/contracts/native/ibc-client/src/contract.rs b/framework/contracts/native/ibc-client/src/contract.rs index dfecbfcd45..478324950b 100644 --- a/framework/contracts/native/ibc-client/src/contract.rs +++ b/framework/contracts/native/ibc-client/src/contract.rs @@ -106,6 +106,11 @@ pub fn execute(deps: DepsMut, env: Env, info: MessageInfo, msg: ExecuteMsg) -> I msg, callback_info, ), + ExecuteMsg::IbcQuery { + host_chain, + query, + callback_info, + } => commands::execute_send_query(deps, env, info, host_chain, query, callback_info), } } diff --git a/framework/contracts/native/ibc-client/src/ibc.rs b/framework/contracts/native/ibc-client/src/ibc.rs index 4e09b641a4..43b947af9b 100644 --- a/framework/contracts/native/ibc-client/src/ibc.rs +++ b/framework/contracts/native/ibc-client/src/ibc.rs @@ -1,5 +1,5 @@ use abstract_core::{ - ibc::IbcCallbackMsg, + ibc::{CallbackResult, IbcCallbackMsg}, ibc_client::{ state::{IBC_INFRA, REVERSE_POLYTONE_NOTE}, IbcClientCallback, @@ -90,17 +90,32 @@ pub fn receive_action_callback( } IbcClientCallback::ModuleRemoteAction { callback_info, - sender_module, + sender_address, initiator_msg, } => { let callback = IbcCallbackMsg { id: callback_info.id.clone(), msg: callback_info.msg, - initiator_msg, - result: callback.result, - sender_module, + result: CallbackResult::from_execute(callback.result, initiator_msg)?, + sender_address, }; - Ok(IbcClientResponse::action("module_specific_callback") + Ok(IbcClientResponse::action("module_action_ibc_callback") + .add_message(callback.into_cosmos_msg(callback_info.receiver)?) + .add_attribute("chain", host_chain.to_string()) + .add_attribute("callback_id", callback_info.id)) + } + IbcClientCallback::ModuleRemoteQuery { + sender_address, + callback_info, + query, + } => { + let callback = IbcCallbackMsg { + id: callback_info.id.clone(), + msg: callback_info.msg, + result: CallbackResult::from_query(callback.result, query)?, + sender_address, + }; + Ok(IbcClientResponse::action("module_query_ibc_callback") .add_message(callback.into_cosmos_msg(callback_info.receiver)?) .add_attribute("chain", host_chain.to_string()) .add_attribute("callback_id", callback_info.id)) diff --git a/framework/packages/abstract-app/src/lib.rs b/framework/packages/abstract-app/src/lib.rs index 092e629f40..311878f17b 100644 --- a/framework/packages/abstract-app/src/lib.rs +++ b/framework/packages/abstract-app/src/lib.rs @@ -75,7 +75,7 @@ pub mod mock { #[cosmwasm_schema::cw_serde] pub struct ReceivedIbcCallbackStatus { - pub received: Option, + pub received: Option, } #[cosmwasm_schema::cw_serde] @@ -133,7 +133,7 @@ pub mod mock { MockAppContract::new(TEST_MODULE_ID, TEST_VERSION, None); // Easy way to see if an ibc-callback was actually received. - pub const IBC_CALLBACK_RECEIVED: Item> = Item::new("ibc_callback_received"); + pub const IBC_CALLBACK_RECEIVED: Item> = Item::new("ibc_callback_received"); pub const MOCK_APP_WITH_DEP: MockAppContract = MockAppContract::new(TEST_WITH_DEP_MODULE_ID, TEST_VERSION, None) @@ -157,7 +157,7 @@ pub mod mock { .with_receive(|_, _, _, _, _| Ok(Response::new().set_data("mock_receive".as_bytes()))) .with_ibc_callbacks(&[("c_id", |deps, _, _, _, msg| { IBC_CALLBACK_RECEIVED - .save(deps.storage, &Some(msg.sender_module)) + .save(deps.storage, &Some(msg.sender_address)) .unwrap(); Ok(Response::new().add_attribute("mock_callback", "executed")) diff --git a/framework/packages/abstract-core/src/native/ibc.rs b/framework/packages/abstract-core/src/native/ibc.rs index a5d9a001c0..a7d9dea502 100644 --- a/framework/packages/abstract-core/src/native/ibc.rs +++ b/framework/packages/abstract-core/src/native/ibc.rs @@ -1,6 +1,8 @@ use cosmwasm_schema::cw_serde; -use cosmwasm_std::{to_json_binary, wasm_execute, Binary, CosmosMsg, Empty, StdResult}; -use polytone::callbacks::Callback; +use cosmwasm_std::{ + to_json_binary, wasm_execute, Binary, CosmosMsg, Empty, QueryRequest, StdError, StdResult, +}; +use polytone::callbacks::{Callback, ErrorResponse, ExecutionResponse}; use schemars::JsonSchema; use crate::{ @@ -28,12 +30,10 @@ pub struct IbcCallbackMsg { /// The msg sent with the callback request. /// This is usually used to provide information to the ibc callback function for context pub msg: Option, - /// The msg that initiated the ibc callback - pub initiator_msg: Binary, - /// This identifies the module that called the action initially + /// This identifies the sender of the callback /// This SHOULD be used by the callback function to identify the callback sender - pub sender_module: ModuleInfo, - pub result: Callback, + pub sender_address: String, + pub result: CallbackResult, } impl IbcCallbackMsg { @@ -57,6 +57,55 @@ impl IbcCallbackMsg { } } +#[cosmwasm_schema::cw_serde] +pub enum CallbackResult { + Query { + query: QueryRequest, + result: Result, ErrorResponse>, + }, + + Execute { + initiator_msg: Binary, + result: Result, + }, + + /// An error occured that could not be recovered from. The only + /// known way that this can occur is message handling running out + /// of gas, in which case the error will be `codespace: sdk, code: + /// 11`. + /// + /// This error is not named becuase it could also occur due to a + /// panic or unhandled error during message processing. We don't + /// expect this to happen and have carefully written the code to + /// avoid it. + FatalError(String), +} + +impl CallbackResult { + pub fn from_query(callback: Callback, query: QueryRequest) -> Result { + match callback { + Callback::Query(q) => Ok(Self::Query { query, result: q }), + Callback::Execute(_) => Err(StdError::generic_err( + "Expected a query result, got an execute result", + )), + Callback::FatalError(e) => Ok(Self::FatalError(e)), + } + } + + pub fn from_execute(callback: Callback, initiator_msg: Binary) -> Result { + match callback { + Callback::Query(_) => Err(StdError::generic_err( + "Expected an execution result, got a query result", + )), + Callback::Execute(e) => Ok(Self::Execute { + initiator_msg, + result: e, + }), + Callback::FatalError(e) => Ok(Self::FatalError(e)), + } + } +} + // ANCHOR: module_ibc_msg #[cw_serde] pub struct ModuleIbcMsg { diff --git a/framework/packages/abstract-core/src/native/ibc_client.rs b/framework/packages/abstract-core/src/native/ibc_client.rs index 276db0edd0..e371089af7 100644 --- a/framework/packages/abstract-core/src/native/ibc_client.rs +++ b/framework/packages/abstract-core/src/native/ibc_client.rs @@ -1,5 +1,5 @@ use cosmwasm_schema::QueryResponses; -use cosmwasm_std::{Addr, Binary, Coin, Deps, StdError}; +use cosmwasm_std::{Addr, Binary, Coin, Deps, Empty, QueryRequest, StdError}; use polytone::callbacks::CallbackMessage; use self::state::IbcInfrastructure; @@ -111,6 +111,11 @@ pub enum ExecuteMsg { msg: Binary, callback_info: Option, }, + IbcQuery { + host_chain: String, + query: QueryRequest, + callback_info: CallbackInfo, + }, RemoteAction { // host chain to be executed on // Example: "osmosis" @@ -130,10 +135,15 @@ pub enum ExecuteMsg { #[cosmwasm_schema::cw_serde] pub enum IbcClientCallback { ModuleRemoteAction { - sender_module: ModuleInfo, + sender_address: String, callback_info: CallbackInfo, initiator_msg: Binary, }, + ModuleRemoteQuery { + sender_address: String, + callback_info: CallbackInfo, + query: QueryRequest, + }, CreateAccount { account_id: AccountId, }, @@ -320,13 +330,12 @@ pub struct RemoteProxyResponse { #[cfg(test)] mod tests { - use cosmwasm_std::{to_json_binary, Binary, CosmosMsg, Empty}; + use cosmwasm_std::{to_json_binary, CosmosMsg, Empty}; use polytone::callbacks::Callback; use speculoos::prelude::*; use crate::app::ExecuteMsg; - use crate::ibc::IbcCallbackMsg; - use crate::objects::module::ModuleInfo; + use crate::ibc::{CallbackResult, IbcCallbackMsg}; // ... (other test functions) @@ -336,14 +345,13 @@ mod tests { let callback_id = "15".to_string(); let callback_msg = to_json_binary("15").unwrap(); - let result = Callback::FatalError("ibc execution error".to_string()); + let result = CallbackResult::FatalError("ibc execution error".to_string()); let response_msg = IbcCallbackMsg { id: callback_id, msg: Some(callback_msg), result, - sender_module: ModuleInfo::from_id_latest("tester:test-module").unwrap(), - initiator_msg: Binary::from(vec![9u8, 7u8]), + sender_address: "action_sender".to_string(), }; let actual: CosmosMsg = response_msg diff --git a/interchain/tests/src/module_to_module_interactions.rs b/interchain/tests/src/module_to_module_interactions.rs index f293354b3d..a0876c16dc 100644 --- a/interchain/tests/src/module_to_module_interactions.rs +++ b/interchain/tests/src/module_to_module_interactions.rs @@ -1,13 +1,15 @@ pub use abstract_core::app; use abstract_core::{ - ibc::{CallbackInfo, ModuleIbcMsg}, + ibc::{CallbackInfo, CallbackResult, ModuleIbcMsg}, ibc_client::{self, InstalledModuleIdentification}, objects::module::ModuleInfo, IBC_CLIENT, }; use cosmwasm_schema::{cw_serde, QueryResponses}; pub use cosmwasm_std::testing::{mock_dependencies, mock_env, mock_info}; -use cosmwasm_std::{to_json_binary, wasm_execute, Response, StdError}; +use cosmwasm_std::{ + from_json, to_json_binary, wasm_execute, AllBalanceResponse, Coin, Response, StdError, +}; use cw_controllers::AdminError; use cw_storage_plus::Item; @@ -28,6 +30,10 @@ pub enum MockExecMsg { remote_chain: String, target_module: ModuleInfo, }, + QuerySomethingIbc { + remote_chain: String, + address: String, + }, } #[cosmwasm_schema::cw_serde] @@ -38,6 +44,9 @@ pub enum MockQueryMsg { #[returns(ReceivedIbcCallbackStatus)] GetReceivedIbcCallbackStatus {}, + #[returns(ReceivedIbcQueryCallbackStatus)] + GetReceivedIbcQueryCallbackStatus {}, + #[returns(ReceivedIbcModuleStatus)] GetReceivedIbcModuleStatus {}, } @@ -47,6 +56,11 @@ pub struct ReceivedIbcCallbackStatus { pub received: bool, } +#[cosmwasm_schema::cw_serde] +pub struct ReceivedIbcQueryCallbackStatus { + pub balance: Vec, +} + #[cosmwasm_schema::cw_serde] pub struct ReceivedIbcModuleStatus { pub received: ModuleInfo, @@ -105,6 +119,9 @@ pub const IBC_CALLBACK_RECEIVED: Item = Item::new("ibc_callback_received") // Easy way to see if an module ibc called was actually received. pub const MODULE_IBC_RECEIVED: Item = Item::new("module_ibc_received"); +// Easy way to see if an ibc-callback was actually received. +pub const IBC_CALLBACK_QUERY_RECEIVED: Item> = Item::new("ibc_callback_query_received"); + pub const fn mock_app(id: &'static str, version: &'static str) -> MockAppContract { MockAppContract::new(id, version, None) .with_instantiate(|deps, _, _, _, _| { @@ -143,6 +160,30 @@ pub const fn mock_app(id: &'static str, version: &'static str) -> MockAppContrac Ok(Response::new().add_message(msg)) } + MockExecMsg::QuerySomethingIbc { + address, + remote_chain, + } => { + let ibc_client_addr = app.modules(deps.as_ref()).module_address(IBC_CLIENT)?; + // We send an IBC Client module message + let msg = wasm_execute( + ibc_client_addr, + &ibc_client::ExecuteMsg::IbcQuery { + host_chain: remote_chain, + callback_info: CallbackInfo { + id: "query_id".to_string(), + msg: None, + receiver: env.contract.address.to_string(), + }, + query: cosmwasm_std::QueryRequest::Bank( + cosmwasm_std::BankQuery::AllBalances { address }, + ), + }, + vec![], + )?; + + Ok(Response::new().add_message(msg)) + } _ => Ok(Response::new().set_data("mock_exec".as_bytes())), }) .with_query(|deps, _, _, msg| match msg { @@ -158,13 +199,32 @@ pub const fn mock_app(id: &'static str, version: &'static str) -> MockAppContrac }) .map_err(Into::into) } + MockQueryMsg::GetReceivedIbcQueryCallbackStatus {} => { + to_json_binary(&ReceivedIbcQueryCallbackStatus { + balance: IBC_CALLBACK_QUERY_RECEIVED.load(deps.storage)?, + }) + .map_err(Into::into) + } }) .with_sudo(|_, _, _, _| Ok(Response::new().set_data("mock_sudo".as_bytes()))) .with_receive(|_, _, _, _, _| Ok(Response::new().set_data("mock_receive".as_bytes()))) - .with_ibc_callbacks(&[("c_id", |deps, _, _, _, _, _, _| { - IBC_CALLBACK_RECEIVED.save(deps.storage, &true).unwrap(); - Ok(Response::new().add_attribute("mock_callback", "executed")) - })]) + .with_ibc_callbacks(&[ + ("c_id", |deps, _, _, _, _| { + IBC_CALLBACK_RECEIVED.save(deps.storage, &true).unwrap(); + Ok(Response::new().add_attribute("mock_callback", "executed")) + }), + ("query_id", |deps, _, _, _, msg| match msg.result { + CallbackResult::Query { query: _, result } => { + let result = result.unwrap()[0].clone(); + let deser: AllBalanceResponse = from_json(result)?; + IBC_CALLBACK_QUERY_RECEIVED + .save(deps.storage, &deser.amount) + .unwrap(); + Ok(Response::new().add_attribute("mock_callback_query", "executed")) + } + _ => panic!("Expected query result"), + }), + ]) .with_replies(&[(1u64, |_, _, _, msg| { Ok(Response::new().set_data(msg.result.unwrap().data.unwrap())) })]) @@ -221,12 +281,27 @@ pub mod test { ); Ok(()) } + + fn assert_query_callback_status( + app: &MockAppOriginI, + balance: Vec, + ) -> AnyResult<()> { + let get_received_ibc_query_callback_status_res: ReceivedIbcQueryCallbackStatus = + app.get_received_ibc_query_callback_status()?; + + assert_eq!( + ReceivedIbcQueryCallbackStatus { balance }, + get_received_ibc_query_callback_status_res + ); + Ok(()) + } use crate::{ interchain_accounts::create_test_remote_account, module_to_module_interactions::{ origin_app::interface::MockAppOriginI, remote_app::{interface::MockAppRemoteI, TEST_MODULE_ID_REMOTE, TEST_VERSION_REMOTE}, MockExecMsgFns, MockInitMsg, MockQueryMsgFns, ReceivedIbcCallbackStatus, + ReceivedIbcQueryCallbackStatus, }, setup::{ ibc_abstract_setup, ibc_connect_polytone_and_abstract, mock_test::logger_test_init, @@ -241,7 +316,7 @@ pub mod test { use abstract_testing::addresses::{TEST_MODULE_ID, TEST_NAMESPACE, TEST_VERSION}; use anyhow::Result as AnyResult; use base64::{engine::general_purpose, Engine}; - use cosmwasm_std::to_json_binary; + use cosmwasm_std::{coins, to_json_binary}; use cw_orch::interchain::MockBech32InterchainEnv; use cw_orch::prelude::*; @@ -383,6 +458,7 @@ pub mod test { Ok(()) } + #[test] fn works() -> AnyResult<()> { logger_test_init(); @@ -475,4 +551,47 @@ pub mod test { Ok(()) } + + pub const REMOTE_AMOUNT: u128 = 5674309; + pub const REMOTE_DENOM: &str = "remote_denom"; + #[test] + fn queries() -> AnyResult<()> { + logger_test_init(); + let mock_interchain = + MockBech32InterchainEnv::new(vec![(JUNO, "juno"), (STARGAZE, "stargaze")]); + + // We just verified all steps pass + let (abstr_origin, _abstr_remote) = ibc_abstract_setup(&mock_interchain, JUNO, STARGAZE)?; + ibc_connect_polytone_and_abstract(&mock_interchain, STARGAZE, JUNO)?; + + let remote_name = ChainName::from_chain_id(STARGAZE).to_string(); + let remote = mock_interchain.chain(STARGAZE)?; + let remote_address = + remote.addr_make_with_balance("remote-test", coins(REMOTE_AMOUNT, REMOTE_DENOM))?; + + let (origin_account, _remote_account_id) = + create_test_remote_account(&abstr_origin, JUNO, STARGAZE, &mock_interchain, None)?; + + // Install local app + let app = MockAppOriginI::new( + TEST_MODULE_ID, + abstr_origin.version_control.get_chain().clone(), + ); + + abstr_origin + .version_control + .claim_namespace(origin_account.id()?, TEST_NAMESPACE.to_owned())?; + + app.deploy(TEST_VERSION.parse()?, DeployStrategy::Try)?; + + origin_account.install_app(&app, &MockInitMsg {}, None)?; + + let query_response = app.query_something_ibc(remote_address.to_string(), remote_name)?; + + assert_query_callback_status(&app, coins(REMOTE_AMOUNT, REMOTE_DENOM)).unwrap_err(); + mock_interchain.wait_ibc(JUNO, query_response)?; + assert_query_callback_status(&app, coins(REMOTE_AMOUNT, REMOTE_DENOM))?; + + Ok(()) + } } From 867278a7b91ed6a40005b661f186b6a9a0524f5b Mon Sep 17 00:00:00 2001 From: Kayanski Date: Tue, 19 Mar 2024 15:35:39 +0000 Subject: [PATCH 30/37] Fixed clippies --- framework/packages/abstract-core/src/native/ibc_client.rs | 1 - interchain/interchain-tests/Cargo.toml | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/packages/abstract-core/src/native/ibc_client.rs b/framework/packages/abstract-core/src/native/ibc_client.rs index e371089af7..ed5afa9605 100644 --- a/framework/packages/abstract-core/src/native/ibc_client.rs +++ b/framework/packages/abstract-core/src/native/ibc_client.rs @@ -331,7 +331,6 @@ pub struct RemoteProxyResponse { #[cfg(test)] mod tests { use cosmwasm_std::{to_json_binary, CosmosMsg, Empty}; - use polytone::callbacks::Callback; use speculoos::prelude::*; use crate::app::ExecuteMsg; diff --git a/interchain/interchain-tests/Cargo.toml b/interchain/interchain-tests/Cargo.toml index b6bd2d8394..8f5c34989b 100644 --- a/interchain/interchain-tests/Cargo.toml +++ b/interchain/interchain-tests/Cargo.toml @@ -32,3 +32,4 @@ cosmwasm-schema.workspace = true cw-controllers = "2.0.0" cw-storage-plus.workspace = true thiserror.workspace = true +base64 = "0.22.0" From 4dea1429079bf924bb378afb90b3ed7b666298a4 Mon Sep 17 00:00:00 2001 From: Kayanski Date: Mon, 25 Mar 2024 14:15:06 +0000 Subject: [PATCH 31/37] Removed cw-controllers too high version --- interchain/interchain-tests/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interchain/interchain-tests/Cargo.toml b/interchain/interchain-tests/Cargo.toml index 8f5c34989b..bfe906646b 100644 --- a/interchain/interchain-tests/Cargo.toml +++ b/interchain/interchain-tests/Cargo.toml @@ -29,7 +29,7 @@ ibc-relayer-types = "0.25" cw-orch-polytone = { workspace = true } polytone = { workspace = true } cosmwasm-schema.workspace = true -cw-controllers = "2.0.0" +cw-controllers = { workspace = true } cw-storage-plus.workspace = true thiserror.workspace = true base64 = "0.22.0" From 5ac11c5969185e1b795f4e55cd1b7c830bc4ab4b Mon Sep 17 00:00:00 2001 From: Kayanski Date: Mon, 25 Mar 2024 19:37:53 +0000 Subject: [PATCH 32/37] Removed callback receiver --- .../contracts/native/ibc-client/src/commands.rs | 1 + framework/contracts/native/ibc-client/src/ibc.rs | 6 ++---- framework/packages/abstract-app/src/lib.rs | 12 +++++------- framework/packages/abstract-core/src/native/ibc.rs | 8 ++------ .../packages/abstract-core/src/native/ibc_client.rs | 1 - .../src/module_to_module_interactions.rs | 4 +--- .../adapters/cw-staking/src/handlers/execute.rs | 1 - .../contracts/adapters/dex/src/handlers/execute.rs | 1 - 8 files changed, 11 insertions(+), 23 deletions(-) diff --git a/framework/contracts/native/ibc-client/src/commands.rs b/framework/contracts/native/ibc-client/src/commands.rs index 5eb3463be2..b2bfcf7c1e 100644 --- a/framework/contracts/native/ibc-client/src/commands.rs +++ b/framework/contracts/native/ibc-client/src/commands.rs @@ -217,6 +217,7 @@ pub fn execute_send_packet( /// Sends a packet with an optional callback. /// This is the top-level function to do IBC related actions. +#[allow(clippy::too_many_arguments)] pub fn execute_send_module_to_module_packet( deps: DepsMut, env: Env, diff --git a/framework/contracts/native/ibc-client/src/ibc.rs b/framework/contracts/native/ibc-client/src/ibc.rs index 43b947af9b..0a75739127 100644 --- a/framework/contracts/native/ibc-client/src/ibc.rs +++ b/framework/contracts/native/ibc-client/src/ibc.rs @@ -97,10 +97,9 @@ pub fn receive_action_callback( id: callback_info.id.clone(), msg: callback_info.msg, result: CallbackResult::from_execute(callback.result, initiator_msg)?, - sender_address, }; Ok(IbcClientResponse::action("module_action_ibc_callback") - .add_message(callback.into_cosmos_msg(callback_info.receiver)?) + .add_message(callback.into_cosmos_msg(sender_address)?) .add_attribute("chain", host_chain.to_string()) .add_attribute("callback_id", callback_info.id)) } @@ -113,10 +112,9 @@ pub fn receive_action_callback( id: callback_info.id.clone(), msg: callback_info.msg, result: CallbackResult::from_query(callback.result, query)?, - sender_address, }; Ok(IbcClientResponse::action("module_query_ibc_callback") - .add_message(callback.into_cosmos_msg(callback_info.receiver)?) + .add_message(callback.into_cosmos_msg(sender_address)?) .add_attribute("chain", host_chain.to_string()) .add_attribute("callback_id", callback_info.id)) } diff --git a/framework/packages/abstract-app/src/lib.rs b/framework/packages/abstract-app/src/lib.rs index 311878f17b..4f623c4036 100644 --- a/framework/packages/abstract-app/src/lib.rs +++ b/framework/packages/abstract-app/src/lib.rs @@ -75,7 +75,7 @@ pub mod mock { #[cosmwasm_schema::cw_serde] pub struct ReceivedIbcCallbackStatus { - pub received: Option, + pub received: bool, } #[cosmwasm_schema::cw_serde] @@ -133,12 +133,12 @@ pub mod mock { MockAppContract::new(TEST_MODULE_ID, TEST_VERSION, None); // Easy way to see if an ibc-callback was actually received. - pub const IBC_CALLBACK_RECEIVED: Item> = Item::new("ibc_callback_received"); + pub const IBC_CALLBACK_RECEIVED: Item = Item::new("ibc_callback_received"); pub const MOCK_APP_WITH_DEP: MockAppContract = MockAppContract::new(TEST_WITH_DEP_MODULE_ID, TEST_VERSION, None) .with_instantiate(|deps, _, _, _, _| { - IBC_CALLBACK_RECEIVED.save(deps.storage, &None)?; + IBC_CALLBACK_RECEIVED.save(deps.storage, &false)?; Ok(Response::new().set_data("mock_init".as_bytes())) }) .with_execute(|_, _, _, _, _| Ok(Response::new().set_data("mock_exec".as_bytes()))) @@ -155,10 +155,8 @@ pub mod mock { }) .with_sudo(|_, _, _, _| Ok(Response::new().set_data("mock_sudo".as_bytes()))) .with_receive(|_, _, _, _, _| Ok(Response::new().set_data("mock_receive".as_bytes()))) - .with_ibc_callbacks(&[("c_id", |deps, _, _, _, msg| { - IBC_CALLBACK_RECEIVED - .save(deps.storage, &Some(msg.sender_address)) - .unwrap(); + .with_ibc_callbacks(&[("c_id", |deps, _, _, _, _| { + IBC_CALLBACK_RECEIVED.save(deps.storage, &true).unwrap(); Ok(Response::new().add_attribute("mock_callback", "executed")) })]) diff --git a/framework/packages/abstract-core/src/native/ibc.rs b/framework/packages/abstract-core/src/native/ibc.rs index a7d9dea502..d2ded3c790 100644 --- a/framework/packages/abstract-core/src/native/ibc.rs +++ b/framework/packages/abstract-core/src/native/ibc.rs @@ -10,7 +10,8 @@ use crate::{ objects::{chain_name::ChainName, module::ModuleInfo}, }; -// CallbackInfo from modules, that is turned into an IbcResponseMsg by the ibc client +/// CallbackInfo from modules, that is turned into an IbcResponseMsg by the ibc client +/// A callback can only be sent to itself #[cosmwasm_schema::cw_serde] pub struct CallbackInfo { /// Used to identify the callback that is sent (acts like the reply ID) @@ -18,8 +19,6 @@ pub struct CallbackInfo { /// Used to add information to the callback. /// This is usually used to provide information to the ibc callback function for context pub msg: Option, - /// Contract that will be called with the callback message - pub receiver: String, } /// IbcResponseMsg should be de/serialized under `IbcCallback()` variant in a ExecuteMsg @@ -30,9 +29,6 @@ pub struct IbcCallbackMsg { /// The msg sent with the callback request. /// This is usually used to provide information to the ibc callback function for context pub msg: Option, - /// This identifies the sender of the callback - /// This SHOULD be used by the callback function to identify the callback sender - pub sender_address: String, pub result: CallbackResult, } diff --git a/framework/packages/abstract-core/src/native/ibc_client.rs b/framework/packages/abstract-core/src/native/ibc_client.rs index ed5afa9605..52d12b4fcb 100644 --- a/framework/packages/abstract-core/src/native/ibc_client.rs +++ b/framework/packages/abstract-core/src/native/ibc_client.rs @@ -350,7 +350,6 @@ mod tests { id: callback_id, msg: Some(callback_msg), result, - sender_address: "action_sender".to_string(), }; let actual: CosmosMsg = response_msg diff --git a/interchain/interchain-tests/src/module_to_module_interactions.rs b/interchain/interchain-tests/src/module_to_module_interactions.rs index a0876c16dc..0be755ac78 100644 --- a/interchain/interchain-tests/src/module_to_module_interactions.rs +++ b/interchain/interchain-tests/src/module_to_module_interactions.rs @@ -128,7 +128,7 @@ pub const fn mock_app(id: &'static str, version: &'static str) -> MockAppContrac IBC_CALLBACK_RECEIVED.save(deps.storage, &false)?; Ok(Response::new().set_data("mock_init".as_bytes())) }) - .with_execute(|deps, env, _, app, msg| match msg { + .with_execute(|deps, _env, _, app, msg| match msg { MockExecMsg::DoSomethingIbc { remote_chain, target_module, @@ -152,7 +152,6 @@ pub const fn mock_app(id: &'static str, version: &'static str) -> MockAppContrac callback_info: Some(CallbackInfo { id: "c_id".to_string(), msg: None, - receiver: env.contract.address.to_string(), }), }, vec![], @@ -173,7 +172,6 @@ pub const fn mock_app(id: &'static str, version: &'static str) -> MockAppContrac callback_info: CallbackInfo { id: "query_id".to_string(), msg: None, - receiver: env.contract.address.to_string(), }, query: cosmwasm_std::QueryRequest::Bank( cosmwasm_std::BankQuery::AllBalances { address }, diff --git a/modules/contracts/adapters/cw-staking/src/handlers/execute.rs b/modules/contracts/adapters/cw-staking/src/handlers/execute.rs index 59fe6985b0..6b7ad05092 100644 --- a/modules/contracts/adapters/cw-staking/src/handlers/execute.rs +++ b/modules/contracts/adapters/cw-staking/src/handlers/execute.rs @@ -101,7 +101,6 @@ fn handle_ibc_request( provider: provider_name.clone(), action: action.clone(), })?), - receiver: info.sender.into_string(), }) }; let ibc_action_msg = ibc_client.host_action(host_chain.to_string(), host_action)?; diff --git a/modules/contracts/adapters/dex/src/handlers/execute.rs b/modules/contracts/adapters/dex/src/handlers/execute.rs index ca4b72c217..5f51a8590a 100644 --- a/modules/contracts/adapters/dex/src/handlers/execute.rs +++ b/modules/contracts/adapters/dex/src/handlers/execute.rs @@ -176,7 +176,6 @@ fn handle_ibc_request( dex: dex_name.clone(), action: action.clone(), })?), - receiver: info.sender.into_string(), }) }; let ibc_action_msg = ibc_client.host_action(host_chain.to_string(), host_action)?; From 6f5ece37fc6f1cedd00672098c36699f6c0ff5d4 Mon Sep 17 00:00:00 2001 From: Kayanski Date: Tue, 23 Apr 2024 12:10:42 +0000 Subject: [PATCH 33/37] Added calling module security test --- .../src/module_to_module_interactions.rs | 110 ++++++++++++++++++ 1 file changed, 110 insertions(+) diff --git a/interchain/interchain-tests/src/module_to_module_interactions.rs b/interchain/interchain-tests/src/module_to_module_interactions.rs index 0be755ac78..4583dae137 100644 --- a/interchain/interchain-tests/src/module_to_module_interactions.rs +++ b/interchain/interchain-tests/src/module_to_module_interactions.rs @@ -592,4 +592,114 @@ pub mod test { Ok(()) } + + pub mod security { + use abstract_core::ibc_client::{ExecuteMsgFns, InstalledModuleIdentification}; + + use crate::module_to_module_interactions::IbcModuleToModuleMsg; + + use super::*; + + #[test] + fn calling_module_should_match() -> AnyResult<()> { + logger_test_init(); + let mock_interchain = + MockBech32InterchainEnv::new(vec![(JUNO, "juno"), (STARGAZE, "stargaze")]); + + // We just verified all steps pass + let (abstr_origin, abstr_remote) = + ibc_abstract_setup(&mock_interchain, JUNO, STARGAZE)?; + ibc_connect_polytone_and_abstract(&mock_interchain, STARGAZE, JUNO)?; + + let remote_name = ChainName::from_chain_id(STARGAZE).to_string(); + + let (origin_account, remote_account_id) = + create_test_remote_account(&abstr_origin, JUNO, STARGAZE, &mock_interchain, None)?; + + let (remote_account, _) = + create_test_remote_account(&abstr_remote, STARGAZE, JUNO, &mock_interchain, None)?; + + // Install local app + let app = MockAppOriginI::new( + TEST_MODULE_ID, + abstr_origin.version_control.get_chain().clone(), + ); + + abstr_origin + .version_control + .claim_namespace(origin_account.id()?, TEST_NAMESPACE.to_owned())?; + + app.deploy(TEST_VERSION.parse()?, DeployStrategy::Try)?; + + origin_account.install_app(&app, &MockInitMsg {}, None)?; + + // Install remote app + let app_remote = MockAppRemoteI::new( + TEST_MODULE_ID_REMOTE, + abstr_remote.version_control.get_chain().clone(), + ); + + abstr_remote + .version_control + .claim_namespace(remote_account.id()?, TEST_NAMESPACE.to_owned())?; + + app_remote.deploy(TEST_VERSION_REMOTE.parse()?, DeployStrategy::Try)?; + + let remote_install_response = origin_account.manager.execute_on_remote( + &remote_name, + manager::ExecuteMsg::InstallModules { + modules: vec![ModuleInstallConfig::new( + ModuleInfo::from_id_latest(TEST_MODULE_ID_REMOTE)?, + Some(to_json_binary(&MockInitMsg {})?), + )], + }, + )?; + + mock_interchain.wait_ibc(JUNO, remote_install_response)?; + + // We get the object for handling the actual module on the remote account + let remote_manager = abstr_remote + .version_control + .account_base(remote_account_id)? + .account_base + .manager; + let manager = Manager::new( + "remote-account-manager", + abstr_remote.version_control.get_chain().clone(), + ); + manager.set_address(&remote_manager); + let module_address = manager.module_info(TEST_MODULE_ID_REMOTE)?.unwrap().address; + let remote_account_app = MockAppRemoteI::new( + "remote-account-app", + abstr_remote.version_control.get_chain().clone(), + ); + remote_account_app.set_address(&module_address); + + // The user on origin chain triggers a module-to-module interaction + let target_module_info = + ModuleInfo::from_id(TEST_MODULE_ID_REMOTE, TEST_VERSION_REMOTE.into())?; + + // The user triggers manually a module-to-module interaction + let err = abstr_origin + .ibc + .client + .module_ibc_action( + remote_name, + to_json_binary(&IbcModuleToModuleMsg { + ibc_msg: "module_to_module:msg".to_string(), + }) + .unwrap(), + InstalledModuleIdentification { + module_info: ModuleInfo::from_id(TEST_MODULE_ID, TEST_VERSION.into()) + .unwrap(), + account_id: Some(origin_account.id()?), + }, + target_module_info, + None, + ) + .unwrap_err(); + + Ok(()) + } + } } From 4e77c7e8af58dac02c9ab36fd4f0adb1a7be7dad Mon Sep 17 00:00:00 2001 From: Kayanski Date: Tue, 23 Apr 2024 12:11:54 +0000 Subject: [PATCH 34/37] Clippy --- .../interchain-tests/src/module_to_module_interactions.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interchain/interchain-tests/src/module_to_module_interactions.rs b/interchain/interchain-tests/src/module_to_module_interactions.rs index 4583dae137..97c2784778 100644 --- a/interchain/interchain-tests/src/module_to_module_interactions.rs +++ b/interchain/interchain-tests/src/module_to_module_interactions.rs @@ -680,7 +680,7 @@ pub mod test { ModuleInfo::from_id(TEST_MODULE_ID_REMOTE, TEST_VERSION_REMOTE.into())?; // The user triggers manually a module-to-module interaction - let err = abstr_origin + abstr_origin .ibc .client .module_ibc_action( From ad4ab6a0f2a3bc009da2b48d8af795b6408a285b Mon Sep 17 00:00:00 2001 From: Kayanski Date: Tue, 30 Apr 2024 14:16:34 +0000 Subject: [PATCH 35/37] Simplified module IBC API --- .../native/ibc-client/src/commands.rs | 82 +++++++------------ .../native/ibc-client/src/contract.rs | 2 - .../src/endpoints/instantiate.rs | 18 ++-- .../packages/abstract-adapter/src/state.rs | 21 +---- .../abstract-app/src/endpoints/instantiate.rs | 4 +- framework/packages/abstract-app/src/state.rs | 17 +--- .../abstract-sdk/src/feature_objects.rs | 8 +- .../packages/abstract-std/src/adapter.rs | 15 +++- framework/packages/abstract-std/src/app.rs | 16 +++- .../abstract-std/src/native/ibc_client.rs | 1 - .../src/module_to_module_interactions.rs | 16 +--- .../apps/etf/src/handlers/execute.rs | 12 +-- 12 files changed, 92 insertions(+), 120 deletions(-) diff --git a/framework/contracts/native/ibc-client/src/commands.rs b/framework/contracts/native/ibc-client/src/commands.rs index 14e064e280..b2da5d41fe 100644 --- a/framework/contracts/native/ibc-client/src/commands.rs +++ b/framework/contracts/native/ibc-client/src/commands.rs @@ -3,27 +3,23 @@ use std::str::FromStr; use abstract_sdk::{ feature_objects::{AnsHost, VersionControlContract}, features::AccountIdentification, - Resolve, + namespaces::BASE_STATE, + ModuleRegistryInterface, Resolve, }; use abstract_std::{ - ibc::CallbackInfo, - ibc_client::{ + app::AppState, ibc::CallbackInfo, ibc_client::{ state::{IbcInfrastructure, ACCOUNTS, CONFIG, IBC_INFRA, REVERSE_POLYTONE_NOTE}, IbcClientCallback, InstalledModuleIdentification, - }, - ibc_host::{self, HostAction, InternalAction}, - manager::{self, ModuleInstallConfig}, - objects::{ + }, ibc_host::{self, HostAction, InternalAction}, manager::{self, ModuleInstallConfig}, objects::{ chain_name::ChainName, module::ModuleInfo, module_reference::ModuleReference, AccountId, AssetEntry, ChannelEntry, - }, - version_control::AccountBase, - ICS20, + }, version_control::AccountBase, ICS20 }; use cosmwasm_std::{ - ensure_eq, to_json_binary, wasm_execute, Binary, Coin, CosmosMsg, Deps, DepsMut, Empty, Env, - IbcMsg, MessageInfo, QueryRequest, Storage, + to_json_binary, wasm_execute, Binary, Coin, CosmosMsg, Deps, DepsMut, Empty, Env, IbcMsg, + MessageInfo, QueryRequest, Storage, }; +use cw_storage_plus::Item; use polytone::callbacks::CallbackRequest; use crate::{ @@ -219,7 +215,6 @@ pub fn execute_send_module_to_module_packet( env: Env, info: MessageInfo, host_chain: String, - source_module: InstalledModuleIdentification, target_module: ModuleInfo, msg: Binary, callback_info: Option, @@ -227,54 +222,37 @@ pub fn execute_send_module_to_module_packet( let host_chain = ChainName::from_str(&host_chain)?; let cfg = CONFIG.load(deps.storage)?; - // We make sure the source_module is indeed who they say they are - let registry = cfg + // Query the sender module information + let module_info = cfg .version_control - .query_module(source_module.module_info.clone(), &deps.querier)?; + .module_registry(deps.as_ref())? + .module_info(info.sender.clone())?; - match registry.reference { + // We need additional information depending on the module type + let source_module = match module_info.reference { ModuleReference::AccountBase(_) => return Err(IbcClientError::Unauthorized {}), ModuleReference::Native(_) => return Err(IbcClientError::Unauthorized {}), - ModuleReference::Adapter(addr) => { - // For adapters, we just need to verify they have the right address - if addr != info.sender { - return Err(IbcClientError::ForbiddenModuleCall {}); - } - } - ModuleReference::App(code_id) | ModuleReference::Standalone(code_id) => { - // We verify the caller has indeed the right code id - let sender_code_id = deps - .querier - .query_wasm_contract_info(info.sender.clone())? - .code_id; - if code_id != sender_code_id { - return Err(IbcClientError::ForbiddenModuleCall {}); + ModuleReference::Standalone(_) => return Err(IbcClientError::Unauthorized {}), + ModuleReference::Adapter(_) => InstalledModuleIdentification { + module_info: module_info.info, + account_id: None, + }, + ModuleReference::App(_) => { + // We verify the associated account id + let proxy_addr = Item::::new(BASE_STATE) + .query(&deps.querier, info.sender.clone())? + .proxy_address; + let account_id = cfg.version_control.account_id(&proxy_addr, &deps.querier)?; + + InstalledModuleIdentification { + module_info: module_info.info, + account_id: Some(account_id), } - // If it does have the right code id, we verify the specified account has the app installed - let account_base = cfg.version_control.account_base( - source_module - .account_id - .as_ref() - .ok_or(IbcClientError::ForbiddenModuleCall {})?, - &deps.querier, - )?; - - let maybe_module_addr = manager::state::ACCOUNT_MODULES.query( - &deps.querier, - account_base.manager, - &source_module.module_info.id(), - )?; - let module_addr = maybe_module_addr.ok_or(IbcClientError::ForbiddenModuleCall {})?; - ensure_eq!( - module_addr, - info.sender, - IbcClientError::ForbiddenModuleCall {} - ); } _ => unimplemented!( "This module type didn't exist when implementing module-to-module interactions" ), - } + }; // We send a message to the target module on the remote chain // Send this message via the Polytone implementation diff --git a/framework/contracts/native/ibc-client/src/contract.rs b/framework/contracts/native/ibc-client/src/contract.rs index 37f60a53b4..50e39f0fac 100644 --- a/framework/contracts/native/ibc-client/src/contract.rs +++ b/framework/contracts/native/ibc-client/src/contract.rs @@ -92,7 +92,6 @@ pub fn execute(deps: DepsMut, env: Env, info: MessageInfo, msg: ExecuteMsg) -> I } ExecuteMsg::ModuleIbcAction { host_chain, - source_module, target_module, msg, callback_info, @@ -101,7 +100,6 @@ pub fn execute(deps: DepsMut, env: Env, info: MessageInfo, msg: ExecuteMsg) -> I env, info, host_chain, - source_module, target_module, msg, callback_info, diff --git a/framework/packages/abstract-adapter/src/endpoints/instantiate.rs b/framework/packages/abstract-adapter/src/endpoints/instantiate.rs index a69c1a3fc0..4e4cf68942 100644 --- a/framework/packages/abstract-adapter/src/endpoints/instantiate.rs +++ b/framework/packages/abstract-adapter/src/endpoints/instantiate.rs @@ -2,13 +2,16 @@ use abstract_sdk::{ base::{Handler, InstantiateEndpoint}, feature_objects::{AnsHost, VersionControlContract}, }; -use abstract_std::{adapter::InstantiateMsg, objects::module_version::set_module_data}; +use abstract_std::{ + adapter::{AdapterState, InstantiateMsg}, + objects::module_version::set_module_data, +}; use cosmwasm_std::{DepsMut, Env, MessageInfo, Response}; use cw2::set_contract_version; use schemars::JsonSchema; use serde::Serialize; -use crate::state::{AdapterContract, ApiState, ContractError}; +use crate::state::{AdapterContract, ContractError}; impl< Error: ContractError, @@ -38,7 +41,7 @@ impl< }; // Base state - let state = ApiState { + let state = AdapterState { version_control, ans_host, }; @@ -61,7 +64,7 @@ mod tests { feature_objects::{AnsHost, VersionControlContract}, }; use abstract_std::{ - adapter::{BaseInstantiateMsg, InstantiateMsg}, + adapter::{AdapterState, BaseInstantiateMsg, InstantiateMsg}, objects::module_version::{ModuleData, MODULE}, }; use abstract_testing::prelude::*; @@ -72,10 +75,7 @@ mod tests { use cw2::{ContractVersion, CONTRACT}; use speculoos::prelude::*; - use crate::{ - mock::{AdapterMockResult, MockInitMsg, MOCK_ADAPTER, MOCK_DEP, TEST_METADATA}, - state::ApiState, - }; + use crate::mock::{AdapterMockResult, MockInitMsg, MOCK_ADAPTER, MOCK_DEP, TEST_METADATA}; #[test] fn successful() -> AdapterMockResult { @@ -115,7 +115,7 @@ mod tests { assert!(none_authorized); let state = api.base_state.load(&deps.storage)?; - assert_that!(state).is_equal_to(ApiState { + assert_that!(state).is_equal_to(AdapterState { version_control: VersionControlContract { address: Addr::unchecked(TEST_VERSION_CONTROL), }, diff --git a/framework/packages/abstract-adapter/src/state.rs b/framework/packages/abstract-adapter/src/state.rs index 36e21ed1f1..ce002eba6d 100644 --- a/framework/packages/abstract-adapter/src/state.rs +++ b/framework/packages/abstract-adapter/src/state.rs @@ -1,20 +1,15 @@ -use std::fmt::Debug; - use abstract_sdk::{ base::{ AbstractContract, ExecuteHandlerFn, Handler, IbcCallbackHandlerFn, InstantiateHandlerFn, ModuleIbcHandlerFn, QueryHandlerFn, ReceiveHandlerFn, ReplyHandlerFn, SudoHandlerFn, }, - feature_objects::{AnsHost, VersionControlContract}, namespaces::BASE_STATE, std::version_control::AccountBase, AbstractSdkError, }; -use abstract_std::{objects::dependency::StaticDependency, AbstractError}; +use abstract_std::{adapter::AdapterState, objects::dependency::StaticDependency, AbstractError}; use cosmwasm_std::{Addr, Empty, StdError, StdResult, Storage}; use cw_storage_plus::{Item, Map}; -use schemars::JsonSchema; -use serde::{Deserialize, Serialize}; use crate::AdapterError; @@ -38,16 +33,6 @@ impl ContractError for T where { } -/// The BaseState contains the main addresses needed for sending and verifying messages -/// Every DApp should use the provided **ans_host** contract for token/contract address resolution. -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] -pub struct ApiState { - /// Used to verify requests - pub version_control: VersionControlContract, - /// AnsHost contract struct (address) - pub ans_host: AnsHost, -} - /// The state variables for our AdapterContract. pub struct AdapterContract< Error: ContractError, @@ -60,7 +45,7 @@ pub struct AdapterContract< Self: Handler, { pub(crate) contract: AbstractContract, - pub(crate) base_state: Item<'static, ApiState>, + pub(crate) base_state: Item<'static, AdapterState>, /// Map ProxyAddr -> AuthorizedAddrs pub authorized_addresses: Map<'static, Addr, Vec>, /// The Account on which commands are executed. Set each time in the [`abstract_std::adapter::ExecuteMsg::Base`] handler. @@ -88,7 +73,7 @@ impl StdResult { + pub fn state(&self, store: &dyn Storage) -> StdResult { self.base_state.load(store) } diff --git a/framework/packages/abstract-app/src/endpoints/instantiate.rs b/framework/packages/abstract-app/src/endpoints/instantiate.rs index 4cfd40de35..b0269082ee 100644 --- a/framework/packages/abstract-app/src/endpoints/instantiate.rs +++ b/framework/packages/abstract-app/src/endpoints/instantiate.rs @@ -1,6 +1,6 @@ use abstract_sdk::feature_objects::{AnsHost, VersionControlContract}; use abstract_std::{ - app::{BaseInstantiateMsg, InstantiateMsg}, + app::{AppState, BaseInstantiateMsg, InstantiateMsg}, objects::module_version::set_module_data, }; use cosmwasm_std::{DepsMut, Env, MessageInfo, Response}; @@ -9,7 +9,7 @@ use schemars::JsonSchema; use serde::{de::DeserializeOwned, Serialize}; use crate::{ - state::{AppContract, AppState, ContractError}, + state::{AppContract, ContractError}, Handler, InstantiateEndpoint, }; diff --git a/framework/packages/abstract-app/src/state.rs b/framework/packages/abstract-app/src/state.rs index 865f69a09e..0c1f72f734 100644 --- a/framework/packages/abstract-app/src/state.rs +++ b/framework/packages/abstract-app/src/state.rs @@ -1,17 +1,15 @@ use abstract_sdk::{ base::{ModuleIbcHandlerFn, SudoHandlerFn}, - feature_objects::{AnsHost, VersionControlContract}, namespaces::{ADMIN_NAMESPACE, BASE_STATE}, AbstractSdkError, }; use abstract_std::{ + app::AppState, objects::{dependency::StaticDependency, nested_admin::NestedAdmin}, AbstractError, }; -use cosmwasm_std::{Addr, Empty, StdResult, Storage}; +use cosmwasm_std::{Empty, StdResult, Storage}; use cw_storage_plus::Item; -use schemars::JsonSchema; -use serde::{Deserialize, Serialize}; use crate::{ AbstractContract, AppError, ExecuteHandlerFn, IbcCallbackHandlerFn, InstantiateHandlerFn, @@ -36,17 +34,6 @@ impl ContractError for T where { } -/// The BaseState contains the main addresses needed for sending and verifying messages -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] -pub struct AppState { - /// Proxy contract address for relaying transactions - pub proxy_address: Addr, - /// AnsHost contract struct (address) - pub ans_host: AnsHost, - /// Used to verify requests - pub version_control: VersionControlContract, -} - /// The state variables for our AppContract. pub struct AppContract< Error: ContractError, diff --git a/framework/packages/abstract-sdk/src/feature_objects.rs b/framework/packages/abstract-sdk/src/feature_objects.rs index 010d5e6c2f..44df98a16d 100644 --- a/framework/packages/abstract-sdk/src/feature_objects.rs +++ b/framework/packages/abstract-sdk/src/feature_objects.rs @@ -5,7 +5,7 @@ //! requiring the usage of a base contract. pub use abstract_std::objects::{ans_host::AnsHost, version_control::VersionControlContract}; -use abstract_std::version_control::AccountBase; +use abstract_std::{version_control::AccountBase, VERSION_CONTROL}; use cosmwasm_std::{Addr, Deps}; use crate::{ @@ -70,6 +70,12 @@ impl crate::features::AbstractRegistryAccess for VersionControlContract { } } +impl ModuleIdentification for VersionControlContract { + fn module_id(&self) -> abstract_std::objects::module::ModuleId<'static> { + VERSION_CONTROL + } +} + impl crate::features::AbstractNameService for AnsHost { fn ans_host(&self, _deps: Deps) -> AbstractSdkResult { Ok(self.clone()) diff --git a/framework/packages/abstract-std/src/adapter.rs b/framework/packages/abstract-std/src/adapter.rs index 38e43a8e66..021a830f48 100644 --- a/framework/packages/abstract-std/src/adapter.rs +++ b/framework/packages/abstract-std/src/adapter.rs @@ -16,7 +16,10 @@ use crate::{ ExecuteMsg as MiddlewareExecMsg, InstantiateMsg as MiddlewareInstantiateMsg, QueryMsg as MiddlewareQueryMsg, }, - objects::module_version::ModuleDataResponse, + objects::{ + ans_host::AnsHost, module_version::ModuleDataResponse, + version_control::VersionControlContract, + }, }; pub type ExecuteMsg = @@ -156,3 +159,13 @@ pub struct AuthorizedAddressesResponse { /// Contains all authorized addresses pub addresses: Vec, } + +/// The BaseState contains the main addresses needed for sending and verifying messages +/// Every DApp should use the provided **ans_host** contract for token/contract address resolution. +#[cosmwasm_schema::cw_serde] +pub struct AdapterState { + /// Used to verify requests + pub version_control: VersionControlContract, + /// AnsHost contract struct (address) + pub ans_host: AnsHost, +} diff --git a/framework/packages/abstract-std/src/app.rs b/framework/packages/abstract-std/src/app.rs index 97e3952112..81f7b75b2a 100644 --- a/framework/packages/abstract-std/src/app.rs +++ b/framework/packages/abstract-std/src/app.rs @@ -9,7 +9,10 @@ use crate::{ ExecuteMsg as EndpointExecMsg, InstantiateMsg as EndpointInstantiateMsg, MigrateMsg as EndpointMigrateMsg, QueryMsg as EndpointQueryMsg, }, - objects::{module_version::ModuleDataResponse, nested_admin::TopLevelOwnerResponse}, + objects::{ + ans_host::AnsHost, module_version::ModuleDataResponse, nested_admin::TopLevelOwnerResponse, + version_control::VersionControlContract, + }, version_control::AccountBase, }; @@ -110,3 +113,14 @@ pub struct AppConfigResponse { #[cosmwasm_schema::cw_serde] pub struct BaseMigrateMsg {} + +/// The BaseState contains the main addresses needed for sending and verifying messages +#[cosmwasm_schema::cw_serde] +pub struct AppState { + /// Proxy contract address for relaying transactions + pub proxy_address: Addr, + /// AnsHost contract struct (address) + pub ans_host: AnsHost, + /// Used to verify requests + pub version_control: VersionControlContract, +} diff --git a/framework/packages/abstract-std/src/native/ibc_client.rs b/framework/packages/abstract-std/src/native/ibc_client.rs index e6127eadb5..781ac6e055 100644 --- a/framework/packages/abstract-std/src/native/ibc_client.rs +++ b/framework/packages/abstract-std/src/native/ibc_client.rs @@ -106,7 +106,6 @@ pub enum ExecuteMsg { }, ModuleIbcAction { host_chain: String, - source_module: InstalledModuleIdentification, target_module: ModuleInfo, msg: Binary, callback_info: Option, diff --git a/interchain/interchain-tests/src/module_to_module_interactions.rs b/interchain/interchain-tests/src/module_to_module_interactions.rs index 014e0e89f0..912cfea854 100644 --- a/interchain/interchain-tests/src/module_to_module_interactions.rs +++ b/interchain/interchain-tests/src/module_to_module_interactions.rs @@ -1,7 +1,7 @@ pub use abstract_std::app; use abstract_std::{ ibc::{CallbackInfo, CallbackResult, ModuleIbcMsg}, - ibc_client::{self, InstalledModuleIdentification}, + ibc_client::{self}, objects::module::ModuleInfo, IBC_CLIENT, }; @@ -75,7 +75,7 @@ pub struct MockReceiveMsg; #[cosmwasm_schema::cw_serde] pub struct MockSudoMsg; -use abstract_sdk::{features::AccountIdentification, AbstractSdkError, ModuleInterface}; +use abstract_sdk::{AbstractSdkError, ModuleInterface}; use thiserror::Error; use abstract_app::{AppContract, AppError}; @@ -139,11 +139,6 @@ pub const fn mock_app(id: &'static str, version: &'static str) -> MockAppContrac ibc_client_addr, &ibc_client::ExecuteMsg::ModuleIbcAction { host_chain: remote_chain, - source_module: InstalledModuleIdentification { - module_info: ModuleInfo::from_id(app.module_id(), app.version().into()) - .unwrap(), - account_id: Some(app.account_id(deps.as_ref())?), - }, target_module, msg: to_json_binary(&IbcModuleToModuleMsg { ibc_msg: "module_to_module:msg".to_string(), @@ -594,7 +589,7 @@ pub mod test { } pub mod security { - use abstract_std::ibc_client::{ExecuteMsgFns, InstalledModuleIdentification}; + use abstract_std::ibc_client::ExecuteMsgFns; use crate::module_to_module_interactions::IbcModuleToModuleMsg; @@ -689,11 +684,6 @@ pub mod test { ibc_msg: "module_to_module:msg".to_string(), }) .unwrap(), - InstalledModuleIdentification { - module_info: ModuleInfo::from_id(TEST_MODULE_ID, TEST_VERSION.into()) - .unwrap(), - account_id: Some(origin_account.id()?), - }, target_module_info, None, ) diff --git a/modules/contracts/apps/etf/src/handlers/execute.rs b/modules/contracts/apps/etf/src/handlers/execute.rs index 6390a811ff..3fd60a530c 100644 --- a/modules/contracts/apps/etf/src/handlers/execute.rs +++ b/modules/contracts/apps/etf/src/handlers/execute.rs @@ -1,9 +1,11 @@ -use abstract_app::sdk::std::{ - objects::{deposit_info::DepositInfo, fee::Fee}, - proxy::AssetsInfoResponse, -}; use abstract_app::sdk::*; -use abstract_app::state::AppState; +use abstract_app::{ + sdk::std::{ + objects::{deposit_info::DepositInfo, fee::Fee}, + proxy::AssetsInfoResponse, + }, + std::app::AppState, +}; use cosmwasm_std::{ to_json_binary, wasm_execute, Addr, CosmosMsg, Decimal, DepsMut, Env, MessageInfo, QuerierWrapper, StdResult, Uint128, WasmMsg, From f39fa36214f2c1123410627a6a5b80259a2a8d9b Mon Sep 17 00:00:00 2001 From: Kayanski Date: Tue, 30 Apr 2024 14:17:11 +0000 Subject: [PATCH 36/37] formatting [skip ci] --- .../contracts/native/ibc-client/src/commands.rs | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/framework/contracts/native/ibc-client/src/commands.rs b/framework/contracts/native/ibc-client/src/commands.rs index b2da5d41fe..18517b03bf 100644 --- a/framework/contracts/native/ibc-client/src/commands.rs +++ b/framework/contracts/native/ibc-client/src/commands.rs @@ -7,13 +7,20 @@ use abstract_sdk::{ ModuleRegistryInterface, Resolve, }; use abstract_std::{ - app::AppState, ibc::CallbackInfo, ibc_client::{ + app::AppState, + ibc::CallbackInfo, + ibc_client::{ state::{IbcInfrastructure, ACCOUNTS, CONFIG, IBC_INFRA, REVERSE_POLYTONE_NOTE}, IbcClientCallback, InstalledModuleIdentification, - }, ibc_host::{self, HostAction, InternalAction}, manager::{self, ModuleInstallConfig}, objects::{ + }, + ibc_host::{self, HostAction, InternalAction}, + manager::{self, ModuleInstallConfig}, + objects::{ chain_name::ChainName, module::ModuleInfo, module_reference::ModuleReference, AccountId, AssetEntry, ChannelEntry, - }, version_control::AccountBase, ICS20 + }, + version_control::AccountBase, + ICS20, }; use cosmwasm_std::{ to_json_binary, wasm_execute, Binary, Coin, CosmosMsg, Deps, DepsMut, Empty, Env, IbcMsg, From f9e778afd2f78c1849d946e4bfcd763a43114762 Mon Sep 17 00:00:00 2001 From: Kayanski Date: Tue, 30 Apr 2024 14:22:21 +0000 Subject: [PATCH 37/37] Double import fix --- framework/contracts/native/ibc-client/src/contract.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/framework/contracts/native/ibc-client/src/contract.rs b/framework/contracts/native/ibc-client/src/contract.rs index 5111dd1693..c2f1666fdf 100644 --- a/framework/contracts/native/ibc-client/src/contract.rs +++ b/framework/contracts/native/ibc-client/src/contract.rs @@ -472,7 +472,6 @@ mod tests { }; use cosmwasm_std::wasm_execute; - use std::str::FromStr; use crate::commands::PACKET_LIFETIME;