use anyhow::Result;
use fvm::executor::{ApplyKind, ApplyRet, Executor};
use fvm_ipld_encoding::tuple::*;
use fvm_ipld_encoding::{BytesSer, RawBytes, strict_bytes};
use fvm_shared::address::Address;
use fvm_shared::message::Message;
use fvm_shared::{ActorID, METHOD_CONSTRUCTOR};
use num_traits::Zero;
use crate::tester::{BasicAccount, BasicTester};
pub const EAM_ADDRESS: Address = Address::new_id(10);
pub const DEFAULT_GAS: u64 = 10_000_000_000;
pub fn create_contract(
tester: &mut BasicTester,
owner: &mut BasicAccount,
contract: &[u8],
) -> Result<ApplyRet> {
let create_msg = Message {
from: owner.account.1,
to: EAM_ADDRESS,
gas_limit: DEFAULT_GAS,
method_num: EAMMethod::CreateExternal as u64,
params: RawBytes::serialize(BytesSer(contract)).unwrap(),
value: Zero::zero(),
sequence: owner.seqno,
..Message::default()
};
let create_mlen = create_msg.params.len();
let create_res = tester
.with_executor(|e| e.execute_message(create_msg, ApplyKind::Explicit, create_mlen))?;
owner.seqno += 1;
Ok(create_res)
}
pub fn invoke_contract(
tester: &mut BasicTester,
src: &mut BasicAccount,
dest: Address,
input_data: &[u8],
gas: u64,
) -> Result<ApplyRet> {
let invoke_msg = Message {
from: src.account.1,
to: dest,
sequence: src.seqno,
gas_limit: gas,
method_num: EVMMethod::InvokeContract as u64,
params: RawBytes::serialize(BytesSer(input_data)).unwrap(),
..Message::default()
};
let invoke_mlen = invoke_msg.params.len();
let invoke_res = tester
.with_executor(|e| e.execute_message(invoke_msg, ApplyKind::Explicit, invoke_mlen))?;
src.seqno += 1;
Ok(invoke_res)
}
#[repr(u64)]
pub enum EAMMethod {
Constructor = METHOD_CONSTRUCTOR,
Create = 2,
Create2 = 3,
CreateExternal = 4,
}
#[repr(u64)]
pub enum EVMMethod {
Constructor = METHOD_CONSTRUCTOR,
Resurrect = 2,
GetBytecode = 3,
GetBytecodeHash = 4,
GetStorageAt = 5,
InvokeContractDelegate = 6,
InvokeContract = 3844450837,
}
#[derive(serde::Deserialize, serde::Serialize, Debug, Clone, Copy, PartialEq, Eq)]
pub struct EthAddress(#[serde(with = "strict_bytes")] pub [u8; 20]);
#[derive(Serialize_tuple, Deserialize_tuple)]
pub struct CreateReturn {
pub actor_id: ActorID,
pub robust_address: Option<Address>,
pub eth_address: EthAddress,
}