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, 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 !validation {
148 evm_env.cfg_env.disable_nonce_check = true;
150 evm_env.cfg_env.disable_base_fee = true;
151 evm_env.cfg_env.tx_gas_limit_cap = Some(u64::MAX);
152 evm_env.block_env.inner_mut().basefee = 0;
153 }
154
155 evm_env.block_env.inner_mut().prevrandao = Some(B256::ZERO);
159 if !this
160 .provider()
161 .chain_spec()
162 .is_paris_active_at_block(evm_env.block_env.number().saturating_to())
163 {
164 evm_env.block_env.inner_mut().difficulty = parent.difficulty();
165 }
166
167 if let Some(block_overrides) = block_overrides {
168 if let Some(gas_limit_override) = block_overrides.gas_limit &&
170 gas_limit_override > evm_env.block_env.gas_limit() &&
171 gas_limit_override > this.call_gas_limit()
172 {
173 return Err(EthApiError::other(EthSimulateError::GasLimitReached).into())
174 }
175 apply_block_overrides(
176 block_overrides,
177 &mut db,
178 evm_env.block_env.inner_mut(),
179 );
180 }
181 if let Some(ref state_overrides) = state_overrides {
182 apply_state_overrides(state_overrides.clone(), &mut db)
183 .map_err(Self::Error::from_eth_err)?;
184 }
185
186 let chain_id = evm_env.cfg_env.chain_id;
187
188 let ctx = this
189 .evm_config()
190 .context_for_next_block(&parent, attributes)
191 .map_err(RethError::other)
192 .map_err(Self::Error::from_eth_err)?;
193 let map_err = |e: EthApiError| -> Self::Error {
194 match e.as_simulate_error() {
195 Some(sim_err) => Self::Error::from_eth_err(EthApiError::other(sim_err)),
196 None => Self::Error::from_eth_err(e),
197 }
198 };
199
200 let (result, results) = if trace_transfers {
201 let inspector = TransferInspector::new(false).with_logs(true);
204 let evm = this
205 .evm_config()
206 .evm_with_env_and_inspector(&mut db, evm_env, inspector);
207 let mut builder = this.evm_config().create_block_builder(evm, &parent, ctx);
208
209 if let Some(ref state_overrides) = state_overrides {
210 simulate::apply_precompile_overrides(
211 state_overrides,
212 builder.evm_mut().precompiles_mut(),
213 )
214 .map_err(|e| Self::Error::from_eth_err(EthApiError::other(e)))?;
215 }
216
217 simulate::execute_transactions(
218 builder,
219 &state_provider,
220 calls,
221 &mut remaining_call_gas_limit,
222 chain_id,
223 this.compute_state_root_for_eth_simulate(),
224 this.converter(),
225 )
226 .map_err(map_err)?
227 } else {
228 let evm = this.evm_config().evm_with_env(&mut db, evm_env);
229 let mut builder = this.evm_config().create_block_builder(evm, &parent, ctx);
230
231 if let Some(ref state_overrides) = state_overrides {
232 simulate::apply_precompile_overrides(
233 state_overrides,
234 builder.evm_mut().precompiles_mut(),
235 )
236 .map_err(|e| Self::Error::from_eth_err(EthApiError::other(e)))?;
237 }
238
239 simulate::execute_transactions(
240 builder,
241 &state_provider,
242 calls,
243 &mut remaining_call_gas_limit,
244 chain_id,
245 this.compute_state_root_for_eth_simulate(),
246 this.converter(),
247 )
248 .map_err(map_err)?
249 };
250
251 let simulated_header = result.block.clone_sealed_header();
252 db.override_block_hashes(BTreeMap::from([(
253 simulated_header.number(),
254 simulated_header.hash(),
255 )]));
256 parent = simulated_header;
257
258 let block = simulate::build_simulated_block::<Self::Error, _>(
259 result.block,
260 results,
261 return_full_transactions.into(),
262 this.converter(),
263 )?;
264
265 blocks.push(block);
266 }
267
268 Ok(blocks)
269 })
270 .await
271 }
272 }
273
274 fn call(
276 &self,
277 request: RpcTxReq<<Self::RpcConvert as RpcConvert>::Network>,
278 block_number: Option<BlockId>,
279 overrides: EvmOverrides,
280 ) -> impl Future<Output = Result<Bytes, Self::Error>> + Send {
281 async move {
282 let _permit = self.acquire_owned_blocking_io().await;
283 let res =
284 self.transact_call_at(request, block_number.unwrap_or_default(), overrides).await?;
285
286 Self::Error::ensure_success(res.result)
287 }
288 }
289
290 fn call_many(
293 &self,
294 bundles: Vec<Bundle<RpcTxReq<<Self::RpcConvert as RpcConvert>::Network>>>,
295 state_context: Option<StateContext>,
296 mut state_override: Option<StateOverride>,
297 ) -> impl Future<Output = Result<Vec<Vec<EthCallResponse>>, Self::Error>> + Send {
298 async move {
299 if bundles.is_empty() {
301 return Err(EthApiError::InvalidParams(String::from("bundles are empty.")).into());
302 }
303
304 let _permit = self.acquire_owned_blocking_io().await;
305
306 let StateContext { transaction_index, block_number } =
307 state_context.unwrap_or_default();
308 let transaction_index = transaction_index.unwrap_or_default();
309
310 let mut target_block = block_number.unwrap_or_default();
311 let is_block_target_pending = target_block.is_pending();
312
313 if !is_block_target_pending {
316 let Some(block_hash) = self
317 .provider()
318 .block_hash_for_id(target_block)
319 .map_err(Self::Error::from_eth_err::<ProviderError>)?
320 else {
321 return Err(EthApiError::HeaderNotFound(target_block).into())
322 };
323 target_block = block_hash.into();
324 }
325
326 let block = self
327 .recovered_block(target_block)
328 .await?
329 .ok_or(EthApiError::HeaderNotFound(target_block))?;
330 let evm_env = self.evm_env_for_header(block.sealed_block().sealed_header())?;
331
332 let mut at = block.parent_hash();
336 let mut replay_block_txs = true;
337
338 let num_txs =
339 transaction_index.index().unwrap_or_else(|| block.body().transactions().len());
340 if !is_block_target_pending && num_txs == block.body().transactions().len() {
344 at = block.hash();
345 replay_block_txs = false;
346 }
347
348 self.spawn_with_state_at_block(at, move |this, mut db| {
349 let mut all_results = Vec::with_capacity(bundles.len());
350
351 if replay_block_txs {
352 let mut executor = RpcNodeCore::evm_config(&this)
353 .executor_for_block(&mut db, block.sealed_block())
354 .map_err(RethError::other)
355 .map_err(Self::Error::from_eth_err)?;
356 executor.apply_pre_execution_changes().map_err(Self::Error::from_eth_err)?;
357 for tx in block.transactions_recovered().take(num_txs) {
358 executor.execute_transaction(tx).map_err(Self::Error::from_eth_err)?;
359 }
360 }
361
362 for (bundle_index, bundle) in bundles.into_iter().enumerate() {
364 let Bundle { transactions, block_override } = bundle;
365 if transactions.is_empty() {
366 continue;
368 }
369
370 let mut bundle_results = Vec::with_capacity(transactions.len());
371 let block_overrides = block_override.map(Box::new);
372
373 for (tx_index, tx) in transactions.into_iter().enumerate() {
375 let overrides =
378 EvmOverrides::new(state_override.take(), block_overrides.clone());
379
380 let (current_evm_env, prepared_tx) = this
381 .prepare_call_env(evm_env.clone(), tx, &mut db, overrides)
382 .map_err(|err| {
383 Self::Error::from_eth_err(EthApiError::call_many_error(
384 bundle_index,
385 tx_index,
386 err.into(),
387 ))
388 })?;
389 let res = this.transact(&mut db, current_evm_env, prepared_tx).map_err(
390 |err| {
391 Self::Error::from_eth_err(EthApiError::call_many_error(
392 bundle_index,
393 tx_index,
394 err.into(),
395 ))
396 },
397 )?;
398
399 match Self::Error::ensure_success(res.result) {
400 Ok(output) => {
401 bundle_results
402 .push(EthCallResponse { value: Some(output), error: None });
403 }
404 Err(err) => {
405 bundle_results.push(EthCallResponse {
406 value: None,
407 error: Some(err.to_string()),
408 });
409 }
410 }
411
412 db.commit(res.state);
415 }
416
417 all_results.push(bundle_results);
418 }
419
420 Ok(all_results)
421 })
422 .await
423 }
424 }
425
426 fn create_access_list_at(
429 &self,
430 request: RpcTxReq<<Self::RpcConvert as RpcConvert>::Network>,
431 block_number: Option<BlockId>,
432 state_override: Option<StateOverride>,
433 ) -> impl Future<Output = Result<AccessListResult, Self::Error>> + Send
434 where
435 Self: Trace,
436 {
437 async move {
438 let block_id = block_number.unwrap_or_default();
439 let (evm_env, at) = self.evm_env_at(block_id).await?;
440
441 self.spawn_blocking_io_fut(async move |this| {
442 this.create_access_list_with(evm_env, at, request, state_override).await
443 })
444 .await
445 }
446 }
447
448 fn create_access_list_with(
451 &self,
452 mut evm_env: EvmEnvFor<Self::Evm>,
453 at: BlockId,
454 request: RpcTxReq<<Self::RpcConvert as RpcConvert>::Network>,
455 state_override: Option<StateOverride>,
456 ) -> impl Future<Output = Result<AccessListResult, Self::Error>> + Send
457 where
458 Self: Trace,
459 {
460 self.spawn_blocking_io_fut(async move |this| {
461 let state = this.state_at_block_id(at).await?;
462 let mut db = State::builder().with_database(StateProviderDatabase::new(state)).build();
463
464 if let Some(state_overrides) = state_override {
465 apply_state_overrides(state_overrides, &mut db)
466 .map_err(Self::Error::from_eth_err)?;
467 }
468
469 let request_has_gas_limit = request.as_ref().gas_limit().is_some();
471 let initial = request.as_ref().access_list().cloned().unwrap_or_default();
472
473 let mut tx_env = this.create_txn_env(&evm_env, request, &mut db)?;
474
475 evm_env.cfg_env.disable_block_gas_limit = true;
478
479 evm_env.cfg_env.disable_base_fee = true;
483
484 evm_env.cfg_env.disable_eip3607 = true;
486
487 evm_env.cfg_env.disable_fee_charge = true;
490
491 evm_env.cfg_env.tx_gas_limit_cap = Some(u64::MAX);
495
496 if !request_has_gas_limit && tx_env.gas_price() > 0 {
497 let cap = this.caller_gas_allowance(&mut db, &evm_env, &tx_env)?;
498 tx_env.set_gas_limit(cap.min(evm_env.block_env.gas_limit()));
501 }
502
503 let mut inspector = AccessListInspector::new(initial);
504
505 let result = this.inspect(&mut db, evm_env.clone(), tx_env.clone(), &mut inspector)?;
506 let access_list = inspector.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 let result = this.transact(&mut db, evm_env, tx_env)?;
519 let gas_used = result.result.tx_gas_used();
520 let error = Self::Error::ensure_success(result.result).err().map(|e| e.to_string());
521
522 Ok(AccessListResult { access_list, gas_used: U256::from(gas_used), error })
523 })
524 }
525}
526
527pub trait Call:
529 LoadState<
530 RpcConvert: RpcConvert<Evm = Self::Evm>,
531 Error: FromEvmError<Self::Evm>
532 + From<<Self::RpcConvert as RpcConvert>::Error>
533 + From<ProviderError>,
534 > + SpawnBlocking
535{
536 fn call_gas_limit(&self) -> u64;
540
541 fn max_simulate_blocks(&self) -> u64;
543
544 fn compute_state_root_for_eth_simulate(&self) -> bool;
546
547 fn evm_memory_limit(&self) -> u64;
549
550 fn caller_gas_allowance(
552 &self,
553 mut db: impl Database<Error: Into<EthApiError>>,
554 _evm_env: &EvmEnvFor<Self::Evm>,
555 tx_env: &TxEnvFor<Self::Evm>,
556 ) -> Result<u64, Self::Error> {
557 alloy_evm::call::caller_gas_allowance(&mut db, tx_env).map_err(Self::Error::from_eth_err)
558 }
559
560 fn with_state_at_block<F, R>(
562 &self,
563 at: BlockId,
564 f: F,
565 ) -> impl Future<Output = Result<R, Self::Error>> + Send
566 where
567 R: Send + 'static,
568 F: FnOnce(Self, StateProviderBox) -> Result<R, Self::Error> + Send + 'static,
569 {
570 self.spawn_blocking_io_fut(async move |this| {
571 let state = this.state_at_block_id(at).await?;
572 f(this, state)
573 })
574 }
575
576 fn transact<DB>(
579 &self,
580 db: DB,
581 evm_env: EvmEnvFor<Self::Evm>,
582 tx_env: TxEnvFor<Self::Evm>,
583 ) -> Result<ResultAndState<HaltReasonFor<Self::Evm>>, Self::Error>
584 where
585 DB: Database<Error = EvmDatabaseError<ProviderError>> + fmt::Debug,
586 {
587 let mut evm = self.evm_config().evm_with_env(db, evm_env);
588 let res = evm.transact(tx_env).map_err(Self::Error::from_evm_err)?;
589
590 Ok(res)
591 }
592
593 fn transact_with_inspector<DB, I>(
596 &self,
597 db: DB,
598 evm_env: EvmEnvFor<Self::Evm>,
599 tx_env: TxEnvFor<Self::Evm>,
600 inspector: I,
601 ) -> Result<ResultAndState<HaltReasonFor<Self::Evm>>, Self::Error>
602 where
603 DB: Database<Error = EvmDatabaseError<ProviderError>> + fmt::Debug,
604 I: InspectorFor<Self::Evm, DB>,
605 {
606 let mut evm = self.evm_config().evm_with_env_and_inspector(db, evm_env, inspector);
607 let res = evm.transact(tx_env).map_err(Self::Error::from_evm_err)?;
608
609 Ok(res)
610 }
611
612 fn transact_call_at(
619 &self,
620 request: RpcTxReq<<Self::RpcConvert as RpcConvert>::Network>,
621 at: BlockId,
622 overrides: EvmOverrides,
623 ) -> impl Future<Output = Result<ResultAndState<HaltReasonFor<Self::Evm>>, Self::Error>> + Send
624 where
625 Self: LoadPendingBlock,
626 {
627 async move {
628 let guard = CancelOnDrop::default();
629 let cancel = guard.clone();
630 let this = self.clone();
631
632 let res = self
633 .spawn_with_call_at(request, at, overrides, move |db, evm_env, tx_env| {
634 if cancel.is_cancelled() {
635 return Err(EthApiError::InternalEthError.into())
637 }
638 this.transact(db, evm_env, tx_env)
639 })
640 .await;
641 drop(guard);
642 res
643 }
644 }
645
646 fn spawn_with_state_at_block<F, R>(
648 &self,
649 at: impl Into<BlockId>,
650 f: F,
651 ) -> impl Future<Output = Result<R, Self::Error>> + Send
652 where
653 F: FnOnce(Self, StateCacheDb) -> Result<R, Self::Error> + Send + 'static,
654 R: Send + 'static,
655 {
656 let at = at.into();
657 self.spawn_blocking_io_fut(async move |this| {
658 let state = this.state_at_block_id(at).await?;
659 let db = State::builder()
660 .with_database(StateProviderDatabase::new(StateProviderTraitObjWrapper(state)))
661 .build();
662 f(this, db)
663 })
664 }
665
666 fn spawn_with_call_at<F, R>(
682 &self,
683 request: RpcTxReq<<Self::RpcConvert as RpcConvert>::Network>,
684 at: BlockId,
685 overrides: EvmOverrides,
686 f: F,
687 ) -> impl Future<Output = Result<R, Self::Error>> + Send
688 where
689 Self: LoadPendingBlock,
690 F: FnOnce(
691 &mut StateCacheDb,
692 EvmEnvFor<Self::Evm>,
693 TxEnvFor<Self::Evm>,
694 ) -> Result<R, Self::Error>
695 + Send
696 + 'static,
697 R: Send + 'static,
698 {
699 async move {
700 let (evm_env, at) = self.evm_env_at(at).await?;
701 self.spawn_with_state_at_block(at, move |this, mut db| {
702 let (evm_env, tx_env) =
703 this.prepare_call_env(evm_env, request, &mut db, overrides)?;
704
705 f(&mut db, evm_env, tx_env)
706 })
707 .await
708 }
709 }
710
711 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) = match self.transaction_and_block(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 let block_txs = block.transactions_recovered();
749
750 let mut executor = RpcNodeCore::evm_config(&this)
751 .executor_for_block(&mut db, block.sealed_block())
752 .map_err(RethError::other)
753 .map_err(Self::Error::from_eth_err)?;
754 executor.apply_pre_execution_changes().map_err(Self::Error::from_eth_err)?;
755
756 for block_tx in block_txs {
758 if block_tx.tx_hash() == tx.tx_hash() {
759 break;
760 }
761 executor.execute_transaction(block_tx).map_err(Self::Error::from_eth_err)?;
762 }
763
764 let tx_env = RpcNodeCore::evm_config(&this).tx_env(tx);
765
766 let res = executor.evm_mut().transact(tx_env).map_err(Self::Error::from_evm_err)?;
767 drop(executor);
768 f(tx_info, res, db)
769 })
770 .await
771 .map(Some)
772 }
773 }
774
775 fn replay_transactions_until<'a, DB, I>(
783 &self,
784 db: &mut DB,
785 evm_env: EvmEnvFor<Self::Evm>,
786 transactions: I,
787 target_tx_hash: B256,
788 ) -> Result<usize, Self::Error>
789 where
790 DB: Database<Error = EvmDatabaseError<ProviderError>> + DatabaseCommit + core::fmt::Debug,
791 I: IntoIterator<Item = Recovered<&'a ProviderTx<Self::Provider>>>,
792 {
793 let mut evm = self.evm_config().evm_with_env(db, evm_env);
794 let mut index = 0;
795 for tx in transactions {
796 if *tx.tx_hash() == target_tx_hash {
797 break
799 }
800
801 let tx_env = self.evm_config().tx_env(tx);
802 evm.transact_commit(tx_env).map_err(Self::Error::from_evm_err)?;
803 index += 1;
804 }
805 Ok(index)
806 }
807
808 fn create_txn_env(
812 &self,
813 evm_env: &EvmEnvFor<Self::Evm>,
814 mut request: RpcTxReq<<Self::RpcConvert as RpcConvert>::Network>,
815 mut db: impl Database<Error: Into<EthApiError>>,
816 ) -> Result<TxEnvFor<Self::Evm>, Self::Error> {
817 if request.as_ref().nonce().is_none() {
818 let nonce = db
819 .basic(request.as_ref().from().unwrap_or_default())
820 .map_err(Into::into)?
821 .map(|acc| acc.nonce)
822 .unwrap_or_default();
823 request.as_mut().set_nonce(nonce);
824 }
825
826 Ok(self.converter().tx_env(request, evm_env)?)
827 }
828
829 #[expect(clippy::type_complexity)]
843 fn prepare_call_env<DB>(
844 &self,
845 mut evm_env: EvmEnvFor<Self::Evm>,
846 mut request: RpcTxReq<<Self::RpcConvert as RpcConvert>::Network>,
847 db: &mut DB,
848 overrides: EvmOverrides,
849 ) -> Result<(EvmEnvFor<Self::Evm>, TxEnvFor<Self::Evm>), Self::Error>
850 where
851 DB: Database + DatabaseCommit + OverrideBlockHashes,
852 EthApiError: From<<DB as Database>::Error>,
853 {
854 let request_has_gas_limit = request.as_ref().gas_limit().is_some();
856
857 if let Some(requested_gas) = request.as_ref().gas_limit() {
858 let global_gas_cap = self.call_gas_limit();
859 if global_gas_cap != 0 && global_gas_cap < requested_gas {
860 warn!(target: "rpc::eth::call", ?request, ?global_gas_cap, "Capping gas limit to global gas cap");
861 request.as_mut().set_gas_limit(global_gas_cap);
862 }
863 } else {
864 request.as_mut().set_gas_limit(self.call_gas_limit());
866 }
867
868 evm_env.cfg_env.disable_block_gas_limit = true;
871
872 evm_env.cfg_env.disable_eip3607 = true;
875
876 evm_env.cfg_env.disable_base_fee = true;
880
881 evm_env.cfg_env.tx_gas_limit_cap = Some(u64::MAX);
883
884 evm_env.cfg_env.disable_fee_charge = true;
888
889 evm_env.cfg_env.memory_limit = self.evm_memory_limit();
890
891 request.as_mut().take_nonce();
893
894 if let Some(block_overrides) = overrides.block {
895 apply_block_overrides(*block_overrides, db, evm_env.block_env.inner_mut());
896 }
897 if let Some(state_overrides) = overrides.state {
898 apply_state_overrides(state_overrides, db)
899 .map_err(EthApiError::from_state_overrides_err)?;
900 }
901
902 let mut tx_env = self.create_txn_env(&evm_env, request, &mut *db)?;
903
904 if tx_env.gas_price() == 0 {
906 evm_env.block_env.inner_mut().basefee = 0;
907 }
908
909 if !request_has_gas_limit {
910 if tx_env.gas_price() > 0 {
912 trace!(target: "rpc::eth::call", ?tx_env, "Applying gas limit cap with caller allowance");
914 let cap = self.caller_gas_allowance(db, &evm_env, &tx_env)?;
915 tx_env.set_gas_limit(cap.min(evm_env.block_env.gas_limit()));
917 }
918 }
919
920 Ok((evm_env, tx_env))
921 }
922}