1use core::fmt;
5
6use super::{LoadBlock, LoadPendingBlock, LoadState, LoadTransaction, SpawnBlocking, Trace};
7use crate::{
8 helpers::estimate::EstimateCall, FromEvmError, FullEthApiTypes, RpcBlock, RpcNodeCore,
9};
10use alloy_consensus::{transaction::TxHashRef, BlockHeader};
11use alloy_eips::eip2930::AccessListResult;
12use alloy_evm::overrides::{apply_block_overrides, apply_state_overrides, OverrideBlockHashes};
13use alloy_network::TransactionBuilder;
14use alloy_primitives::{Bytes, B256, U256};
15use alloy_rpc_types_eth::{
16 simulate::{SimBlock, SimulatePayload, SimulatedBlock},
17 state::{EvmOverrides, StateOverride},
18 BlockId, Bundle, EthCallResponse, StateContext, TransactionInfo,
19};
20use futures::Future;
21use reth_chainspec::{ChainSpecProvider, EthChainSpec, EthereumHardforks};
22use reth_errors::{ProviderError, RethError};
23use reth_evm::{
24 block::BlockExecutor, env::BlockEnvironment, execute::BlockBuilder, ConfigureEvm, Evm,
25 EvmEnvFor, EvmFor, HaltReasonFor, InspectorFor, TransactionEnvMut, TxEnvFor,
26};
27use reth_node_api::BlockBody;
28use reth_primitives_traits::Recovered;
29use reth_revm::{
30 database::StateProviderDatabase,
31 db::{
32 bal::{BalState, EvmDatabaseError},
33 State,
34 },
35};
36use reth_rpc_convert::{RpcConvert, RpcTxReq};
37use reth_rpc_eth_types::{
38 cache::db::attach_bal_before_tx,
39 error::{AsEthApiError, FromEthApiError},
40 simulate::{self, EthSimulateError},
41 EthApiError, StateCacheDb,
42};
43use reth_storage_api::{BlockIdReader, ProviderTx, StateProvider};
44use reth_tasks::{cancel::is_cancelled, CancelOnDrop};
45use revm::{
46 context::Block,
47 context_interface::{result::ResultAndState, Cfg, Transaction},
48 Database, DatabaseCommit,
49};
50use revm_inspectors::{access_list::AccessListInspector, transfer::TransferInspector};
51use std::collections::BTreeMap;
52use tracing::{debug, trace};
53
54pub type SimulatedBlocksResult<N, E> = Result<Vec<SimulatedBlock<RpcBlock<N>>>, E>;
56
57pub trait EthCall: EstimateCall + LoadBlock + FullEthApiTypes {
60 fn estimate_gas_at(
62 &self,
63 request: RpcTxReq<<Self::RpcConvert as RpcConvert>::Network>,
64 at: BlockId,
65 overrides: EvmOverrides,
66 ) -> impl Future<Output = Result<U256, Self::Error>> + Send {
67 EstimateCall::estimate_gas_at(self, request, at, overrides)
68 }
69
70 fn simulate_v1(
75 &self,
76 payload: SimulatePayload<RpcTxReq<<Self::RpcConvert as RpcConvert>::Network>>,
77 block: Option<BlockId>,
78 ) -> impl Future<Output = SimulatedBlocksResult<Self::NetworkTypes, Self::Error>> + Send {
79 async move {
80 if payload.block_state_calls.len() > self.max_simulate_blocks() as usize {
81 return Err(EthApiError::other(EthSimulateError::TooManyBlocks).into())
82 }
83
84 let block = block.unwrap_or_default();
85
86 let SimulatePayload {
87 block_state_calls,
88 trace_transfers,
89 validation,
90 return_full_transactions,
91 } = payload;
92
93 if block_state_calls.is_empty() {
94 return Err(EthApiError::InvalidParams(String::from("calls are empty.")).into())
95 }
96
97 let permit = self
98 .acquire_owned_blocking_io()
99 .await
100 .map_err(|_| EthApiError::InternalEthError)?;
101
102 let base_block = self
103 .recovered_block(block)
104 .await?
105 .ok_or_else(|| EthApiError::other(EthSimulateError::BlockNotFound { block }))?;
106 let parent = base_block.sealed_header().clone();
107 let max_simulate_blocks = self.max_simulate_blocks();
108 let state_at = if block.is_pending() { block } else { parent.hash().into() };
111
112 self.spawn_with_state_at_block(state_at, move |this, db| {
113 let _permit = permit;
114 let state_provider = db.database.into_inner();
115 let mut db = State::builder()
116 .with_database(StateProviderDatabase::new(&state_provider))
117 .with_bundle_update()
118 .build();
119 let mut parent = parent;
120
121 let chain_id = this.provider().chain_spec().chain_id();
122
123 let block_state_calls = simulate::sanitize_chain(
128 block_state_calls,
129 &parent,
130 chain_id,
131 max_simulate_blocks,
132 )?;
133
134 let mut blocks: Vec<SimulatedBlock<RpcBlock<Self::NetworkTypes>>> =
135 Vec::with_capacity(block_state_calls.len());
136
137 let call_gas_limit = this.call_gas_limit();
138 let mut remaining_call_gas_limit = (call_gas_limit > 0).then_some(call_gas_limit);
139
140 for block in block_state_calls {
141 let SimBlock { block_overrides, state_overrides, calls } = block;
142
143 let attributes = this
144 .pending_env_builder()
145 .pending_env_attributes(&parent, block_overrides.as_ref())
146 .map_err(Self::Error::from_eth_err)?;
147
148 let mut evm_env = this
149 .evm_config()
150 .next_evm_env(&parent, &attributes)
151 .map_err(RethError::other)
152 .map_err(Self::Error::from_eth_err)?;
153
154 evm_env.cfg_env.disable_eip3607 = true;
156
157 if !validation || !evm_env.cfg_env.is_amsterdam_eip8037_enabled() {
161 evm_env.cfg_env.tx_gas_limit_cap = Some(u64::MAX);
162 }
163
164 if !validation {
165 evm_env.cfg_env.disable_nonce_check = true;
167 evm_env.cfg_env.disable_base_fee = true;
168 evm_env.block_env.inner_mut().basefee = 0;
169 }
170
171 evm_env.block_env.inner_mut().prevrandao = Some(B256::ZERO);
175 if !this
176 .provider()
177 .chain_spec()
178 .is_paris_active_at_block(evm_env.block_env.number().saturating_to())
179 {
180 evm_env.block_env.inner_mut().difficulty = parent.difficulty();
181 }
182
183 if let Some(block_overrides) = block_overrides {
184 if let Some(gas_limit_override) = block_overrides.gas_limit &&
186 gas_limit_override > evm_env.block_env.gas_limit() &&
187 gas_limit_override > this.call_gas_limit()
188 {
189 return Err(EthApiError::other(EthSimulateError::GasLimitReached).into())
190 }
191 apply_block_overrides(
192 block_overrides,
193 &mut db,
194 evm_env.block_env.inner_mut(),
195 );
196 }
197 if let Some(ref state_overrides) = state_overrides {
198 apply_state_overrides(state_overrides.clone(), &mut db)
199 .map_err(Self::Error::from_eth_err)?;
200 }
201
202 let chain_id = evm_env.cfg_env.chain_id;
203
204 if this.provider().chain_spec().is_amsterdam_active_at_timestamp(
206 evm_env.block_env.timestamp().saturating_to(),
207 ) {
208 db.bal_state = BalState::new().with_bal_builder();
209 }
210
211 let ctx = this
212 .evm_config()
213 .context_for_next_block(&parent, attributes)
214 .map_err(RethError::other)
215 .map_err(Self::Error::from_eth_err)?;
216 let map_err = |e: EthApiError| -> Self::Error {
217 match e.as_simulate_error() {
218 Some(sim_err) => Self::Error::from_eth_err(EthApiError::other(sim_err)),
219 None => Self::Error::from_eth_err(e),
220 }
221 };
222
223 let trace_transfers = trace_transfers &&
225 (!Cfg::spec(&evm_env.cfg_env)
226 .into()
227 .is_enabled_in(revm::primitives::hardfork::SpecId::AMSTERDAM) ||
228 evm_env.cfg_env.is_eip7708_disabled());
229 let (result, results) = if trace_transfers {
230 let inspector = TransferInspector::new(false).with_logs(true);
233 let evm = this
234 .evm_config()
235 .evm_with_env_and_inspector(&mut db, evm_env, inspector);
236 let mut builder = this.evm_config().create_block_builder(evm, &parent, ctx);
237
238 if let Some(ref state_overrides) = state_overrides {
239 simulate::apply_precompile_overrides(
240 state_overrides,
241 builder.evm_mut().precompiles_mut(),
242 )
243 .map_err(|e| Self::Error::from_eth_err(EthApiError::other(e)))?;
244 }
245
246 simulate::execute_transactions(
247 builder,
248 &*state_provider,
249 calls,
250 &mut remaining_call_gas_limit,
251 chain_id,
252 this.compute_state_root_for_eth_simulate(),
253 this.converter(),
254 )
255 .map_err(map_err)?
256 } else {
257 let evm = this.evm_config().evm_with_env(&mut db, evm_env);
258 let mut builder = this.evm_config().create_block_builder(evm, &parent, ctx);
259
260 if let Some(ref state_overrides) = state_overrides {
261 simulate::apply_precompile_overrides(
262 state_overrides,
263 builder.evm_mut().precompiles_mut(),
264 )
265 .map_err(|e| Self::Error::from_eth_err(EthApiError::other(e)))?;
266 }
267
268 simulate::execute_transactions(
269 builder,
270 &*state_provider,
271 calls,
272 &mut remaining_call_gas_limit,
273 chain_id,
274 this.compute_state_root_for_eth_simulate(),
275 this.converter(),
276 )
277 .map_err(map_err)?
278 };
279
280 let simulated_header = result.block.clone_sealed_header();
281 db.override_block_hashes(BTreeMap::from([(
282 simulated_header.number(),
283 simulated_header.hash(),
284 )]));
285 parent = simulated_header;
286
287 let block = simulate::build_simulated_block::<Self::Error, _>(
288 result.block,
289 results,
290 return_full_transactions.into(),
291 this.converter(),
292 )?;
293
294 blocks.push(block);
295 }
296
297 Ok(blocks)
298 })
299 .await
300 }
301 }
302
303 fn call(
305 &self,
306 request: RpcTxReq<<Self::RpcConvert as RpcConvert>::Network>,
307 block_number: Option<BlockId>,
308 overrides: EvmOverrides,
309 ) -> impl Future<Output = Result<Bytes, Self::Error>> + Send {
310 async move {
311 let res =
312 self.transact_call_at(request, block_number.unwrap_or_default(), overrides).await?;
313
314 Self::Error::ensure_success(res.result)
315 }
316 }
317
318 fn call_many(
321 &self,
322 bundles: Vec<Bundle<RpcTxReq<<Self::RpcConvert as RpcConvert>::Network>>>,
323 state_context: Option<StateContext>,
324 mut state_override: Option<StateOverride>,
325 ) -> impl Future<Output = Result<Vec<Vec<EthCallResponse>>, Self::Error>> + Send
326 where
327 Self: Trace,
328 {
329 async move {
330 if bundles.is_empty() {
332 return Err(EthApiError::InvalidParams(String::from("bundles are empty.")).into());
333 }
334
335 let permit = self
336 .acquire_owned_blocking_io()
337 .await
338 .map_err(|_| EthApiError::InternalEthError)?;
339
340 let StateContext { transaction_index, block_number } =
341 state_context.unwrap_or_default();
342 let transaction_index = transaction_index.unwrap_or_default();
343
344 let mut target_block = block_number.unwrap_or_default();
345 let is_block_target_pending = target_block.is_pending();
346
347 if !is_block_target_pending {
350 let Some(block_hash) = self
351 .provider()
352 .block_hash_for_id(target_block)
353 .map_err(Self::Error::from_eth_err::<ProviderError>)?
354 else {
355 return Err(EthApiError::HeaderNotFound(target_block).into())
356 };
357 target_block = block_hash.into();
358 }
359
360 let block = self
361 .recovered_block(target_block)
362 .await?
363 .ok_or(EthApiError::HeaderNotFound(target_block))?;
364 let evm_env = self.evm_env_for_header(block.sealed_block().sealed_header())?;
365
366 let mut at = block.parent_hash();
370 let mut replay_block_txs = true;
371
372 let num_txs =
373 transaction_index.index().unwrap_or_else(|| block.body().transactions().len());
374 if !is_block_target_pending && num_txs == block.body().transactions().len() {
378 at = block.hash();
379 replay_block_txs = false;
380 }
381
382 self.spawn_with_state_at_block(at, move |this, mut db| {
383 let _permit = permit;
384 let mut all_results = Vec::with_capacity(bundles.len());
385
386 if replay_block_txs {
387 this.replay_block_until(&mut db, &block, num_txs, None)?;
390 }
391
392 for (bundle_index, bundle) in bundles.into_iter().enumerate() {
394 let Bundle { transactions, block_override } = bundle;
395 if transactions.is_empty() {
396 continue;
398 }
399
400 let mut bundle_results = Vec::with_capacity(transactions.len());
401 let block_overrides = block_override.map(Box::new);
402
403 for (tx_index, tx) in transactions.into_iter().enumerate() {
405 if is_cancelled() {
406 return Err(EthApiError::InternalEthError.into())
407 }
408
409 let overrides =
412 EvmOverrides::new(state_override.take(), block_overrides.clone());
413
414 let (current_evm_env, prepared_tx) = this
415 .prepare_call_env(evm_env.clone(), tx, &mut db, overrides)
416 .map_err(|err| {
417 Self::Error::from_eth_err(EthApiError::call_many_error(
418 bundle_index,
419 tx_index,
420 err.into(),
421 ))
422 })?;
423 let res = this.transact(&mut db, current_evm_env, prepared_tx).map_err(
424 |err| {
425 Self::Error::from_eth_err(EthApiError::call_many_error(
426 bundle_index,
427 tx_index,
428 err.into(),
429 ))
430 },
431 )?;
432
433 match Self::Error::ensure_success(res.result) {
434 Ok(output) => {
435 bundle_results
436 .push(EthCallResponse { value: Some(output), error: None });
437 }
438 Err(err) => {
439 bundle_results.push(EthCallResponse {
440 value: None,
441 error: Some(err.to_string()),
442 });
443 }
444 }
445
446 db.commit(res.state);
449 }
450
451 all_results.push(bundle_results);
452 }
453
454 Ok(all_results)
455 })
456 .await
457 }
458 }
459
460 fn create_access_list_at(
463 &self,
464 request: RpcTxReq<<Self::RpcConvert as RpcConvert>::Network>,
465 block_number: Option<BlockId>,
466 state_override: Option<StateOverride>,
467 ) -> impl Future<Output = Result<AccessListResult, Self::Error>> + Send
468 where
469 Self: Trace,
470 {
471 async move {
472 let block_id = block_number.unwrap_or_default();
473 let (evm_env, at) = self.evm_env_at(block_id).await?;
474
475 self.create_access_list_with(evm_env, at, request, state_override).await
476 }
477 }
478
479 fn create_access_list_with(
482 &self,
483 evm_env: EvmEnvFor<Self::Evm>,
484 at: BlockId,
485 request: RpcTxReq<<Self::RpcConvert as RpcConvert>::Network>,
486 state_override: Option<StateOverride>,
487 ) -> impl Future<Output = Result<AccessListResult, Self::Error>> + Send
488 where
489 Self: Trace,
490 {
491 self.spawn_with_state_at_block(at, |this, mut db| {
492 let initial = request.as_ref().access_list().cloned().unwrap_or_default();
493 let (evm_env, mut tx_env) = this.prepare_call_env(
494 evm_env,
495 request,
496 &mut db,
497 EvmOverrides::state(state_override),
498 )?;
499
500 let mut evm = this.evm_config().evm_with_env_and_inspector(
501 &mut db,
502 evm_env,
503 AccessListInspector::new(initial),
504 );
505
506 let result = evm.transact(tx_env.clone())?;
507 let access_list = core::mem::take(evm.inspector_mut()).into_access_list();
508 let gas_used = result.result.tx_gas_used();
509 tx_env.set_access_list(access_list.clone());
510 if let Err(err) = Self::Error::ensure_success(result.result) {
511 return Ok(AccessListResult {
512 access_list,
513 gas_used: U256::from(gas_used),
514 error: Some(err.to_string()),
515 });
516 }
517
518 evm.disable_inspector();
520 let result = evm.transact(tx_env)?;
521 let gas_used = result.result.tx_gas_used();
522 let error = Self::Error::ensure_success(result.result).err().map(|e| e.to_string());
523
524 Ok(AccessListResult { access_list, gas_used: U256::from(gas_used), error })
525 })
526 }
527}
528
529pub trait Call:
531 LoadState<
532 RpcConvert: RpcConvert<Evm = Self::Evm>,
533 Error: FromEvmError<Self::Evm>
534 + From<<Self::RpcConvert as RpcConvert>::Error>
535 + From<ProviderError>,
536 > + SpawnBlocking
537{
538 fn call_gas_limit(&self) -> u64 {
542 self.eth_api_settings().gas_cap
543 }
544
545 fn max_simulate_blocks(&self) -> u64 {
547 self.eth_api_settings().max_simulate_blocks
548 }
549
550 fn compute_state_root_for_eth_simulate(&self) -> bool {
552 self.eth_api_settings().compute_state_root_for_eth_simulate
553 }
554
555 fn evm_memory_limit(&self) -> u64 {
557 self.eth_api_settings().evm_memory_limit
558 }
559
560 fn caller_gas_allowance(
562 &self,
563 mut db: impl Database<Error: Into<EthApiError>>,
564 _evm_env: &EvmEnvFor<Self::Evm>,
565 tx_env: &TxEnvFor<Self::Evm>,
566 ) -> Result<u64, Self::Error> {
567 alloy_evm::call::caller_gas_allowance(&mut db, tx_env).map_err(Self::Error::from_eth_err)
568 }
569
570 fn transact<DB>(
573 &self,
574 db: DB,
575 evm_env: EvmEnvFor<Self::Evm>,
576 tx_env: TxEnvFor<Self::Evm>,
577 ) -> Result<ResultAndState<HaltReasonFor<Self::Evm>>, Self::Error>
578 where
579 DB: Database<Error = EvmDatabaseError<ProviderError>> + fmt::Debug,
580 {
581 let mut evm = self.evm_config().evm_with_env(db, evm_env);
582 let res = evm.transact(tx_env).map_err(Self::Error::from_evm_err)?;
583
584 Ok(res)
585 }
586
587 fn transact_with_inspector<DB, I>(
590 &self,
591 db: DB,
592 evm_env: EvmEnvFor<Self::Evm>,
593 tx_env: TxEnvFor<Self::Evm>,
594 inspector: I,
595 ) -> Result<ResultAndState<HaltReasonFor<Self::Evm>>, Self::Error>
596 where
597 DB: Database<Error = EvmDatabaseError<ProviderError>> + fmt::Debug,
598 I: InspectorFor<Self::Evm, DB>,
599 {
600 let mut evm = self.evm_config().evm_with_env_and_inspector(db, evm_env, inspector);
601 let res = evm.transact(tx_env).map_err(Self::Error::from_evm_err)?;
602
603 Ok(res)
604 }
605
606 fn transact_call_at(
613 &self,
614 request: RpcTxReq<<Self::RpcConvert as RpcConvert>::Network>,
615 at: BlockId,
616 overrides: EvmOverrides,
617 ) -> impl Future<Output = Result<ResultAndState<HaltReasonFor<Self::Evm>>, Self::Error>> + Send
618 where
619 Self: LoadPendingBlock,
620 {
621 async move {
622 let permit = self
623 .acquire_owned_blocking_io()
624 .await
625 .map_err(|_| EthApiError::InternalEthError)?;
626 let guard = CancelOnDrop::default();
627 let cancel = guard.clone();
628 let this = self.clone();
629
630 let res = self
631 .spawn_with_call_at(request, at, overrides, move |db, evm_env, tx_env| {
632 let _permit = permit;
633 if cancel.is_cancelled() {
634 return Err(EthApiError::InternalEthError.into())
636 }
637 this.transact(db, evm_env, tx_env)
638 })
639 .await;
640 drop(guard);
641 res
642 }
643 }
644
645 fn spawn_with_state_at_block<F, R>(
647 &self,
648 at: impl Into<BlockId>,
649 f: F,
650 ) -> impl Future<Output = Result<R, Self::Error>> + Send
651 where
652 F: FnOnce(Self, StateCacheDb) -> Result<R, Self::Error> + Send + 'static,
653 R: Send + 'static,
654 {
655 self.spawn_blocking_io_with_state(at.into(), move |this, state| {
656 let db = State::builder()
657 .with_database(StateProviderDatabase::new(state.into_evm_state_provider()))
658 .build();
659 f(this, db)
660 })
661 }
662
663 fn spawn_with_call_at<F, R>(
679 &self,
680 request: RpcTxReq<<Self::RpcConvert as RpcConvert>::Network>,
681 at: BlockId,
682 overrides: EvmOverrides,
683 f: F,
684 ) -> impl Future<Output = Result<R, Self::Error>> + Send
685 where
686 Self: LoadPendingBlock,
687 F: FnOnce(
688 &mut StateCacheDb,
689 EvmEnvFor<Self::Evm>,
690 TxEnvFor<Self::Evm>,
691 ) -> Result<R, Self::Error>
692 + Send
693 + 'static,
694 R: Send + 'static,
695 {
696 async move {
697 let (evm_env, at) = self.evm_env_at(at).await?;
698 self.spawn_with_state_at_block(at, move |this, mut db| {
699 let (evm_env, tx_env) =
700 this.prepare_call_env(evm_env, request, &mut db, overrides)?;
701
702 f(&mut db, evm_env, tx_env)
703 })
704 .await
705 }
706 }
707
708 fn spawn_replay_transaction<F, R>(
721 &self,
722 hash: B256,
723 f: F,
724 ) -> impl Future<Output = Result<Option<R>, Self::Error>> + Send
725 where
726 Self: LoadBlock + LoadTransaction,
727 F: FnOnce(
728 TransactionInfo,
729 ResultAndState<HaltReasonFor<Self::Evm>>,
730 StateCacheDb,
731 ) -> Result<R, Self::Error>
732 + Send
733 + 'static,
734 R: Send + 'static,
735 {
736 async move {
737 let (transaction, block, bal) =
738 match self.transaction_and_block_and_maybe_bal(hash).await? {
739 None => return Ok(None),
740 Some(res) => res,
741 };
742 let (tx, tx_info) = transaction.split();
743
744 let parent_block = block.parent_hash();
747
748 self.spawn_with_state_at_block(parent_block, move |this, mut db| {
749 if let Some((bal, tx_index)) = bal.zip(tx_info.index) {
750 attach_bal_before_tx(&mut db, &bal, tx_index as usize);
751
752 let evm_env = this.evm_env_for_header(block.sealed_block().sealed_header())?;
753 let tx_env = RpcNodeCore::evm_config(&this).tx_env(tx);
754 let res = this.transact(&mut db, evm_env, tx_env)?;
755 return f(tx_info, res, db)
756 }
757
758 let block_txs = block.transactions_recovered();
759
760 let mut executor = RpcNodeCore::evm_config(&this)
761 .executor_for_block(&mut db, block.sealed_block())
762 .map_err(RethError::other)
763 .map_err(Self::Error::from_eth_err)?;
764 executor.apply_pre_execution_changes().map_err(Self::Error::from_eth_err)?;
765
766 for block_tx in block_txs {
768 if block_tx.tx_hash() == tx.tx_hash() {
769 break;
770 }
771 if is_cancelled() {
772 return Err(EthApiError::InternalEthError.into())
773 }
774 executor.execute_transaction(block_tx).map_err(Self::Error::from_eth_err)?;
775 }
776
777 let tx_env = RpcNodeCore::evm_config(&this).tx_env(tx);
778
779 let res = executor.evm_mut().transact(tx_env).map_err(Self::Error::from_evm_err)?;
780 drop(executor);
781 f(tx_info, res, db)
782 })
783 .await
784 .map(Some)
785 }
786 }
787
788 fn replay_transactions_until_with_evm<'a, DB, I, Txs>(
798 &self,
799 evm: &mut EvmFor<Self::Evm, DB, I>,
800 transactions: Txs,
801 target_tx_index: usize,
802 ) -> Result<(), Self::Error>
803 where
804 DB: Database<Error = EvmDatabaseError<ProviderError>> + DatabaseCommit + core::fmt::Debug,
805 I: InspectorFor<Self::Evm, DB>,
806 Txs: IntoIterator<Item = Recovered<&'a ProviderTx<Self::Provider>>>,
807 {
808 for (index, tx) in transactions.into_iter().enumerate() {
809 if index == target_tx_index {
810 break
812 }
813 if is_cancelled() {
814 return Err(EthApiError::InternalEthError.into())
815 }
816
817 let tx_env = self.evm_config().tx_env(tx);
818 evm.transact_commit(tx_env).map_err(Self::Error::from_evm_err)?;
819 }
820 Ok(())
821 }
822
823 fn create_txn_env(
827 &self,
828 evm_env: &EvmEnvFor<Self::Evm>,
829 mut request: RpcTxReq<<Self::RpcConvert as RpcConvert>::Network>,
830 mut db: impl Database<Error: Into<EthApiError>>,
831 ) -> Result<TxEnvFor<Self::Evm>, Self::Error> {
832 if request.as_ref().nonce().is_none() {
833 let nonce = db
834 .basic(request.as_ref().from().unwrap_or_default())
835 .map_err(Into::into)?
836 .map(|acc| acc.nonce)
837 .unwrap_or_default();
838 request.as_mut().set_nonce(nonce);
839 }
840
841 Ok(self.converter().tx_env(request, evm_env)?)
842 }
843
844 #[expect(clippy::type_complexity)]
858 fn prepare_call_env<DB>(
859 &self,
860 mut evm_env: EvmEnvFor<Self::Evm>,
861 mut request: RpcTxReq<<Self::RpcConvert as RpcConvert>::Network>,
862 db: &mut DB,
863 overrides: EvmOverrides,
864 ) -> Result<(EvmEnvFor<Self::Evm>, TxEnvFor<Self::Evm>), Self::Error>
865 where
866 DB: Database + DatabaseCommit + OverrideBlockHashes,
867 EthApiError: From<<DB as Database>::Error>,
868 {
869 let request_has_gas_limit = request.as_ref().gas_limit().is_some();
871
872 if let Some(requested_gas) = request.as_ref().gas_limit() {
873 let global_gas_cap = self.call_gas_limit();
874 if global_gas_cap != 0 && global_gas_cap < requested_gas {
875 debug!(target: "rpc::eth::call", requested_gas, global_gas_cap, "Capping gas limit to global gas cap");
878 request.as_mut().set_gas_limit(global_gas_cap);
879 }
880 } else {
881 request.as_mut().set_gas_limit(self.call_gas_limit());
883 }
884
885 evm_env.cfg_env.disable_block_gas_limit = true;
888
889 evm_env.cfg_env.disable_eip3607 = true;
892
893 evm_env.cfg_env.disable_base_fee = true;
897
898 if !evm_env.cfg_env.is_amsterdam_eip8037_enabled() {
902 evm_env.cfg_env.tx_gas_limit_cap = Some(u64::MAX);
903 }
904
905 evm_env.cfg_env.disable_fee_charge = true;
909
910 evm_env.cfg_env.memory_limit = self.evm_memory_limit();
911
912 request.as_mut().take_nonce();
914
915 if let Some(block_overrides) = overrides.block {
916 apply_block_overrides(*block_overrides, db, evm_env.block_env.inner_mut());
917 }
918 if let Some(state_overrides) = overrides.state {
919 apply_state_overrides(state_overrides, db)
920 .map_err(EthApiError::from_state_overrides_err)?;
921 }
922
923 let mut tx_env = self.create_txn_env(&evm_env, request, &mut *db)?;
924
925 if tx_env.gas_price() == 0 {
927 evm_env.block_env.inner_mut().basefee = 0;
928 }
929
930 if !request_has_gas_limit {
931 if tx_env.gas_price() > 0 {
933 trace!(target: "rpc::eth::call", ?tx_env, "Applying gas limit cap with caller allowance");
935 let mut cap = self.caller_gas_allowance(db, &evm_env, &tx_env)?;
936 if self.call_gas_limit() != 0 {
938 cap = cap.min(tx_env.gas_limit());
939 }
940 tx_env.set_gas_limit(cap.min(evm_env.block_env.gas_limit()));
942 }
943 }
944
945 Ok((evm_env, tx_env))
946 }
947}