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 ConfigureEvm, Evm, EvmEnv, EvmEnvFor, HaltReasonFor, InspectorFor, SpecFor, TransactionEnv,
24 TxEnvFor,
25};
26use reth_node_api::BlockBody;
27use reth_primitives_traits::Recovered;
28use reth_revm::{
29 database::StateProviderDatabase,
30 db::{CacheDB, State},
31};
32use reth_rpc_convert::{RpcConvert, RpcTxReq};
33use reth_rpc_eth_types::{
34 cache::db::{StateCacheDbRefMutWrapper, StateProviderTraitObjWrapper},
35 error::{api::FromEvmHalt, ensure_success, FromEthApiError},
36 simulate::{self, EthSimulateError},
37 EthApiError, RevertError, StateCacheDb,
38};
39use reth_storage_api::{BlockIdReader, ProviderTx};
40use revm::{
41 context_interface::{
42 result::{ExecutionResult, ResultAndState},
43 Transaction,
44 },
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 state_override: Option<StateOverride>,
62 ) -> impl Future<Output = Result<U256, Self::Error>> + Send {
63 EstimateCall::estimate_gas_at(self, request, at, state_override)
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::InvalidParams("too many blocks.".to_string()).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 base_block =
94 self.recovered_block(block).await?.ok_or(EthApiError::HeaderNotFound(block))?;
95 let mut parent = base_block.sealed_header().clone();
96
97 let this = self.clone();
98 self.spawn_with_state_at_block(block, move |state| {
99 let mut db =
100 State::builder().with_database(StateProviderDatabase::new(state)).build();
101 let mut blocks: Vec<SimulatedBlock<RpcBlock<Self::NetworkTypes>>> =
102 Vec::with_capacity(block_state_calls.len());
103 for block in block_state_calls {
104 let mut evm_env = this
105 .evm_config()
106 .next_evm_env(&parent, &this.next_env_attributes(&parent)?)
107 .map_err(RethError::other)
108 .map_err(Self::Error::from_eth_err)?;
109
110 evm_env.cfg_env.disable_eip3607 = true;
112
113 if !validation {
114 evm_env.cfg_env.disable_nonce_check = true;
116 evm_env.cfg_env.disable_base_fee = true;
117 evm_env.cfg_env.tx_gas_limit_cap = Some(u64::MAX);
118 evm_env.block_env.basefee = 0;
119 }
120
121 let SimBlock { block_overrides, state_overrides, calls } = block;
122
123 if let Some(block_overrides) = block_overrides {
124 if let Some(gas_limit_override) = block_overrides.gas_limit &&
126 gas_limit_override > evm_env.block_env.gas_limit &&
127 gas_limit_override > this.call_gas_limit()
128 {
129 return Err(EthApiError::other(EthSimulateError::GasLimitReached).into())
130 }
131 apply_block_overrides(block_overrides, &mut db, &mut evm_env.block_env);
132 }
133 if let Some(state_overrides) = state_overrides {
134 apply_state_overrides(state_overrides, &mut db)
135 .map_err(Self::Error::from_eth_err)?;
136 }
137
138 let block_gas_limit = evm_env.block_env.gas_limit;
139 let chain_id = evm_env.cfg_env.chain_id;
140
141 let default_gas_limit = {
142 let total_specified_gas =
143 calls.iter().filter_map(|tx| tx.as_ref().gas_limit()).sum::<u64>();
144 let txs_without_gas_limit =
145 calls.iter().filter(|tx| tx.as_ref().gas_limit().is_none()).count();
146
147 if total_specified_gas > block_gas_limit {
148 return Err(EthApiError::Other(Box::new(
149 EthSimulateError::BlockGasLimitExceeded,
150 ))
151 .into())
152 }
153
154 if txs_without_gas_limit > 0 {
155 (block_gas_limit - total_specified_gas) / txs_without_gas_limit as u64
156 } else {
157 0
158 }
159 };
160
161 let ctx = this
162 .evm_config()
163 .context_for_next_block(&parent, this.next_env_attributes(&parent)?)
164 .map_err(RethError::other)
165 .map_err(Self::Error::from_eth_err)?;
166 let (result, results) = if trace_transfers {
167 let inspector = TransferInspector::new(false).with_logs(true);
170 let evm = this
171 .evm_config()
172 .evm_with_env_and_inspector(&mut db, evm_env, inspector);
173 let builder = this.evm_config().create_block_builder(evm, &parent, ctx);
174 simulate::execute_transactions(
175 builder,
176 calls,
177 default_gas_limit,
178 chain_id,
179 this.tx_resp_builder(),
180 )?
181 } else {
182 let evm = this.evm_config().evm_with_env(&mut db, evm_env);
183 let builder = this.evm_config().create_block_builder(evm, &parent, ctx);
184 simulate::execute_transactions(
185 builder,
186 calls,
187 default_gas_limit,
188 chain_id,
189 this.tx_resp_builder(),
190 )?
191 };
192
193 parent = result.block.clone_sealed_header();
194
195 let block = simulate::build_simulated_block(
196 result.block,
197 results,
198 return_full_transactions.into(),
199 this.tx_resp_builder(),
200 )?;
201
202 blocks.push(block);
203 }
204
205 Ok(blocks)
206 })
207 .await
208 }
209 }
210
211 fn call(
213 &self,
214 request: RpcTxReq<<Self::RpcConvert as RpcConvert>::Network>,
215 block_number: Option<BlockId>,
216 overrides: EvmOverrides,
217 ) -> impl Future<Output = Result<Bytes, Self::Error>> + Send {
218 async move {
219 let res =
220 self.transact_call_at(request, block_number.unwrap_or_default(), overrides).await?;
221
222 ensure_success(res.result)
223 }
224 }
225
226 fn call_many(
229 &self,
230 bundles: Vec<Bundle<RpcTxReq<<Self::RpcConvert as RpcConvert>::Network>>>,
231 state_context: Option<StateContext>,
232 mut state_override: Option<StateOverride>,
233 ) -> impl Future<Output = Result<Vec<Vec<EthCallResponse>>, Self::Error>> + Send {
234 async move {
235 if bundles.is_empty() {
237 return Err(EthApiError::InvalidParams(String::from("bundles are empty.")).into());
238 }
239
240 let StateContext { transaction_index, block_number } =
241 state_context.unwrap_or_default();
242 let transaction_index = transaction_index.unwrap_or_default();
243
244 let mut target_block = block_number.unwrap_or_default();
245 let is_block_target_pending = target_block.is_pending();
246
247 if !is_block_target_pending {
250 target_block = self
251 .provider()
252 .block_hash_for_id(target_block)
253 .map_err(|_| EthApiError::HeaderNotFound(target_block))?
254 .ok_or_else(|| EthApiError::HeaderNotFound(target_block))?
255 .into();
256 }
257
258 let ((evm_env, _), block) = futures::try_join!(
259 self.evm_env_at(target_block),
260 self.recovered_block(target_block)
261 )?;
262
263 let block = block.ok_or(EthApiError::HeaderNotFound(target_block))?;
264
265 let mut at = block.parent_hash();
269 let mut replay_block_txs = true;
270
271 let num_txs =
272 transaction_index.index().unwrap_or_else(|| block.body().transactions().len());
273 if !is_block_target_pending && num_txs == block.body().transactions().len() {
277 at = block.hash();
278 replay_block_txs = false;
279 }
280
281 let this = self.clone();
282 self.spawn_with_state_at_block(at.into(), move |state| {
283 let mut all_results = Vec::with_capacity(bundles.len());
284 let mut db = CacheDB::new(StateProviderDatabase::new(state));
285
286 if replay_block_txs {
287 let block_transactions = block.transactions_recovered().take(num_txs);
290 for tx in block_transactions {
291 let tx_env = RpcNodeCore::evm_config(&this).tx_env(tx);
292 let res = this.transact(&mut db, evm_env.clone(), tx_env)?;
293 db.commit(res.state);
294 }
295 }
296
297 for bundle in bundles {
299 let Bundle { transactions, block_override } = bundle;
300 if transactions.is_empty() {
301 continue;
303 }
304
305 let mut bundle_results = Vec::with_capacity(transactions.len());
306 let block_overrides = block_override.map(Box::new);
307
308 for tx in transactions {
310 let overrides =
313 EvmOverrides::new(state_override.take(), block_overrides.clone());
314
315 let (current_evm_env, prepared_tx) =
316 this.prepare_call_env(evm_env.clone(), tx, &mut db, overrides)?;
317 let res = this.transact(&mut db, current_evm_env, prepared_tx)?;
318
319 match ensure_success::<_, Self::Error>(res.result) {
320 Ok(output) => {
321 bundle_results
322 .push(EthCallResponse { value: Some(output), error: None });
323 }
324 Err(err) => {
325 bundle_results.push(EthCallResponse {
326 value: None,
327 error: Some(err.to_string()),
328 });
329 }
330 }
331
332 db.commit(res.state);
335 }
336
337 all_results.push(bundle_results);
338 }
339
340 Ok(all_results)
341 })
342 .await
343 }
344 }
345
346 fn create_access_list_at(
349 &self,
350 request: RpcTxReq<<Self::RpcConvert as RpcConvert>::Network>,
351 block_number: Option<BlockId>,
352 state_override: Option<StateOverride>,
353 ) -> impl Future<Output = Result<AccessListResult, Self::Error>> + Send
354 where
355 Self: Trace,
356 {
357 async move {
358 let block_id = block_number.unwrap_or_default();
359 let (evm_env, at) = self.evm_env_at(block_id).await?;
360
361 self.spawn_blocking_io_fut(move |this| async move {
362 this.create_access_list_with(evm_env, at, request, state_override).await
363 })
364 .await
365 }
366 }
367
368 fn create_access_list_with(
371 &self,
372 mut evm_env: EvmEnvFor<Self::Evm>,
373 at: BlockId,
374 request: RpcTxReq<<Self::RpcConvert as RpcConvert>::Network>,
375 state_override: Option<StateOverride>,
376 ) -> impl Future<Output = Result<AccessListResult, Self::Error>> + Send
377 where
378 Self: Trace,
379 {
380 self.spawn_blocking_io_fut(move |this| async move {
381 let state = this.state_at_block_id(at).await?;
382 let mut db = CacheDB::new(StateProviderDatabase::new(state));
383
384 if let Some(state_overrides) = state_override {
385 apply_state_overrides(state_overrides, &mut db)
386 .map_err(Self::Error::from_eth_err)?;
387 }
388
389 let mut tx_env = this.create_txn_env(&evm_env, request.clone(), &mut db)?;
390
391 evm_env.cfg_env.disable_block_gas_limit = true;
394
395 evm_env.cfg_env.disable_base_fee = true;
399
400 evm_env.cfg_env.disable_eip3607 = true;
402
403 if request.as_ref().gas_limit().is_none() && tx_env.gas_price() > 0 {
404 let cap = this.caller_gas_allowance(&mut db, &evm_env, &tx_env)?;
405 tx_env.set_gas_limit(cap.min(evm_env.block_env.gas_limit));
408 }
409
410 let initial = request.as_ref().access_list().cloned().unwrap_or_default();
412
413 let mut inspector = AccessListInspector::new(initial);
414
415 let result = this.inspect(&mut db, evm_env.clone(), tx_env.clone(), &mut inspector)?;
416 let access_list = inspector.into_access_list();
417 tx_env.set_access_list(access_list.clone());
418 match result.result {
419 ExecutionResult::Halt { reason, gas_used } => {
420 let error =
421 Some(Self::Error::from_evm_halt(reason, tx_env.gas_limit()).to_string());
422 return Ok(AccessListResult {
423 access_list,
424 gas_used: U256::from(gas_used),
425 error,
426 })
427 }
428 ExecutionResult::Revert { output, gas_used } => {
429 let error = Some(RevertError::new(output).to_string());
430 return Ok(AccessListResult {
431 access_list,
432 gas_used: U256::from(gas_used),
433 error,
434 })
435 }
436 ExecutionResult::Success { .. } => {}
437 };
438
439 let gas_limit = tx_env.gas_limit();
441 let result = this.transact(&mut db, evm_env, tx_env)?;
442 let res = match result.result {
443 ExecutionResult::Halt { reason, gas_used } => {
444 let error = Some(Self::Error::from_evm_halt(reason, gas_limit).to_string());
445 AccessListResult { access_list, gas_used: U256::from(gas_used), error }
446 }
447 ExecutionResult::Revert { output, gas_used } => {
448 let error = Some(RevertError::new(output).to_string());
449 AccessListResult { access_list, gas_used: U256::from(gas_used), error }
450 }
451 ExecutionResult::Success { gas_used, .. } => {
452 AccessListResult { access_list, gas_used: U256::from(gas_used), error: None }
453 }
454 };
455
456 Ok(res)
457 })
458 }
459}
460
461pub trait Call:
463 LoadState<
464 RpcConvert: RpcConvert<TxEnv = TxEnvFor<Self::Evm>, Spec = SpecFor<Self::Evm>>,
465 Error: FromEvmError<Self::Evm>
466 + From<<Self::RpcConvert as RpcConvert>::Error>
467 + From<ProviderError>,
468 > + SpawnBlocking
469{
470 fn call_gas_limit(&self) -> u64;
474
475 fn max_simulate_blocks(&self) -> u64;
477
478 fn caller_gas_allowance(
480 &self,
481 mut db: impl Database<Error: Into<EthApiError>>,
482 _evm_env: &EvmEnvFor<Self::Evm>,
483 tx_env: &TxEnvFor<Self::Evm>,
484 ) -> Result<u64, Self::Error> {
485 alloy_evm::call::caller_gas_allowance(&mut db, tx_env).map_err(Self::Error::from_eth_err)
486 }
487
488 fn with_state_at_block<F, R>(
490 &self,
491 at: BlockId,
492 f: F,
493 ) -> impl Future<Output = Result<R, Self::Error>> + Send
494 where
495 R: Send + 'static,
496 F: FnOnce(Self, StateProviderTraitObjWrapper<'_>) -> Result<R, Self::Error>
497 + Send
498 + 'static,
499 {
500 self.spawn_blocking_io_fut(move |this| async move {
501 let state = this.state_at_block_id(at).await?;
502 f(this, StateProviderTraitObjWrapper(&state))
503 })
504 }
505
506 fn transact<DB>(
509 &self,
510 db: DB,
511 evm_env: EvmEnvFor<Self::Evm>,
512 tx_env: TxEnvFor<Self::Evm>,
513 ) -> Result<ResultAndState<HaltReasonFor<Self::Evm>>, Self::Error>
514 where
515 DB: Database<Error = ProviderError> + fmt::Debug,
516 {
517 let mut evm = self.evm_config().evm_with_env(db, evm_env);
518 let res = evm.transact(tx_env).map_err(Self::Error::from_evm_err)?;
519
520 Ok(res)
521 }
522
523 fn transact_with_inspector<DB, I>(
526 &self,
527 db: DB,
528 evm_env: EvmEnvFor<Self::Evm>,
529 tx_env: TxEnvFor<Self::Evm>,
530 inspector: I,
531 ) -> Result<ResultAndState<HaltReasonFor<Self::Evm>>, Self::Error>
532 where
533 DB: Database<Error = ProviderError> + fmt::Debug,
534 I: InspectorFor<Self::Evm, DB>,
535 {
536 let mut evm = self.evm_config().evm_with_env_and_inspector(db, evm_env, inspector);
537 let res = evm.transact(tx_env).map_err(Self::Error::from_evm_err)?;
538
539 Ok(res)
540 }
541
542 fn transact_call_at(
544 &self,
545 request: RpcTxReq<<Self::RpcConvert as RpcConvert>::Network>,
546 at: BlockId,
547 overrides: EvmOverrides,
548 ) -> impl Future<Output = Result<ResultAndState<HaltReasonFor<Self::Evm>>, Self::Error>> + Send
549 where
550 Self: LoadPendingBlock,
551 {
552 let this = self.clone();
553 self.spawn_with_call_at(request, at, overrides, move |db, evm_env, tx_env| {
554 this.transact(db, evm_env, tx_env)
555 })
556 }
557
558 fn spawn_with_state_at_block<F, R>(
560 &self,
561 at: BlockId,
562 f: F,
563 ) -> impl Future<Output = Result<R, Self::Error>> + Send
564 where
565 F: FnOnce(StateProviderTraitObjWrapper<'_>) -> Result<R, Self::Error> + Send + 'static,
566 R: Send + 'static,
567 {
568 self.spawn_blocking_io_fut(move |this| async move {
569 let state = this.state_at_block_id(at).await?;
570 f(StateProviderTraitObjWrapper(&state))
571 })
572 }
573
574 fn spawn_with_call_at<F, R>(
590 &self,
591 request: RpcTxReq<<Self::RpcConvert as RpcConvert>::Network>,
592 at: BlockId,
593 overrides: EvmOverrides,
594 f: F,
595 ) -> impl Future<Output = Result<R, Self::Error>> + Send
596 where
597 Self: LoadPendingBlock,
598 F: FnOnce(
599 StateCacheDbRefMutWrapper<'_, '_>,
600 EvmEnvFor<Self::Evm>,
601 TxEnvFor<Self::Evm>,
602 ) -> Result<R, Self::Error>
603 + Send
604 + 'static,
605 R: Send + 'static,
606 {
607 async move {
608 let (evm_env, at) = self.evm_env_at(at).await?;
609 let this = self.clone();
610 self.spawn_blocking_io_fut(move |_| async move {
611 let state = this.state_at_block_id(at).await?;
612 let mut db =
613 CacheDB::new(StateProviderDatabase::new(StateProviderTraitObjWrapper(&state)));
614
615 let (evm_env, tx_env) =
616 this.prepare_call_env(evm_env, request, &mut db, overrides)?;
617
618 f(StateCacheDbRefMutWrapper(&mut db), evm_env, tx_env)
619 })
620 .await
621 }
622 }
623
624 fn spawn_replay_transaction<F, R>(
634 &self,
635 hash: B256,
636 f: F,
637 ) -> impl Future<Output = Result<Option<R>, Self::Error>> + Send
638 where
639 Self: LoadBlock + LoadTransaction,
640 F: FnOnce(
641 TransactionInfo,
642 ResultAndState<HaltReasonFor<Self::Evm>>,
643 StateCacheDb<'_>,
644 ) -> Result<R, Self::Error>
645 + Send
646 + 'static,
647 R: Send + 'static,
648 {
649 async move {
650 let (transaction, block) = match self.transaction_and_block(hash).await? {
651 None => return Ok(None),
652 Some(res) => res,
653 };
654 let (tx, tx_info) = transaction.split();
655
656 let (evm_env, _) = self.evm_env_at(block.hash().into()).await?;
657
658 let parent_block = block.parent_hash();
661
662 let this = self.clone();
663 self.spawn_with_state_at_block(parent_block.into(), move |state| {
664 let mut db = CacheDB::new(StateProviderDatabase::new(state));
665 let block_txs = block.transactions_recovered();
666
667 this.replay_transactions_until(&mut db, evm_env.clone(), block_txs, *tx.tx_hash())?;
669
670 let tx_env = RpcNodeCore::evm_config(&this).tx_env(tx);
671
672 let res = this.transact(&mut db, evm_env, tx_env)?;
673 f(tx_info, res, db)
674 })
675 .await
676 .map(Some)
677 }
678 }
679
680 fn replay_transactions_until<'a, DB, I>(
688 &self,
689 db: &mut DB,
690 evm_env: EvmEnvFor<Self::Evm>,
691 transactions: I,
692 target_tx_hash: B256,
693 ) -> Result<usize, Self::Error>
694 where
695 DB: Database<Error = ProviderError> + DatabaseCommit + core::fmt::Debug,
696 I: IntoIterator<Item = Recovered<&'a ProviderTx<Self::Provider>>>,
697 {
698 let mut evm = self.evm_config().evm_with_env(db, evm_env);
699 let mut index = 0;
700 for tx in transactions {
701 if *tx.tx_hash() == target_tx_hash {
702 break
704 }
705
706 let tx_env = self.evm_config().tx_env(tx);
707 evm.transact_commit(tx_env).map_err(Self::Error::from_evm_err)?;
708 index += 1;
709 }
710 Ok(index)
711 }
712
713 fn create_txn_env(
717 &self,
718 evm_env: &EvmEnv<SpecFor<Self::Evm>>,
719 mut request: RpcTxReq<<Self::RpcConvert as RpcConvert>::Network>,
720 mut db: impl Database<Error: Into<EthApiError>>,
721 ) -> Result<TxEnvFor<Self::Evm>, Self::Error> {
722 if request.as_ref().nonce().is_none() {
723 let nonce = db
724 .basic(request.as_ref().from().unwrap_or_default())
725 .map_err(Into::into)?
726 .map(|acc| acc.nonce)
727 .unwrap_or_default();
728 request.as_mut().set_nonce(nonce);
729 }
730
731 Ok(self.tx_resp_builder().tx_env(request, &evm_env.cfg_env, &evm_env.block_env)?)
732 }
733
734 #[expect(clippy::type_complexity)]
748 fn prepare_call_env<DB>(
749 &self,
750 mut evm_env: EvmEnvFor<Self::Evm>,
751 mut request: RpcTxReq<<Self::RpcConvert as RpcConvert>::Network>,
752 db: &mut DB,
753 overrides: EvmOverrides,
754 ) -> Result<(EvmEnvFor<Self::Evm>, TxEnvFor<Self::Evm>), Self::Error>
755 where
756 DB: Database + DatabaseCommit + OverrideBlockHashes,
757 EthApiError: From<<DB as Database>::Error>,
758 {
759 let request_has_gas_limit = request.as_ref().gas_limit().is_some();
761
762 if let Some(requested_gas) = request.as_ref().gas_limit() {
763 let global_gas_cap = self.call_gas_limit();
764 if global_gas_cap != 0 && global_gas_cap < requested_gas {
765 warn!(target: "rpc::eth::call", ?request, ?global_gas_cap, "Capping gas limit to global gas cap");
766 request.as_mut().set_gas_limit(global_gas_cap);
767 }
768 } else {
769 request.as_mut().set_gas_limit(self.call_gas_limit());
771 }
772
773 evm_env.cfg_env.disable_block_gas_limit = true;
776
777 evm_env.cfg_env.disable_eip3607 = true;
780
781 evm_env.cfg_env.disable_base_fee = true;
785
786 evm_env.cfg_env.tx_gas_limit_cap = Some(u64::MAX);
788
789 request.as_mut().take_nonce();
791
792 if let Some(block_overrides) = overrides.block {
793 apply_block_overrides(*block_overrides, db, &mut evm_env.block_env);
794 }
795 if let Some(state_overrides) = overrides.state {
796 apply_state_overrides(state_overrides, db)
797 .map_err(EthApiError::from_state_overrides_err)?;
798 }
799
800 let mut tx_env = self.create_txn_env(&evm_env, request, &mut *db)?;
801
802 if tx_env.gas_price() == 0 {
804 evm_env.block_env.basefee = 0;
805 }
806
807 if !request_has_gas_limit {
808 if tx_env.gas_price() > 0 {
810 trace!(target: "rpc::eth::call", ?tx_env, "Applying gas limit cap with caller allowance");
812 let cap = self.caller_gas_allowance(db, &evm_env, &tx_env)?;
813 tx_env.set_gas_limit(cap.min(evm_env.block_env.gas_limit));
815 }
816 }
817
818 Ok((evm_env, tx_env))
819 }
820}