fix: add full block and tx context to call (#10)

This commit is contained in:
Noah Citron 2022-09-02 15:29:51 -04:00 committed by GitHub
parent dbeeffb9f9
commit 95daee7186
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 32 additions and 21 deletions

View File

@ -80,13 +80,13 @@ impl Client {
pub fn call(&self, opts: &CallOpts, block: &Option<u64>) -> Result<Vec<u8>> { pub fn call(&self, opts: &CallOpts, block: &Option<u64>) -> Result<Vec<u8>> {
let payload = self.get_payload(block)?; let payload = self.get_payload(block)?;
let mut evm = Evm::new(self.execution.clone(), payload); let mut evm = Evm::new(self.execution.clone(), payload, self.chain_id());
evm.call(opts) evm.call(opts)
} }
pub fn estimate_gas(&self, opts: &CallOpts) -> Result<u64> { pub fn estimate_gas(&self, opts: &CallOpts) -> Result<u64> {
let payload = self.get_payload(&None)?; let payload = self.get_payload(&None)?;
let mut evm = Evm::new(self.execution.clone(), payload); let mut evm = Evm::new(self.execution.clone(), payload, self.chain_id());
evm.estimate_gas(opts) evm.estimate_gas(opts)
} }

View File

@ -14,26 +14,20 @@ use super::ExecutionClient;
pub struct Evm { pub struct Evm {
evm: EVM<ProofDB>, evm: EVM<ProofDB>,
chain_id: u64,
} }
impl Evm { impl Evm {
pub fn new(execution: ExecutionClient, payload: ExecutionPayload) -> Self { pub fn new(execution: ExecutionClient, payload: ExecutionPayload, chain_id: u64) -> Self {
let mut evm: EVM<ProofDB> = EVM::new(); let mut evm: EVM<ProofDB> = EVM::new();
let db = ProofDB::new(execution, payload); let db = ProofDB::new(execution, payload);
evm.database(db); evm.database(db);
Evm { evm } Evm { evm, chain_id }
} }
pub fn call(&mut self, opts: &CallOpts) -> Result<Vec<u8>> { pub fn call(&mut self, opts: &CallOpts) -> Result<Vec<u8>> {
let mut env = Env::default(); self.evm.env = self.get_env(opts);
env.tx.transact_to = TransactTo::Call(opts.to);
env.tx.caller = opts.from.unwrap_or(Address::zero());
env.tx.value = opts.value.unwrap_or(U256::from(0));
env.tx.data = Bytes::from(opts.data.clone().unwrap_or(vec![]));
self.evm.env = env;
let output = self.evm.transact().1; let output = self.evm.transact().1;
if let Some(err) = &self.evm.db.as_ref().unwrap().error { if let Some(err) = &self.evm.db.as_ref().unwrap().error {
@ -48,21 +42,36 @@ impl Evm {
} }
pub fn estimate_gas(&mut self, opts: &CallOpts) -> Result<u64> { pub fn estimate_gas(&mut self, opts: &CallOpts) -> Result<u64> {
let mut env = Env::default(); self.evm.env = self.get_env(opts);
env.tx.transact_to = TransactTo::Call(opts.to);
env.tx.caller = opts.from.unwrap_or(Address::zero());
env.tx.value = opts.value.unwrap_or(U256::from(0));
env.tx.data = Bytes::from(opts.data.clone().unwrap_or(vec![]));
self.evm.env = env;
let gas = self.evm.transact().2; let gas = self.evm.transact().2;
if let Some(err) = &self.evm.db.as_ref().unwrap().error { if let Some(err) = &self.evm.db.as_ref().unwrap().error {
return Err(eyre::eyre!(err.clone())); return Err(eyre::eyre!(err.clone()));
} }
Ok(gas) let gas_scaled = (1.10 * gas as f64) as u64;
Ok(gas_scaled)
}
fn get_env(&self, opts: &CallOpts) -> Env {
let mut env = Env::default();
let payload = &self.evm.db.as_ref().unwrap().payload;
env.tx.transact_to = TransactTo::Call(opts.to);
env.tx.caller = opts.from.unwrap_or(Address::zero());
env.tx.value = opts.value.unwrap_or(U256::from(0));
env.tx.data = Bytes::from(opts.data.clone().unwrap_or(vec![]));
env.tx.gas_limit = opts.gas.map(|v| v.as_u64()).unwrap_or(u64::MAX);
env.tx.gas_price = opts.gas_price.unwrap_or(U256::zero());
env.block.number = U256::from(payload.block_number);
env.block.coinbase = Address::from_slice(&payload.fee_recipient);
env.block.timestamp = U256::from(payload.timestamp);
env.block.difficulty = U256::from_little_endian(&payload.prev_randao);
env.cfg.chain_id = self.chain_id.into();
env
} }
} }

View File

@ -73,10 +73,12 @@ pub struct ExecutionBlock {
} }
#[derive(Deserialize, Serialize, Debug)] #[derive(Deserialize, Serialize, Debug)]
#[serde(rename_all = "camelCase")]
pub struct CallOpts { pub struct CallOpts {
pub from: Option<Address>, pub from: Option<Address>,
pub to: Address, pub to: Address,
pub gas: Option<U256>, pub gas: Option<U256>,
pub gas_price: Option<U256>,
pub value: Option<U256>, pub value: Option<U256>,
#[serde(default, deserialize_with = "bytes_deserialize")] #[serde(default, deserialize_with = "bytes_deserialize")]
pub data: Option<Vec<u8>>, pub data: Option<Vec<u8>>,