diff --git a/crates/rpc/rpc-convert/src/evm.rs b/crates/rpc/rpc-convert/src/evm.rs new file mode 100644 index 00000000000..27ab38dda29 --- /dev/null +++ b/crates/rpc/rpc-convert/src/evm.rs @@ -0,0 +1,34 @@ +use reth_evm::EvmEnv; +use std::{convert::Infallible, fmt::Debug}; + +/// Performs an [`EvmEnv`] to [`EvmEnv`] conversion accompanied by the `TxReq`. +/// +/// The `TxReq` represents the transaction request this [`EvmEnv`] has been created for. +/// +/// Allows for custom effects on the [`EvmEnv`]. Default implementation `()` passes the input +/// argument with no change. +pub trait EvmEnvConverter: Clone + Debug + Unpin + Send + Sync + 'static { + /// An associated error that can occur during the conversion. + type Err; + + /// Performs the conversion. + /// + /// See [`EvmEnvConverter`] for more details. + fn convert_evm_env( + &self, + request: &TxReq, + evm_env: EvmEnv, + ) -> Result, Self::Err>; +} + +impl EvmEnvConverter for () { + type Err = Infallible; + + fn convert_evm_env( + &self, + _request: &TxReq, + evm_env: EvmEnv, + ) -> Result, Self::Err> { + Ok(evm_env) + } +} diff --git a/crates/rpc/rpc-convert/src/lib.rs b/crates/rpc/rpc-convert/src/lib.rs index 5ea281c4ef8..60f5e7662cf 100644 --- a/crates/rpc/rpc-convert/src/lib.rs +++ b/crates/rpc/rpc-convert/src/lib.rs @@ -11,12 +11,14 @@ #![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))] pub mod block; +mod evm; mod fees; pub mod receipt; mod rpc; pub mod transaction; pub use block::TryFromBlockResponse; +pub use evm::EvmEnvConverter; pub use fees::{CallFees, CallFeesError}; pub use receipt::TryFromReceiptResponse; pub use rpc::*; diff --git a/crates/rpc/rpc-convert/src/transaction.rs b/crates/rpc/rpc-convert/src/transaction.rs index affba2aa0a4..2b063f3d6db 100644 --- a/crates/rpc/rpc-convert/src/transaction.rs +++ b/crates/rpc/rpc-convert/src/transaction.rs @@ -1,6 +1,7 @@ //! Compatibility functions for rpc `Transaction` type. use crate::{ + evm::EvmEnvConverter, fees::{CallFees, CallFeesError}, RpcHeader, RpcReceipt, RpcTransaction, RpcTxReq, RpcTypes, }; @@ -16,7 +17,7 @@ use alloy_rpc_types_eth::{ use core::error; use reth_evm::{ revm::context_interface::{either::Either, Block}, - ConfigureEvm, TxEnvFor, + ConfigureEvm, EvmEnv, TxEnvFor, }; use reth_primitives_traits::{ HeaderTy, NodePrimitives, SealedHeader, SealedHeaderFor, TransactionMeta, TxTy, @@ -144,6 +145,14 @@ pub trait RpcConvert: Send + Sync + Unpin + Clone + Debug + 'static { block_env: &BlockEnv, ) -> Result; + /// Creates an EVM environment for execution based on `request` with corresponding + /// `cfg_env` and `block_env`. + fn evm_env( + &self, + request: &RpcTxReq, + evm_env: EvmEnv, + ) -> Result, Self::Error>; + /// Converts a set of primitive receipts to RPC representations. It is guaranteed that all /// receipts are from the same block. fn convert_receipts( @@ -505,7 +514,16 @@ pub struct TransactionConversionError(String); /// is [`TransactionInfo`] then `()` can be used as `Map` which trivially passes over the input /// object. #[derive(Debug)] -pub struct RpcConverter { +pub struct RpcConverter< + Network, + Evm, + Receipt, + Header = (), + Map = (), + SimTx = (), + RpcTx = (), + EvmEnvC = (), +> { network: PhantomData, evm: PhantomData, receipt_converter: Receipt, @@ -513,6 +531,7 @@ pub struct RpcConverter RpcConverter { @@ -526,15 +545,18 @@ impl RpcConverter { mapper: (), sim_tx_converter: (), rpc_tx_converter: (), + evm_env_converter: (), } } } -impl - RpcConverter +impl + RpcConverter { /// Converts the network type - pub fn with_network(self) -> RpcConverter { + pub fn with_network( + self, + ) -> RpcConverter { let Self { receipt_converter, header_converter, @@ -542,6 +564,7 @@ impl evm, sim_tx_converter, rpc_tx_converter, + evm_env_converter, .. } = self; RpcConverter { @@ -552,6 +575,7 @@ impl evm, sim_tx_converter, rpc_tx_converter, + evm_env_converter, } } @@ -559,7 +583,7 @@ impl pub fn with_header_converter( self, header_converter: HeaderNew, - ) -> RpcConverter { + ) -> RpcConverter { let Self { receipt_converter, header_converter: _, @@ -568,6 +592,7 @@ impl evm, sim_tx_converter, rpc_tx_converter, + evm_env_converter, } = self; RpcConverter { receipt_converter, @@ -577,6 +602,7 @@ impl evm, sim_tx_converter, rpc_tx_converter, + evm_env_converter, } } @@ -584,7 +610,7 @@ impl pub fn with_mapper( self, mapper: MapNew, - ) -> RpcConverter { + ) -> RpcConverter { let Self { receipt_converter, header_converter, @@ -593,6 +619,7 @@ impl evm, sim_tx_converter, rpc_tx_converter, + evm_env_converter, } = self; RpcConverter { receipt_converter, @@ -602,6 +629,7 @@ impl evm, sim_tx_converter, rpc_tx_converter, + evm_env_converter, } } @@ -609,7 +637,7 @@ impl pub fn with_sim_tx_converter( self, sim_tx_converter: SimTxNew, - ) -> RpcConverter { + ) -> RpcConverter { let Self { receipt_converter, header_converter, @@ -617,6 +645,7 @@ impl network, evm, rpc_tx_converter, + evm_env_converter, .. } = self; RpcConverter { @@ -627,6 +656,7 @@ impl evm, sim_tx_converter, rpc_tx_converter, + evm_env_converter, } } @@ -634,7 +664,7 @@ impl pub fn with_rpc_tx_converter( self, rpc_tx_converter: RpcTxNew, - ) -> RpcConverter { + ) -> RpcConverter { let Self { receipt_converter, header_converter, @@ -642,6 +672,7 @@ impl network, evm, sim_tx_converter, + evm_env_converter, .. } = self; RpcConverter { @@ -652,6 +683,34 @@ impl evm, sim_tx_converter, rpc_tx_converter, + evm_env_converter, + } + } + + /// Swaps the EVM environment converter with `evm_env_converter`. + pub fn with_evm_env_converter( + self, + evm_env_converter: EvmEnvNew, + ) -> RpcConverter { + let Self { + receipt_converter, + header_converter, + mapper, + network, + evm, + sim_tx_converter, + rpc_tx_converter, + .. + } = self; + RpcConverter { + receipt_converter, + header_converter, + mapper, + network, + evm, + sim_tx_converter, + rpc_tx_converter, + evm_env_converter, } } } @@ -674,12 +733,21 @@ where mapper: Default::default(), sim_tx_converter: Default::default(), rpc_tx_converter: Default::default(), + evm_env_converter: Default::default(), } } } -impl Clone - for RpcConverter +impl< + Network, + Evm, + Receipt: Clone, + Header: Clone, + Map: Clone, + SimTx: Clone, + RpcTx: Clone, + EvmEnvC: Clone, + > Clone for RpcConverter { fn clone(&self) -> Self { Self { @@ -690,12 +758,13 @@ impl RpcConvert - for RpcConverter +impl RpcConvert + for RpcConverter where N: NodePrimitives, Network: RpcTypes + Send + Sync + Unpin + Clone + Debug, @@ -713,6 +782,7 @@ where + Unpin + Sync + Send + + From + Into>, > + Send + Sync @@ -724,6 +794,7 @@ where SimTx: SimTxConverter, TxTy>, RpcTx: RpcTxConverter, Network::TransactionResponse, >>::Out>, + EvmEnvC: EvmEnvConverter>, { type Primitives = N; type Network = Network; @@ -760,6 +831,14 @@ where Ok(request.try_into_tx_env(cfg_env, block_env)?) } + fn evm_env( + &self, + request: &RpcTxReq, + evm_env: EvmEnv, + ) -> Result, Self::Error> { + Ok(self.evm_env_converter.convert_evm_env(request, evm_env)?) + } + fn convert_receipts( &self, receipts: Vec>, diff --git a/crates/rpc/rpc-eth-api/src/helpers/call.rs b/crates/rpc/rpc-eth-api/src/helpers/call.rs index b95b290de46..3d038389481 100644 --- a/crates/rpc/rpc-eth-api/src/helpers/call.rs +++ b/crates/rpc/rpc-eth-api/src/helpers/call.rs @@ -760,6 +760,7 @@ pub trait Call: } let request_gas = request.as_ref().gas_limit(); + evm_env = self.tx_resp_builder().evm_env(&request, evm_env)?; let mut tx_env = self.create_txn_env(&evm_env, request, &mut *db)?; // lower the basefee to 0 to avoid breaking EVM invariants (basefee < gasprice):