evm_note/
contract.rs

1#[cfg(not(feature = "library"))]
2use cosmwasm_std::entry_point;
3use cosmwasm_std::{
4    to_json_binary, Binary, Deps, DepsMut, Env, IbcMsg, IbcTimeout, MessageInfo, Order, Response,
5    StdResult,
6};
7use cw2::set_contract_version;
8use cw_storage_plus::Bound;
9use polytone_evm::callbacks::CallbackRequestType;
10use polytone_evm::ibc::Packet;
11use polytone_evm::{accounts, callbacks, ibc, EVM_NOTE_ID};
12
13use crate::error::ContractError;
14
15use crate::ibc::ERR_GAS_NEEDED;
16use crate::msg::{AckInfosResponse, ExecuteMsg, InstantiateMsg, MigrateMsg, Pair, QueryMsg};
17use crate::state::{increment_sequence_number, BLOCK_MAX_GAS, CHANNEL, CONNECTION_REMOTE_PORT};
18
19pub const CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION");
20
21#[cfg_attr(not(feature = "library"), entry_point)]
22pub fn instantiate(
23    deps: DepsMut,
24    _env: Env,
25    _info: MessageInfo,
26    msg: InstantiateMsg,
27) -> Result<Response, ContractError> {
28    set_contract_version(deps.storage, EVM_NOTE_ID, CONTRACT_VERSION)?;
29
30    if msg.block_max_gas.u64() <= ERR_GAS_NEEDED {
31        return Err(ContractError::GasLimitsMismatch);
32    }
33
34    BLOCK_MAX_GAS.save(deps.storage, &msg.block_max_gas.u64())?;
35
36    let mut response = Response::default()
37        .add_attribute("method", "instantiate")
38        .add_attribute("block_max_gas", msg.block_max_gas);
39
40    if let Some(Pair {
41        connection_id,
42        remote_port,
43    }) = msg.pair
44    {
45        response = response
46            .add_attribute("pair_connection", connection_id.to_string())
47            .add_attribute("pair_port", remote_port.to_string());
48        CONNECTION_REMOTE_PORT.save(deps.storage, &(connection_id, remote_port))?;
49    };
50
51    Ok(response)
52}
53
54#[cfg_attr(not(feature = "library"), entry_point)]
55pub fn execute(
56    deps: DepsMut,
57    env: Env,
58    info: MessageInfo,
59    msg: ExecuteMsg,
60) -> Result<Response, ContractError> {
61    let (msg, callback, timeout_seconds, request_type) = match msg {
62        ExecuteMsg::Execute {
63            msgs,
64            callback,
65            timeout_seconds,
66        } => (
67            ibc::Msg::Execute { msgs },
68            callback,
69            timeout_seconds,
70            CallbackRequestType::Execute,
71        ),
72        // ExecuteMsg::Query {
73        //     msgs,
74        //     callback,
75        //     timeout_seconds,
76        // } => (
77        //     ibc::Msg::Query { msgs },
78        //     Some(callback),
79        //     timeout_seconds,
80        //     CallbackRequestType::Query,
81        // ),
82    };
83
84    let channel_id = CHANNEL
85        .may_load(deps.storage)?
86        .ok_or(ContractError::NoPair)?;
87
88    let sequence_number = increment_sequence_number(deps.storage, channel_id.clone())?;
89
90    callbacks::request_callback(
91        deps.storage,
92        deps.api,
93        channel_id.clone(),
94        sequence_number,
95        info.sender.clone(),
96        callback,
97        request_type,
98    )?;
99
100    accounts::on_send_packet(
101        deps.storage,
102        channel_id.clone(),
103        sequence_number,
104        &info.sender,
105    )?;
106
107    Ok(Response::default()
108        .add_attribute("method", "execute")
109        .add_message(IbcMsg::SendPacket {
110            channel_id,
111            data: Packet {
112                sender: info.sender.to_string(),
113                msg,
114            }
115            .encode()
116            .unwrap()
117            .into(),
118            timeout: IbcTimeout::with_timestamp(env.block.time.plus_seconds(timeout_seconds.u64())),
119        }))
120}
121
122#[cfg_attr(not(feature = "library"), entry_point)]
123pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> StdResult<Binary> {
124    match msg {
125        QueryMsg::ActiveChannel => to_json_binary(&CHANNEL.may_load(deps.storage)?),
126        QueryMsg::Pair => to_json_binary(&CONNECTION_REMOTE_PORT.may_load(deps.storage)?.map(
127            |(connection_id, remote_port)| Pair {
128                connection_id,
129                remote_port,
130            },
131        )),
132        QueryMsg::RemoteAddress { local_address } => to_json_binary(&accounts::query_account(
133            deps.storage,
134            deps.api.addr_validate(&local_address)?,
135        )?),
136        QueryMsg::BlockMaxGas => to_json_binary(&BLOCK_MAX_GAS.load(deps.storage)?),
137        QueryMsg::AckInfos { start_after, limit } => {
138            let limit = limit.unwrap_or(10).min(25) as usize;
139            let start_bound = start_after.map(Bound::exclusive);
140
141            let res: Result<Vec<(u64, crate::ibc::temp_test::AckInfo)>, _> =
142                crate::ibc::temp_test::ACK_DATAS
143                    .range(deps.storage, start_bound, None, Order::Ascending)
144                    .take(limit)
145                    .collect();
146
147            to_json_binary(&AckInfosResponse { acks: res? })
148        }
149    }
150}
151
152#[cfg_attr(not(feature = "library"), entry_point)]
153pub fn migrate(deps: DepsMut, _env: Env, msg: MigrateMsg) -> Result<Response, ContractError> {
154    cw2::set_contract_version(deps.storage, EVM_NOTE_ID, CONTRACT_VERSION)?;
155
156    match msg {
157        MigrateMsg::WithUpdate { block_max_gas } => {
158            if block_max_gas.u64() <= ERR_GAS_NEEDED {
159                return Err(ContractError::GasLimitsMismatch);
160            }
161
162            BLOCK_MAX_GAS.save(deps.storage, &block_max_gas.u64())?;
163            Ok(Response::default()
164                .add_attribute("method", "migrate_with_update")
165                .add_attribute("block_max_gas", block_max_gas))
166        }
167        MigrateMsg::None => Ok(Response::default().add_attribute("method", "migrate")),
168    }
169}