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 + Call + LoadPendingBlock + 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 !evm_env.cfg_env.is_amsterdam_eip8037_enabled() {
160 evm_env.cfg_env.tx_gas_limit_cap = Some(u64::MAX);
161 }
162
163 if !validation {
164 evm_env.cfg_env.disable_nonce_check = true;
166 evm_env.cfg_env.disable_base_fee = true;
167 evm_env.block_env.inner_mut().basefee = 0;
168 }
169
170 evm_env.block_env.inner_mut().prevrandao = Some(B256::ZERO);
174 if !this
175 .provider()
176 .chain_spec()
177 .is_paris_active_at_block(evm_env.block_env.number().saturating_to())
178 {
179 evm_env.block_env.inner_mut().difficulty = parent.difficulty();
180 }
181
182 if let Some(block_overrides) = block_overrides {
183 if let Some(gas_limit_override) = block_overrides.gas_limit &&
185 gas_limit_override > evm_env.block_env.gas_limit() &&
186 gas_limit_override > this.call_gas_limit()
187 {
188 return Err(EthApiError::other(EthSimulateError::GasLimitReached).into())
189 }
190 apply_block_overrides(
191 block_overrides,
192 &mut db,
193 evm_env.block_env.inner_mut(),
194 );
195 }
196 if let Some(ref state_overrides) = state_overrides {
197 apply_state_overrides(state_overrides.clone(), &mut db)
198 .map_err(Self::Error::from_eth_err)?;
199 }
200
201 let chain_id = evm_env.cfg_env.chain_id;
202
203 if this.provider().chain_spec().is_amsterdam_active_at_timestamp(
205 evm_env.block_env.timestamp().saturating_to(),
206 ) {
207 db.bal_state = BalState::new().with_bal_builder();
208 }
209
210 let ctx = this
211 .evm_config()
212 .context_for_next_block(&parent, attributes)
213 .map_err(RethError::other)
214 .map_err(Self::Error::from_eth_err)?;
215 let map_err = |e: EthApiError| -> Self::Error {
216 match e.as_simulate_error() {
217 Some(sim_err) => Self::Error::from_eth_err(EthApiError::other(sim_err)),
218 None => Self::Error::from_eth_err(e),
219 }
220 };
221
222 let trace_transfers = trace_transfers &&
224 (!Cfg::spec(&evm_env.cfg_env)
225 .into()
226 .is_enabled_in(revm::primitives::hardfork::SpecId::AMSTERDAM) ||
227 evm_env.cfg_env.is_eip7708_disabled());
228 let (result, results) = if trace_transfers {
229 let inspector = TransferInspector::new(false).with_logs(true);
232 let evm = this
233 .evm_config()
234 .evm_with_env_and_inspector(&mut db, evm_env, inspector);
235 let mut builder = this.evm_config().create_block_builder(evm, &parent, ctx);
236
237 if let Some(ref state_overrides) = state_overrides {
238 simulate::apply_precompile_overrides(
239 state_overrides,
240 builder.evm_mut().precompiles_mut(),
241 )
242 .map_err(|e| Self::Error::from_eth_err(EthApiError::other(e)))?;
243 }
244
245 simulate::execute_transactions(
246 builder,
247 &*state_provider,
248 calls,
249 &mut remaining_call_gas_limit,
250 chain_id,
251 this.compute_state_root_for_eth_simulate(),
252 this.converter(),
253 )
254 .map_err(map_err)?
255 } else {
256 let evm = this.evm_config().evm_with_env(&mut db, evm_env);
257 let mut builder = this.evm_config().create_block_builder(evm, &parent, ctx);
258
259 if let Some(ref state_overrides) = state_overrides {
260 simulate::apply_precompile_overrides(
261 state_overrides,
262 builder.evm_mut().precompiles_mut(),
263 )
264 .map_err(|e| Self::Error::from_eth_err(EthApiError::other(e)))?;
265 }
266
267 simulate::execute_transactions(
268 builder,
269 &*state_provider,
270 calls,
271 &mut remaining_call_gas_limit,
272 chain_id,
273 this.compute_state_root_for_eth_simulate(),
274 this.converter(),
275 )
276 .map_err(map_err)?
277 };
278
279 let simulated_header = result.block.clone_sealed_header();
280 db.override_block_hashes(BTreeMap::from([(
281 simulated_header.number(),
282 simulated_header.hash(),
283 )]));
284 parent = simulated_header;
285
286 let block = simulate::build_simulated_block::<Self::Error, _>(
287 result.block,
288 results,
289 return_full_transactions.into(),
290 this.converter(),
291 )?;
292
293 blocks.push(block);
294 }
295
296 Ok(blocks)
297 })
298 .await
299 }
300 }
301
302 fn call(
304 &self,
305 request: RpcTxReq<<Self::RpcConvert as RpcConvert>::Network>,
306 block_number: Option<BlockId>,
307 overrides: EvmOverrides,
308 ) -> impl Future<Output = Result<Bytes, Self::Error>> + Send {
309 async move {
310 let res =
311 self.transact_call_at(request, block_number.unwrap_or_default(), overrides).await?;
312
313 Self::Error::ensure_success(res.result)
314 }
315 }
316
317 fn call_many(
320 &self,
321 bundles: Vec<Bundle<RpcTxReq<<Self::RpcConvert as RpcConvert>::Network>>>,
322 state_context: Option<StateContext>,
323 mut state_override: Option<StateOverride>,
324 ) -> impl Future<Output = Result<Vec<Vec<EthCallResponse>>, Self::Error>> + Send
325 where
326 Self: Trace,
327 {
328 async move {
329 if bundles.is_empty() {
331 return Err(EthApiError::InvalidParams(String::from("bundles are empty.")).into());
332 }
333
334 let permit = self
335 .acquire_owned_blocking_io()
336 .await
337 .map_err(|_| EthApiError::InternalEthError)?;
338
339 let StateContext { transaction_index, block_number } =
340 state_context.unwrap_or_default();
341 let transaction_index = transaction_index.unwrap_or_default();
342
343 let mut target_block = block_number.unwrap_or_default();
344 let is_block_target_pending = target_block.is_pending();
345
346 if !is_block_target_pending {
349 let Some(block_hash) = self
350 .provider()
351 .block_hash_for_id(target_block)
352 .map_err(Self::Error::from_eth_err::<ProviderError>)?
353 else {
354 return Err(EthApiError::HeaderNotFound(target_block).into())
355 };
356 target_block = block_hash.into();
357 }
358
359 let block = self
360 .recovered_block(target_block)
361 .await?
362 .ok_or(EthApiError::HeaderNotFound(target_block))?;
363 let evm_env = self.evm_env_for_header(block.sealed_block().sealed_header())?;
364
365 let mut at = block.parent_hash();
369 let mut replay_block_txs = true;
370
371 let num_txs =
372 transaction_index.index().unwrap_or_else(|| block.body().transactions().len());
373 if !is_block_target_pending && num_txs == block.body().transactions().len() {
377 at = block.hash();
378 replay_block_txs = false;
379 }
380
381 self.spawn_with_state_at_block(at, move |this, mut db| {
382 let _permit = permit;
383 let mut all_results = Vec::with_capacity(bundles.len());
384
385 if replay_block_txs {
386 this.replay_block_until(&mut db, &block, num_txs, None)?;
389 }
390
391 for (bundle_index, bundle) in bundles.into_iter().enumerate() {
393 let Bundle { transactions, block_override } = bundle;
394 if transactions.is_empty() {
395 continue;
397 }
398
399 let mut bundle_results = Vec::with_capacity(transactions.len());
400 let block_overrides = block_override.map(Box::new);
401
402 for (tx_index, tx) in transactions.into_iter().enumerate() {
404 if is_cancelled() {
405 return Err(EthApiError::InternalEthError.into())
406 }
407
408 let overrides =
411 EvmOverrides::new(state_override.take(), block_overrides.clone());
412
413 let (current_evm_env, prepared_tx) = this
414 .prepare_call_env(evm_env.clone(), tx, &mut db, overrides)
415 .map_err(|err| {
416 Self::Error::from_eth_err(EthApiError::call_many_error(
417 bundle_index,
418 tx_index,
419 err.into(),
420 ))
421 })?;
422 let res = this.transact(&mut db, current_evm_env, prepared_tx).map_err(
423 |err| {
424 Self::Error::from_eth_err(EthApiError::call_many_error(
425 bundle_index,
426 tx_index,
427 err.into(),
428 ))
429 },
430 )?;
431
432 match Self::Error::ensure_success(res.result) {
433 Ok(output) => {
434 bundle_results
435 .push(EthCallResponse { value: Some(output), error: None });
436 }
437 Err(err) => {
438 bundle_results.push(EthCallResponse {
439 value: None,
440 error: Some(err.to_string()),
441 });
442 }
443 }
444
445 db.commit(res.state);
448 }
449
450 all_results.push(bundle_results);
451 }
452
453 Ok(all_results)
454 })
455 .await
456 }
457 }
458
459 fn create_access_list_at(
462 &self,
463 request: RpcTxReq<<Self::RpcConvert as RpcConvert>::Network>,
464 block_number: Option<BlockId>,
465 state_override: Option<StateOverride>,
466 ) -> impl Future<Output = Result<AccessListResult, Self::Error>> + Send
467 where
468 Self: Trace,
469 {
470 async move {
471 let block_id = block_number.unwrap_or_default();
472 let (evm_env, at) = self.evm_env_at(block_id).await?;
473
474 self.create_access_list_with(evm_env, at, request, state_override).await
475 }
476 }
477
478 fn create_access_list_with(
481 &self,
482 evm_env: EvmEnvFor<Self::Evm>,
483 at: BlockId,
484 request: RpcTxReq<<Self::RpcConvert as RpcConvert>::Network>,
485 state_override: Option<StateOverride>,
486 ) -> impl Future<Output = Result<AccessListResult, Self::Error>> + Send
487 where
488 Self: Trace,
489 {
490 self.spawn_with_state_at_block(at, |this, mut db| {
491 let initial = request.as_ref().access_list().cloned().unwrap_or_default();
492 let (evm_env, mut tx_env) = this.prepare_call_env(
493 evm_env,
494 request,
495 &mut db,
496 EvmOverrides::state(state_override),
497 )?;
498
499 let mut evm = this.evm_config().evm_with_env_and_inspector(
500 &mut db,
501 evm_env,
502 AccessListInspector::new(initial),
503 );
504
505 let result = evm.transact(tx_env.clone())?;
506 let access_list = core::mem::take(evm.inspector_mut()).into_access_list();
507 let gas_used = result.result.tx_gas_used();
508 tx_env.set_access_list(access_list.clone());
509 if let Err(err) = Self::Error::ensure_success(result.result) {
510 return Ok(AccessListResult {
511 access_list,
512 gas_used: U256::from(gas_used),
513 error: Some(err.to_string()),
514 });
515 }
516
517 evm.disable_inspector();
519 let result = evm.transact(tx_env)?;
520 let gas_used = result.result.tx_gas_used();
521 let error = Self::Error::ensure_success(result.result).err().map(|e| e.to_string());
522
523 Ok(AccessListResult { access_list, gas_used: U256::from(gas_used), error })
524 })
525 }
526}
527
528pub trait Call:
530 LoadState<
531 RpcConvert: RpcConvert<Evm = Self::Evm>,
532 Error: FromEvmError<Self::Evm>
533 + From<<Self::RpcConvert as RpcConvert>::Error>
534 + From<ProviderError>,
535 > + SpawnBlocking
536{
537 fn call_gas_limit(&self) -> u64 {
541 self.eth_api_settings().gas_cap
542 }
543
544 fn max_simulate_blocks(&self) -> u64 {
546 self.eth_api_settings().max_simulate_blocks
547 }
548
549 fn compute_state_root_for_eth_simulate(&self) -> bool {
551 self.eth_api_settings().compute_state_root_for_eth_simulate
552 }
553
554 fn evm_memory_limit(&self) -> u64 {
556 self.eth_api_settings().evm_memory_limit
557 }
558
559 fn caller_gas_allowance(
561 &self,
562 mut db: impl Database<Error: Into<EthApiError>>,
563 _evm_env: &EvmEnvFor<Self::Evm>,
564 tx_env: &TxEnvFor<Self::Evm>,
565 ) -> Result<u64, Self::Error> {
566 alloy_evm::call::caller_gas_allowance(&mut db, tx_env).map_err(Self::Error::from_eth_err)
567 }
568
569 fn transact<DB>(
572 &self,
573 db: DB,
574 evm_env: EvmEnvFor<Self::Evm>,
575 tx_env: TxEnvFor<Self::Evm>,
576 ) -> Result<ResultAndState<HaltReasonFor<Self::Evm>>, Self::Error>
577 where
578 DB: Database<Error = EvmDatabaseError<ProviderError>> + fmt::Debug,
579 {
580 let mut evm = self.evm_config().evm_with_env(db, evm_env);
581 let res = evm.transact(tx_env).map_err(Self::Error::from_evm_err)?;
582
583 Ok(res)
584 }
585
586 fn transact_with_inspector<DB, I>(
589 &self,
590 db: DB,
591 evm_env: EvmEnvFor<Self::Evm>,
592 tx_env: TxEnvFor<Self::Evm>,
593 inspector: I,
594 ) -> Result<ResultAndState<HaltReasonFor<Self::Evm>>, Self::Error>
595 where
596 DB: Database<Error = EvmDatabaseError<ProviderError>> + fmt::Debug,
597 I: InspectorFor<Self::Evm, DB>,
598 {
599 let mut evm = self.evm_config().evm_with_env_and_inspector(db, evm_env, inspector);
600 let res = evm.transact(tx_env).map_err(Self::Error::from_evm_err)?;
601
602 Ok(res)
603 }
604
605 fn transact_call_at(
612 &self,
613 request: RpcTxReq<<Self::RpcConvert as RpcConvert>::Network>,
614 at: BlockId,
615 overrides: EvmOverrides,
616 ) -> impl Future<Output = Result<ResultAndState<HaltReasonFor<Self::Evm>>, Self::Error>> + Send
617 where
618 Self: LoadPendingBlock,
619 {
620 async move {
621 let permit = self
622 .acquire_owned_blocking_io()
623 .await
624 .map_err(|_| EthApiError::InternalEthError)?;
625 let guard = CancelOnDrop::default();
626 let cancel = guard.clone();
627 let this = self.clone();
628
629 let res = self
630 .spawn_with_call_at(request, at, overrides, move |db, evm_env, tx_env| {
631 let _permit = permit;
632 if cancel.is_cancelled() {
633 return Err(EthApiError::InternalEthError.into())
635 }
636 this.transact(db, evm_env, tx_env)
637 })
638 .await;
639 drop(guard);
640 res
641 }
642 }
643
644 fn spawn_with_state_at_block<F, R>(
646 &self,
647 at: impl Into<BlockId>,
648 f: F,
649 ) -> impl Future<Output = Result<R, Self::Error>> + Send
650 where
651 F: FnOnce(Self, StateCacheDb) -> Result<R, Self::Error> + Send + 'static,
652 R: Send + 'static,
653 {
654 self.spawn_blocking_io_with_state(at.into(), move |this, state| {
655 let db = State::builder()
656 .with_database(StateProviderDatabase::new(state.into_evm_state_provider()))
657 .build();
658 f(this, db)
659 })
660 }
661
662 fn spawn_with_call_at<F, R>(
678 &self,
679 request: RpcTxReq<<Self::RpcConvert as RpcConvert>::Network>,
680 at: BlockId,
681 overrides: EvmOverrides,
682 f: F,
683 ) -> impl Future<Output = Result<R, Self::Error>> + Send
684 where
685 Self: LoadPendingBlock,
686 F: FnOnce(
687 &mut StateCacheDb,
688 EvmEnvFor<Self::Evm>,
689 TxEnvFor<Self::Evm>,
690 ) -> Result<R, Self::Error>
691 + Send
692 + 'static,
693 R: Send + 'static,
694 {
695 async move {
696 let (evm_env, at) = self.evm_env_at(at).await?;
697 self.spawn_with_state_at_block(at, move |this, mut db| {
698 let (evm_env, tx_env) =
699 this.prepare_call_env(evm_env, request, &mut db, overrides)?;
700
701 f(&mut db, evm_env, tx_env)
702 })
703 .await
704 }
705 }
706
707 fn spawn_replay_transaction<F, R>(
720 &self,
721 hash: B256,
722 f: F,
723 ) -> impl Future<Output = Result<Option<R>, Self::Error>> + Send
724 where
725 Self: LoadBlock + LoadTransaction,
726 F: FnOnce(
727 TransactionInfo,
728 ResultAndState<HaltReasonFor<Self::Evm>>,
729 StateCacheDb,
730 ) -> Result<R, Self::Error>
731 + Send
732 + 'static,
733 R: Send + 'static,
734 {
735 async move {
736 let (transaction, block, bal) =
737 match self.transaction_and_block_and_maybe_bal(hash).await? {
738 None => return Ok(None),
739 Some(res) => res,
740 };
741 let (tx, tx_info) = transaction.split();
742
743 let parent_block = block.parent_hash();
746
747 self.spawn_with_state_at_block(parent_block, move |this, mut db| {
748 if let Some((bal, tx_index)) = bal.zip(tx_info.index) {
749 attach_bal_before_tx(&mut db, &bal, tx_index as usize);
750
751 let evm_env = this.evm_env_for_header(block.sealed_block().sealed_header())?;
752 let tx_env = RpcNodeCore::evm_config(&this).tx_env(tx);
753 let res = this.transact(&mut db, evm_env, tx_env)?;
754 return f(tx_info, res, db)
755 }
756
757 let block_txs = block.transactions_recovered();
758
759 let mut executor = RpcNodeCore::evm_config(&this)
760 .executor_for_block(&mut db, block.sealed_block())
761 .map_err(RethError::other)
762 .map_err(Self::Error::from_eth_err)?;
763 executor.apply_pre_execution_changes().map_err(Self::Error::from_eth_err)?;
764
765 for block_tx in block_txs {
767 if block_tx.tx_hash() == tx.tx_hash() {
768 break;
769 }
770 if is_cancelled() {
771 return Err(EthApiError::InternalEthError.into())
772 }
773 executor.execute_transaction(block_tx).map_err(Self::Error::from_eth_err)?;
774 }
775
776 let tx_env = RpcNodeCore::evm_config(&this).tx_env(tx);
777
778 let res = executor.evm_mut().transact(tx_env).map_err(Self::Error::from_evm_err)?;
779 drop(executor);
780 f(tx_info, res, db)
781 })
782 .await
783 .map(Some)
784 }
785 }
786
787 fn replay_transactions_until_with_evm<'a, DB, I, Txs>(
797 &self,
798 evm: &mut EvmFor<Self::Evm, DB, I>,
799 transactions: Txs,
800 target_tx_index: usize,
801 ) -> Result<(), Self::Error>
802 where
803 DB: Database<Error = EvmDatabaseError<ProviderError>> + DatabaseCommit + core::fmt::Debug,
804 I: InspectorFor<Self::Evm, DB>,
805 Txs: IntoIterator<Item = Recovered<&'a ProviderTx<Self::Provider>>>,
806 {
807 for (index, tx) in transactions.into_iter().enumerate() {
808 if index == target_tx_index {
809 break
811 }
812 if is_cancelled() {
813 return Err(EthApiError::InternalEthError.into())
814 }
815
816 let tx_env = self.evm_config().tx_env(tx);
817 evm.transact_commit(tx_env).map_err(Self::Error::from_evm_err)?;
818 }
819 Ok(())
820 }
821
822 fn create_txn_env(
826 &self,
827 evm_env: &EvmEnvFor<Self::Evm>,
828 mut request: RpcTxReq<<Self::RpcConvert as RpcConvert>::Network>,
829 mut db: impl Database<Error: Into<EthApiError>>,
830 ) -> Result<TxEnvFor<Self::Evm>, Self::Error> {
831 if request.as_ref().nonce().is_none() {
832 let nonce = db
833 .basic(request.as_ref().from().unwrap_or_default())
834 .map_err(Into::into)?
835 .map(|acc| acc.nonce)
836 .unwrap_or_default();
837 request.as_mut().set_nonce(nonce);
838 }
839
840 Ok(self.converter().tx_env(request, evm_env)?)
841 }
842
843 #[expect(clippy::type_complexity)]
857 fn prepare_call_env<DB>(
858 &self,
859 mut evm_env: EvmEnvFor<Self::Evm>,
860 mut request: RpcTxReq<<Self::RpcConvert as RpcConvert>::Network>,
861 db: &mut DB,
862 overrides: EvmOverrides,
863 ) -> Result<(EvmEnvFor<Self::Evm>, TxEnvFor<Self::Evm>), Self::Error>
864 where
865 DB: Database + DatabaseCommit + OverrideBlockHashes,
866 EthApiError: From<<DB as Database>::Error>,
867 {
868 let request_has_gas_limit = request.as_ref().gas_limit().is_some();
870
871 if let Some(requested_gas) = request.as_ref().gas_limit() {
872 let global_gas_cap = self.call_gas_limit();
873 if global_gas_cap != 0 && global_gas_cap < requested_gas {
874 debug!(target: "rpc::eth::call", requested_gas, global_gas_cap, "Capping gas limit to global gas cap");
877 request.as_mut().set_gas_limit(global_gas_cap);
878 }
879 } else {
880 request.as_mut().set_gas_limit(self.call_gas_limit());
882 }
883
884 evm_env.cfg_env.disable_block_gas_limit = true;
887
888 evm_env.cfg_env.disable_eip3607 = true;
891
892 evm_env.cfg_env.disable_base_fee = true;
896
897 if !evm_env.cfg_env.is_amsterdam_eip8037_enabled() {
901 evm_env.cfg_env.tx_gas_limit_cap = Some(u64::MAX);
902 }
903
904 evm_env.cfg_env.disable_fee_charge = true;
908
909 evm_env.cfg_env.memory_limit = self.evm_memory_limit();
910
911 request.as_mut().take_nonce();
913
914 if let Some(block_overrides) = overrides.block {
915 apply_block_overrides(*block_overrides, db, evm_env.block_env.inner_mut());
916 }
917 if let Some(state_overrides) = overrides.state {
918 apply_state_overrides(state_overrides, db)
919 .map_err(EthApiError::from_state_overrides_err)?;
920 }
921
922 let mut tx_env = self.create_txn_env(&evm_env, request, &mut *db)?;
923
924 if tx_env.gas_price() == 0 {
926 evm_env.block_env.inner_mut().basefee = 0;
927 }
928
929 if !request_has_gas_limit {
930 if tx_env.gas_price() > 0 {
932 trace!(target: "rpc::eth::call", ?tx_env, "Applying gas limit cap with caller allowance");
934 let mut cap = self.caller_gas_allowance(db, &evm_env, &tx_env)?;
935 if self.call_gas_limit() != 0 {
937 cap = cap.min(tx_env.gas_limit());
938 }
939 tx_env.set_gas_limit(cap.min(evm_env.block_env.gas_limit()));
941 }
942 }
943
944 Ok((evm_env, tx_env))
945 }
946}