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};
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 tracing::{trace, warn};
49
50pub type SimulatedBlocksResult<N, E> = Result<Vec<SimulatedBlock<RpcBlock<N>>>, E>;
52
53pub trait EthCall: EstimateCall + Call + LoadPendingBlock + LoadBlock + FullEthApiTypes {
56 fn estimate_gas_at(
58 &self,
59 request: RpcTxReq<<Self::RpcConvert as RpcConvert>::Network>,
60 at: BlockId,
61 overrides: EvmOverrides,
62 ) -> impl Future<Output = Result<U256, Self::Error>> + Send {
63 EstimateCall::estimate_gas_at(self, request, at, overrides)
64 }
65
66 fn simulate_v1(
71 &self,
72 payload: SimulatePayload<RpcTxReq<<Self::RpcConvert as RpcConvert>::Network>>,
73 block: Option<BlockId>,
74 ) -> impl Future<Output = SimulatedBlocksResult<Self::NetworkTypes, Self::Error>> + Send {
75 async move {
76 if payload.block_state_calls.len() > self.max_simulate_blocks() as usize {
77 return Err(EthApiError::other(EthSimulateError::TooManyBlocks).into())
78 }
79
80 let block = block.unwrap_or_default();
81
82 let SimulatePayload {
83 block_state_calls,
84 trace_transfers,
85 validation,
86 return_full_transactions,
87 } = payload;
88
89 if block_state_calls.is_empty() {
90 return Err(EthApiError::InvalidParams(String::from("calls are empty.")).into())
91 }
92
93 let _permit = self.acquire_owned_blocking_io().await;
94
95 let base_block =
96 self.recovered_block(block).await?.ok_or(EthApiError::HeaderNotFound(block))?;
97 let parent = base_block.sealed_header().clone();
98 let max_simulate_blocks = self.max_simulate_blocks();
99
100 self.spawn_with_state_at_block(block, move |this, mut db| {
101 let mut parent = parent;
102
103 let chain_id = this.provider().chain_spec().chain_id();
104
105 let block_state_calls = simulate::sanitize_chain(
110 block_state_calls,
111 &parent,
112 chain_id,
113 max_simulate_blocks,
114 )?;
115
116 let mut blocks: Vec<SimulatedBlock<RpcBlock<Self::NetworkTypes>>> =
117 Vec::with_capacity(block_state_calls.len());
118
119 let call_gas_limit = this.call_gas_limit();
120 let mut remaining_call_gas_limit = (call_gas_limit > 0).then_some(call_gas_limit);
121
122 for block in block_state_calls {
123 let SimBlock { block_overrides, state_overrides, calls } = block;
124
125 let attributes = this
126 .pending_env_builder()
127 .pending_env_attributes(&parent, block_overrides.as_ref())
128 .map_err(Self::Error::from_eth_err)?;
129
130 let mut evm_env = this
131 .evm_config()
132 .next_evm_env(&parent, &attributes)
133 .map_err(RethError::other)
134 .map_err(Self::Error::from_eth_err)?;
135
136 evm_env.cfg_env.disable_eip3607 = true;
138
139 if !validation {
140 evm_env.cfg_env.disable_nonce_check = true;
142 evm_env.cfg_env.disable_base_fee = true;
143 evm_env.cfg_env.tx_gas_limit_cap = Some(u64::MAX);
144 evm_env.block_env.inner_mut().basefee = 0;
145 }
146
147 evm_env.block_env.inner_mut().prevrandao = Some(B256::ZERO);
151
152 if let Some(block_overrides) = block_overrides {
153 if let Some(gas_limit_override) = block_overrides.gas_limit &&
155 gas_limit_override > evm_env.block_env.gas_limit() &&
156 gas_limit_override > this.call_gas_limit()
157 {
158 return Err(EthApiError::other(EthSimulateError::GasLimitReached).into())
159 }
160 apply_block_overrides(
161 block_overrides,
162 &mut db,
163 evm_env.block_env.inner_mut(),
164 );
165 }
166 if let Some(ref state_overrides) = state_overrides {
167 apply_state_overrides(state_overrides.clone(), &mut db)
168 .map_err(Self::Error::from_eth_err)?;
169 }
170
171 let chain_id = evm_env.cfg_env.chain_id;
172
173 let ctx = this
174 .evm_config()
175 .context_for_next_block(&parent, attributes)
176 .map_err(RethError::other)
177 .map_err(Self::Error::from_eth_err)?;
178 let map_err = |e: EthApiError| -> Self::Error {
179 match e.as_simulate_error() {
180 Some(sim_err) => Self::Error::from_eth_err(EthApiError::other(sim_err)),
181 None => Self::Error::from_eth_err(e),
182 }
183 };
184
185 let (result, results) = if trace_transfers {
186 let inspector = TransferInspector::new(false).with_logs(true);
189 let evm = this
190 .evm_config()
191 .evm_with_env_and_inspector(&mut db, evm_env, inspector);
192 let mut builder = this.evm_config().create_block_builder(evm, &parent, ctx);
193
194 if let Some(ref state_overrides) = state_overrides {
195 simulate::apply_precompile_overrides(
196 state_overrides,
197 builder.evm_mut().precompiles_mut(),
198 )
199 .map_err(|e| Self::Error::from_eth_err(EthApiError::other(e)))?;
200 }
201
202 simulate::execute_transactions(
203 builder,
204 calls,
205 &mut remaining_call_gas_limit,
206 chain_id,
207 this.converter(),
208 )
209 .map_err(map_err)?
210 } else {
211 let evm = this.evm_config().evm_with_env(&mut db, evm_env);
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 calls,
225 &mut remaining_call_gas_limit,
226 chain_id,
227 this.converter(),
228 )
229 .map_err(map_err)?
230 };
231
232 parent = result.block.clone_sealed_header();
233
234 let block = simulate::build_simulated_block::<Self::Error, _>(
235 result.block,
236 results,
237 return_full_transactions.into(),
238 this.converter(),
239 )?;
240
241 blocks.push(block);
242 }
243
244 Ok(blocks)
245 })
246 .await
247 }
248 }
249
250 fn call(
252 &self,
253 request: RpcTxReq<<Self::RpcConvert as RpcConvert>::Network>,
254 block_number: Option<BlockId>,
255 overrides: EvmOverrides,
256 ) -> impl Future<Output = Result<Bytes, Self::Error>> + Send {
257 async move {
258 let _permit = self.acquire_owned_blocking_io().await;
259 let res =
260 self.transact_call_at(request, block_number.unwrap_or_default(), overrides).await?;
261
262 Self::Error::ensure_success(res.result)
263 }
264 }
265
266 fn call_many(
269 &self,
270 bundles: Vec<Bundle<RpcTxReq<<Self::RpcConvert as RpcConvert>::Network>>>,
271 state_context: Option<StateContext>,
272 mut state_override: Option<StateOverride>,
273 ) -> impl Future<Output = Result<Vec<Vec<EthCallResponse>>, Self::Error>> + Send {
274 async move {
275 if bundles.is_empty() {
277 return Err(EthApiError::InvalidParams(String::from("bundles are empty.")).into());
278 }
279
280 let _permit = self.acquire_owned_blocking_io().await;
281
282 let StateContext { transaction_index, block_number } =
283 state_context.unwrap_or_default();
284 let transaction_index = transaction_index.unwrap_or_default();
285
286 let mut target_block = block_number.unwrap_or_default();
287 let is_block_target_pending = target_block.is_pending();
288
289 if !is_block_target_pending {
292 let Some(block_hash) = self
293 .provider()
294 .block_hash_for_id(target_block)
295 .map_err(Self::Error::from_eth_err::<ProviderError>)?
296 else {
297 return Err(EthApiError::HeaderNotFound(target_block).into())
298 };
299 target_block = block_hash.into();
300 }
301
302 let block = self
303 .recovered_block(target_block)
304 .await?
305 .ok_or(EthApiError::HeaderNotFound(target_block))?;
306 let evm_env = self.evm_env_for_header(block.sealed_block().sealed_header())?;
307
308 let mut at = block.parent_hash();
312 let mut replay_block_txs = true;
313
314 let num_txs =
315 transaction_index.index().unwrap_or_else(|| block.body().transactions().len());
316 if !is_block_target_pending && num_txs == block.body().transactions().len() {
320 at = block.hash();
321 replay_block_txs = false;
322 }
323
324 self.spawn_with_state_at_block(at, move |this, mut db| {
325 let mut all_results = Vec::with_capacity(bundles.len());
326
327 if replay_block_txs {
328 let mut executor = RpcNodeCore::evm_config(&this)
329 .executor_for_block(&mut db, block.sealed_block())
330 .map_err(RethError::other)
331 .map_err(Self::Error::from_eth_err)?;
332 executor.apply_pre_execution_changes().map_err(Self::Error::from_eth_err)?;
333 for tx in block.transactions_recovered().take(num_txs) {
334 executor.execute_transaction(tx).map_err(Self::Error::from_eth_err)?;
335 }
336 }
337
338 for (bundle_index, bundle) in bundles.into_iter().enumerate() {
340 let Bundle { transactions, block_override } = bundle;
341 if transactions.is_empty() {
342 continue;
344 }
345
346 let mut bundle_results = Vec::with_capacity(transactions.len());
347 let block_overrides = block_override.map(Box::new);
348
349 for (tx_index, tx) in transactions.into_iter().enumerate() {
351 let overrides =
354 EvmOverrides::new(state_override.take(), block_overrides.clone());
355
356 let (current_evm_env, prepared_tx) = this
357 .prepare_call_env(evm_env.clone(), tx, &mut db, overrides)
358 .map_err(|err| {
359 Self::Error::from_eth_err(EthApiError::call_many_error(
360 bundle_index,
361 tx_index,
362 err.into(),
363 ))
364 })?;
365 let res = this.transact(&mut db, current_evm_env, prepared_tx).map_err(
366 |err| {
367 Self::Error::from_eth_err(EthApiError::call_many_error(
368 bundle_index,
369 tx_index,
370 err.into(),
371 ))
372 },
373 )?;
374
375 match Self::Error::ensure_success(res.result) {
376 Ok(output) => {
377 bundle_results
378 .push(EthCallResponse { value: Some(output), error: None });
379 }
380 Err(err) => {
381 bundle_results.push(EthCallResponse {
382 value: None,
383 error: Some(err.to_string()),
384 });
385 }
386 }
387
388 db.commit(res.state);
391 }
392
393 all_results.push(bundle_results);
394 }
395
396 Ok(all_results)
397 })
398 .await
399 }
400 }
401
402 fn create_access_list_at(
405 &self,
406 request: RpcTxReq<<Self::RpcConvert as RpcConvert>::Network>,
407 block_number: Option<BlockId>,
408 state_override: Option<StateOverride>,
409 ) -> impl Future<Output = Result<AccessListResult, Self::Error>> + Send
410 where
411 Self: Trace,
412 {
413 async move {
414 let block_id = block_number.unwrap_or_default();
415 let (evm_env, at) = self.evm_env_at(block_id).await?;
416
417 self.spawn_blocking_io_fut(async move |this| {
418 this.create_access_list_with(evm_env, at, request, state_override).await
419 })
420 .await
421 }
422 }
423
424 fn create_access_list_with(
427 &self,
428 mut evm_env: EvmEnvFor<Self::Evm>,
429 at: BlockId,
430 request: RpcTxReq<<Self::RpcConvert as RpcConvert>::Network>,
431 state_override: Option<StateOverride>,
432 ) -> impl Future<Output = Result<AccessListResult, Self::Error>> + Send
433 where
434 Self: Trace,
435 {
436 self.spawn_blocking_io_fut(async move |this| {
437 let state = this.state_at_block_id(at).await?;
438 let mut db = State::builder().with_database(StateProviderDatabase::new(state)).build();
439
440 if let Some(state_overrides) = state_override {
441 apply_state_overrides(state_overrides, &mut db)
442 .map_err(Self::Error::from_eth_err)?;
443 }
444
445 let request_has_gas_limit = request.as_ref().gas_limit().is_some();
447 let initial = request.as_ref().access_list().cloned().unwrap_or_default();
448
449 let mut tx_env = this.create_txn_env(&evm_env, request, &mut db)?;
450
451 evm_env.cfg_env.disable_block_gas_limit = true;
454
455 evm_env.cfg_env.disable_base_fee = true;
459
460 evm_env.cfg_env.disable_eip3607 = true;
462
463 evm_env.cfg_env.disable_fee_charge = true;
466
467 evm_env.cfg_env.tx_gas_limit_cap = Some(u64::MAX);
471
472 if !request_has_gas_limit && tx_env.gas_price() > 0 {
473 let cap = this.caller_gas_allowance(&mut db, &evm_env, &tx_env)?;
474 tx_env.set_gas_limit(cap.min(evm_env.block_env.gas_limit()));
477 }
478
479 let mut inspector = AccessListInspector::new(initial);
480
481 let result = this.inspect(&mut db, evm_env.clone(), tx_env.clone(), &mut inspector)?;
482 let access_list = inspector.into_access_list();
483 let gas_used = result.result.tx_gas_used();
484 tx_env.set_access_list(access_list.clone());
485 if let Err(err) = Self::Error::ensure_success(result.result) {
486 return Ok(AccessListResult {
487 access_list,
488 gas_used: U256::from(gas_used),
489 error: Some(err.to_string()),
490 });
491 }
492
493 let result = this.transact(&mut db, evm_env, tx_env)?;
495 let gas_used = result.result.tx_gas_used();
496 let error = Self::Error::ensure_success(result.result).err().map(|e| e.to_string());
497
498 Ok(AccessListResult { access_list, gas_used: U256::from(gas_used), error })
499 })
500 }
501}
502
503pub trait Call:
505 LoadState<
506 RpcConvert: RpcConvert<Evm = Self::Evm>,
507 Error: FromEvmError<Self::Evm>
508 + From<<Self::RpcConvert as RpcConvert>::Error>
509 + From<ProviderError>,
510 > + SpawnBlocking
511{
512 fn call_gas_limit(&self) -> u64;
516
517 fn max_simulate_blocks(&self) -> u64;
519
520 fn evm_memory_limit(&self) -> u64;
522
523 fn caller_gas_allowance(
525 &self,
526 mut db: impl Database<Error: Into<EthApiError>>,
527 _evm_env: &EvmEnvFor<Self::Evm>,
528 tx_env: &TxEnvFor<Self::Evm>,
529 ) -> Result<u64, Self::Error> {
530 alloy_evm::call::caller_gas_allowance(&mut db, tx_env).map_err(Self::Error::from_eth_err)
531 }
532
533 fn with_state_at_block<F, R>(
535 &self,
536 at: BlockId,
537 f: F,
538 ) -> impl Future<Output = Result<R, Self::Error>> + Send
539 where
540 R: Send + 'static,
541 F: FnOnce(Self, StateProviderBox) -> Result<R, Self::Error> + Send + 'static,
542 {
543 self.spawn_blocking_io_fut(async move |this| {
544 let state = this.state_at_block_id(at).await?;
545 f(this, state)
546 })
547 }
548
549 fn transact<DB>(
552 &self,
553 db: DB,
554 evm_env: EvmEnvFor<Self::Evm>,
555 tx_env: TxEnvFor<Self::Evm>,
556 ) -> Result<ResultAndState<HaltReasonFor<Self::Evm>>, Self::Error>
557 where
558 DB: Database<Error = EvmDatabaseError<ProviderError>> + fmt::Debug,
559 {
560 let mut evm = self.evm_config().evm_with_env(db, evm_env);
561 let res = evm.transact(tx_env).map_err(Self::Error::from_evm_err)?;
562
563 Ok(res)
564 }
565
566 fn transact_with_inspector<DB, I>(
569 &self,
570 db: DB,
571 evm_env: EvmEnvFor<Self::Evm>,
572 tx_env: TxEnvFor<Self::Evm>,
573 inspector: I,
574 ) -> Result<ResultAndState<HaltReasonFor<Self::Evm>>, Self::Error>
575 where
576 DB: Database<Error = EvmDatabaseError<ProviderError>> + fmt::Debug,
577 I: InspectorFor<Self::Evm, DB>,
578 {
579 let mut evm = self.evm_config().evm_with_env_and_inspector(db, evm_env, inspector);
580 let res = evm.transact(tx_env).map_err(Self::Error::from_evm_err)?;
581
582 Ok(res)
583 }
584
585 fn transact_call_at(
592 &self,
593 request: RpcTxReq<<Self::RpcConvert as RpcConvert>::Network>,
594 at: BlockId,
595 overrides: EvmOverrides,
596 ) -> impl Future<Output = Result<ResultAndState<HaltReasonFor<Self::Evm>>, Self::Error>> + Send
597 where
598 Self: LoadPendingBlock,
599 {
600 async move {
601 let guard = CancelOnDrop::default();
602 let cancel = guard.clone();
603 let this = self.clone();
604
605 let res = self
606 .spawn_with_call_at(request, at, overrides, move |db, evm_env, tx_env| {
607 if cancel.is_cancelled() {
608 return Err(EthApiError::InternalEthError.into())
610 }
611 this.transact(db, evm_env, tx_env)
612 })
613 .await;
614 drop(guard);
615 res
616 }
617 }
618
619 fn spawn_with_state_at_block<F, R>(
621 &self,
622 at: impl Into<BlockId>,
623 f: F,
624 ) -> impl Future<Output = Result<R, Self::Error>> + Send
625 where
626 F: FnOnce(Self, StateCacheDb) -> Result<R, Self::Error> + Send + 'static,
627 R: Send + 'static,
628 {
629 let at = at.into();
630 self.spawn_blocking_io_fut(async move |this| {
631 let state = this.state_at_block_id(at).await?;
632 let db = State::builder()
633 .with_database(StateProviderDatabase::new(StateProviderTraitObjWrapper(state)))
634 .build();
635 f(this, db)
636 })
637 }
638
639 fn spawn_with_call_at<F, R>(
655 &self,
656 request: RpcTxReq<<Self::RpcConvert as RpcConvert>::Network>,
657 at: BlockId,
658 overrides: EvmOverrides,
659 f: F,
660 ) -> impl Future<Output = Result<R, Self::Error>> + Send
661 where
662 Self: LoadPendingBlock,
663 F: FnOnce(
664 &mut StateCacheDb,
665 EvmEnvFor<Self::Evm>,
666 TxEnvFor<Self::Evm>,
667 ) -> Result<R, Self::Error>
668 + Send
669 + 'static,
670 R: Send + 'static,
671 {
672 async move {
673 let (evm_env, at) = self.evm_env_at(at).await?;
674 self.spawn_with_state_at_block(at, move |this, mut db| {
675 let (evm_env, tx_env) =
676 this.prepare_call_env(evm_env, request, &mut db, overrides)?;
677
678 f(&mut db, evm_env, tx_env)
679 })
680 .await
681 }
682 }
683
684 fn spawn_replay_transaction<F, R>(
694 &self,
695 hash: B256,
696 f: F,
697 ) -> impl Future<Output = Result<Option<R>, Self::Error>> + Send
698 where
699 Self: LoadBlock + LoadTransaction,
700 F: FnOnce(
701 TransactionInfo,
702 ResultAndState<HaltReasonFor<Self::Evm>>,
703 StateCacheDb,
704 ) -> Result<R, Self::Error>
705 + Send
706 + 'static,
707 R: Send + 'static,
708 {
709 async move {
710 let (transaction, block) = match self.transaction_and_block(hash).await? {
711 None => return Ok(None),
712 Some(res) => res,
713 };
714 let (tx, tx_info) = transaction.split();
715
716 let parent_block = block.parent_hash();
719
720 self.spawn_with_state_at_block(parent_block, move |this, mut db| {
721 let block_txs = block.transactions_recovered();
722
723 let mut executor = RpcNodeCore::evm_config(&this)
724 .executor_for_block(&mut db, block.sealed_block())
725 .map_err(RethError::other)
726 .map_err(Self::Error::from_eth_err)?;
727 executor.apply_pre_execution_changes().map_err(Self::Error::from_eth_err)?;
728
729 for block_tx in block_txs {
731 if block_tx.tx_hash() == tx.tx_hash() {
732 break;
733 }
734 executor.execute_transaction(block_tx).map_err(Self::Error::from_eth_err)?;
735 }
736
737 let tx_env = RpcNodeCore::evm_config(&this).tx_env(tx);
738
739 let res = executor.evm_mut().transact(tx_env).map_err(Self::Error::from_evm_err)?;
740 drop(executor);
741 f(tx_info, res, db)
742 })
743 .await
744 .map(Some)
745 }
746 }
747
748 fn replay_transactions_until<'a, DB, I>(
756 &self,
757 db: &mut DB,
758 evm_env: EvmEnvFor<Self::Evm>,
759 transactions: I,
760 target_tx_hash: B256,
761 ) -> Result<usize, Self::Error>
762 where
763 DB: Database<Error = EvmDatabaseError<ProviderError>> + DatabaseCommit + core::fmt::Debug,
764 I: IntoIterator<Item = Recovered<&'a ProviderTx<Self::Provider>>>,
765 {
766 let mut evm = self.evm_config().evm_with_env(db, evm_env);
767 let mut index = 0;
768 for tx in transactions {
769 if *tx.tx_hash() == target_tx_hash {
770 break
772 }
773
774 let tx_env = self.evm_config().tx_env(tx);
775 evm.transact_commit(tx_env).map_err(Self::Error::from_evm_err)?;
776 index += 1;
777 }
778 Ok(index)
779 }
780
781 fn create_txn_env(
785 &self,
786 evm_env: &EvmEnvFor<Self::Evm>,
787 mut request: RpcTxReq<<Self::RpcConvert as RpcConvert>::Network>,
788 mut db: impl Database<Error: Into<EthApiError>>,
789 ) -> Result<TxEnvFor<Self::Evm>, Self::Error> {
790 if request.as_ref().nonce().is_none() {
791 let nonce = db
792 .basic(request.as_ref().from().unwrap_or_default())
793 .map_err(Into::into)?
794 .map(|acc| acc.nonce)
795 .unwrap_or_default();
796 request.as_mut().set_nonce(nonce);
797 }
798
799 Ok(self.converter().tx_env(request, evm_env)?)
800 }
801
802 #[expect(clippy::type_complexity)]
816 fn prepare_call_env<DB>(
817 &self,
818 mut evm_env: EvmEnvFor<Self::Evm>,
819 mut request: RpcTxReq<<Self::RpcConvert as RpcConvert>::Network>,
820 db: &mut DB,
821 overrides: EvmOverrides,
822 ) -> Result<(EvmEnvFor<Self::Evm>, TxEnvFor<Self::Evm>), Self::Error>
823 where
824 DB: Database + DatabaseCommit + OverrideBlockHashes,
825 EthApiError: From<<DB as Database>::Error>,
826 {
827 let request_has_gas_limit = request.as_ref().gas_limit().is_some();
829
830 if let Some(requested_gas) = request.as_ref().gas_limit() {
831 let global_gas_cap = self.call_gas_limit();
832 if global_gas_cap != 0 && global_gas_cap < requested_gas {
833 warn!(target: "rpc::eth::call", ?request, ?global_gas_cap, "Capping gas limit to global gas cap");
834 request.as_mut().set_gas_limit(global_gas_cap);
835 }
836 } else {
837 request.as_mut().set_gas_limit(self.call_gas_limit());
839 }
840
841 evm_env.cfg_env.disable_block_gas_limit = true;
844
845 evm_env.cfg_env.disable_eip3607 = true;
848
849 evm_env.cfg_env.disable_base_fee = true;
853
854 evm_env.cfg_env.tx_gas_limit_cap = Some(u64::MAX);
856
857 evm_env.cfg_env.disable_fee_charge = true;
861
862 evm_env.cfg_env.memory_limit = self.evm_memory_limit();
863
864 request.as_mut().take_nonce();
866
867 if let Some(block_overrides) = overrides.block {
868 apply_block_overrides(*block_overrides, db, evm_env.block_env.inner_mut());
869 }
870 if let Some(state_overrides) = overrides.state {
871 apply_state_overrides(state_overrides, db)
872 .map_err(EthApiError::from_state_overrides_err)?;
873 }
874
875 let mut tx_env = self.create_txn_env(&evm_env, request, &mut *db)?;
876
877 if tx_env.gas_price() == 0 {
879 evm_env.block_env.inner_mut().basefee = 0;
880 }
881
882 if !request_has_gas_limit {
883 if tx_env.gas_price() > 0 {
885 trace!(target: "rpc::eth::call", ?tx_env, "Applying gas limit cap with caller allowance");
887 let cap = self.caller_gas_allowance(db, &evm_env, &tx_env)?;
888 tx_env.set_gas_limit(cap.min(evm_env.block_env.gas_limit()));
890 }
891 }
892
893 Ok((evm_env, tx_env))
894 }
895}