abstract_ibc_host/endpoints/
execute.rs

1use abstract_sdk::std::ibc_host::ExecuteMsg;
2use abstract_std::{
3    ibc_host::state::{CHAIN_PROXIES, REVERSE_CHAIN_PROXIES},
4    objects::TruncatedChainId,
5};
6use cosmwasm_std::{BankMsg, DepsMut, Env, MessageInfo, Response};
7
8use super::packet::{handle_host_action, handle_module_execute};
9use crate::{
10    account_commands::{self, receive_register},
11    contract::{HostResponse, HostResult},
12    HostError,
13};
14
15pub fn execute(deps: DepsMut, env: Env, info: MessageInfo, msg: ExecuteMsg) -> HostResult {
16    match msg {
17        ExecuteMsg::RegisterChainProxy { chain, proxy } => {
18            register_chain_proxy(deps, info, chain, proxy)
19        }
20        ExecuteMsg::RemoveChainProxy { chain } => remove_chain_proxy(deps, info, chain),
21        ExecuteMsg::Execute {
22            account_address,
23            account_id,
24            action,
25        } => {
26            // This endpoint retrieves the chain name from the executor of the message
27            let src_chain: TruncatedChainId =
28                REVERSE_CHAIN_PROXIES.load(deps.storage, &info.sender)?;
29
30            handle_host_action(deps, env, src_chain, account_address, account_id, action)
31        }
32        ExecuteMsg::UpdateOwnership(action) => {
33            cw_ownable::update_ownership(deps, &env.block, &info.sender, action)?;
34            Ok(HostResponse::action("update_ownership"))
35        }
36        ExecuteMsg::ModuleExecute {
37            msg,
38            source_module,
39            target_module,
40        } => {
41            let src_chain: TruncatedChainId =
42                REVERSE_CHAIN_PROXIES.load(deps.storage, &info.sender)?;
43
44            handle_module_execute(deps, env, src_chain, source_module, target_module, msg)
45        }
46        ExecuteMsg::Fund {
47            src_account,
48            src_chain,
49        } => {
50            // Push the client chain to the account trace
51            let account_id = {
52                let mut account_id = src_account.clone();
53                account_id.push_chain(src_chain.clone());
54                account_id
55            };
56            if let Ok(account) = account_commands::get_account(deps.as_ref(), &env, &account_id) {
57                // Send funds to the account
58
59                Ok(Response::new().add_message(BankMsg::Send {
60                    to_address: account.addr().to_string(),
61                    amount: info.funds,
62                }))
63            } else {
64                // If no account is created already, we create one and send the funds during instantiation directly
65                // The account metadata are not set with this call
66                // One will have to change them at a later point if they decide to
67                let name = format!(
68                    "Remote Abstract Account for {}/{}",
69                    src_chain.as_str(),
70                    account_id
71                );
72
73                receive_register(
74                    deps,
75                    env,
76                    account_id,
77                    Some(name),
78                    None,
79                    None,
80                    None,
81                    vec![],
82                    false,
83                    info.funds,
84                )
85            }
86        }
87    }
88}
89
90/// Register the polytone proxy address for a given chain
91/// The polytone proxy will send messages to this address when it needs to execute actions on a local account.
92fn register_chain_proxy(
93    deps: DepsMut,
94    info: MessageInfo,
95    chain: TruncatedChainId,
96    proxy: String,
97) -> HostResult {
98    cw_ownable::assert_owner(deps.storage, &info.sender)?;
99
100    chain.verify()?;
101
102    // We validate the proxy address, because this is the Polytone counterpart on the local chain
103    let proxy = deps.api.addr_validate(&proxy)?;
104    // Can't register if it already exists
105    if CHAIN_PROXIES.has(deps.storage, &chain) || REVERSE_CHAIN_PROXIES.has(deps.storage, &proxy) {
106        return Err(HostError::ProxyAddressExists {});
107    }
108
109    CHAIN_PROXIES.save(deps.storage, &chain, &proxy)?;
110    REVERSE_CHAIN_PROXIES.save(deps.storage, &proxy, &chain)?;
111    Ok(HostResponse::action("register_chain_client"))
112}
113
114fn remove_chain_proxy(deps: DepsMut, info: MessageInfo, chain: TruncatedChainId) -> HostResult {
115    cw_ownable::assert_owner(deps.storage, &info.sender)?;
116
117    chain.verify()?;
118
119    if let Some(proxy) = CHAIN_PROXIES.may_load(deps.storage, &chain)? {
120        REVERSE_CHAIN_PROXIES.remove(deps.storage, &proxy);
121    }
122
123    CHAIN_PROXIES.remove(deps.storage, &chain);
124    Ok(HostResponse::action("register_chain_client"))
125}