1use super::{LoadBlock, LoadPendingBlock, LoadState, LoadTransaction, SpawnBlocking, Trace};
5use crate::{helpers::estimate::EstimateCall, FromEvmError, FullEthApiTypes, RpcBlock};
6use alloy_consensus::{transaction::Transaction, BlockHeader};
7use alloy_eip7928::BlockAccessIndex;
8use alloy_eips::{
9 eip1559::calc_effective_gas_price, eip2718::Typed2718, eip2930::AccessListResult,
10};
11use alloy_network::TransactionBuilder;
12use alloy_primitives::{Bytes, B256, U256};
13use alloy_rpc_types_eth::{
14 simulate::{SimBlock, SimulatePayload, SimulatedBlock},
15 state::{EvmOverrides, StateOverride},
16 BlockId, Bundle, EthCallResponse, StateContext, TransactionInfo,
17};
18use evm2::evm::{CacheDB, DynDatabase};
19use evm2_inspectors::{access_list::AccessListInspector, transfer::TransferInspector};
20use futures::Future;
21use reth_chainspec::{ChainSpecProvider, EthChainSpec, EthereumHardforks};
22use reth_errors::{ProviderError, RethError};
23use reth_evm::{
24 database::StateProviderDatabase,
25 execute::{BlockBuilder, BlockExecutor, BlockExecutorFactory, BlockTransactionResult},
26 BlockExecutorFor, BundleState, ConfigureEvm, Database, Evm, EvmEnv, EvmEnvFor, EvmTypesFor,
27 TransactionEnvMut, TxEnvFor, TxResultWithStateFor,
28};
29use reth_execution_types::BundleSource;
30use reth_primitives_traits::{BlockBody, BlockTy, Recovered, RecoveredBlock};
31use reth_rpc_convert::{RpcConvert, RpcTxReq};
32use reth_rpc_eth_types::{
33 cache::db::{
34 apply_block_overrides, apply_state_overrides, apply_state_overrides_with_state,
35 attach_bal_before_tx,
36 },
37 error::{AsEthApiError, FromEthApiError},
38 simulate::{self, EthSimulateError, SimulatedState},
39 utils::CallManyBudget,
40 EthApiError, RpcInvalidTransactionError, StateCacheDb,
41};
42use reth_storage_api::{BlockIdReader, ProviderTx, StateProvider};
43use reth_tasks::{cancel::is_cancelled, CancelOnDrop};
44use std::fmt;
45use tracing::{debug, trace};
46
47pub type SimulatedBlocksResult<N, E> = Result<Vec<SimulatedBlock<RpcBlock<N>>>, E>;
49
50pub trait EthCall: EstimateCall + LoadBlock + FullEthApiTypes {
53 fn estimate_gas_at(
55 &self,
56 request: RpcTxReq<<Self::RpcConvert as RpcConvert>::Network>,
57 at: BlockId,
58 overrides: EvmOverrides,
59 ) -> impl Future<Output = Result<U256, Self::Error>> + Send {
60 EstimateCall::estimate_gas_at(self, request, at, overrides)
61 }
62
63 fn simulate_v1(
68 &self,
69 payload: SimulatePayload<RpcTxReq<<Self::RpcConvert as RpcConvert>::Network>>,
70 block: Option<BlockId>,
71 ) -> impl Future<Output = SimulatedBlocksResult<Self::NetworkTypes, Self::Error>> + Send {
72 async move {
73 if payload.block_state_calls.len() > self.max_simulate_blocks() as usize {
74 return Err(EthApiError::other(EthSimulateError::TooManyBlocks).into())
75 }
76
77 let block = block.unwrap_or_default();
78
79 let SimulatePayload {
80 block_state_calls,
81 trace_transfers,
82 validation,
83 return_full_transactions,
84 } = payload;
85
86 if block_state_calls.is_empty() {
87 return Err(EthApiError::InvalidParams(String::from("calls are empty.")).into())
88 }
89
90 let permit = self
91 .acquire_owned_blocking_io()
92 .await
93 .map_err(|_| EthApiError::InternalEthError)?;
94
95 let base_block = self
96 .recovered_block(block)
97 .await?
98 .ok_or_else(|| EthApiError::other(EthSimulateError::BlockNotFound { block }))?;
99 let parent = base_block.sealed_header().clone();
100 let max_simulate_blocks = self.max_simulate_blocks();
101 let state_at = if block.is_pending() { block } else { parent.hash().into() };
104
105 self.spawn_with_state_at_block(state_at, move |this, db| {
106 let _permit = permit;
107 let state_provider = db.db.into_inner().into_inner().0;
108 let mut db = CacheDB::new(evm2::evm::Db::new(StateProviderDatabase::new(
109 (&state_provider).into_evm_state_provider(),
110 )));
111 let mut parent = parent;
112 let mut simulation_state =
113 this.compute_state_root_for_eth_simulate().then(SimulatedState::default);
114
115 let chain_id = this.provider().chain_spec().chain_id();
116
117 let block_state_calls = simulate::sanitize_chain(
122 block_state_calls,
123 &parent,
124 chain_id,
125 max_simulate_blocks,
126 )?;
127
128 let mut blocks: Vec<SimulatedBlock<RpcBlock<Self::NetworkTypes>>> =
129 Vec::with_capacity(block_state_calls.len());
130
131 let call_gas_limit = this.call_gas_limit();
132 let mut remaining_call_gas_limit = (call_gas_limit > 0).then_some(call_gas_limit);
133
134 for block in block_state_calls {
135 let SimBlock { block_overrides, state_overrides, calls } = block;
136
137 let attributes = this
138 .pending_env_builder()
139 .pending_env_attributes(&parent, block_overrides.as_ref())
140 .map_err(Self::Error::from_eth_err)?;
141
142 let mut evm_env = this
143 .evm_config()
144 .next_evm_env(&parent, &attributes)
145 .map_err(RethError::other)
146 .map_err(Self::Error::from_eth_err)?;
147
148 evm_env.version_mut().features.remove(evm2::EvmFeatures::EIP3607);
150
151 if !validation || !evm_env.version().feature(evm2::EvmFeatures::EIP8037) {
155 evm_env.version_mut().tx_gas_limit_cap = u64::MAX;
156 }
157
158 if !validation {
159 evm_env.version_mut().features.remove(evm2::EvmFeatures::NONCE_CHECK);
161 evm_env.version_mut().features.remove(evm2::EvmFeatures::BASE_FEE_CHECK);
162 evm_env.block_env_mut().basefee = U256::ZERO;
163 }
164
165 evm_env.block_env_mut().prevrandao = U256::ZERO;
169 if !this
170 .provider()
171 .chain_spec()
172 .is_paris_active_at_block(evm_env.block_env().number.to())
173 {
174 evm_env.block_env_mut().difficulty = parent.difficulty();
175 }
176
177 if let Some(block_overrides) = block_overrides {
178 if let Some(gas_limit_override) = block_overrides.gas_limit &&
180 gas_limit_override > evm_env.block_env().gas_limit.to::<u64>() &&
181 gas_limit_override > this.call_gas_limit()
182 {
183 return Err(EthApiError::other(EthSimulateError::GasLimitReached).into())
184 }
185 apply_block_overrides(block_overrides, &mut db, &mut evm_env);
186 }
187 if let Some(ref state_overrides) = state_overrides {
188 let mut changes = simulation_state.as_ref().map(|_| BundleState::default());
189 apply_state_overrides_with_state(
190 state_overrides.clone(),
191 &mut db,
192 changes.as_mut(),
193 )
194 .map_err(Self::Error::from_eth_err)?;
195 if let Some(simulation_state) = simulation_state.as_mut() &&
196 let Some(changes) = changes
197 {
198 simulation_state
199 .extend(&state_provider, &changes)
200 .map_err(Self::Error::from_eth_err)?;
201 }
202 }
203
204 let chain_id = evm_env.chain_id();
205 let build_bal = this.provider().chain_spec().is_amsterdam_active_at_timestamp(
206 evm_env.block_env().timestamp.to::<u64>(),
207 );
208
209 let ctx = this
210 .evm_config()
211 .context_for_next_block(&parent, attributes)
212 .map_err(RethError::other)
213 .map_err(Self::Error::from_eth_err)?;
214 let map_err = |e: EthApiError| -> Self::Error {
215 match e.as_simulate_error() {
216 Some(sim_err) => Self::Error::from_eth_err(EthApiError::other(sim_err)),
217 None => Self::Error::from_eth_err(e),
218 }
219 };
220
221 let trace_transfers =
223 trace_transfers && !evm_env.version().feature(evm2::EvmFeatures::EIP7708);
224 let mut evm = this.evm_config().evm_with_env(&mut db, evm_env.clone());
225 if trace_transfers {
226 evm.set_inspector(TransferInspector::new(false).with_logs(true));
229 }
230 let mut builder =
231 this.evm_config().create_block_builder(evm, evm_env, &parent, ctx);
232 if build_bal {
233 builder.executor_mut().enable_block_access_list_builder();
234 }
235
236 if let Some(ref state_overrides) = state_overrides {
237 simulate::apply_precompile_overrides(state_overrides, builder.evm_mut())
238 .map_err(|e| Self::Error::from_eth_err(EthApiError::other(e)))?;
239 }
240
241 let (result, results) = simulate::execute_transactions(
242 builder,
243 &*state_provider,
244 calls,
245 &mut remaining_call_gas_limit,
246 chain_id,
247 simulation_state.as_mut(),
248 this.converter(),
249 |call, db| this.simulate_call_nonce(call, db),
250 )
251 .map_err(map_err)?;
252
253 db.commit_source(&BundleSource(&result.execution_state));
254 let simulated_header = result.block.clone_sealed_header();
255 db.insert_block_hash(
256 &U256::from(simulated_header.number()),
257 &simulated_header.hash(),
258 );
259 parent = simulated_header;
260
261 let block =
262 simulate::build_simulated_block::<Self::Error, _, EvmTypesFor<Self::Evm>>(
263 result.block,
264 results,
265 return_full_transactions.into(),
266 this.converter(),
267 )?;
268
269 blocks.push(block);
270 }
271
272 Ok(blocks)
273 })
274 .await
275 }
276 }
277
278 fn call(
280 &self,
281 request: RpcTxReq<<Self::RpcConvert as RpcConvert>::Network>,
282 block_number: Option<BlockId>,
283 overrides: EvmOverrides,
284 ) -> impl Future<Output = Result<Bytes, Self::Error>> + Send {
285 async move {
286 let res =
287 self.transact_call_at(request, block_number.unwrap_or_default(), overrides).await?;
288
289 Self::Error::ensure_success::<EvmTypesFor<Self::Evm>>(res.result)
290 }
291 }
292
293 fn call_many(
298 &self,
299 bundles: Vec<Bundle<RpcTxReq<<Self::RpcConvert as RpcConvert>::Network>>>,
300 state_context: Option<StateContext>,
301 mut state_override: Option<StateOverride>,
302 ) -> impl Future<Output = Result<Vec<Vec<EthCallResponse>>, Self::Error>> + Send
303 where
304 Self: Trace,
305 {
306 async move {
307 if bundles.is_empty() {
309 return Err(EthApiError::InvalidParams(String::from("bundles are empty.")).into());
310 }
311 let mut budget = CallManyBudget::for_bundles(&bundles, self.call_gas_limit())?;
312
313 let permit = self
314 .acquire_owned_blocking_io()
315 .await
316 .map_err(|_| EthApiError::InternalEthError)?;
317
318 let StateContext { transaction_index, block_number } =
319 state_context.unwrap_or_default();
320 let transaction_index = transaction_index.unwrap_or_default();
321
322 let mut target_block = block_number.unwrap_or_default();
323 let is_block_target_pending = target_block.is_pending();
324
325 if !is_block_target_pending {
328 let Some(block_hash) = self
329 .provider()
330 .block_hash_for_id(target_block)
331 .map_err(Self::Error::from_eth_err::<ProviderError>)?
332 else {
333 return Err(EthApiError::HeaderNotFound(target_block).into())
334 };
335 target_block = block_hash.into();
336 }
337
338 let block = self
339 .recovered_block(target_block)
340 .await?
341 .ok_or(EthApiError::HeaderNotFound(target_block))?;
342 let evm_env = self.evm_env_for_header(block.sealed_block().sealed_header())?;
343
344 let mut at = block.parent_hash();
348 let mut replay_block_txs = true;
349
350 let num_txs =
351 transaction_index.index().unwrap_or_else(|| block.body().transactions().len());
352 if !is_block_target_pending && num_txs == block.body().transactions().len() {
356 at = block.hash();
357 replay_block_txs = false;
358 }
359
360 self.spawn_with_state_at_block(at, move |this, mut db| {
361 let _permit = permit;
362 let mut all_results = Vec::with_capacity(bundles.len());
363
364 if replay_block_txs {
365 this.replay_block_until(&mut db, &block, num_txs, None)?;
368 }
369
370 for (bundle_index, bundle) in bundles.into_iter().enumerate() {
372 let Bundle { transactions, block_override } = bundle;
373 if transactions.is_empty() {
374 continue;
376 }
377
378 let mut bundle_results = Vec::with_capacity(transactions.len());
379 let block_overrides = block_override.map(Box::new);
380
381 for (tx_index, tx) in transactions.into_iter().enumerate() {
383 if is_cancelled() {
384 return Err(EthApiError::InternalEthError.into())
385 }
386
387 let overrides =
390 EvmOverrides::new(state_override.take(), block_overrides.clone());
391
392 let (current_evm_env, mut prepared_tx) = this
393 .prepare_call_env(evm_env.clone(), tx, &mut db, overrides)
394 .map_err(|err| {
395 Self::Error::from_eth_err(EthApiError::call_many_error(
396 bundle_index,
397 tx_index,
398 err.into(),
399 ))
400 })?;
401 budget.admit(&mut prepared_tx)?;
402 let res = this.transact(&mut db, current_evm_env, prepared_tx).map_err(
403 |err| {
404 Self::Error::from_eth_err(EthApiError::call_many_error(
405 bundle_index,
406 tx_index,
407 budget.map_call_err(err).into(),
408 ))
409 },
410 )?;
411 budget.charge(&res.result).map_err(|err| {
412 Self::Error::from_eth_err(EthApiError::call_many_error(
413 bundle_index,
414 tx_index,
415 err.into(),
416 ))
417 })?;
418
419 match Self::Error::ensure_success::<EvmTypesFor<Self::Evm>>(res.result) {
420 Ok(output) => {
421 bundle_results
422 .push(EthCallResponse { value: Some(output), error: None });
423 }
424 Err(err) => {
425 bundle_results.push(EthCallResponse {
426 value: None,
427 error: Some(err.to_string()),
428 });
429 }
430 }
431
432 db.commit_source(&res.pending_state);
435 }
436
437 all_results.push(bundle_results);
438 }
439
440 Ok(all_results)
441 })
442 .await
443 }
444 }
445
446 fn create_access_list_at(
449 &self,
450 request: RpcTxReq<<Self::RpcConvert as RpcConvert>::Network>,
451 block_number: Option<BlockId>,
452 state_override: Option<StateOverride>,
453 ) -> impl Future<Output = Result<AccessListResult, Self::Error>> + Send
454 where
455 Self: Trace,
456 {
457 async move {
458 let block_id = block_number.unwrap_or_default();
459 let (evm_env, at) = self.evm_env_at(block_id).await?;
460
461 self.create_access_list_with(evm_env, at, request, state_override).await
462 }
463 }
464
465 fn create_access_list_with(
468 &self,
469 evm_env: EvmEnvFor<Self::Evm>,
470 at: BlockId,
471 request: RpcTxReq<<Self::RpcConvert as RpcConvert>::Network>,
472 state_override: Option<StateOverride>,
473 ) -> impl Future<Output = Result<AccessListResult, Self::Error>> + Send
474 where
475 Self: Trace,
476 {
477 self.spawn_with_state_at_block(at, |this, mut db| {
478 let initial = request.as_ref().access_list().cloned().unwrap_or_default();
479 let (evm_env, mut tx_env) = this.prepare_call_env(
480 evm_env,
481 request,
482 &mut db,
483 EvmOverrides::state(state_override),
484 )?;
485 let chain_id = evm_env.chain_id();
486
487 let mut evm = this.evm_config().evm_with_env(&mut db, evm_env);
488
489 let inspector =
492 AccessListInspector::new(initial).with_excluded_from_tx(tx_env.inner(), chain_id);
493 let (inspector, result) = evm
494 .transact_with_inspector(&tx_env, inspector)
495 .map_err(Self::Error::from_evm_err)?;
496 let access_list = inspector.into_access_list();
497 let gas_used = result.result.tx_gas_used();
498 if let Err(err) = Self::Error::ensure_success::<EvmTypesFor<Self::Evm>>(result.result) {
499 return Ok(AccessListResult {
500 access_list,
501 gas_used: U256::from(gas_used),
502 error: Some(err.to_string()),
503 });
504 }
505
506 tx_env.inner_mut().set_access_list(access_list.clone());
507
508 let result = evm.transact_result(&tx_env).map_err(Self::Error::from_evm_err)?;
510 let gas_used = result.tx_gas_used();
511 let error = Self::Error::ensure_success::<EvmTypesFor<Self::Evm>>(result)
512 .err()
513 .map(|e| e.to_string());
514
515 Ok(AccessListResult { access_list, gas_used: U256::from(gas_used), error })
516 })
517 }
518}
519
520pub trait Call:
522 LoadState<
523 RpcConvert: RpcConvert<Evm = Self::Evm>,
524 Error: FromEvmError<Self::Evm>
525 + From<<Self::RpcConvert as RpcConvert>::Error>
526 + From<ProviderError>,
527 > + SpawnBlocking
528{
529 fn call_gas_limit(&self) -> u64 {
533 self.eth_api_settings().gas_cap
534 }
535
536 fn max_simulate_blocks(&self) -> u64 {
538 self.eth_api_settings().max_simulate_blocks
539 }
540
541 fn compute_state_root_for_eth_simulate(&self) -> bool {
543 self.eth_api_settings().compute_state_root_for_eth_simulate
544 }
545
546 fn evm_memory_limit(&self) -> u64 {
548 self.eth_api_settings().evm_memory_limit
549 }
550
551 fn simulate_call_nonce(
556 &self,
557 _request: &RpcTxReq<<Self::RpcConvert as RpcConvert>::Network>,
558 _db: &mut dyn DynDatabase,
559 ) -> Result<Option<u64>, EthApiError> {
560 Ok(None)
561 }
562
563 fn caller_gas_allowance(
565 &self,
566 mut db: impl Database<Error: Into<EthApiError>>,
567 _evm_env: &EvmEnvFor<Self::Evm>,
568 tx_env: &TxEnvFor<Self::Evm>,
569 ) -> Result<u64, Self::Error> {
570 let balance = db
571 .get_account(&tx_env.signer())
572 .map_err(Into::into)
573 .map_err(Self::Error::from_eth_err)?
574 .map(|account| account.balance)
575 .unwrap_or_default();
576 let value = tx_env.value();
577 let blob_fee = if tx_env.is_eip4844() {
578 U256::from(tx_env.blob_gas_used().unwrap_or_default()) *
579 U256::from(tx_env.max_fee_per_blob_gas().unwrap_or_default())
580 } else {
581 U256::ZERO
582 };
583 let available = balance
586 .checked_sub(value)
587 .and_then(|remaining| remaining.checked_sub(blob_fee))
588 .ok_or_else(|| {
589 EthApiError::from(RpcInvalidTransactionError::InsufficientFunds {
590 cost: value.saturating_add(blob_fee),
591 balance,
592 })
593 })?;
594
595 Ok(available
596 .checked_div(U256::from(tx_env.effective_gas_price(None)))
597 .unwrap_or_default()
598 .saturating_to())
599 }
600
601 fn transact<DB>(
604 &self,
605 db: DB,
606 evm_env: EvmEnvFor<Self::Evm>,
607 tx_env: TxEnvFor<Self::Evm>,
608 ) -> Result<TxResultWithStateFor<Self::Evm>, Self::Error>
609 where
610 DB: Database + fmt::Debug,
611 {
612 let mut evm = self.evm_config().evm_with_env(db, evm_env);
613 let res = evm.transact(&tx_env).map_err(Self::Error::from_evm_err)?;
614
615 Ok(res)
616 }
617
618 fn transact_with_inspector<DB, I>(
621 &self,
622 db: DB,
623 evm_env: EvmEnvFor<Self::Evm>,
624 tx_env: TxEnvFor<Self::Evm>,
625 inspector: I,
626 ) -> Result<(I, TxResultWithStateFor<Self::Evm>), Self::Error>
627 where
628 DB: Database + fmt::Debug,
629 I: evm2::Inspector<EvmTypesFor<Self::Evm>> + 'static,
630 {
631 let mut evm = self.evm_config().evm_with_env(db, evm_env);
632 let res =
633 evm.transact_with_inspector(&tx_env, inspector).map_err(Self::Error::from_evm_err)?;
634
635 Ok(res)
636 }
637
638 fn transact_call_at(
645 &self,
646 request: RpcTxReq<<Self::RpcConvert as RpcConvert>::Network>,
647 at: BlockId,
648 overrides: EvmOverrides,
649 ) -> impl Future<Output = Result<TxResultWithStateFor<Self::Evm>, Self::Error>> + Send
650 where
651 Self: LoadPendingBlock,
652 {
653 async move {
654 let permit = self
655 .acquire_owned_blocking_io()
656 .await
657 .map_err(|_| EthApiError::InternalEthError)?;
658 let guard = CancelOnDrop::default();
659 let cancel = guard.clone();
660 let this = self.clone();
661
662 let res = self
663 .spawn_with_call_at(request, at, overrides, move |db, evm_env, tx_env| {
664 let _permit = permit;
665 if cancel.is_cancelled() {
666 return Err(EthApiError::InternalEthError.into())
668 }
669 this.transact(db, evm_env, tx_env)
670 })
671 .await;
672 drop(guard);
673 res
674 }
675 }
676
677 fn spawn_with_state_at_block<F, R>(
679 &self,
680 at: impl Into<BlockId>,
681 f: F,
682 ) -> impl Future<Output = Result<R, Self::Error>> + Send
683 where
684 F: FnOnce(Self, StateCacheDb) -> Result<R, Self::Error> + Send + 'static,
685 R: Send + 'static,
686 {
687 self.spawn_blocking_io_with_state(at.into(), move |this, state| {
688 let db = evm2::evm::CacheDB::new(evm2::evm::Db::new(StateProviderDatabase::new(
689 state.into_evm_state_provider(),
690 )));
691 f(this, db)
692 })
693 }
694
695 fn spawn_with_call_at<F, R>(
711 &self,
712 request: RpcTxReq<<Self::RpcConvert as RpcConvert>::Network>,
713 at: BlockId,
714 overrides: EvmOverrides,
715 f: F,
716 ) -> impl Future<Output = Result<R, Self::Error>> + Send
717 where
718 Self: LoadPendingBlock,
719 F: FnOnce(
720 &mut StateCacheDb,
721 EvmEnvFor<Self::Evm>,
722 TxEnvFor<Self::Evm>,
723 ) -> Result<R, Self::Error>
724 + Send
725 + 'static,
726 R: Send + 'static,
727 {
728 async move {
729 let (evm_env, at) = self.evm_env_at(at).await?;
730 self.spawn_with_state_at_block(at, move |this, mut db| {
731 let (evm_env, tx_env) =
732 this.prepare_call_env(evm_env, request, &mut db, overrides)?;
733
734 f(&mut db, evm_env, tx_env)
735 })
736 .await
737 }
738 }
739
740 fn spawn_replay_transaction<F, R>(
753 &self,
754 hash: B256,
755 f: F,
756 ) -> impl Future<Output = Result<Option<R>, Self::Error>> + Send
757 where
758 Self: LoadBlock + LoadTransaction,
759 F: FnOnce(
760 TransactionInfo,
761 TxResultWithStateFor<Self::Evm>,
762 StateCacheDb,
763 ) -> Result<R, Self::Error>
764 + Send
765 + 'static,
766 R: Send + 'static,
767 {
768 async move {
769 let (transaction, block, bal) =
770 match self.transaction_and_block_and_maybe_bal(hash).await? {
771 None => return Ok(None),
772 Some(res) => res,
773 };
774 let (tx, tx_info) = transaction.split();
775
776 let parent_block = block.parent_hash();
779 let evm_env = self.evm_env_for_header(block.sealed_block().sealed_header())?;
780
781 self.spawn_with_state_at_block(parent_block, move |this, mut db| {
782 if let Some((bal, tx_index)) = bal.zip(tx_info.index) {
783 attach_bal_before_tx(&mut db, &bal, tx_index as usize);
784
785 let mut executor = this.block_executor(&block, &mut db, evm_env)?;
786 executor.set_block_access_index(BlockAccessIndex::from_tx_index(tx_index));
787 let res = executor
788 .execute_transaction_without_commit(tx)
789 .map_err(Self::Error::from_evm_err)?
790 .into_result();
791 let cache = executor.evm_mut().take_state_cache();
792 drop(executor);
793 db.cache.merge(cache);
794 return f(tx_info, res, db)
795 }
796
797 let block_txs = block.transactions_recovered();
798
799 let ctx = this
800 .evm_config()
801 .context_for_block(block.sealed_block())
802 .map_err(RethError::other)
803 .map_err(Self::Error::from_eth_err)?;
804 let changes = this
805 .evm_config()
806 .pre_block_state_changes(&mut db, evm_env.clone(), ctx)
807 .map_err(|err| EthApiError::EvmCustom(err.to_string()))
808 .map_err(Self::Error::from_eth_err)?;
809 db.commit_source(&reth_execution_types::BundleSource(&changes));
810
811 let mut executor = this.block_executor(&block, &mut db, evm_env)?;
812 this.replay_transactions_until_with_executor(
813 &mut executor,
814 block_txs,
815 tx_info.index.expect("included transaction has an index") as usize,
816 )?;
817 let res = executor
818 .execute_transaction_without_commit(tx)
819 .map_err(Self::Error::from_evm_err)?
820 .into_result();
821 let cache = executor.evm_mut().take_state_cache();
822 drop(executor);
823 db.cache.merge(cache);
824 f(tx_info, res, db)
825 })
826 .await
827 .map(Some)
828 }
829 }
830
831 fn replay_transactions_until_with_executor<'a, Txs>(
836 &self,
837 executor: &mut BlockExecutorFor<'_, Self::Evm>,
838 transactions: Txs,
839 target_tx_index: usize,
840 ) -> Result<(), Self::Error>
841 where
842 Txs: IntoIterator<Item = Recovered<&'a ProviderTx<Self::Provider>>>,
843 {
844 for (index, tx) in transactions.into_iter().enumerate() {
845 if index == target_tx_index {
846 break
848 }
849 if is_cancelled() {
850 return Err(EthApiError::InternalEthError.into())
851 }
852
853 executor.execute_transaction(tx).map_err(Self::Error::from_evm_err)?;
854 }
855 Ok(())
856 }
857
858 fn block_executor<'a>(
866 &'a self,
867 block: &'a RecoveredBlock<BlockTy<Self::Primitives>>,
868 db: &'a mut StateCacheDb,
869 evm_env: EvmEnvFor<Self::Evm>,
870 ) -> Result<BlockExecutorFor<'a, Self::Evm>, Self::Error> {
871 let ctx = self
872 .evm_config()
873 .context_for_block(block.sealed_block())
874 .map_err(RethError::other)
875 .map_err(Self::Error::from_eth_err)?;
876 let evm = self.evm_config().evm_with_env(db, evm_env);
877 Ok(self.evm_config().block_executor_factory().create_executor(evm, ctx))
878 }
879
880 fn create_txn_env(
884 &self,
885 evm_env: &EvmEnvFor<Self::Evm>,
886 mut request: RpcTxReq<<Self::RpcConvert as RpcConvert>::Network>,
887 mut db: impl Database<Error: Into<EthApiError>>,
888 ) -> Result<TxEnvFor<Self::Evm>, Self::Error> {
889 if request.as_ref().nonce().is_none() {
890 let nonce = db
891 .get_account(&request.as_ref().from().unwrap_or_default())
892 .map_err(Into::into)
893 .map_err(Self::Error::from_eth_err)?
894 .map(|account| account.nonce)
895 .unwrap_or_default();
896 request.as_mut().set_nonce(nonce);
897 }
898
899 Ok(self.converter().tx_env(request, evm_env)?)
900 }
901
902 #[expect(clippy::type_complexity)]
916 fn prepare_call_env<DB>(
917 &self,
918 mut evm_env: EvmEnvFor<Self::Evm>,
919 mut request: RpcTxReq<<Self::RpcConvert as RpcConvert>::Network>,
920 db: &mut CacheDB<DB>,
921 overrides: EvmOverrides,
922 ) -> Result<(EvmEnvFor<Self::Evm>, TxEnvFor<Self::Evm>), Self::Error>
923 where
924 DB: DynDatabase,
925 {
926 let requested_gas = request.as_ref().gas_limit();
928
929 evm_env.version_mut().features.remove(evm2::EvmFeatures::BLOCK_GAS_LIMIT_CHECK);
932
933 evm_env.version_mut().features.remove(evm2::EvmFeatures::EIP3607);
936
937 evm_env.version_mut().features.remove(evm2::EvmFeatures::BASE_FEE_CHECK);
941
942 if !evm_env.version().feature(evm2::EvmFeatures::EIP8037) {
946 evm_env.version_mut().tx_gas_limit_cap = u64::MAX;
947 }
948
949 evm_env.version_mut().features.remove(evm2::EvmFeatures::FEE_CHARGE);
953
954 evm_env
957 .version_mut()
958 .features
959 .remove(evm2::EvmFeatures::BALANCE_CHECK | evm2::EvmFeatures::BALANCE_TOP_UP);
960
961 evm_env.version_mut().memory_limit = self.evm_memory_limit();
962
963 request.as_mut().take_nonce();
965
966 if let Some(block_overrides) = overrides.block {
967 apply_block_overrides(*block_overrides, db, &mut evm_env);
968 }
969 if let Some(state_overrides) = overrides.state {
970 apply_state_overrides(state_overrides, db)
971 .map_err(EthApiError::from_state_overrides_err)?;
972 }
973
974 let gas_price = request_gas_price(request.as_ref(), evm_env.block_base_fee());
975 let mut tx_env = self.create_txn_env(&evm_env, request, &mut *db)?;
979
980 if let Some(requested_gas) = requested_gas {
981 let global_gas_cap = self.call_gas_limit();
982 if global_gas_cap != 0 && global_gas_cap < requested_gas {
983 debug!(target: "rpc::eth::call", requested_gas, global_gas_cap, "Capping gas limit to global gas cap");
986 tx_env.inner_mut().set_gas_limit(global_gas_cap);
987 }
988 } else {
989 tx_env
991 .inner_mut()
992 .set_gas_limit(self.call_gas_limit().min(evm_env.version().tx_gas_caps().0));
993 }
994
995 if gas_price == 0 {
997 evm_env.block_env_mut().basefee = U256::ZERO;
998 }
999
1000 if requested_gas.is_none() {
1001 if gas_price > 0 {
1003 trace!(target: "rpc::eth::call", ?tx_env, "Applying gas limit cap with caller allowance");
1005 let mut cap = self.caller_gas_allowance(&mut *db, &evm_env, &tx_env)?;
1006 if self.call_gas_limit() != 0 {
1008 cap = cap.min(tx_env.gas_limit());
1009 }
1010 tx_env
1012 .inner_mut()
1013 .set_gas_limit(cap.min(evm_env.block_env().gas_limit.to::<u64>()));
1014 }
1015 }
1016
1017 Ok((evm_env, tx_env))
1018 }
1019}
1020
1021pub(super) fn request_gas_price(
1022 request: &alloy_rpc_types_eth::TransactionRequest,
1023 block_base_fee: u64,
1024) -> u128 {
1025 if let Some(gas_price) = request.gas_price {
1026 return gas_price
1027 }
1028
1029 match (request.max_fee_per_gas, request.max_priority_fee_per_gas) {
1030 (None, None) => 0,
1031 (max_fee, priority_fee) => calc_effective_gas_price(
1032 max_fee.unwrap_or(u128::MAX),
1033 priority_fee.unwrap_or_default(),
1034 Some(block_base_fee),
1035 ),
1036 }
1037}