use crate::erc20::Erc20Token;
use alloy::primitives::{Address, AddressError};
use alloy_sol_types::SolValue;
use cosmwasm_schema::cw_serde;
use cosmwasm_std::HexBinary;
pub trait EvmAddressLike {}
impl EvmAddressLike for String {}
impl EvmAddressLike for HexBinary {}
impl EvmAddressLike for Address {}
#[cw_serde]
pub enum EvmMsg<T: EvmAddressLike> {
Call { to: T, data: HexBinary },
}
impl<T> EvmMsg<T>
where
T: EvmAddressLike,
{
pub fn call(to: T, data: impl Into<HexBinary>) -> Self {
EvmMsg::Call {
to,
data: data.into(),
}
}
}
impl EvmMsg<String> {
pub fn check(self) -> Result<EvmMsg<Address>, AddressError> {
match self {
EvmMsg::Call { to, data } => {
let to: Address = Address::parse_checksummed(to, None)?;
Ok(EvmMsg::Call { to, data })
}
}
}
}
impl EvmMsg<Address> {
pub fn encode(self) -> Vec<u8> {
match self {
EvmMsg::Call { to, data } => {
let data = data.to_vec();
let call = abi_types::CallMessage {
to,
data: data.to_vec().into(),
}
.abi_encode();
abi_types::EvmMsg {
msgType: abi_types::EvmMsgType::Call,
message: call.into(),
}
.abi_encode()
}
}
}
#[allow(dead_code)]
fn unchecked(self) -> EvmMsg<String> {
match self {
EvmMsg::Call { to, data } => EvmMsg::Call {
to: to.to_string(),
data,
},
}
}
}
pub(crate) mod abi_types {
use alloy_sol_types::sol;
sol! {
struct Packet {
string sender;
Msg msg;
}
struct Msg {
MsgType msgType;
bytes[] data;
}
enum MsgType {
Execute
}
struct EvmMsg {
EvmMsgType msgType;
bytes message;
}
enum EvmMsgType {
Call,
}
struct CallMessage {
address to;
bytes data;
}
struct ExecuteResult {
bool success;
bytes data;
}
struct ExecuteResponsePacket {
address executedBy;
ExecuteResult[] result;
}
struct Token {
address denom;
uint128 amount;
}
}
}
impl From<abi_types::Token> for Erc20Token<String> {
fn from(token: abi_types::Token) -> Self {
Erc20Token {
address: token.denom.to_string(),
amount: token.amount.into(),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
mod call_message {
use crate::ibc::{Msg, Packet};
use super::*;
#[test]
fn call_message() {
let msg = abi_types::CallMessage {
to: "0x785B548D3d7064F77A26e479AC7847DBCE0c1B46"
.parse()
.unwrap(),
data: HexBinary::from_hex("b49004e9").unwrap().to_vec().into(),
};
let encoded = msg.abi_encode();
let actual = HexBinary::from(encoded);
let expected = HexBinary::from_hex("0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000785b548d3d7064f77a26e479ac7847dbce0c1b4600000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000004b49004e900000000000000000000000000000000000000000000000000000000").unwrap();
assert_eq!(actual, expected);
}
#[test]
fn evm_msg() {
let msg = EvmMsg::Call {
to: "0x785B548D3d7064F77A26e479AC7847DBCE0c1B46".to_string(),
data: HexBinary::from_hex("b49004e9").unwrap(),
}
.check()
.unwrap();
let encoded = msg.encode();
let actual = HexBinary::from(encoded);
let expected = HexBinary::from_hex("00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000785b548d3d7064f77a26e479ac7847dbce0c1b4600000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000004b49004e900000000000000000000000000000000000000000000000000000000").unwrap();
assert_eq!(actual, expected);
}
const TEST_SENDER: &str =
"union1tw2y3uk7fwcjeh208gdwaqd3utkuzmnp2fyvqve00jg8vtyhuhfqsender";
#[test]
fn packet() {
let evm_msg = EvmMsg::Call {
to: "0x785B548D3d7064F77A26e479AC7847DBCE0c1B46".to_string(),
data: HexBinary::from_hex("b49004e9").unwrap(),
};
let msg = Msg::Execute {
msgs: vec![evm_msg],
};
let request: Packet = Packet {
msg,
sender: TEST_SENDER.to_string(),
};
let encoded = request.encode().unwrap();
let actual = HexBinary::from(encoded);
let expected = HexBinary::from_hex("0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000040756e696f6e317477327933756b376677636a65683230386764776171643375746b757a6d6e703266797671766530306a6738767479687568667173656e6465720000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000785b548d3d7064f77a26e479ac7847dbce0c1b4600000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000004b49004e900000000000000000000000000000000000000000000000000000000").unwrap();
assert_eq!(actual, expected);
}
}
#[test]
fn test_address() {
EvmMsg::call(
"0x785B548D3d7064F77A26e479AC7847DBCE0c1B46".to_string(),
HexBinary::from_hex("b49004e9").unwrap(),
);
}
}