diff --git a/framework/contracts/native/ica-client/src/chain_types/evm.rs b/framework/contracts/native/ica-client/src/chain_types/evm.rs index f248503d9..2591b197f 100644 --- a/framework/contracts/native/ica-client/src/chain_types/evm.rs +++ b/framework/contracts/native/ica-client/src/chain_types/evm.rs @@ -1,28 +1,19 @@ -use abstract_ica::EVM_NOTE_ID; -use abstract_sdk::{ - feature_objects::{AnsHost, RegistryContract}, - Resolve, -}; +use abstract_sdk::{feature_objects::AnsHost, Resolve}; use abstract_std::{ ibc::PACKET_LIFETIME, native_addrs, - objects::{module::ModuleInfo, ChannelEntry, ContractEntry, TruncatedChainId}, -}; -use cosmwasm_std::{ - wasm_execute, Addr, Binary, Coin, CosmosMsg, Deps, Env, HexBinary, QuerierWrapper, WasmMsg, + objects::{ChannelEntry, ContractEntry, TruncatedChainId}, }; +use cosmwasm_std::{wasm_execute, Addr, Binary, Coin, CosmosMsg, Deps, Env, HexBinary, WasmMsg}; use evm_note::msg::{CallbackRequest, EvmMsg}; use crate::{contract::IcaClientResult, error::IcaClientError}; pub fn execute( - querier: &QuerierWrapper, - vc: &RegistryContract, + note_addr: Addr, msgs: Vec>, callback: Option, ) -> IcaClientResult { - let note_addr = evm_note_addr(vc, querier)?; - wasm_execute( note_addr, &evm_note::msg::ExecuteMsg::Execute { @@ -38,6 +29,7 @@ pub fn execute( pub fn send_funds( deps: Deps, env: &Env, + note_addr: &Addr, evm_chain: &TruncatedChainId, funds: Vec, receiver: Option, @@ -50,12 +42,9 @@ pub fn send_funds( let receiver: HexBinary = match receiver { Some(r) => r.into(), None => { - let registry = RegistryContract::new(deps, abstract_code_id)?; - let note_addr = evm_note_addr(®istry, &deps.querier)?; - // If state objects will be public on evm_note let remote_acc: Option = deps.querier.query_wasm_smart( - ¬e_addr, + note_addr, &evm_note::msg::QueryMsg::RemoteAddress { local_address: env.contract.address.to_string(), }, @@ -100,16 +89,6 @@ pub fn send_funds( Ok(forwarder_msg) } -fn evm_note_addr(vc: &RegistryContract, querier: &QuerierWrapper) -> IcaClientResult { - let evm_note_entry = - ModuleInfo::from_id(EVM_NOTE_ID, abstract_ica::POLYTONE_EVM_VERSION.parse()?)?; - - vc.query_module(evm_note_entry, querier)? - .reference - .unwrap_native() - .map_err(Into::into) -} - pub(crate) mod types { use super::*; diff --git a/framework/contracts/native/ica-client/src/contract.rs b/framework/contracts/native/ica-client/src/contract.rs index 0daa05ca6..01ce74e45 100644 --- a/framework/contracts/native/ica-client/src/contract.rs +++ b/framework/contracts/native/ica-client/src/contract.rs @@ -1,7 +1,11 @@ use crate::msg::*; use abstract_macros::abstract_response; use abstract_std::{ - objects::module_version::{assert_cw_contract_upgrade, migrate_module_data}, + ica_client::state::{IcaInfrastructure, ICA_INFRA}, + objects::{ + module_version::{assert_cw_contract_upgrade, migrate_module_data}, + TruncatedChainId, + }, ICA_CLIENT, }; use cosmwasm_std::{to_json_binary, Deps, DepsMut, Env, MessageInfo, QueryResponse, Response}; @@ -36,7 +40,57 @@ pub fn execute(deps: DepsMut, env: Env, info: MessageInfo, msg: ExecuteMsg) -> I cw_ownable::update_ownership(deps, &env.block, &info.sender, action)?; Ok(IcaClientResponse::action("update_ownership")) } + ExecuteMsg::RegisterInfrastructure { chain, note} => { + execute_register_infrastructure(deps, info, chain, note) + } + ExecuteMsg::RemoveHost { host_chain } => execute_remove_host(deps, info, host_chain), + } +} + +/// Registers a chain to the client. +/// This registration includes the counterparty information (note and proxy address) +pub fn execute_register_infrastructure( + deps: DepsMut, + info: MessageInfo, + host_chain: TruncatedChainId, + note: String, +) -> IcaClientResult { + host_chain.verify()?; + + // auth check + cw_ownable::assert_owner(deps.storage, &info.sender)?; + + let note = deps.api.addr_validate(¬e)?; + // Can't allow if it already exists + if ICA_INFRA.has(deps.storage, &host_chain) { + return Err(IcaClientError::ChainExists {}); } + + ICA_INFRA.save( + deps.storage, + &host_chain, + &IcaInfrastructure { + polytone_note: note.clone(), + }, + )?; + + Ok(IcaClientResponse::action("register_infrastructure")) +} + +// allows admins to clear host if needed +pub fn execute_remove_host( + deps: DepsMut, + info: MessageInfo, + host_chain: TruncatedChainId, +) -> IcaClientResult { + host_chain.verify()?; + + // auth check + cw_ownable::assert_owner(deps.storage, &info.sender)?; + + ICA_INFRA.remove(deps.storage, &host_chain); + + Ok(IcaClientResponse::action("remove_host")) } #[cfg_attr(feature = "export", cosmwasm_std::entry_point)] diff --git a/framework/contracts/native/ica-client/src/error.rs b/framework/contracts/native/ica-client/src/error.rs index c269c90ee..e46d8df2a 100644 --- a/framework/contracts/native/ica-client/src/error.rs +++ b/framework/contracts/native/ica-client/src/error.rs @@ -30,4 +30,7 @@ pub enum IcaClientError { #[error("messages for chain {chain} are not of type {ty}")] WrongChainType { chain: String, ty: String }, + + #[error("Chain already registered.")] + ChainExists {}, } diff --git a/framework/contracts/native/ica-client/src/queries.rs b/framework/contracts/native/ica-client/src/queries.rs index c4a5001dc..e20ae31bf 100644 --- a/framework/contracts/native/ica-client/src/queries.rs +++ b/framework/contracts/native/ica-client/src/queries.rs @@ -1,6 +1,6 @@ use abstract_ica::{msg::ConfigResponse, ChainType, IcaAction, IcaActionResponse}; use abstract_sdk::feature_objects::{AnsHost, RegistryContract}; -use abstract_std::{native_addrs, objects::TruncatedChainId}; +use abstract_std::{ica_client::state::ICA_INFRA, native_addrs, objects::TruncatedChainId}; use cosmwasm_std::{ensure_eq, CosmosMsg, Deps, Env}; use crate::{chain_types::evm, contract::IcaClientResult, error::IcaClientError}; @@ -28,6 +28,13 @@ pub(crate) fn ica_action( chain: chain.to_string(), })?; + let ica_infra = + ICA_INFRA + .may_load(deps.storage, &chain)? + .ok_or(IcaClientError::NoChainType { + chain: chain.to_string(), + })?; + let process_action = |action: IcaAction| -> IcaClientResult> { match action { IcaAction::Execute(ica_exec) => match ica_exec { @@ -40,13 +47,8 @@ pub(crate) fn ica_action( ty: chain_type.to_string() } ); - let abstract_code_id = native_addrs::abstract_code_id( - &deps.querier, - env.contract.address.clone(), - )?; - let registry = RegistryContract::new(deps, abstract_code_id)?; - let msg = evm::execute(&deps.querier, ®istry, msgs, callback)?; + let msg = evm::execute(ica_infra.polytone_note.clone(), msgs, callback)?; Ok(vec![msg.into()]) } @@ -58,7 +60,13 @@ pub(crate) fn ica_action( memo, } => match chain_type { ChainType::Evm => Ok(vec![evm::send_funds( - deps, &env, &chain, funds, receiver, memo, + deps, + &env, + &ica_infra.polytone_note, + &chain, + funds, + receiver, + memo, )?]), _ => unimplemented!(), }, diff --git a/framework/packages/abstract-ica/src/msg.rs b/framework/packages/abstract-ica/src/msg.rs index 460d6d5e7..2313e3eb5 100644 --- a/framework/packages/abstract-ica/src/msg.rs +++ b/framework/packages/abstract-ica/src/msg.rs @@ -17,10 +17,21 @@ pub enum MigrateMsg { Migrate {}, } +pub type EvmChainId = u64; + #[cw_ownable_execute] #[cosmwasm_schema::cw_serde] #[derive(cw_orch::ExecuteFns)] -pub enum ExecuteMsg {} +pub enum ExecuteMsg { + RegisterInfrastructure { + /// Chain to register the infrastructure for ("sepolia", "osmosis", "holesky", etc.) + chain: TruncatedChainId, + /// Polytone note (locally deployed) + note: String, + }, + /// Owner method: Remove connection for remote chain + RemoveHost { host_chain: TruncatedChainId }, +} #[cw_ownable_query] #[cosmwasm_schema::cw_serde] diff --git a/framework/packages/abstract-std/src/native/ibc/ica_client.rs b/framework/packages/abstract-std/src/native/ibc/ica_client.rs index 80b926c7d..fbad9397c 100644 --- a/framework/packages/abstract-std/src/native/ibc/ica_client.rs +++ b/framework/packages/abstract-std/src/native/ibc/ica_client.rs @@ -1 +1,16 @@ -pub mod state {} +pub mod state { + use cosmwasm_std::Addr; + use cw_storage_plus::Map; + + use crate::objects::{storage_namespaces, TruncatedChainId}; + + /// Information about the deployed infrastructure we're connected to. + #[cosmwasm_schema::cw_serde] + pub struct IcaInfrastructure { + /// Address of the polytone note deployed on the local chain. This contract will forward the messages for us. + pub polytone_note: Addr, + } + + pub const ICA_INFRA: Map<&TruncatedChainId, IcaInfrastructure> = + Map::new(storage_namespaces::ica_client::ICA_INFRA); +} diff --git a/framework/packages/abstract-std/src/objects/storage_namespaces.rs b/framework/packages/abstract-std/src/objects/storage_namespaces.rs index d5166821c..81e57a43c 100644 --- a/framework/packages/abstract-std/src/objects/storage_namespaces.rs +++ b/framework/packages/abstract-std/src/objects/storage_namespaces.rs @@ -68,4 +68,6 @@ pub mod ibc_host { pub const TEMP_ACTION_AFTER_CREATION: &str = "fc"; } -pub mod ica_client {} +pub mod ica_client { + pub const ICA_INFRA: &str = "ga"; +}