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, HaltReasonFor, InspectorFor, TransactionEnvMut, TxEnvFor,
26};
27use reth_node_api::BlockBody;
28use reth_primitives_traits::Recovered;
29use reth_revm::{
30 cancelled::CancelOnDrop,
31 database::StateProviderDatabase,
32 db::{bal::EvmDatabaseError, State},
33};
34use reth_rpc_convert::{RpcConvert, RpcTxReq};
35use reth_rpc_eth_types::{
36 cache::db::StateProviderTraitObjWrapper,
37 error::{AsEthApiError, FromEthApiError},
38 simulate::{self, EthSimulateError},
39 EthApiError, StateCacheDb,
40};
41use reth_storage_api::{BlockIdReader, ProviderTx, StateProviderBox};
42use revm::{
43 context::Block,
44 context_interface::{result::ResultAndState, Cfg, Transaction},
45 Database, DatabaseCommit,
46};
47use revm_inspectors::{access_list::AccessListInspector, transfer::TransferInspector};
48use std::collections::BTreeMap;
49use tracing::{trace, warn};
50
51pub type SimulatedBlocksResult<N, E> = Result<Vec<SimulatedBlock<RpcBlock<N>>>, E>;
53
54pub trait EthCall: EstimateCall + Call + LoadPendingBlock + LoadBlock + FullEthApiTypes {
57 fn estimate_gas_at(
59 &self,
60 request: RpcTxReq<<Self::RpcConvert as RpcConvert>::Network>,
61 at: BlockId,
62 overrides: EvmOverrides,
63 ) -> impl Future<Output = Result<U256, Self::Error>> + Send {
64 EstimateCall::estimate_gas_at(self, request, at, overrides)
65 }
66
67 fn simulate_v1(
72 &self,
73 payload: SimulatePayload<RpcTxReq<<Self::RpcConvert as RpcConvert>::Network>>,
74 block: Option<BlockId>,
75 ) -> impl Future<Output = SimulatedBlocksResult<Self::NetworkTypes, Self::Error>> + Send {
76 async move {
77 if payload.block_state_calls.len() > self.max_simulate_blocks() as usize {
78 return Err(EthApiError::other(EthSimulateError::TooManyBlocks).into())
79 }
80
81 let block = block.unwrap_or_default();
82
83 let SimulatePayload {
84 block_state_calls,
85 trace_transfers,
86 validation,
87 return_full_transactions,
88 } = payload;
89
90 if block_state_calls.is_empty() {
91 return Err(EthApiError::InvalidParams(String::from("calls are empty.")).into())
92 }
93
94 let _permit = self.acquire_owned_blocking_io().await;
95
96 let base_block = self
97 .recovered_block(block)
98 .await?
99 .ok_or_else(|| EthApiError::other(EthSimulateError::BlockNotFound { block }))?;
100 let parent = base_block.sealed_header().clone();
101 let max_simulate_blocks = self.max_simulate_blocks();
102
103 self.spawn_with_state_at_block(block, move |this, db| {
104 let state_provider = db.database.0 .0;
105 let mut db = State::builder()
106 .with_database(StateProviderDatabase::new(&state_provider))
107 .with_bundle_update()
108 .build();
109 let mut parent = parent;
110
111 let chain_id = this.provider().chain_spec().chain_id();
112
113 let block_state_calls = simulate::sanitize_chain(
118 block_state_calls,
119 &parent,
120 chain_id,
121 max_simulate_blocks,
122 )?;
123
124 let mut blocks: Vec<SimulatedBlock<RpcBlock<Self::NetworkTypes>>> =
125 Vec::with_capacity(block_state_calls.len());
126
127 let call_gas_limit = this.call_gas_limit();
128 let mut remaining_call_gas_limit = (call_gas_limit > 0).then_some(call_gas_limit);
129
130 for block in block_state_calls {
131 let SimBlock { block_overrides, state_overrides, calls } = block;
132
133 let attributes = this
134 .pending_env_builder()
135 .pending_env_attributes(&parent, block_overrides.as_ref())
136 .map_err(Self::Error::from_eth_err)?;
137
138 let mut evm_env = this
139 .evm_config()
140 .next_evm_env(&parent, &attributes)
141 .map_err(RethError::other)
142 .map_err(Self::Error::from_eth_err)?;
143
144 evm_env.cfg_env.disable_eip3607 = true;
146
147 if !evm_env.cfg_env.is_amsterdam_eip8037_enabled() {
150 evm_env.cfg_env.tx_gas_limit_cap = Some(u64::MAX);
151 }
152
153 if !validation {
154 evm_env.cfg_env.disable_nonce_check = true;
156 evm_env.cfg_env.disable_base_fee = true;
157 evm_env.block_env.inner_mut().basefee = 0;
158 }
159
160 evm_env.block_env.inner_mut().prevrandao = Some(B256::ZERO);
164 if !this
165 .provider()
166 .chain_spec()
167 .is_paris_active_at_block(evm_env.block_env.number().saturating_to())
168 {
169 evm_env.block_env.inner_mut().difficulty = parent.difficulty();
170 }
171
172 if let Some(block_overrides) = block_overrides {
173 if let Some(gas_limit_override) = block_overrides.gas_limit &&
175 gas_limit_override > evm_env.block_env.gas_limit() &&
176 gas_limit_override > this.call_gas_limit()
177 {
178 return Err(EthApiError::other(EthSimulateError::GasLimitReached).into())
179 }
180 apply_block_overrides(
181 block_overrides,
182 &mut db,
183 evm_env.block_env.inner_mut(),
184 );
185 }
186 if let Some(ref state_overrides) = state_overrides {
187 apply_state_overrides(state_overrides.clone(), &mut db)
188 .map_err(Self::Error::from_eth_err)?;
189 }
190
191 let chain_id = evm_env.cfg_env.chain_id;
192
193 let ctx = this
194 .evm_config()
195 .context_for_next_block(&parent, attributes)
196 .map_err(RethError::other)
197 .map_err(Self::Error::from_eth_err)?;
198 let map_err = |e: EthApiError| -> Self::Error {
199 match e.as_simulate_error() {
200 Some(sim_err) => Self::Error::from_eth_err(EthApiError::other(sim_err)),
201 None => Self::Error::from_eth_err(e),
202 }
203 };
204
205 let (result, results) = if trace_transfers {
206 let inspector = TransferInspector::new(false).with_logs(true);
209 let evm = this
210 .evm_config()
211 .evm_with_env_and_inspector(&mut db, evm_env, inspector);
212 let mut builder = this.evm_config().create_block_builder(evm, &parent, ctx);
213
214 if let Some(ref state_overrides) = state_overrides {
215 simulate::apply_precompile_overrides(
216 state_overrides,
217 builder.evm_mut().precompiles_mut(),
218 )
219 .map_err(|e| Self::Error::from_eth_err(EthApiError::other(e)))?;
220 }
221
222 simulate::execute_transactions(
223 builder,
224 &state_provider,
225 calls,
226 &mut remaining_call_gas_limit,
227 chain_id,
228 this.compute_state_root_for_eth_simulate(),
229 this.converter(),
230 )
231 .map_err(map_err)?
232 } else {
233 let evm = this.evm_config().evm_with_env(&mut db, evm_env);
234 let mut builder = this.evm_config().create_block_builder(evm, &parent, ctx);
235
236 if let Some(ref state_overrides) = state_overrides {
237 simulate::apply_precompile_overrides(
238 state_overrides,
239 builder.evm_mut().precompiles_mut(),
240 )
241 .map_err(|e| Self::Error::from_eth_err(EthApiError::other(e)))?;
242 }
243
244 simulate::execute_transactions(
245 builder,
246 &state_provider,
247 calls,
248 &mut remaining_call_gas_limit,
249 chain_id,
250 this.compute_state_root_for_eth_simulate(),
251 this.converter(),
252 )
253 .map_err(map_err)?
254 };
255
256 let simulated_header = result.block.clone_sealed_header();
257 db.override_block_hashes(BTreeMap::from([(
258 simulated_header.number(),
259 simulated_header.hash(),
260 )]));
261 parent = simulated_header;
262
263 let block = simulate::build_simulated_block::<Self::Error, _>(
264 result.block,
265 results,
266 return_full_transactions.into(),
267 this.converter(),
268 )?;
269
270 blocks.push(block);
271 }
272
273 Ok(blocks)
274 })
275 .await
276 }
277 }
278
279 fn call(
281 &self,
282 request: RpcTxReq<<Self::RpcConvert as RpcConvert>::Network>,
283 block_number: Option<BlockId>,
284 overrides: EvmOverrides,
285 ) -> impl Future<Output = Result<Bytes, Self::Error>> + Send {
286 async move {
287 let _permit = self.acquire_owned_blocking_io().await;
288 let res =
289 self.transact_call_at(request, block_number.unwrap_or_default(), overrides).await?;
290
291 Self::Error::ensure_success(res.result)
292 }
293 }
294
295 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 async move {
304 if bundles.is_empty() {
306 return Err(EthApiError::InvalidParams(String::from("bundles are empty.")).into());
307 }
308
309 let _permit = self.acquire_owned_blocking_io().await;
310
311 let StateContext { transaction_index, block_number } =
312 state_context.unwrap_or_default();
313 let transaction_index = transaction_index.unwrap_or_default();
314
315 let mut target_block = block_number.unwrap_or_default();
316 let is_block_target_pending = target_block.is_pending();
317
318 if !is_block_target_pending {
321 let Some(block_hash) = self
322 .provider()
323 .block_hash_for_id(target_block)
324 .map_err(Self::Error::from_eth_err::<ProviderError>)?
325 else {
326 return Err(EthApiError::HeaderNotFound(target_block).into())
327 };
328 target_block = block_hash.into();
329 }
330
331 let block = self
332 .recovered_block(target_block)
333 .await?
334 .ok_or(EthApiError::HeaderNotFound(target_block))?;
335 let evm_env = self.evm_env_for_header(block.sealed_block().sealed_header())?;
336
337 let mut at = block.parent_hash();
341 let mut replay_block_txs = true;
342
343 let num_txs =
344 transaction_index.index().unwrap_or_else(|| block.body().transactions().len());
345 if !is_block_target_pending && num_txs == block.body().transactions().len() {
349 at = block.hash();
350 replay_block_txs = false;
351 }
352
353 self.spawn_with_state_at_block(at, move |this, mut db| {
354 let mut all_results = Vec::with_capacity(bundles.len());
355
356 if replay_block_txs {
357 let mut executor = RpcNodeCore::evm_config(&this)
358 .executor_for_block(&mut db, block.sealed_block())
359 .map_err(RethError::other)
360 .map_err(Self::Error::from_eth_err)?;
361 executor.apply_pre_execution_changes().map_err(Self::Error::from_eth_err)?;
362 for tx in block.transactions_recovered().take(num_txs) {
363 executor.execute_transaction(tx).map_err(Self::Error::from_eth_err)?;
364 }
365 }
366
367 for (bundle_index, bundle) in bundles.into_iter().enumerate() {
369 let Bundle { transactions, block_override } = bundle;
370 if transactions.is_empty() {
371 continue;
373 }
374
375 let mut bundle_results = Vec::with_capacity(transactions.len());
376 let block_overrides = block_override.map(Box::new);
377
378 for (tx_index, tx) in transactions.into_iter().enumerate() {
380 let overrides =
383 EvmOverrides::new(state_override.take(), block_overrides.clone());
384
385 let (current_evm_env, prepared_tx) = this
386 .prepare_call_env(evm_env.clone(), tx, &mut db, overrides)
387 .map_err(|err| {
388 Self::Error::from_eth_err(EthApiError::call_many_error(
389 bundle_index,
390 tx_index,
391 err.into(),
392 ))
393 })?;
394 let res = this.transact(&mut db, current_evm_env, prepared_tx).map_err(
395 |err| {
396 Self::Error::from_eth_err(EthApiError::call_many_error(
397 bundle_index,
398 tx_index,
399 err.into(),
400 ))
401 },
402 )?;
403
404 match Self::Error::ensure_success(res.result) {
405 Ok(output) => {
406 bundle_results
407 .push(EthCallResponse { value: Some(output), error: None });
408 }
409 Err(err) => {
410 bundle_results.push(EthCallResponse {
411 value: None,
412 error: Some(err.to_string()),
413 });
414 }
415 }
416
417 db.commit(res.state);
420 }
421
422 all_results.push(bundle_results);
423 }
424
425 Ok(all_results)
426 })
427 .await
428 }
429 }
430
431 fn create_access_list_at(
434 &self,
435 request: RpcTxReq<<Self::RpcConvert as RpcConvert>::Network>,
436 block_number: Option<BlockId>,
437 state_override: Option<StateOverride>,
438 ) -> impl Future<Output = Result<AccessListResult, Self::Error>> + Send
439 where
440 Self: Trace,
441 {
442 async move {
443 let block_id = block_number.unwrap_or_default();
444 let (evm_env, at) = self.evm_env_at(block_id).await?;
445
446 self.spawn_blocking_io_fut(async move |this| {
447 this.create_access_list_with(evm_env, at, request, state_override).await
448 })
449 .await
450 }
451 }
452
453 fn create_access_list_with(
456 &self,
457 mut evm_env: EvmEnvFor<Self::Evm>,
458 at: BlockId,
459 request: RpcTxReq<<Self::RpcConvert as RpcConvert>::Network>,
460 state_override: Option<StateOverride>,
461 ) -> impl Future<Output = Result<AccessListResult, Self::Error>> + Send
462 where
463 Self: Trace,
464 {
465 self.spawn_blocking_io_fut(async move |this| {
466 let state = this.state_at_block_id(at).await?;
467 let mut db = State::builder().with_database(StateProviderDatabase::new(state)).build();
468
469 if let Some(state_overrides) = state_override {
470 apply_state_overrides(state_overrides, &mut db)
471 .map_err(Self::Error::from_eth_err)?;
472 }
473
474 let request_has_gas_limit = request.as_ref().gas_limit().is_some();
476 let initial = request.as_ref().access_list().cloned().unwrap_or_default();
477
478 let mut tx_env = this.create_txn_env(&evm_env, request, &mut db)?;
479
480 evm_env.cfg_env.disable_block_gas_limit = true;
483
484 evm_env.cfg_env.disable_base_fee = true;
488
489 evm_env.cfg_env.disable_eip3607 = true;
491
492 evm_env.cfg_env.disable_fee_charge = true;
495
496 evm_env.cfg_env.tx_gas_limit_cap = Some(u64::MAX);
500
501 if !request_has_gas_limit && tx_env.gas_price() > 0 {
502 let cap = this.caller_gas_allowance(&mut db, &evm_env, &tx_env)?;
503 tx_env.set_gas_limit(cap.min(evm_env.block_env.gas_limit()));
506 }
507
508 let mut inspector = AccessListInspector::new(initial);
509
510 let result = this.inspect(&mut db, evm_env.clone(), tx_env.clone(), &mut inspector)?;
511 let access_list = inspector.into_access_list();
512 let gas_used = result.result.tx_gas_used();
513 tx_env.set_access_list(access_list.clone());
514 if let Err(err) = Self::Error::ensure_success(result.result) {
515 return Ok(AccessListResult {
516 access_list,
517 gas_used: U256::from(gas_used),
518 error: Some(err.to_string()),
519 });
520 }
521
522 let result = this.transact(&mut db, evm_env, tx_env)?;
524 let gas_used = result.result.tx_gas_used();
525 let error = Self::Error::ensure_success(result.result).err().map(|e| e.to_string());
526
527 Ok(AccessListResult { access_list, gas_used: U256::from(gas_used), error })
528 })
529 }
530}
531
532pub trait Call:
534 LoadState<
535 RpcConvert: RpcConvert<Evm = Self::Evm>,
536 Error: FromEvmError<Self::Evm>
537 + From<<Self::RpcConvert as RpcConvert>::Error>
538 + From<ProviderError>,
539 > + SpawnBlocking
540{
541 fn call_gas_limit(&self) -> u64;
545
546 fn max_simulate_blocks(&self) -> u64;
548
549 fn compute_state_root_for_eth_simulate(&self) -> bool;
551
552 fn evm_memory_limit(&self) -> u64;
554
555 fn caller_gas_allowance(
557 &self,
558 mut db: impl Database<Error: Into<EthApiError>>,
559 _evm_env: &EvmEnvFor<Self::Evm>,
560 tx_env: &TxEnvFor<Self::Evm>,
561 ) -> Result<u64, Self::Error> {
562 alloy_evm::call::caller_gas_allowance(&mut db, tx_env).map_err(Self::Error::from_eth_err)
563 }
564
565 fn with_state_at_block<F, R>(
567 &self,
568 at: BlockId,
569 f: F,
570 ) -> impl Future<Output = Result<R, Self::Error>> + Send
571 where
572 R: Send + 'static,
573 F: FnOnce(Self, StateProviderBox) -> Result<R, Self::Error> + Send + 'static,
574 {
575 self.spawn_blocking_io_fut(async move |this| {
576 let state = this.state_at_block_id(at).await?;
577 f(this, state)
578 })
579 }
580
581 fn transact<DB>(
584 &self,
585 db: DB,
586 evm_env: EvmEnvFor<Self::Evm>,
587 tx_env: TxEnvFor<Self::Evm>,
588 ) -> Result<ResultAndState<HaltReasonFor<Self::Evm>>, Self::Error>
589 where
590 DB: Database<Error = EvmDatabaseError<ProviderError>> + fmt::Debug,
591 {
592 let mut evm = self.evm_config().evm_with_env(db, evm_env);
593 let res = evm.transact(tx_env).map_err(Self::Error::from_evm_err)?;
594
595 Ok(res)
596 }
597
598 fn transact_with_inspector<DB, I>(
601 &self,
602 db: DB,
603 evm_env: EvmEnvFor<Self::Evm>,
604 tx_env: TxEnvFor<Self::Evm>,
605 inspector: I,
606 ) -> Result<ResultAndState<HaltReasonFor<Self::Evm>>, Self::Error>
607 where
608 DB: Database<Error = EvmDatabaseError<ProviderError>> + fmt::Debug,
609 I: InspectorFor<Self::Evm, DB>,
610 {
611 let mut evm = self.evm_config().evm_with_env_and_inspector(db, evm_env, inspector);
612 let res = evm.transact(tx_env).map_err(Self::Error::from_evm_err)?;
613
614 Ok(res)
615 }
616
617 fn transact_call_at(
624 &self,
625 request: RpcTxReq<<Self::RpcConvert as RpcConvert>::Network>,
626 at: BlockId,
627 overrides: EvmOverrides,
628 ) -> impl Future<Output = Result<ResultAndState<HaltReasonFor<Self::Evm>>, Self::Error>> + Send
629 where
630 Self: LoadPendingBlock,
631 {
632 async move {
633 let guard = CancelOnDrop::default();
634 let cancel = guard.clone();
635 let this = self.clone();
636
637 let res = self
638 .spawn_with_call_at(request, at, overrides, move |db, evm_env, tx_env| {
639 if cancel.is_cancelled() {
640 return Err(EthApiError::InternalEthError.into())
642 }
643 this.transact(db, evm_env, tx_env)
644 })
645 .await;
646 drop(guard);
647 res
648 }
649 }
650
651 fn spawn_with_state_at_block<F, R>(
653 &self,
654 at: impl Into<BlockId>,
655 f: F,
656 ) -> impl Future<Output = Result<R, Self::Error>> + Send
657 where
658 F: FnOnce(Self, StateCacheDb) -> Result<R, Self::Error> + Send + 'static,
659 R: Send + 'static,
660 {
661 let at = at.into();
662 self.spawn_blocking_io_fut(async move |this| {
663 let state = this.state_at_block_id(at).await?;
664 let db = State::builder()
665 .with_database(StateProviderDatabase::new(StateProviderTraitObjWrapper(state)))
666 .build();
667 f(this, db)
668 })
669 }
670
671 fn spawn_with_call_at<F, R>(
687 &self,
688 request: RpcTxReq<<Self::RpcConvert as RpcConvert>::Network>,
689 at: BlockId,
690 overrides: EvmOverrides,
691 f: F,
692 ) -> impl Future<Output = Result<R, Self::Error>> + Send
693 where
694 Self: LoadPendingBlock,
695 F: FnOnce(
696 &mut StateCacheDb,
697 EvmEnvFor<Self::Evm>,
698 TxEnvFor<Self::Evm>,
699 ) -> Result<R, Self::Error>
700 + Send
701 + 'static,
702 R: Send + 'static,
703 {
704 async move {
705 let (evm_env, at) = self.evm_env_at(at).await?;
706 self.spawn_with_state_at_block(at, move |this, mut db| {
707 let (evm_env, tx_env) =
708 this.prepare_call_env(evm_env, request, &mut db, overrides)?;
709
710 f(&mut db, evm_env, tx_env)
711 })
712 .await
713 }
714 }
715
716 fn spawn_replay_transaction<F, R>(
726 &self,
727 hash: B256,
728 f: F,
729 ) -> impl Future<Output = Result<Option<R>, Self::Error>> + Send
730 where
731 Self: LoadBlock + LoadTransaction,
732 F: FnOnce(
733 TransactionInfo,
734 ResultAndState<HaltReasonFor<Self::Evm>>,
735 StateCacheDb,
736 ) -> Result<R, Self::Error>
737 + Send
738 + 'static,
739 R: Send + 'static,
740 {
741 async move {
742 let (transaction, block) = match self.transaction_and_block(hash).await? {
743 None => return Ok(None),
744 Some(res) => res,
745 };
746 let (tx, tx_info) = transaction.split();
747
748 let parent_block = block.parent_hash();
751
752 self.spawn_with_state_at_block(parent_block, move |this, mut db| {
753 let block_txs = block.transactions_recovered();
754
755 let mut executor = RpcNodeCore::evm_config(&this)
756 .executor_for_block(&mut db, block.sealed_block())
757 .map_err(RethError::other)
758 .map_err(Self::Error::from_eth_err)?;
759 executor.apply_pre_execution_changes().map_err(Self::Error::from_eth_err)?;
760
761 for block_tx in block_txs {
763 if block_tx.tx_hash() == tx.tx_hash() {
764 break;
765 }
766 executor.execute_transaction(block_tx).map_err(Self::Error::from_eth_err)?;
767 }
768
769 let tx_env = RpcNodeCore::evm_config(&this).tx_env(tx);
770
771 let res = executor.evm_mut().transact(tx_env).map_err(Self::Error::from_evm_err)?;
772 drop(executor);
773 f(tx_info, res, db)
774 })
775 .await
776 .map(Some)
777 }
778 }
779
780 fn replay_transactions_until<'a, DB, I>(
788 &self,
789 db: &mut DB,
790 evm_env: EvmEnvFor<Self::Evm>,
791 transactions: I,
792 target_tx_hash: B256,
793 ) -> Result<usize, Self::Error>
794 where
795 DB: Database<Error = EvmDatabaseError<ProviderError>> + DatabaseCommit + core::fmt::Debug,
796 I: IntoIterator<Item = Recovered<&'a ProviderTx<Self::Provider>>>,
797 {
798 let mut evm = self.evm_config().evm_with_env(db, evm_env);
799 let mut index = 0;
800 for tx in transactions {
801 if *tx.tx_hash() == target_tx_hash {
802 break
804 }
805
806 let tx_env = self.evm_config().tx_env(tx);
807 evm.transact_commit(tx_env).map_err(Self::Error::from_evm_err)?;
808 index += 1;
809 }
810 Ok(index)
811 }
812
813 fn create_txn_env(
817 &self,
818 evm_env: &EvmEnvFor<Self::Evm>,
819 mut request: RpcTxReq<<Self::RpcConvert as RpcConvert>::Network>,
820 mut db: impl Database<Error: Into<EthApiError>>,
821 ) -> Result<TxEnvFor<Self::Evm>, Self::Error> {
822 if request.as_ref().nonce().is_none() {
823 let nonce = db
824 .basic(request.as_ref().from().unwrap_or_default())
825 .map_err(Into::into)?
826 .map(|acc| acc.nonce)
827 .unwrap_or_default();
828 request.as_mut().set_nonce(nonce);
829 }
830
831 Ok(self.converter().tx_env(request, evm_env)?)
832 }
833
834 #[expect(clippy::type_complexity)]
848 fn prepare_call_env<DB>(
849 &self,
850 mut evm_env: EvmEnvFor<Self::Evm>,
851 mut request: RpcTxReq<<Self::RpcConvert as RpcConvert>::Network>,
852 db: &mut DB,
853 overrides: EvmOverrides,
854 ) -> Result<(EvmEnvFor<Self::Evm>, TxEnvFor<Self::Evm>), Self::Error>
855 where
856 DB: Database + DatabaseCommit + OverrideBlockHashes,
857 EthApiError: From<<DB as Database>::Error>,
858 {
859 let request_has_gas_limit = request.as_ref().gas_limit().is_some();
861
862 if let Some(requested_gas) = request.as_ref().gas_limit() {
863 let global_gas_cap = self.call_gas_limit();
864 if global_gas_cap != 0 && global_gas_cap < requested_gas {
865 warn!(target: "rpc::eth::call", ?request, ?global_gas_cap, "Capping gas limit to global gas cap");
866 request.as_mut().set_gas_limit(global_gas_cap);
867 }
868 } else {
869 request.as_mut().set_gas_limit(self.call_gas_limit());
871 }
872
873 evm_env.cfg_env.disable_block_gas_limit = true;
876
877 evm_env.cfg_env.disable_eip3607 = true;
880
881 evm_env.cfg_env.disable_base_fee = true;
885
886 evm_env.cfg_env.tx_gas_limit_cap = Some(u64::MAX);
888
889 evm_env.cfg_env.disable_fee_charge = true;
893
894 evm_env.cfg_env.memory_limit = self.evm_memory_limit();
895
896 request.as_mut().take_nonce();
898
899 if let Some(block_overrides) = overrides.block {
900 apply_block_overrides(*block_overrides, db, evm_env.block_env.inner_mut());
901 }
902 if let Some(state_overrides) = overrides.state {
903 apply_state_overrides(state_overrides, db)
904 .map_err(EthApiError::from_state_overrides_err)?;
905 }
906
907 let mut tx_env = self.create_txn_env(&evm_env, request, &mut *db)?;
908
909 if tx_env.gas_price() == 0 {
911 evm_env.block_env.inner_mut().basefee = 0;
912 }
913
914 if !request_has_gas_limit {
915 if tx_env.gas_price() > 0 {
917 trace!(target: "rpc::eth::call", ?tx_env, "Applying gas limit cap with caller allowance");
919 let cap = self.caller_gas_allowance(db, &evm_env, &tx_env)?;
920 tx_env.set_gas_limit(cap.min(evm_env.block_env.gas_limit()));
922 }
923 }
924
925 Ok((evm_env, tx_env))
926 }
927}