mirror of
https://github.com/hl-archive-node/nanoreth.git
synced 2025-12-06 10:59:55 +00:00
Integrate Request evm env filling in ethapi (#9358)
Co-authored-by: Emilia Hane <elsaemiliaevahane@gmail.com>
This commit is contained in:
@ -6,7 +6,7 @@ use reth_evm::{ConfigureEvm, ConfigureEvmEnv};
|
||||
use reth_primitives::{
|
||||
revm_primitives::{
|
||||
BlockEnv, CfgEnvWithHandlerCfg, EnvWithHandlerCfg, ExecutionResult, HaltReason,
|
||||
ResultAndState, TransactTo,
|
||||
ResultAndState, TransactTo, TxEnv,
|
||||
},
|
||||
Bytes, TransactionSignedEcRecovered, TxKind, B256, U256,
|
||||
};
|
||||
@ -16,8 +16,8 @@ use reth_rpc_eth_types::{
|
||||
cache::db::{StateCacheDbRefMutWrapper, StateProviderTraitObjWrapper},
|
||||
error::ensure_success,
|
||||
revm_utils::{
|
||||
apply_state_overrides, build_call_evm_env, caller_gas_allowance,
|
||||
cap_tx_gas_limit_with_caller_allowance, get_precompiles, prepare_call_env,
|
||||
apply_block_overrides, apply_state_overrides, caller_gas_allowance,
|
||||
cap_tx_gas_limit_with_caller_allowance, get_precompiles, CallFees,
|
||||
},
|
||||
EthApiError, EthResult, RevertError, RpcInvalidTransactionError, StateCacheDb,
|
||||
};
|
||||
@ -29,6 +29,8 @@ use reth_rpc_types::{
|
||||
};
|
||||
use revm::{Database, DatabaseCommit};
|
||||
use revm_inspectors::access_list::AccessListInspector;
|
||||
#[cfg(feature = "optimism")]
|
||||
use revm_primitives::OptimismFields;
|
||||
use tracing::trace;
|
||||
|
||||
use super::{LoadBlock, LoadPendingBlock, LoadState, LoadTransaction, SpawnBlocking, Trace};
|
||||
@ -136,7 +138,7 @@ pub trait EthCall: Call + LoadPendingBlock {
|
||||
let state_overrides = state_override.take();
|
||||
let overrides = EvmOverrides::new(state_overrides, block_overrides.clone());
|
||||
|
||||
let env = prepare_call_env(
|
||||
let env = this.prepare_call_env(
|
||||
cfg.clone(),
|
||||
block_env.clone(),
|
||||
tx,
|
||||
@ -206,7 +208,7 @@ pub trait EthCall: Call + LoadPendingBlock {
|
||||
{
|
||||
let state = self.state_at_block_id(at)?;
|
||||
|
||||
let mut env = build_call_evm_env(cfg, block, request.clone())?;
|
||||
let mut env = self.build_call_evm_env(cfg, block, request.clone())?;
|
||||
|
||||
// we want to disable this in eth_createAccessList, since this is common practice used by
|
||||
// other node impls and providers <https://github.com/foundry-rs/foundry/issues/4388>
|
||||
@ -359,7 +361,7 @@ pub trait Call: LoadState + SpawnBlocking {
|
||||
let mut db =
|
||||
CacheDB::new(StateProviderDatabase::new(StateProviderTraitObjWrapper(&state)));
|
||||
|
||||
let env = prepare_call_env(
|
||||
let env = this.prepare_call_env(
|
||||
cfg,
|
||||
block_env,
|
||||
request,
|
||||
@ -530,7 +532,7 @@ pub trait Call: LoadState + SpawnBlocking {
|
||||
.unwrap_or(block_env_gas_limit);
|
||||
|
||||
// Configure the evm env
|
||||
let mut env = build_call_evm_env(cfg, block, request)?;
|
||||
let mut env = self.build_call_evm_env(cfg, block, request)?;
|
||||
let mut db = CacheDB::new(StateProviderDatabase::new(state));
|
||||
|
||||
// Apply any state overrides if specified.
|
||||
@ -776,4 +778,161 @@ pub trait Call: LoadState + SpawnBlocking {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Configures a new [`TxEnv`] for the [`TransactionRequest`]
|
||||
///
|
||||
/// All [`TxEnv`] fields are derived from the given [`TransactionRequest`], if fields are
|
||||
/// `None`, they fall back to the [`BlockEnv`]'s settings.
|
||||
fn create_txn_env(
|
||||
&self,
|
||||
block_env: &BlockEnv,
|
||||
request: TransactionRequest,
|
||||
) -> EthResult<TxEnv> {
|
||||
// Ensure that if versioned hashes are set, they're not empty
|
||||
if request.blob_versioned_hashes.as_ref().map_or(false, |hashes| hashes.is_empty()) {
|
||||
return Err(RpcInvalidTransactionError::BlobTransactionMissingBlobHashes.into())
|
||||
}
|
||||
|
||||
let TransactionRequest {
|
||||
from,
|
||||
to,
|
||||
gas_price,
|
||||
max_fee_per_gas,
|
||||
max_priority_fee_per_gas,
|
||||
gas,
|
||||
value,
|
||||
input,
|
||||
nonce,
|
||||
access_list,
|
||||
chain_id,
|
||||
blob_versioned_hashes,
|
||||
max_fee_per_blob_gas,
|
||||
..
|
||||
} = request;
|
||||
|
||||
let CallFees { max_priority_fee_per_gas, gas_price, max_fee_per_blob_gas } =
|
||||
CallFees::ensure_fees(
|
||||
gas_price.map(U256::from),
|
||||
max_fee_per_gas.map(U256::from),
|
||||
max_priority_fee_per_gas.map(U256::from),
|
||||
block_env.basefee,
|
||||
blob_versioned_hashes.as_deref(),
|
||||
max_fee_per_blob_gas.map(U256::from),
|
||||
block_env.get_blob_gasprice().map(U256::from),
|
||||
)?;
|
||||
|
||||
let gas_limit = gas.unwrap_or_else(|| block_env.gas_limit.min(U256::from(u64::MAX)).to());
|
||||
let env = TxEnv {
|
||||
gas_limit: gas_limit
|
||||
.try_into()
|
||||
.map_err(|_| RpcInvalidTransactionError::GasUintOverflow)?,
|
||||
nonce,
|
||||
caller: from.unwrap_or_default(),
|
||||
gas_price,
|
||||
gas_priority_fee: max_priority_fee_per_gas,
|
||||
transact_to: to.unwrap_or(TxKind::Create),
|
||||
value: value.unwrap_or_default(),
|
||||
data: input.try_into_unique_input()?.unwrap_or_default(),
|
||||
chain_id,
|
||||
access_list: access_list.unwrap_or_default().into(),
|
||||
// EIP-4844 fields
|
||||
blob_hashes: blob_versioned_hashes.unwrap_or_default(),
|
||||
max_fee_per_blob_gas,
|
||||
authorization_list: None,
|
||||
#[cfg(feature = "optimism")]
|
||||
optimism: OptimismFields { enveloped_tx: Some(Bytes::new()), ..Default::default() },
|
||||
};
|
||||
|
||||
Ok(env)
|
||||
}
|
||||
|
||||
/// Creates a new [`EnvWithHandlerCfg`] to be used for executing the [`TransactionRequest`] in
|
||||
/// `eth_call`.
|
||||
///
|
||||
/// Note: this does _not_ access the Database to check the sender.
|
||||
fn build_call_evm_env(
|
||||
&self,
|
||||
cfg: CfgEnvWithHandlerCfg,
|
||||
block: BlockEnv,
|
||||
request: TransactionRequest,
|
||||
) -> EthResult<EnvWithHandlerCfg> {
|
||||
let tx = self.create_txn_env(&block, request)?;
|
||||
Ok(EnvWithHandlerCfg::new_with_cfg_env(cfg, block, tx))
|
||||
}
|
||||
|
||||
/// Prepares the [`EnvWithHandlerCfg`] for execution.
|
||||
///
|
||||
/// Does not commit any changes to the underlying database.
|
||||
///
|
||||
/// EVM settings:
|
||||
/// - `disable_block_gas_limit` is set to `true`
|
||||
/// - `disable_eip3607` is set to `true`
|
||||
/// - `disable_base_fee` is set to `true`
|
||||
/// - `nonce` is set to `None`
|
||||
fn prepare_call_env<DB>(
|
||||
&self,
|
||||
mut cfg: CfgEnvWithHandlerCfg,
|
||||
mut block: BlockEnv,
|
||||
request: TransactionRequest,
|
||||
gas_limit: u64,
|
||||
db: &mut CacheDB<DB>,
|
||||
overrides: EvmOverrides,
|
||||
) -> EthResult<EnvWithHandlerCfg>
|
||||
where
|
||||
DB: DatabaseRef,
|
||||
EthApiError: From<<DB as DatabaseRef>::Error>,
|
||||
{
|
||||
// we want to disable this in eth_call, since this is common practice used by other node
|
||||
// impls and providers <https://github.com/foundry-rs/foundry/issues/4388>
|
||||
cfg.disable_block_gas_limit = true;
|
||||
|
||||
// Disabled because eth_call is sometimes used with eoa senders
|
||||
// See <https://github.com/paradigmxyz/reth/issues/1959>
|
||||
cfg.disable_eip3607 = true;
|
||||
|
||||
// The basefee should be ignored for eth_call
|
||||
// See:
|
||||
// <https://github.com/ethereum/go-ethereum/blob/ee8e83fa5f6cb261dad2ed0a7bbcde4930c41e6c/internal/ethapi/api.go#L985>
|
||||
cfg.disable_base_fee = true;
|
||||
|
||||
// apply block overrides, we need to apply them first so that they take effect when we we
|
||||
// create the evm env via `build_call_evm_env`, e.g. basefee
|
||||
if let Some(mut block_overrides) = overrides.block {
|
||||
if let Some(block_hashes) = block_overrides.block_hash.take() {
|
||||
// override block hashes
|
||||
db.block_hashes
|
||||
.extend(block_hashes.into_iter().map(|(num, hash)| (U256::from(num), hash)))
|
||||
}
|
||||
apply_block_overrides(*block_overrides, &mut block);
|
||||
}
|
||||
|
||||
let request_gas = request.gas;
|
||||
let mut env = self.build_call_evm_env(cfg, block, request)?;
|
||||
// set nonce to None so that the next nonce is used when transacting the call
|
||||
env.tx.nonce = None;
|
||||
|
||||
// apply state overrides
|
||||
if let Some(state_overrides) = overrides.state {
|
||||
apply_state_overrides(state_overrides, db)?;
|
||||
}
|
||||
|
||||
if request_gas.is_none() {
|
||||
// No gas limit was provided in the request, so we need to cap the transaction gas limit
|
||||
if env.tx.gas_price > U256::ZERO {
|
||||
// If gas price is specified, cap transaction gas limit with caller allowance
|
||||
trace!(target: "rpc::eth::call", ?env, "Applying gas limit cap with caller allowance");
|
||||
cap_tx_gas_limit_with_caller_allowance(db, &mut env.tx)?;
|
||||
} else {
|
||||
// If no gas price is specified, use maximum allowed gas limit. The reason for this
|
||||
// is that both Erigon and Geth use pre-configured gas cap even if
|
||||
// it's possible to derive the gas limit from the block:
|
||||
// <https://github.com/ledgerwatch/erigon/blob/eae2d9a79cb70dbe30b3a6b79c436872e4605458/cmd/rpcdaemon/commands/trace_adhoc.go#L956
|
||||
// https://github.com/ledgerwatch/erigon/blob/eae2d9a79cb70dbe30b3a6b79c436872e4605458/eth/ethconfig/config.go#L94>
|
||||
trace!(target: "rpc::eth::call", ?env, "Applying gas limit cap as the maximum gas limit");
|
||||
env.tx.gas_limit = gas_limit;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(env)
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,23 +1,18 @@
|
||||
//! utilities for working with revm
|
||||
|
||||
use std::cmp::min;
|
||||
|
||||
use reth_primitives::{Address, TxKind, B256, U256};
|
||||
use reth_primitives::{Address, B256, U256};
|
||||
use reth_rpc_types::{
|
||||
state::{AccountOverride, EvmOverrides, StateOverride},
|
||||
BlockOverrides, TransactionRequest,
|
||||
state::{AccountOverride, StateOverride},
|
||||
BlockOverrides,
|
||||
};
|
||||
#[cfg(feature = "optimism")]
|
||||
use revm::primitives::{Bytes, OptimismFields};
|
||||
use revm::{
|
||||
db::CacheDB,
|
||||
precompile::{PrecompileSpecId, Precompiles},
|
||||
primitives::{
|
||||
db::DatabaseRef, BlockEnv, Bytecode, CfgEnvWithHandlerCfg, EnvWithHandlerCfg, SpecId, TxEnv,
|
||||
},
|
||||
primitives::{db::DatabaseRef, Bytecode, SpecId, TxEnv},
|
||||
Database,
|
||||
};
|
||||
use tracing::trace;
|
||||
use revm_primitives::BlockEnv;
|
||||
use std::cmp::min;
|
||||
|
||||
use super::{EthApiError, EthResult, RpcInvalidTransactionError};
|
||||
|
||||
@ -28,155 +23,6 @@ pub fn get_precompiles(spec_id: SpecId) -> impl IntoIterator<Item = Address> {
|
||||
Precompiles::new(spec).addresses().copied().map(Address::from)
|
||||
}
|
||||
|
||||
/// Prepares the [`EnvWithHandlerCfg`] for execution.
|
||||
///
|
||||
/// Does not commit any changes to the underlying database.
|
||||
///
|
||||
/// EVM settings:
|
||||
/// - `disable_block_gas_limit` is set to `true`
|
||||
/// - `disable_eip3607` is set to `true`
|
||||
/// - `disable_base_fee` is set to `true`
|
||||
/// - `nonce` is set to `None`
|
||||
pub fn prepare_call_env<DB>(
|
||||
mut cfg: CfgEnvWithHandlerCfg,
|
||||
mut block: BlockEnv,
|
||||
request: TransactionRequest,
|
||||
gas_limit: u64,
|
||||
db: &mut CacheDB<DB>,
|
||||
overrides: EvmOverrides,
|
||||
) -> EthResult<EnvWithHandlerCfg>
|
||||
where
|
||||
DB: DatabaseRef,
|
||||
EthApiError: From<<DB as DatabaseRef>::Error>,
|
||||
{
|
||||
// we want to disable this in eth_call, since this is common practice used by other node
|
||||
// impls and providers <https://github.com/foundry-rs/foundry/issues/4388>
|
||||
cfg.disable_block_gas_limit = true;
|
||||
|
||||
// Disabled because eth_call is sometimes used with eoa senders
|
||||
// See <https://github.com/paradigmxyz/reth/issues/1959>
|
||||
cfg.disable_eip3607 = true;
|
||||
|
||||
// The basefee should be ignored for eth_call
|
||||
// See:
|
||||
// <https://github.com/ethereum/go-ethereum/blob/ee8e83fa5f6cb261dad2ed0a7bbcde4930c41e6c/internal/ethapi/api.go#L985>
|
||||
cfg.disable_base_fee = true;
|
||||
|
||||
// apply block overrides, we need to apply them first so that they take effect when we we create
|
||||
// the evm env via `build_call_evm_env`, e.g. basefee
|
||||
if let Some(mut block_overrides) = overrides.block {
|
||||
if let Some(block_hashes) = block_overrides.block_hash.take() {
|
||||
// override block hashes
|
||||
db.block_hashes
|
||||
.extend(block_hashes.into_iter().map(|(num, hash)| (U256::from(num), hash)))
|
||||
}
|
||||
apply_block_overrides(*block_overrides, &mut block);
|
||||
}
|
||||
|
||||
let request_gas = request.gas;
|
||||
let mut env = build_call_evm_env(cfg, block, request)?;
|
||||
// set nonce to None so that the next nonce is used when transacting the call
|
||||
env.tx.nonce = None;
|
||||
|
||||
// apply state overrides
|
||||
if let Some(state_overrides) = overrides.state {
|
||||
apply_state_overrides(state_overrides, db)?;
|
||||
}
|
||||
|
||||
if request_gas.is_none() {
|
||||
// No gas limit was provided in the request, so we need to cap the transaction gas limit
|
||||
if env.tx.gas_price > U256::ZERO {
|
||||
// If gas price is specified, cap transaction gas limit with caller allowance
|
||||
trace!(target: "rpc::eth::call", ?env, "Applying gas limit cap with caller allowance");
|
||||
cap_tx_gas_limit_with_caller_allowance(db, &mut env.tx)?;
|
||||
} else {
|
||||
// If no gas price is specified, use maximum allowed gas limit. The reason for this is
|
||||
// that both Erigon and Geth use pre-configured gas cap even if it's possible
|
||||
// to derive the gas limit from the block:
|
||||
// <https://github.com/ledgerwatch/erigon/blob/eae2d9a79cb70dbe30b3a6b79c436872e4605458/cmd/rpcdaemon/commands/trace_adhoc.go#L956
|
||||
// https://github.com/ledgerwatch/erigon/blob/eae2d9a79cb70dbe30b3a6b79c436872e4605458/eth/ethconfig/config.go#L94>
|
||||
trace!(target: "rpc::eth::call", ?env, "Applying gas limit cap as the maximum gas limit");
|
||||
env.tx.gas_limit = gas_limit;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(env)
|
||||
}
|
||||
|
||||
/// Creates a new [`EnvWithHandlerCfg`] to be used for executing the [`TransactionRequest`] in
|
||||
/// `eth_call`.
|
||||
///
|
||||
/// Note: this does _not_ access the Database to check the sender.
|
||||
pub fn build_call_evm_env(
|
||||
cfg: CfgEnvWithHandlerCfg,
|
||||
block: BlockEnv,
|
||||
request: TransactionRequest,
|
||||
) -> EthResult<EnvWithHandlerCfg> {
|
||||
let tx = create_txn_env(&block, request)?;
|
||||
Ok(EnvWithHandlerCfg::new_with_cfg_env(cfg, block, tx))
|
||||
}
|
||||
|
||||
/// Configures a new [`TxEnv`] for the [`TransactionRequest`]
|
||||
///
|
||||
/// All [`TxEnv`] fields are derived from the given [`TransactionRequest`], if fields are `None`,
|
||||
/// they fall back to the [`BlockEnv`]'s settings.
|
||||
pub fn create_txn_env(block_env: &BlockEnv, request: TransactionRequest) -> EthResult<TxEnv> {
|
||||
// Ensure that if versioned hashes are set, they're not empty
|
||||
if request.blob_versioned_hashes.as_ref().map_or(false, |hashes| hashes.is_empty()) {
|
||||
return Err(RpcInvalidTransactionError::BlobTransactionMissingBlobHashes.into())
|
||||
}
|
||||
|
||||
let TransactionRequest {
|
||||
from,
|
||||
to,
|
||||
gas_price,
|
||||
max_fee_per_gas,
|
||||
max_priority_fee_per_gas,
|
||||
gas,
|
||||
value,
|
||||
input,
|
||||
nonce,
|
||||
access_list,
|
||||
chain_id,
|
||||
blob_versioned_hashes,
|
||||
max_fee_per_blob_gas,
|
||||
..
|
||||
} = request;
|
||||
|
||||
let CallFees { max_priority_fee_per_gas, gas_price, max_fee_per_blob_gas } =
|
||||
CallFees::ensure_fees(
|
||||
gas_price.map(U256::from),
|
||||
max_fee_per_gas.map(U256::from),
|
||||
max_priority_fee_per_gas.map(U256::from),
|
||||
block_env.basefee,
|
||||
blob_versioned_hashes.as_deref(),
|
||||
max_fee_per_blob_gas.map(U256::from),
|
||||
block_env.get_blob_gasprice().map(U256::from),
|
||||
)?;
|
||||
|
||||
let gas_limit = gas.unwrap_or_else(|| block_env.gas_limit.min(U256::from(u64::MAX)).to());
|
||||
let env = TxEnv {
|
||||
gas_limit: gas_limit.try_into().map_err(|_| RpcInvalidTransactionError::GasUintOverflow)?,
|
||||
nonce,
|
||||
caller: from.unwrap_or_default(),
|
||||
gas_price,
|
||||
gas_priority_fee: max_priority_fee_per_gas,
|
||||
transact_to: to.unwrap_or(TxKind::Create),
|
||||
value: value.unwrap_or_default(),
|
||||
data: input.try_into_unique_input()?.unwrap_or_default(),
|
||||
chain_id,
|
||||
access_list: access_list.unwrap_or_default().into(),
|
||||
// EIP-4844 fields
|
||||
blob_hashes: blob_versioned_hashes.unwrap_or_default(),
|
||||
max_fee_per_blob_gas,
|
||||
authorization_list: None,
|
||||
#[cfg(feature = "optimism")]
|
||||
optimism: OptimismFields { enveloped_tx: Some(Bytes::new()), ..Default::default() },
|
||||
};
|
||||
|
||||
Ok(env)
|
||||
}
|
||||
|
||||
/// Caps the configured [`TxEnv`] `gas_limit` with the allowance of the caller.
|
||||
pub fn cap_tx_gas_limit_with_caller_allowance<DB>(db: &mut DB, env: &mut TxEnv) -> EthResult<()>
|
||||
where
|
||||
@ -217,26 +63,26 @@ where
|
||||
.unwrap_or_default())
|
||||
}
|
||||
|
||||
/// Helper type for representing the fees of a [`TransactionRequest`]
|
||||
/// Helper type for representing the fees of a [`reth_rpc_types::TransactionRequest`]
|
||||
#[derive(Debug)]
|
||||
pub struct CallFees {
|
||||
/// EIP-1559 priority fee
|
||||
max_priority_fee_per_gas: Option<U256>,
|
||||
pub max_priority_fee_per_gas: Option<U256>,
|
||||
/// Unified gas price setting
|
||||
///
|
||||
/// Will be the configured `basefee` if unset in the request
|
||||
///
|
||||
/// `gasPrice` for legacy,
|
||||
/// `maxFeePerGas` for EIP-1559
|
||||
gas_price: U256,
|
||||
pub gas_price: U256,
|
||||
/// Max Fee per Blob gas for EIP-4844 transactions
|
||||
max_fee_per_blob_gas: Option<U256>,
|
||||
pub max_fee_per_blob_gas: Option<U256>,
|
||||
}
|
||||
|
||||
// === impl CallFees ===
|
||||
|
||||
impl CallFees {
|
||||
/// Ensures the fields of a [`TransactionRequest`] are not conflicting.
|
||||
/// Ensures the fields of a [`reth_rpc_types::TransactionRequest`] are not conflicting.
|
||||
///
|
||||
/// # EIP-4844 transactions
|
||||
///
|
||||
@ -246,7 +92,7 @@ impl CallFees {
|
||||
///
|
||||
/// Note: Due to the `Default` impl of [`BlockEnv`] (Some(0)) this assumes the `block_blob_fee`
|
||||
/// is always `Some`
|
||||
fn ensure_fees(
|
||||
pub fn ensure_fees(
|
||||
call_gas_price: Option<U256>,
|
||||
call_max_fee: Option<U256>,
|
||||
call_priority_fee: Option<U256>,
|
||||
@ -346,7 +192,7 @@ impl CallFees {
|
||||
}
|
||||
|
||||
/// Applies the given block overrides to the env
|
||||
fn apply_block_overrides(overrides: BlockOverrides, env: &mut BlockEnv) {
|
||||
pub fn apply_block_overrides(overrides: BlockOverrides, env: &mut BlockEnv) {
|
||||
let BlockOverrides {
|
||||
number,
|
||||
difficulty,
|
||||
|
||||
@ -15,7 +15,7 @@ use reth_provider::{
|
||||
use reth_revm::database::StateProviderDatabase;
|
||||
use reth_rpc_api::DebugApiServer;
|
||||
use reth_rpc_eth_api::helpers::{Call, EthApiSpec, EthTransactions, TraceExt};
|
||||
use reth_rpc_eth_types::{revm_utils::prepare_call_env, EthApiError, EthResult, StateCacheDb};
|
||||
use reth_rpc_eth_types::{EthApiError, EthResult, StateCacheDb};
|
||||
use reth_rpc_server_types::{result::internal_rpc_err, ToRpcResult};
|
||||
use reth_rpc_types::{
|
||||
state::EvmOverrides,
|
||||
@ -503,7 +503,7 @@ where
|
||||
let state_overrides = state_overrides.take();
|
||||
let overrides = EvmOverrides::new(state_overrides, block_overrides.clone());
|
||||
|
||||
let env = prepare_call_env(
|
||||
let env = this.eth_api().prepare_call_env(
|
||||
cfg.clone(),
|
||||
block_env.clone(),
|
||||
tx,
|
||||
|
||||
@ -14,7 +14,6 @@ use reth_rpc_api::TraceApiServer;
|
||||
use reth_rpc_eth_api::helpers::{Call, TraceExt};
|
||||
use reth_rpc_eth_types::{
|
||||
error::{EthApiError, EthResult},
|
||||
revm_utils::prepare_call_env,
|
||||
utils::recover_raw_transaction,
|
||||
};
|
||||
use reth_rpc_types::{
|
||||
@ -158,7 +157,7 @@ where
|
||||
let mut calls = calls.into_iter().peekable();
|
||||
|
||||
while let Some((call, trace_types)) = calls.next() {
|
||||
let env = prepare_call_env(
|
||||
let env = this.eth_api().prepare_call_env(
|
||||
cfg.clone(),
|
||||
block_env.clone(),
|
||||
call,
|
||||
|
||||
Reference in New Issue
Block a user