1use crate::evm::abi_types::{
2 EvmMsg as IEvmMsg, EvmMsgType as IEvmMsgType, ExecuteResponsePacket as IExecuteResponsePacket,
3 ExecuteResult as IExecuteResult, Msg as IMsg, MsgType as IMsgType, Packet as IPacket,
4};
5use alloy::primitives::Address;
6use alloy_sol_types::SolValue;
7use cosmwasm_schema::cw_serde;
8use cosmwasm_std::HexBinary;
9use msg_data::MsgData as _;
10
11use crate::evm::EvmMsg;
12
13pub const VERSION: &str = "polytone-evm-1";
14
15#[cw_serde]
16pub struct Packet {
17 pub sender: String,
19 pub msg: Msg,
21}
22
23impl Packet {
24 pub fn encode(self) -> Result<Vec<u8>, alloy_sol_types::Error> {
25 Ok(IPacket {
26 sender: self.sender.clone(),
27 msg: self.msg.encode()?,
28 }
29 .abi_encode())
30 }
31 pub fn decode(bytes: impl AsRef<[u8]>) -> Result<Self, alloy_sol_types::Error> {
32 let packet = IPacket::abi_decode(bytes.as_ref(), true)?;
33 Ok(Packet {
34 sender: packet.sender,
35 msg: Msg::decode(&packet.msg)?,
36 })
37 }
38}
39
40#[cw_serde]
41pub enum Msg {
43 Execute { msgs: Vec<EvmMsg<String>> },
45}
46
47#[cw_serde]
48pub struct ExecuteResponsePacket {
49 pub executed_by: String,
50 pub result: Vec<ExecuteResult>,
51}
52
53impl ExecuteResponsePacket {
54 pub fn decode_bytes(bz: impl AsRef<[u8]>) -> Result<Self, alloy_sol_types::Error> {
55 let packet = IExecuteResponsePacket::abi_decode(bz.as_ref(), true)?;
56 Ok(ExecuteResponsePacket {
57 executed_by: packet.executedBy.to_checksum(None),
58 result: packet
59 .result
60 .into_iter()
61 .map(|res| ExecuteResult {
62 success: res.success,
63 data: HexBinary::from(res.data.to_vec()),
64 })
65 .collect(),
66 })
67 }
68}
69
70#[cw_serde]
71pub struct ExecuteResult {
72 pub success: bool,
73 pub data: HexBinary,
74}
75
76pub mod msg_data {
77 use alloy::primitives::Bytes;
78 use cosmwasm_std::HexBinary;
79
80 use crate::evm::abi_types::CallMessage;
81
82 use super::*;
83
84 pub trait MsgData: Sized {
86 type EvmType: SolValue;
87
88 fn encode(self) -> Result<Self::EvmType, alloy_sol_types::Error> {
89 unimplemented!("Type does not support encoding");
90 }
91 #[allow(unused_variables)]
92 fn decode(evm_type: &Self::EvmType) -> Result<Self, alloy_sol_types::Error> {
93 unimplemented!("Type does not support decoding");
94 }
95 }
96
97 impl MsgData for EvmMsg<Address> {
98 type EvmType = IEvmMsg;
99
100 fn encode(self) -> Result<Self::EvmType, alloy_sol_types::Error> {
101 match &self {
102 EvmMsg::Call { .. } => Ok(IEvmMsg {
103 msgType: IEvmMsgType::Call,
104 message: self.encode().into(),
105 }),
106 EvmMsg::DelegateCall { .. } => Ok(IEvmMsg {
107 msgType: IEvmMsgType::DelegateCall,
108 message: self.encode().into(),
109 }),
110 }
111 }
112 }
113
114 impl MsgData for EvmMsg<String> {
115 type EvmType = IEvmMsg;
116
117 fn decode(evm_msg: &IEvmMsg) -> Result<Self, alloy_sol_types::Error> {
118 match evm_msg.msgType {
119 IEvmMsgType::Call => {
120 let call_msg = CallMessage::abi_decode(evm_msg.message.as_ref(), true)?;
121 Ok(EvmMsg::Call {
122 to: call_msg.to.to_string(),
123 data: HexBinary::from(call_msg.data.to_vec()),
124 allow_failure: Some(call_msg.allowFailure),
125 value: Some(call_msg.value.to::<u128>().into()),
126 })
127 }
128 IEvmMsgType::DelegateCall => {
129 let call_msg = CallMessage::abi_decode(evm_msg.message.as_ref(), true)?;
130 Ok(EvmMsg::DelegateCall {
131 to: call_msg.to.to_string(),
132 data: HexBinary::from(call_msg.data.to_vec()),
133 allow_failure: Some(call_msg.allowFailure),
134 value: Some(call_msg.value.to::<u128>().into()),
135 })
136 }
137 IEvmMsgType::__Invalid => panic!(),
138 }
139 }
140 }
141
142 impl MsgData for Msg {
143 type EvmType = IMsg;
144
145 fn encode(self) -> Result<Self::EvmType, alloy_sol_types::Error> {
146 match self {
147 Msg::Execute { msgs } => Ok(IMsg {
148 msgType: IMsgType::Execute,
149 data: msgs
150 .into_iter()
151 .map(|m| m.check().unwrap().encode().into())
152 .collect::<Vec<Bytes>>(),
153 }),
154 }
155 }
156
157 fn decode(msg: &IMsg) -> Result<Self, alloy_sol_types::Error> {
158 match msg.msgType {
159 IMsgType::Execute => {
160 let mut msgs = Vec::with_capacity(msg.data.len());
161 for data in &msg.data {
162 let evm_msg = IEvmMsg::abi_decode(data, true)?;
163 msgs.push(EvmMsg::decode(&evm_msg)?);
164 }
165 Ok(Msg::Execute { msgs })
166 }
167 IMsgType::__Invalid => panic!(),
168 }
169 }
170 }
171
172 impl MsgData for ExecuteResponsePacket {
173 type EvmType = IExecuteResponsePacket;
174 fn decode(evm_type: &Self::EvmType) -> Result<Self, alloy_sol_types::Error> {
175 let mut results = Vec::with_capacity(evm_type.result.len());
176 for res in &evm_type.result {
177 results.push(ExecuteResult::decode(res)?);
178 }
179 Ok(ExecuteResponsePacket {
180 executed_by: evm_type.executedBy.to_string(),
181 result: results,
182 })
183 }
184 }
185
186 impl MsgData for ExecuteResult {
187 type EvmType = IExecuteResult;
188 fn decode(evm_type: &Self::EvmType) -> Result<Self, alloy_sol_types::Error> {
189 Ok(ExecuteResult {
190 success: evm_type.success,
191 data: HexBinary::from(evm_type.data.to_vec()),
192 })
193 }
194 }
195}