use std::str::FromStr;
use bytes::Bytes;
use primitive_types::{H160, U256};
use revm::{Env, TransactTo};
use structopt::StructOpt;
#[derive(StructOpt, Clone, Debug)]
pub struct CliEnv {
#[structopt(flatten)]
block: CliEnvBlock,
#[structopt(flatten)]
tx: CliEnvTx,
}
macro_rules! local_fill {
($left:expr, $right:expr, $fun:expr) => {
if let Some(right) = $right {
$left = $fun(right)
}
};
($left:expr, $right:expr) => {
if let Some(right) = $right {
$left = right
}
};
}
impl From<CliEnv> for Env {
fn from(from: CliEnv) -> Self {
let mut env = Env::default();
local_fill!(env.block.gas_limit, from.block.block_gas_limit, U256::from);
local_fill!(env.block.number, from.block.number, U256::from);
local_fill!(env.block.coinbase, from.block.coinbase);
local_fill!(env.block.timestamp, from.block.timestamp, U256::from);
local_fill!(env.block.difficulty, from.block.difficulty, U256::from);
local_fill!(env.block.basefee, from.block.basefee, U256::from);
local_fill!(env.tx.caller, from.tx.caller);
local_fill!(env.tx.gas_limit, from.tx.tx_gas_limit);
local_fill!(env.tx.value, from.tx.value, U256::from);
local_fill!(env.tx.data, from.tx.data);
env.tx.gas_priority_fee = from.tx.gas_priority_fee.map(U256::from);
env.tx.chain_id = from.tx.chain_id;
env.tx.nonce = from.tx.nonce;
env.tx.transact_to = if let Some(to) = from.tx.transact_to {
TransactTo::Call(to)
} else {
TransactTo::create()
};
env
}
}
#[derive(StructOpt, Clone, Debug)]
pub struct CliEnvBlock {
#[structopt(long = "env.block.gas_limit")]
pub block_gas_limit: Option<u64>,
#[structopt(long = "env.block.number")]
pub number: Option<u64>,
#[structopt(long = "env.block.coinbase", parse(try_from_str = parse_h160))]
pub coinbase: Option<H160>,
#[structopt(long = "env.block.timestamp")]
pub timestamp: Option<u64>,
#[structopt(long = "env.block.difficulty")]
pub difficulty: Option<u64>,
#[structopt(long = "env.block.basefee")]
pub basefee: Option<u64>,
}
#[derive(StructOpt, Clone, Debug)]
pub struct CliEnvTx {
#[structopt(long = "env.tx.caller", parse(try_from_str = parse_h160))]
pub caller: Option<H160>,
#[structopt(long = "env.tx.gas_limit")]
pub tx_gas_limit: Option<u64>,
#[structopt(long = "env.tx.gas_price")]
pub gas_price: Option<u64>,
#[structopt(long = "env.tx.gas_priority_fee")]
pub gas_priority_fee: Option<u64>,
#[structopt(long = "env.tx.to", parse(try_from_str = parse_h160))]
pub transact_to: Option<H160>,
#[structopt(long = "env.tx.value")]
pub value: Option<u64>,
#[structopt(long = "env.tx.data", parse(try_from_str = parse_hex))]
pub data: Option<Bytes>,
#[structopt(long = "env.tx.chain_id")]
pub chain_id: Option<u64>,
#[structopt(long = "env.tx.nonce")]
pub nonce: Option<u64>,
}
fn parse_hex(src: &str) -> Result<Bytes, hex::FromHexError> {
Ok(Bytes::from(hex::decode(src)?))
}
pub fn parse_h160(input: &str) -> Result<H160, <H160 as FromStr>::Err> {
H160::from_str(input)
}