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_errors::{ProviderError, RethError};
22use reth_evm::{
23 env::BlockEnvironment, ConfigureEvm, Evm, EvmEnvFor, HaltReasonFor, InspectorFor,
24 TransactionEnv, TxEnvFor,
25};
26use reth_node_api::BlockBody;
27use reth_primitives_traits::Recovered;
28use reth_revm::{database::StateProviderDatabase, db::State};
29use reth_rpc_convert::{RpcConvert, RpcTxReq};
30use reth_rpc_eth_types::{
31 cache::db::{StateCacheDbRefMutWrapper, StateProviderTraitObjWrapper},
32 error::{api::FromEvmHalt, ensure_success, FromEthApiError},
33 simulate::{self, EthSimulateError},
34 EthApiError, RevertError, StateCacheDb,
35};
36use reth_storage_api::{BlockIdReader, ProviderTx};
37use revm::{
38 context::Block,
39 context_interface::{
40 result::{ExecutionResult, ResultAndState},
41 Transaction,
42 },
43 Database, DatabaseCommit,
44};
45use revm_inspectors::{access_list::AccessListInspector, transfer::TransferInspector};
46use tracing::{trace, warn};
47
48pub type SimulatedBlocksResult<N, E> = Result<Vec<SimulatedBlock<RpcBlock<N>>>, E>;
50
51pub trait EthCall: EstimateCall + Call + LoadPendingBlock + LoadBlock + FullEthApiTypes {
54 fn estimate_gas_at(
56 &self,
57 request: RpcTxReq<<Self::RpcConvert as RpcConvert>::Network>,
58 at: BlockId,
59 state_override: Option<StateOverride>,
60 ) -> impl Future<Output = Result<U256, Self::Error>> + Send {
61 EstimateCall::estimate_gas_at(self, request, at, state_override)
62 }
63
64 fn simulate_v1(
69 &self,
70 payload: SimulatePayload<RpcTxReq<<Self::RpcConvert as RpcConvert>::Network>>,
71 block: Option<BlockId>,
72 ) -> impl Future<Output = SimulatedBlocksResult<Self::NetworkTypes, Self::Error>> + Send {
73 async move {
74 if payload.block_state_calls.len() > self.max_simulate_blocks() as usize {
75 return Err(EthApiError::InvalidParams("too many blocks.".to_string()).into())
76 }
77
78 let block = block.unwrap_or_default();
79
80 let SimulatePayload {
81 block_state_calls,
82 trace_transfers,
83 validation,
84 return_full_transactions,
85 } = payload;
86
87 if block_state_calls.is_empty() {
88 return Err(EthApiError::InvalidParams(String::from("calls are empty.")).into())
89 }
90
91 let base_block =
92 self.recovered_block(block).await?.ok_or(EthApiError::HeaderNotFound(block))?;
93 let mut parent = base_block.sealed_header().clone();
94
95 let this = self.clone();
96 self.spawn_with_state_at_block(block, move |state| {
97 let mut db =
98 State::builder().with_database(StateProviderDatabase::new(state)).build();
99 let mut blocks: Vec<SimulatedBlock<RpcBlock<Self::NetworkTypes>>> =
100 Vec::with_capacity(block_state_calls.len());
101 for block in block_state_calls {
102 let mut evm_env = this
103 .evm_config()
104 .next_evm_env(&parent, &this.next_env_attributes(&parent)?)
105 .map_err(RethError::other)
106 .map_err(Self::Error::from_eth_err)?;
107
108 evm_env.cfg_env.disable_eip3607 = true;
110
111 if !validation {
112 evm_env.cfg_env.disable_nonce_check = true;
114 evm_env.cfg_env.disable_base_fee = true;
115 evm_env.cfg_env.tx_gas_limit_cap = Some(u64::MAX);
116 evm_env.block_env.inner_mut().basefee = 0;
117 }
118
119 let SimBlock { block_overrides, state_overrides, calls } = block;
120
121 if let Some(block_overrides) = block_overrides {
122 if let Some(gas_limit_override) = block_overrides.gas_limit &&
124 gas_limit_override > evm_env.block_env.gas_limit() &&
125 gas_limit_override > this.call_gas_limit()
126 {
127 return Err(EthApiError::other(EthSimulateError::GasLimitReached).into())
128 }
129 apply_block_overrides(
130 block_overrides,
131 &mut db,
132 evm_env.block_env.inner_mut(),
133 );
134 }
135 if let Some(state_overrides) = state_overrides {
136 apply_state_overrides(state_overrides, &mut db)
137 .map_err(Self::Error::from_eth_err)?;
138 }
139
140 let block_gas_limit = evm_env.block_env.gas_limit();
141 let chain_id = evm_env.cfg_env.chain_id;
142
143 let default_gas_limit = {
144 let total_specified_gas =
145 calls.iter().filter_map(|tx| tx.as_ref().gas_limit()).sum::<u64>();
146 let txs_without_gas_limit =
147 calls.iter().filter(|tx| tx.as_ref().gas_limit().is_none()).count();
148
149 if total_specified_gas > block_gas_limit {
150 return Err(EthApiError::Other(Box::new(
151 EthSimulateError::BlockGasLimitExceeded,
152 ))
153 .into())
154 }
155
156 if txs_without_gas_limit > 0 {
157 (block_gas_limit - total_specified_gas) / txs_without_gas_limit as u64
158 } else {
159 0
160 }
161 };
162
163 let ctx = this
164 .evm_config()
165 .context_for_next_block(&parent, this.next_env_attributes(&parent)?)
166 .map_err(RethError::other)
167 .map_err(Self::Error::from_eth_err)?;
168 let (result, results) = if trace_transfers {
169 let inspector = TransferInspector::new(false).with_logs(true);
172 let evm = this
173 .evm_config()
174 .evm_with_env_and_inspector(&mut db, evm_env, inspector);
175 let builder = this.evm_config().create_block_builder(evm, &parent, ctx);
176 simulate::execute_transactions(
177 builder,
178 calls,
179 default_gas_limit,
180 chain_id,
181 this.tx_resp_builder(),
182 )?
183 } else {
184 let evm = this.evm_config().evm_with_env(&mut db, evm_env);
185 let builder = this.evm_config().create_block_builder(evm, &parent, ctx);
186 simulate::execute_transactions(
187 builder,
188 calls,
189 default_gas_limit,
190 chain_id,
191 this.tx_resp_builder(),
192 )?
193 };
194
195 parent = result.block.clone_sealed_header();
196
197 let block = simulate::build_simulated_block(
198 result.block,
199 results,
200 return_full_transactions.into(),
201 this.tx_resp_builder(),
202 )?;
203
204 blocks.push(block);
205 }
206
207 Ok(blocks)
208 })
209 .await
210 }
211 }
212
213 fn call(
215 &self,
216 request: RpcTxReq<<Self::RpcConvert as RpcConvert>::Network>,
217 block_number: Option<BlockId>,
218 overrides: EvmOverrides,
219 ) -> impl Future<Output = Result<Bytes, Self::Error>> + Send {
220 async move {
221 let res =
222 self.transact_call_at(request, block_number.unwrap_or_default(), overrides).await?;
223
224 ensure_success(res.result)
225 }
226 }
227
228 fn call_many(
231 &self,
232 bundles: Vec<Bundle<RpcTxReq<<Self::RpcConvert as RpcConvert>::Network>>>,
233 state_context: Option<StateContext>,
234 mut state_override: Option<StateOverride>,
235 ) -> impl Future<Output = Result<Vec<Vec<EthCallResponse>>, Self::Error>> + Send {
236 async move {
237 if bundles.is_empty() {
239 return Err(EthApiError::InvalidParams(String::from("bundles are empty.")).into());
240 }
241
242 let StateContext { transaction_index, block_number } =
243 state_context.unwrap_or_default();
244 let transaction_index = transaction_index.unwrap_or_default();
245
246 let mut target_block = block_number.unwrap_or_default();
247 let is_block_target_pending = target_block.is_pending();
248
249 if !is_block_target_pending {
252 target_block = self
253 .provider()
254 .block_hash_for_id(target_block)
255 .map_err(|_| EthApiError::HeaderNotFound(target_block))?
256 .ok_or_else(|| EthApiError::HeaderNotFound(target_block))?
257 .into();
258 }
259
260 let ((evm_env, _), block) = futures::try_join!(
261 self.evm_env_at(target_block),
262 self.recovered_block(target_block)
263 )?;
264
265 let block = block.ok_or(EthApiError::HeaderNotFound(target_block))?;
266
267 let mut at = block.parent_hash();
271 let mut replay_block_txs = true;
272
273 let num_txs =
274 transaction_index.index().unwrap_or_else(|| block.body().transactions().len());
275 if !is_block_target_pending && num_txs == block.body().transactions().len() {
279 at = block.hash();
280 replay_block_txs = false;
281 }
282
283 let this = self.clone();
284 self.spawn_with_state_at_block(at.into(), move |state| {
285 let mut all_results = Vec::with_capacity(bundles.len());
286 let mut db =
287 State::builder().with_database(StateProviderDatabase::new(state)).build();
288
289 if replay_block_txs {
290 let block_transactions = block.transactions_recovered().take(num_txs);
293 for tx in block_transactions {
294 let tx_env = RpcNodeCore::evm_config(&this).tx_env(tx);
295 let res = this.transact(&mut db, evm_env.clone(), tx_env)?;
296 db.commit(res.state);
297 }
298 }
299
300 for (bundle_index, bundle) in bundles.into_iter().enumerate() {
302 let Bundle { transactions, block_override } = bundle;
303 if transactions.is_empty() {
304 continue;
306 }
307
308 let mut bundle_results = Vec::with_capacity(transactions.len());
309 let block_overrides = block_override.map(Box::new);
310
311 for (tx_index, tx) in transactions.into_iter().enumerate() {
313 let overrides =
316 EvmOverrides::new(state_override.take(), block_overrides.clone());
317
318 let (current_evm_env, prepared_tx) = this
319 .prepare_call_env(evm_env.clone(), tx, &mut db, overrides)
320 .map_err(|err| {
321 Self::Error::from_eth_err(EthApiError::call_many_error(
322 bundle_index,
323 tx_index,
324 err.into(),
325 ))
326 })?;
327 let res = this.transact(&mut db, current_evm_env, prepared_tx).map_err(
328 |err| {
329 Self::Error::from_eth_err(EthApiError::call_many_error(
330 bundle_index,
331 tx_index,
332 err.into(),
333 ))
334 },
335 )?;
336
337 match ensure_success::<_, Self::Error>(res.result) {
338 Ok(output) => {
339 bundle_results
340 .push(EthCallResponse { value: Some(output), error: None });
341 }
342 Err(err) => {
343 bundle_results.push(EthCallResponse {
344 value: None,
345 error: Some(err.to_string()),
346 });
347 }
348 }
349
350 db.commit(res.state);
353 }
354
355 all_results.push(bundle_results);
356 }
357
358 Ok(all_results)
359 })
360 .await
361 }
362 }
363
364 fn create_access_list_at(
367 &self,
368 request: RpcTxReq<<Self::RpcConvert as RpcConvert>::Network>,
369 block_number: Option<BlockId>,
370 state_override: Option<StateOverride>,
371 ) -> impl Future<Output = Result<AccessListResult, Self::Error>> + Send
372 where
373 Self: Trace,
374 {
375 async move {
376 let block_id = block_number.unwrap_or_default();
377 let (evm_env, at) = self.evm_env_at(block_id).await?;
378
379 self.spawn_blocking_io_fut(move |this| async move {
380 this.create_access_list_with(evm_env, at, request, state_override).await
381 })
382 .await
383 }
384 }
385
386 fn create_access_list_with(
389 &self,
390 mut evm_env: EvmEnvFor<Self::Evm>,
391 at: BlockId,
392 request: RpcTxReq<<Self::RpcConvert as RpcConvert>::Network>,
393 state_override: Option<StateOverride>,
394 ) -> impl Future<Output = Result<AccessListResult, Self::Error>> + Send
395 where
396 Self: Trace,
397 {
398 self.spawn_blocking_io_fut(move |this| async move {
399 let state = this.state_at_block_id(at).await?;
400 let mut db = State::builder().with_database(StateProviderDatabase::new(state)).build();
401
402 if let Some(state_overrides) = state_override {
403 apply_state_overrides(state_overrides, &mut db)
404 .map_err(Self::Error::from_eth_err)?;
405 }
406
407 let mut tx_env = this.create_txn_env(&evm_env, request.clone(), &mut db)?;
408
409 evm_env.cfg_env.disable_block_gas_limit = true;
412
413 evm_env.cfg_env.disable_base_fee = true;
417
418 evm_env.cfg_env.disable_eip3607 = true;
420
421 if request.as_ref().gas_limit().is_none() && tx_env.gas_price() > 0 {
422 let cap = this.caller_gas_allowance(&mut db, &evm_env, &tx_env)?;
423 tx_env.set_gas_limit(cap.min(evm_env.block_env.gas_limit()));
426 }
427
428 let initial = request.as_ref().access_list().cloned().unwrap_or_default();
430
431 let mut inspector = AccessListInspector::new(initial);
432
433 let result = this.inspect(&mut db, evm_env.clone(), tx_env.clone(), &mut inspector)?;
434 let access_list = inspector.into_access_list();
435 tx_env.set_access_list(access_list.clone());
436 match result.result {
437 ExecutionResult::Halt { reason, gas_used } => {
438 let error =
439 Some(Self::Error::from_evm_halt(reason, tx_env.gas_limit()).to_string());
440 return Ok(AccessListResult {
441 access_list,
442 gas_used: U256::from(gas_used),
443 error,
444 })
445 }
446 ExecutionResult::Revert { output, gas_used } => {
447 let error = Some(RevertError::new(output).to_string());
448 return Ok(AccessListResult {
449 access_list,
450 gas_used: U256::from(gas_used),
451 error,
452 })
453 }
454 ExecutionResult::Success { .. } => {}
455 };
456
457 let gas_limit = tx_env.gas_limit();
459 let result = this.transact(&mut db, evm_env, tx_env)?;
460 let res = match result.result {
461 ExecutionResult::Halt { reason, gas_used } => {
462 let error = Some(Self::Error::from_evm_halt(reason, gas_limit).to_string());
463 AccessListResult { access_list, gas_used: U256::from(gas_used), error }
464 }
465 ExecutionResult::Revert { output, gas_used } => {
466 let error = Some(RevertError::new(output).to_string());
467 AccessListResult { access_list, gas_used: U256::from(gas_used), error }
468 }
469 ExecutionResult::Success { gas_used, .. } => {
470 AccessListResult { access_list, gas_used: U256::from(gas_used), error: None }
471 }
472 };
473
474 Ok(res)
475 })
476 }
477}
478
479pub trait Call:
481 LoadState<
482 RpcConvert: RpcConvert<Evm = Self::Evm>,
483 Error: FromEvmError<Self::Evm>
484 + From<<Self::RpcConvert as RpcConvert>::Error>
485 + From<ProviderError>,
486 > + SpawnBlocking
487{
488 fn call_gas_limit(&self) -> u64;
492
493 fn max_simulate_blocks(&self) -> u64;
495
496 fn evm_memory_limit(&self) -> u64;
498
499 fn caller_gas_allowance(
501 &self,
502 mut db: impl Database<Error: Into<EthApiError>>,
503 _evm_env: &EvmEnvFor<Self::Evm>,
504 tx_env: &TxEnvFor<Self::Evm>,
505 ) -> Result<u64, Self::Error> {
506 alloy_evm::call::caller_gas_allowance(&mut db, tx_env).map_err(Self::Error::from_eth_err)
507 }
508
509 fn with_state_at_block<F, R>(
511 &self,
512 at: BlockId,
513 f: F,
514 ) -> impl Future<Output = Result<R, Self::Error>> + Send
515 where
516 R: Send + 'static,
517 F: FnOnce(Self, StateProviderTraitObjWrapper<'_>) -> Result<R, Self::Error>
518 + Send
519 + 'static,
520 {
521 self.spawn_blocking_io_fut(move |this| async move {
522 let state = this.state_at_block_id(at).await?;
523 f(this, StateProviderTraitObjWrapper(&state))
524 })
525 }
526
527 fn transact<DB>(
530 &self,
531 db: DB,
532 evm_env: EvmEnvFor<Self::Evm>,
533 tx_env: TxEnvFor<Self::Evm>,
534 ) -> Result<ResultAndState<HaltReasonFor<Self::Evm>>, Self::Error>
535 where
536 DB: Database<Error = ProviderError> + fmt::Debug,
537 {
538 let mut evm = self.evm_config().evm_with_env(db, evm_env);
539 let res = evm.transact(tx_env).map_err(Self::Error::from_evm_err)?;
540
541 Ok(res)
542 }
543
544 fn transact_with_inspector<DB, I>(
547 &self,
548 db: DB,
549 evm_env: EvmEnvFor<Self::Evm>,
550 tx_env: TxEnvFor<Self::Evm>,
551 inspector: I,
552 ) -> Result<ResultAndState<HaltReasonFor<Self::Evm>>, Self::Error>
553 where
554 DB: Database<Error = ProviderError> + fmt::Debug,
555 I: InspectorFor<Self::Evm, DB>,
556 {
557 let mut evm = self.evm_config().evm_with_env_and_inspector(db, evm_env, inspector);
558 let res = evm.transact(tx_env).map_err(Self::Error::from_evm_err)?;
559
560 Ok(res)
561 }
562
563 fn transact_call_at(
565 &self,
566 request: RpcTxReq<<Self::RpcConvert as RpcConvert>::Network>,
567 at: BlockId,
568 overrides: EvmOverrides,
569 ) -> impl Future<Output = Result<ResultAndState<HaltReasonFor<Self::Evm>>, Self::Error>> + Send
570 where
571 Self: LoadPendingBlock,
572 {
573 let this = self.clone();
574 self.spawn_with_call_at(request, at, overrides, move |db, evm_env, tx_env| {
575 this.transact(db, evm_env, tx_env)
576 })
577 }
578
579 fn spawn_with_state_at_block<F, R>(
581 &self,
582 at: BlockId,
583 f: F,
584 ) -> impl Future<Output = Result<R, Self::Error>> + Send
585 where
586 F: FnOnce(StateProviderTraitObjWrapper<'_>) -> Result<R, Self::Error> + Send + 'static,
587 R: Send + 'static,
588 {
589 self.spawn_blocking_io_fut(move |this| async move {
590 let state = this.state_at_block_id(at).await?;
591 f(StateProviderTraitObjWrapper(&state))
592 })
593 }
594
595 fn spawn_with_call_at<F, R>(
611 &self,
612 request: RpcTxReq<<Self::RpcConvert as RpcConvert>::Network>,
613 at: BlockId,
614 overrides: EvmOverrides,
615 f: F,
616 ) -> impl Future<Output = Result<R, Self::Error>> + Send
617 where
618 Self: LoadPendingBlock,
619 F: FnOnce(
620 StateCacheDbRefMutWrapper<'_, '_>,
621 EvmEnvFor<Self::Evm>,
622 TxEnvFor<Self::Evm>,
623 ) -> Result<R, Self::Error>
624 + Send
625 + 'static,
626 R: Send + 'static,
627 {
628 async move {
629 let (evm_env, at) = self.evm_env_at(at).await?;
630 let this = self.clone();
631 self.spawn_blocking_io_fut(move |_| async move {
632 let state = this.state_at_block_id(at).await?;
633 let mut db = State::builder()
634 .with_database(StateProviderDatabase::new(StateProviderTraitObjWrapper(&state)))
635 .build();
636
637 let (evm_env, tx_env) =
638 this.prepare_call_env(evm_env, request, &mut db, overrides)?;
639
640 f(StateCacheDbRefMutWrapper(&mut db), evm_env, tx_env)
641 })
642 .await
643 }
644 }
645
646 fn spawn_replay_transaction<F, R>(
656 &self,
657 hash: B256,
658 f: F,
659 ) -> impl Future<Output = Result<Option<R>, Self::Error>> + Send
660 where
661 Self: LoadBlock + LoadTransaction,
662 F: FnOnce(
663 TransactionInfo,
664 ResultAndState<HaltReasonFor<Self::Evm>>,
665 StateCacheDb<'_>,
666 ) -> Result<R, Self::Error>
667 + Send
668 + 'static,
669 R: Send + 'static,
670 {
671 async move {
672 let (transaction, block) = match self.transaction_and_block(hash).await? {
673 None => return Ok(None),
674 Some(res) => res,
675 };
676 let (tx, tx_info) = transaction.split();
677
678 let (evm_env, _) = self.evm_env_at(block.hash().into()).await?;
679
680 let parent_block = block.parent_hash();
683
684 let this = self.clone();
685 self.spawn_with_state_at_block(parent_block.into(), move |state| {
686 let mut db =
687 State::builder().with_database(StateProviderDatabase::new(state)).build();
688 let block_txs = block.transactions_recovered();
689
690 this.replay_transactions_until(&mut db, evm_env.clone(), block_txs, *tx.tx_hash())?;
692
693 let tx_env = RpcNodeCore::evm_config(&this).tx_env(tx);
694
695 let res = this.transact(&mut db, evm_env, tx_env)?;
696 f(tx_info, res, db)
697 })
698 .await
699 .map(Some)
700 }
701 }
702
703 fn replay_transactions_until<'a, DB, I>(
711 &self,
712 db: &mut DB,
713 evm_env: EvmEnvFor<Self::Evm>,
714 transactions: I,
715 target_tx_hash: B256,
716 ) -> Result<usize, Self::Error>
717 where
718 DB: Database<Error = ProviderError> + DatabaseCommit + core::fmt::Debug,
719 I: IntoIterator<Item = Recovered<&'a ProviderTx<Self::Provider>>>,
720 {
721 let mut evm = self.evm_config().evm_with_env(db, evm_env);
722 let mut index = 0;
723 for tx in transactions {
724 if *tx.tx_hash() == target_tx_hash {
725 break
727 }
728
729 let tx_env = self.evm_config().tx_env(tx);
730 evm.transact_commit(tx_env).map_err(Self::Error::from_evm_err)?;
731 index += 1;
732 }
733 Ok(index)
734 }
735
736 fn create_txn_env(
740 &self,
741 evm_env: &EvmEnvFor<Self::Evm>,
742 mut request: RpcTxReq<<Self::RpcConvert as RpcConvert>::Network>,
743 mut db: impl Database<Error: Into<EthApiError>>,
744 ) -> Result<TxEnvFor<Self::Evm>, Self::Error> {
745 if request.as_ref().nonce().is_none() {
746 let nonce = db
747 .basic(request.as_ref().from().unwrap_or_default())
748 .map_err(Into::into)?
749 .map(|acc| acc.nonce)
750 .unwrap_or_default();
751 request.as_mut().set_nonce(nonce);
752 }
753
754 Ok(self.tx_resp_builder().tx_env(request, evm_env)?)
755 }
756
757 #[expect(clippy::type_complexity)]
771 fn prepare_call_env<DB>(
772 &self,
773 mut evm_env: EvmEnvFor<Self::Evm>,
774 mut request: RpcTxReq<<Self::RpcConvert as RpcConvert>::Network>,
775 db: &mut DB,
776 overrides: EvmOverrides,
777 ) -> Result<(EvmEnvFor<Self::Evm>, TxEnvFor<Self::Evm>), Self::Error>
778 where
779 DB: Database + DatabaseCommit + OverrideBlockHashes,
780 EthApiError: From<<DB as Database>::Error>,
781 {
782 let request_has_gas_limit = request.as_ref().gas_limit().is_some();
784
785 if let Some(requested_gas) = request.as_ref().gas_limit() {
786 let global_gas_cap = self.call_gas_limit();
787 if global_gas_cap != 0 && global_gas_cap < requested_gas {
788 warn!(target: "rpc::eth::call", ?request, ?global_gas_cap, "Capping gas limit to global gas cap");
789 request.as_mut().set_gas_limit(global_gas_cap);
790 }
791 } else {
792 request.as_mut().set_gas_limit(self.call_gas_limit());
794 }
795
796 evm_env.cfg_env.disable_block_gas_limit = true;
799
800 evm_env.cfg_env.disable_eip3607 = true;
803
804 evm_env.cfg_env.disable_base_fee = true;
808
809 evm_env.cfg_env.tx_gas_limit_cap = Some(u64::MAX);
811
812 evm_env.cfg_env.disable_fee_charge = true;
816
817 evm_env.cfg_env.memory_limit = self.evm_memory_limit();
818
819 request.as_mut().take_nonce();
821
822 if let Some(block_overrides) = overrides.block {
823 apply_block_overrides(*block_overrides, db, evm_env.block_env.inner_mut());
824 }
825 if let Some(state_overrides) = overrides.state {
826 apply_state_overrides(state_overrides, db)
827 .map_err(EthApiError::from_state_overrides_err)?;
828 }
829
830 let mut tx_env = self.create_txn_env(&evm_env, request, &mut *db)?;
831
832 if tx_env.gas_price() == 0 {
834 evm_env.block_env.inner_mut().basefee = 0;
835 }
836
837 if !request_has_gas_limit {
838 if tx_env.gas_price() > 0 {
840 trace!(target: "rpc::eth::call", ?tx_env, "Applying gas limit cap with caller allowance");
842 let cap = self.caller_gas_allowance(db, &evm_env, &tx_env)?;
843 tx_env.set_gas_limit(cap.min(evm_env.block_env.gas_limit()));
845 }
846 }
847
848 Ok((evm_env, tx_env))
849 }
850}