Skip to content

Integrate module to module IBC messages #259

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 46 commits into from
Apr 30, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
9efa1f3
Started impl, first test creation
Kayanski Feb 16, 2024
5393958
formatting [skip ci]
Kayanski Feb 16, 2024
f449ec1
Restart impl
Kayanski Mar 6, 2024
4554f42
Added verifiedsender to ibc-callback
Kayanski Mar 6, 2024
81f1556
Modified implementation with InstalledModuleIdentification for all mo…
Kayanski Mar 6, 2024
883a09a
Added test
Kayanski Mar 7, 2024
76ed58d
Merged with main
Kayanski Mar 7, 2024
1515665
Module-to-module works
Kayanski Mar 7, 2024
658907b
Fixed tests and clippy
Kayanski Mar 7, 2024
c9c466a
Clippy
Kayanski Mar 7, 2024
301c373
Fixed test after error change
Kayanski Mar 7, 2024
de6a62e
Fixed error
Kayanski Mar 11, 2024
46d2920
Removed user initiated callbacks
Kayanski Mar 11, 2024
1eac1f8
Add source module in callback
Kayanski Mar 11, 2024
a75829f
Added callback handler identification
Kayanski Mar 11, 2024
2850733
Fixed tests
Kayanski Mar 11, 2024
4b9bcf9
Fixed tests
Kayanski Mar 11, 2024
62e836d
not use latest but current version for client and host verification
Kayanski Mar 11, 2024
6869f92
Removed cross-account calls
Kayanski Mar 11, 2024
43174c9
Fixed test
Kayanski Mar 11, 2024
502e4ef
Better addr getter for installed module
Kayanski Mar 11, 2024
ed19f5e
Added account + native module error
Kayanski Mar 12, 2024
d561c1c
rm unneeded clone
CyberHoward Mar 12, 2024
2085a47
use raw query for module install verification
CyberHoward Mar 12, 2024
e823031
update error msg
CyberHoward Mar 12, 2024
642a161
rm redundant type
CyberHoward Mar 12, 2024
1a686b5
Added docs
Kayanski Mar 13, 2024
539cfe6
Merged
Kayanski Mar 13, 2024
a7ea538
Some nits
Kayanski Mar 13, 2024
389706e
formatting [skip ci]
Kayanski Mar 13, 2024
6962d1e
Added error on no module ibc endpoint
Kayanski Mar 19, 2024
84f95e8
Fixed module queries and added calbackresult
Kayanski Mar 19, 2024
441dc3e
Merge with main
Kayanski Mar 19, 2024
867278a
Fixed clippies
Kayanski Mar 19, 2024
7777d60
Merge branch 'main' into feature/module-ibc
Kayanski Mar 25, 2024
4dea142
Removed cw-controllers too high version
Kayanski Mar 25, 2024
67d633f
Merge branch 'feature/module-ibc' of github.com:AbstractSDK/abstract …
Kayanski Mar 25, 2024
5ac11c5
Removed callback receiver
Kayanski Mar 25, 2024
6f5ece3
Added calling module security test
Kayanski Apr 23, 2024
4e77c7e
Clippy
Kayanski Apr 23, 2024
3c3606a
Merged with main
Kayanski Apr 23, 2024
2a5f2d3
Merge with main
Kayanski Apr 30, 2024
ad4ab6a
Simplified module IBC API
Kayanski Apr 30, 2024
a8afe4c
Merge remote-tracking branch 'origin/main' into feature/module-ibc
Kayanski Apr 30, 2024
f39fa36
formatting [skip ci]
Kayanski Apr 30, 2024
f9e778a
Double import fix
Kayanski Apr 30, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
127 changes: 100 additions & 27 deletions framework/contracts/native/ibc-client/src/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::{
Expand All @@ -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;

Expand Down Expand Up @@ -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<CallbackRequest>,
) -> IbcClientResult<CosmosMsg<Empty>> {
// 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,
Expand Down Expand Up @@ -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))
}
Expand Down
3 changes: 3 additions & 0 deletions framework/contracts/native/ibc-client/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {},

Expand Down
15 changes: 15 additions & 0 deletions framework/contracts/native/ibc-client/src/ibc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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))
}
}
}
10 changes: 9 additions & 1 deletion framework/contracts/native/ibc-host/src/endpoints/execute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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)
}
}
}

Expand Down
38 changes: 35 additions & 3 deletions framework/contracts/native/ibc-host/src/endpoints/packet.rs
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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::<Empty, Empty>(ModuleIbcMsg {
client_chain,
source_module,
msg,
}),
vec![],
)?;

Ok(Response::new()
.add_attribute("action", "module-ibc-call")
.add_message(msg))
}
1 change: 1 addition & 0 deletions framework/packages/abstract-adapter/src/endpoints.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
mod execute;
mod ibc_callback;
mod instantiate;
mod module_ibc;
mod query;
mod receive;
mod reply;
Expand Down
3 changes: 2 additions & 1 deletion framework/packages/abstract-adapter/src/endpoints/execute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
};
Expand Down Expand Up @@ -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),
}
}
}
Expand Down
33 changes: 33 additions & 0 deletions framework/packages/abstract-adapter/src/endpoints/module_ibc.rs
Original file line number Diff line number Diff line change
@@ -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<Error: ContractError, CustomInitMsg, CustomExecMsg, CustomQueryMsg, ReceiveMsg, SudoMsg>
ModuleIbcEndpoint
for AdapterContract<Error, CustomInitMsg, CustomExecMsg, CustomQueryMsg, ReceiveMsg, SudoMsg>
{
fn ibc_host(&self, deps: cosmwasm_std::Deps) -> Result<Addr, Self::Error> {
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
})?)
}
}
1 change: 1 addition & 0 deletions framework/packages/abstract-app/src/endpoints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ mod execute;
mod ibc_callback;
pub mod instantiate;
mod migrate;
mod module_ibc;
mod query;
mod receive;
mod reply;
Expand Down
10 changes: 6 additions & 4 deletions framework/packages/abstract-app/src/endpoints/execute.rs
Original file line number Diff line number Diff line change
@@ -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;

Expand Down Expand Up @@ -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),
}
}
}
Expand Down
29 changes: 29 additions & 0 deletions framework/packages/abstract-app/src/endpoints/module_ibc.rs
Original file line number Diff line number Diff line change
@@ -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<cw_orch::prelude::Addr, Self::Error> {
let ibc_client = self.modules(deps).module_address(IBC_HOST)?;
Ok(ibc_client)
}
}
Loading