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, EvmFor, HaltReasonFor, InspectorFor, TransactionEnvMut, TxEnvFor,
26};
27use reth_node_api::BlockBody;
28use reth_primitives_traits::Recovered;
29use reth_revm::{
30 database::StateProviderDatabase,
31 db::{
32 bal::{BalState, EvmDatabaseError},
33 State,
34 },
35};
36use reth_rpc_convert::{RpcConvert, RpcTxReq};
37use reth_rpc_eth_types::{
38 cache::db::attach_bal_before_tx,
39 error::{AsEthApiError, FromEthApiError},
40 simulate::{self, EthSimulateError},
41 EthApiError, StateCacheDb,
42};
43use reth_storage_api::{BlockIdReader, ProviderTx, StateProvider};
44use reth_tasks::{cancel::is_cancelled, CancelOnDrop};
45use revm::{
46 context::Block,
47 context_interface::{result::ResultAndState, Cfg, Transaction},
48 Database, DatabaseCommit,
49};
50use revm_inspectors::{access_list::AccessListInspector, transfer::TransferInspector};
51use std::collections::BTreeMap;
52use tracing::{debug, trace};
53
54pub type SimulatedBlocksResult<N, E> = Result<Vec<SimulatedBlock<RpcBlock<N>>>, E>;
56
57pub trait EthCall: EstimateCall + Call + LoadPendingBlock + LoadBlock + FullEthApiTypes {
60 fn estimate_gas_at(
62 &self,
63 request: RpcTxReq<<Self::RpcConvert as RpcConvert>::Network>,
64 at: BlockId,
65 overrides: EvmOverrides,
66 ) -> impl Future<Output = Result<U256, Self::Error>> + Send {
67 EstimateCall::estimate_gas_at(self, request, at, overrides)
68 }
69
70 fn simulate_v1(
75 &self,
76 payload: SimulatePayload<RpcTxReq<<Self::RpcConvert as RpcConvert>::Network>>,
77 block: Option<BlockId>,
78 ) -> impl Future<Output = SimulatedBlocksResult<Self::NetworkTypes, Self::Error>> + Send {
79 async move {
80 if payload.block_state_calls.len() > self.max_simulate_blocks() as usize {
81 return Err(EthApiError::other(EthSimulateError::TooManyBlocks).into())
82 }
83
84 let block = block.unwrap_or_default();
85
86 let SimulatePayload {
87 block_state_calls,
88 trace_transfers,
89 validation,
90 return_full_transactions,
91 } = payload;
92
93 if block_state_calls.is_empty() {
94 return Err(EthApiError::InvalidParams(String::from("calls are empty.")).into())
95 }
96
97 let permit = self
98 .acquire_owned_blocking_io()
99 .await
100 .map_err(|_| EthApiError::InternalEthError)?;
101
102 let base_block = self
103 .recovered_block(block)
104 .await?
105 .ok_or_else(|| EthApiError::other(EthSimulateError::BlockNotFound { block }))?;
106 let parent = base_block.sealed_header().clone();
107 let max_simulate_blocks = self.max_simulate_blocks();
108
109 self.spawn_with_state_at_block(block, move |this, db| {
110 let _permit = permit;
111 let state_provider = db.database.into_inner();
112 let mut db = State::builder()
113 .with_database(StateProviderDatabase::new(&state_provider))
114 .with_bundle_update()
115 .build();
116 let mut parent = parent;
117
118 let chain_id = this.provider().chain_spec().chain_id();
119
120 let block_state_calls = simulate::sanitize_chain(
125 block_state_calls,
126 &parent,
127 chain_id,
128 max_simulate_blocks,
129 )?;
130
131 let mut blocks: Vec<SimulatedBlock<RpcBlock<Self::NetworkTypes>>> =
132 Vec::with_capacity(block_state_calls.len());
133
134 let call_gas_limit = this.call_gas_limit();
135 let mut remaining_call_gas_limit = (call_gas_limit > 0).then_some(call_gas_limit);
136
137 for block in block_state_calls {
138 let SimBlock { block_overrides, state_overrides, calls } = block;
139
140 let attributes = this
141 .pending_env_builder()
142 .pending_env_attributes(&parent, block_overrides.as_ref())
143 .map_err(Self::Error::from_eth_err)?;
144
145 let mut evm_env = this
146 .evm_config()
147 .next_evm_env(&parent, &attributes)
148 .map_err(RethError::other)
149 .map_err(Self::Error::from_eth_err)?;
150
151 evm_env.cfg_env.disable_eip3607 = true;
153
154 if !evm_env.cfg_env.is_amsterdam_eip8037_enabled() {
157 evm_env.cfg_env.tx_gas_limit_cap = Some(u64::MAX);
158 }
159
160 if !validation {
161 evm_env.cfg_env.disable_nonce_check = true;
163 evm_env.cfg_env.disable_base_fee = true;
164 evm_env.block_env.inner_mut().basefee = 0;
165 }
166
167 evm_env.block_env.inner_mut().prevrandao = Some(B256::ZERO);
171 if !this
172 .provider()
173 .chain_spec()
174 .is_paris_active_at_block(evm_env.block_env.number().saturating_to())
175 {
176 evm_env.block_env.inner_mut().difficulty = parent.difficulty();
177 }
178
179 if let Some(block_overrides) = block_overrides {
180 if let Some(gas_limit_override) = block_overrides.gas_limit &&
182 gas_limit_override > evm_env.block_env.gas_limit() &&
183 gas_limit_override > this.call_gas_limit()
184 {
185 return Err(EthApiError::other(EthSimulateError::GasLimitReached).into())
186 }
187 apply_block_overrides(
188 block_overrides,
189 &mut db,
190 evm_env.block_env.inner_mut(),
191 );
192 }
193 if let Some(ref state_overrides) = state_overrides {
194 apply_state_overrides(state_overrides.clone(), &mut db)
195 .map_err(Self::Error::from_eth_err)?;
196 }
197
198 let chain_id = evm_env.cfg_env.chain_id;
199
200 if this.provider().chain_spec().is_amsterdam_active_at_timestamp(
202 evm_env.block_env.timestamp().saturating_to(),
203 ) {
204 db.bal_state = BalState::new().with_bal_builder();
205 }
206
207 let ctx = this
208 .evm_config()
209 .context_for_next_block(&parent, attributes)
210 .map_err(RethError::other)
211 .map_err(Self::Error::from_eth_err)?;
212 let map_err = |e: EthApiError| -> Self::Error {
213 match e.as_simulate_error() {
214 Some(sim_err) => Self::Error::from_eth_err(EthApiError::other(sim_err)),
215 None => Self::Error::from_eth_err(e),
216 }
217 };
218
219 let trace_transfers = trace_transfers &&
221 (!Cfg::spec(&evm_env.cfg_env)
222 .into()
223 .is_enabled_in(revm::primitives::hardfork::SpecId::AMSTERDAM) ||
224 evm_env.cfg_env.is_eip7708_disabled());
225 let (result, results) = if trace_transfers {
226 let inspector = TransferInspector::new(false).with_logs(true);
229 let evm = this
230 .evm_config()
231 .evm_with_env_and_inspector(&mut db, evm_env, inspector);
232 let mut builder = this.evm_config().create_block_builder(evm, &parent, ctx);
233
234 if let Some(ref state_overrides) = state_overrides {
235 simulate::apply_precompile_overrides(
236 state_overrides,
237 builder.evm_mut().precompiles_mut(),
238 )
239 .map_err(|e| Self::Error::from_eth_err(EthApiError::other(e)))?;
240 }
241
242 simulate::execute_transactions(
243 builder,
244 &*state_provider,
245 calls,
246 &mut remaining_call_gas_limit,
247 chain_id,
248 this.compute_state_root_for_eth_simulate(),
249 this.converter(),
250 )
251 .map_err(map_err)?
252 } else {
253 let evm = this.evm_config().evm_with_env(&mut db, evm_env);
254 let mut builder = this.evm_config().create_block_builder(evm, &parent, ctx);
255
256 if let Some(ref state_overrides) = state_overrides {
257 simulate::apply_precompile_overrides(
258 state_overrides,
259 builder.evm_mut().precompiles_mut(),
260 )
261 .map_err(|e| Self::Error::from_eth_err(EthApiError::other(e)))?;
262 }
263
264 simulate::execute_transactions(
265 builder,
266 &*state_provider,
267 calls,
268 &mut remaining_call_gas_limit,
269 chain_id,
270 this.compute_state_root_for_eth_simulate(),
271 this.converter(),
272 )
273 .map_err(map_err)?
274 };
275
276 let simulated_header = result.block.clone_sealed_header();
277 db.override_block_hashes(BTreeMap::from([(
278 simulated_header.number(),
279 simulated_header.hash(),
280 )]));
281 parent = simulated_header;
282
283 let block = simulate::build_simulated_block::<Self::Error, _>(
284 result.block,
285 results,
286 return_full_transactions.into(),
287 this.converter(),
288 )?;
289
290 blocks.push(block);
291 }
292
293 Ok(blocks)
294 })
295 .await
296 }
297 }
298
299 fn call(
301 &self,
302 request: RpcTxReq<<Self::RpcConvert as RpcConvert>::Network>,
303 block_number: Option<BlockId>,
304 overrides: EvmOverrides,
305 ) -> impl Future<Output = Result<Bytes, Self::Error>> + Send {
306 async move {
307 let res =
308 self.transact_call_at(request, block_number.unwrap_or_default(), overrides).await?;
309
310 Self::Error::ensure_success(res.result)
311 }
312 }
313
314 fn call_many(
317 &self,
318 bundles: Vec<Bundle<RpcTxReq<<Self::RpcConvert as RpcConvert>::Network>>>,
319 state_context: Option<StateContext>,
320 mut state_override: Option<StateOverride>,
321 ) -> impl Future<Output = Result<Vec<Vec<EthCallResponse>>, Self::Error>> + Send
322 where
323 Self: Trace,
324 {
325 async move {
326 if bundles.is_empty() {
328 return Err(EthApiError::InvalidParams(String::from("bundles are empty.")).into());
329 }
330
331 let permit = self
332 .acquire_owned_blocking_io()
333 .await
334 .map_err(|_| EthApiError::InternalEthError)?;
335
336 let StateContext { transaction_index, block_number } =
337 state_context.unwrap_or_default();
338 let transaction_index = transaction_index.unwrap_or_default();
339
340 let mut target_block = block_number.unwrap_or_default();
341 let is_block_target_pending = target_block.is_pending();
342
343 if !is_block_target_pending {
346 let Some(block_hash) = self
347 .provider()
348 .block_hash_for_id(target_block)
349 .map_err(Self::Error::from_eth_err::<ProviderError>)?
350 else {
351 return Err(EthApiError::HeaderNotFound(target_block).into())
352 };
353 target_block = block_hash.into();
354 }
355
356 let block = self
357 .recovered_block(target_block)
358 .await?
359 .ok_or(EthApiError::HeaderNotFound(target_block))?;
360 let evm_env = self.evm_env_for_header(block.sealed_block().sealed_header())?;
361
362 let mut at = block.parent_hash();
366 let mut replay_block_txs = true;
367
368 let num_txs =
369 transaction_index.index().unwrap_or_else(|| block.body().transactions().len());
370 if !is_block_target_pending && num_txs == block.body().transactions().len() {
374 at = block.hash();
375 replay_block_txs = false;
376 }
377
378 self.spawn_with_state_at_block(at, move |this, mut db| {
379 let _permit = permit;
380 let mut all_results = Vec::with_capacity(bundles.len());
381
382 if replay_block_txs {
383 this.replay_block_until(&mut db, &block, num_txs, None)?;
386 }
387
388 for (bundle_index, bundle) in bundles.into_iter().enumerate() {
390 let Bundle { transactions, block_override } = bundle;
391 if transactions.is_empty() {
392 continue;
394 }
395
396 let mut bundle_results = Vec::with_capacity(transactions.len());
397 let block_overrides = block_override.map(Box::new);
398
399 for (tx_index, tx) in transactions.into_iter().enumerate() {
401 if is_cancelled() {
402 return Err(EthApiError::InternalEthError.into())
403 }
404
405 let overrides =
408 EvmOverrides::new(state_override.take(), block_overrides.clone());
409
410 let (current_evm_env, prepared_tx) = this
411 .prepare_call_env(evm_env.clone(), tx, &mut db, overrides)
412 .map_err(|err| {
413 Self::Error::from_eth_err(EthApiError::call_many_error(
414 bundle_index,
415 tx_index,
416 err.into(),
417 ))
418 })?;
419 let res = this.transact(&mut db, current_evm_env, prepared_tx).map_err(
420 |err| {
421 Self::Error::from_eth_err(EthApiError::call_many_error(
422 bundle_index,
423 tx_index,
424 err.into(),
425 ))
426 },
427 )?;
428
429 match Self::Error::ensure_success(res.result) {
430 Ok(output) => {
431 bundle_results
432 .push(EthCallResponse { value: Some(output), error: None });
433 }
434 Err(err) => {
435 bundle_results.push(EthCallResponse {
436 value: None,
437 error: Some(err.to_string()),
438 });
439 }
440 }
441
442 db.commit(res.state);
445 }
446
447 all_results.push(bundle_results);
448 }
449
450 Ok(all_results)
451 })
452 .await
453 }
454 }
455
456 fn create_access_list_at(
459 &self,
460 request: RpcTxReq<<Self::RpcConvert as RpcConvert>::Network>,
461 block_number: Option<BlockId>,
462 state_override: Option<StateOverride>,
463 ) -> impl Future<Output = Result<AccessListResult, Self::Error>> + Send
464 where
465 Self: Trace,
466 {
467 async move {
468 let block_id = block_number.unwrap_or_default();
469 let (evm_env, at) = self.evm_env_at(block_id).await?;
470
471 self.create_access_list_with(evm_env, at, request, state_override).await
472 }
473 }
474
475 fn create_access_list_with(
478 &self,
479 evm_env: EvmEnvFor<Self::Evm>,
480 at: BlockId,
481 request: RpcTxReq<<Self::RpcConvert as RpcConvert>::Network>,
482 state_override: Option<StateOverride>,
483 ) -> impl Future<Output = Result<AccessListResult, Self::Error>> + Send
484 where
485 Self: Trace,
486 {
487 self.spawn_with_state_at_block(at, |this, mut db| {
488 let initial = request.as_ref().access_list().cloned().unwrap_or_default();
489 let (evm_env, mut tx_env) = this.prepare_call_env(
490 evm_env,
491 request,
492 &mut db,
493 EvmOverrides::state(state_override),
494 )?;
495
496 let mut evm = this.evm_config().evm_with_env_and_inspector(
497 &mut db,
498 evm_env,
499 AccessListInspector::new(initial),
500 );
501
502 let result = evm.transact(tx_env.clone())?;
503 let access_list = core::mem::take(evm.inspector_mut()).into_access_list();
504 let gas_used = result.result.tx_gas_used();
505 tx_env.set_access_list(access_list.clone());
506 if let Err(err) = Self::Error::ensure_success(result.result) {
507 return Ok(AccessListResult {
508 access_list,
509 gas_used: U256::from(gas_used),
510 error: Some(err.to_string()),
511 });
512 }
513
514 evm.disable_inspector();
516 let result = evm.transact(tx_env)?;
517 let gas_used = result.result.tx_gas_used();
518 let error = Self::Error::ensure_success(result.result).err().map(|e| e.to_string());
519
520 Ok(AccessListResult { access_list, gas_used: U256::from(gas_used), error })
521 })
522 }
523}
524
525pub trait Call:
527 LoadState<
528 RpcConvert: RpcConvert<Evm = Self::Evm>,
529 Error: FromEvmError<Self::Evm>
530 + From<<Self::RpcConvert as RpcConvert>::Error>
531 + From<ProviderError>,
532 > + SpawnBlocking
533{
534 fn call_gas_limit(&self) -> u64 {
538 self.eth_api_settings().gas_cap
539 }
540
541 fn max_simulate_blocks(&self) -> u64 {
543 self.eth_api_settings().max_simulate_blocks
544 }
545
546 fn compute_state_root_for_eth_simulate(&self) -> bool {
548 self.eth_api_settings().compute_state_root_for_eth_simulate
549 }
550
551 fn evm_memory_limit(&self) -> u64 {
553 self.eth_api_settings().evm_memory_limit
554 }
555
556 fn caller_gas_allowance(
558 &self,
559 mut db: impl Database<Error: Into<EthApiError>>,
560 _evm_env: &EvmEnvFor<Self::Evm>,
561 tx_env: &TxEnvFor<Self::Evm>,
562 ) -> Result<u64, Self::Error> {
563 alloy_evm::call::caller_gas_allowance(&mut db, tx_env).map_err(Self::Error::from_eth_err)
564 }
565
566 fn transact<DB>(
569 &self,
570 db: DB,
571 evm_env: EvmEnvFor<Self::Evm>,
572 tx_env: TxEnvFor<Self::Evm>,
573 ) -> Result<ResultAndState<HaltReasonFor<Self::Evm>>, Self::Error>
574 where
575 DB: Database<Error = EvmDatabaseError<ProviderError>> + fmt::Debug,
576 {
577 let mut evm = self.evm_config().evm_with_env(db, evm_env);
578 let res = evm.transact(tx_env).map_err(Self::Error::from_evm_err)?;
579
580 Ok(res)
581 }
582
583 fn transact_with_inspector<DB, I>(
586 &self,
587 db: DB,
588 evm_env: EvmEnvFor<Self::Evm>,
589 tx_env: TxEnvFor<Self::Evm>,
590 inspector: I,
591 ) -> Result<ResultAndState<HaltReasonFor<Self::Evm>>, Self::Error>
592 where
593 DB: Database<Error = EvmDatabaseError<ProviderError>> + fmt::Debug,
594 I: InspectorFor<Self::Evm, DB>,
595 {
596 let mut evm = self.evm_config().evm_with_env_and_inspector(db, evm_env, inspector);
597 let res = evm.transact(tx_env).map_err(Self::Error::from_evm_err)?;
598
599 Ok(res)
600 }
601
602 fn transact_call_at(
609 &self,
610 request: RpcTxReq<<Self::RpcConvert as RpcConvert>::Network>,
611 at: BlockId,
612 overrides: EvmOverrides,
613 ) -> impl Future<Output = Result<ResultAndState<HaltReasonFor<Self::Evm>>, Self::Error>> + Send
614 where
615 Self: LoadPendingBlock,
616 {
617 async move {
618 let permit = self
619 .acquire_owned_blocking_io()
620 .await
621 .map_err(|_| EthApiError::InternalEthError)?;
622 let guard = CancelOnDrop::default();
623 let cancel = guard.clone();
624 let this = self.clone();
625
626 let res = self
627 .spawn_with_call_at(request, at, overrides, move |db, evm_env, tx_env| {
628 let _permit = permit;
629 if cancel.is_cancelled() {
630 return Err(EthApiError::InternalEthError.into())
632 }
633 this.transact(db, evm_env, tx_env)
634 })
635 .await;
636 drop(guard);
637 res
638 }
639 }
640
641 fn spawn_with_state_at_block<F, R>(
643 &self,
644 at: impl Into<BlockId>,
645 f: F,
646 ) -> impl Future<Output = Result<R, Self::Error>> + Send
647 where
648 F: FnOnce(Self, StateCacheDb) -> Result<R, Self::Error> + Send + 'static,
649 R: Send + 'static,
650 {
651 self.spawn_blocking_io_with_state(at.into(), move |this, state| {
652 let db = State::builder()
653 .with_database(StateProviderDatabase::new(state.into_evm_state_provider()))
654 .build();
655 f(this, db)
656 })
657 }
658
659 fn spawn_with_call_at<F, R>(
675 &self,
676 request: RpcTxReq<<Self::RpcConvert as RpcConvert>::Network>,
677 at: BlockId,
678 overrides: EvmOverrides,
679 f: F,
680 ) -> impl Future<Output = Result<R, Self::Error>> + Send
681 where
682 Self: LoadPendingBlock,
683 F: FnOnce(
684 &mut StateCacheDb,
685 EvmEnvFor<Self::Evm>,
686 TxEnvFor<Self::Evm>,
687 ) -> Result<R, Self::Error>
688 + Send
689 + 'static,
690 R: Send + 'static,
691 {
692 async move {
693 let (evm_env, at) = self.evm_env_at(at).await?;
694 self.spawn_with_state_at_block(at, move |this, mut db| {
695 let (evm_env, tx_env) =
696 this.prepare_call_env(evm_env, request, &mut db, overrides)?;
697
698 f(&mut db, evm_env, tx_env)
699 })
700 .await
701 }
702 }
703
704 fn spawn_replay_transaction<F, R>(
717 &self,
718 hash: B256,
719 f: F,
720 ) -> impl Future<Output = Result<Option<R>, Self::Error>> + Send
721 where
722 Self: LoadBlock + LoadTransaction,
723 F: FnOnce(
724 TransactionInfo,
725 ResultAndState<HaltReasonFor<Self::Evm>>,
726 StateCacheDb,
727 ) -> Result<R, Self::Error>
728 + Send
729 + 'static,
730 R: Send + 'static,
731 {
732 async move {
733 let (transaction, block, bal) =
734 match self.transaction_and_block_and_maybe_bal(hash).await? {
735 None => return Ok(None),
736 Some(res) => res,
737 };
738 let (tx, tx_info) = transaction.split();
739
740 let parent_block = block.parent_hash();
743
744 self.spawn_with_state_at_block(parent_block, move |this, mut db| {
745 if let Some((bal, tx_index)) = bal.zip(tx_info.index) {
746 attach_bal_before_tx(&mut db, &bal, tx_index as usize);
747
748 let evm_env = this.evm_env_for_header(block.sealed_block().sealed_header())?;
749 let tx_env = RpcNodeCore::evm_config(&this).tx_env(tx);
750 let res = this.transact(&mut db, evm_env, tx_env)?;
751 return f(tx_info, res, db)
752 }
753
754 let block_txs = block.transactions_recovered();
755
756 let mut executor = RpcNodeCore::evm_config(&this)
757 .executor_for_block(&mut db, block.sealed_block())
758 .map_err(RethError::other)
759 .map_err(Self::Error::from_eth_err)?;
760 executor.apply_pre_execution_changes().map_err(Self::Error::from_eth_err)?;
761
762 for block_tx in block_txs {
764 if block_tx.tx_hash() == tx.tx_hash() {
765 break;
766 }
767 if is_cancelled() {
768 return Err(EthApiError::InternalEthError.into())
769 }
770 executor.execute_transaction(block_tx).map_err(Self::Error::from_eth_err)?;
771 }
772
773 let tx_env = RpcNodeCore::evm_config(&this).tx_env(tx);
774
775 let res = executor.evm_mut().transact(tx_env).map_err(Self::Error::from_evm_err)?;
776 drop(executor);
777 f(tx_info, res, db)
778 })
779 .await
780 .map(Some)
781 }
782 }
783
784 fn replay_transactions_until_with_evm<'a, DB, I, Txs>(
794 &self,
795 evm: &mut EvmFor<Self::Evm, DB, I>,
796 transactions: Txs,
797 target_tx_index: usize,
798 ) -> Result<(), Self::Error>
799 where
800 DB: Database<Error = EvmDatabaseError<ProviderError>> + DatabaseCommit + core::fmt::Debug,
801 I: InspectorFor<Self::Evm, DB>,
802 Txs: IntoIterator<Item = Recovered<&'a ProviderTx<Self::Provider>>>,
803 {
804 for (index, tx) in transactions.into_iter().enumerate() {
805 if index == target_tx_index {
806 break
808 }
809 if is_cancelled() {
810 return Err(EthApiError::InternalEthError.into())
811 }
812
813 let tx_env = self.evm_config().tx_env(tx);
814 evm.transact_commit(tx_env).map_err(Self::Error::from_evm_err)?;
815 }
816 Ok(())
817 }
818
819 fn create_txn_env(
823 &self,
824 evm_env: &EvmEnvFor<Self::Evm>,
825 mut request: RpcTxReq<<Self::RpcConvert as RpcConvert>::Network>,
826 mut db: impl Database<Error: Into<EthApiError>>,
827 ) -> Result<TxEnvFor<Self::Evm>, Self::Error> {
828 if request.as_ref().nonce().is_none() {
829 let nonce = db
830 .basic(request.as_ref().from().unwrap_or_default())
831 .map_err(Into::into)?
832 .map(|acc| acc.nonce)
833 .unwrap_or_default();
834 request.as_mut().set_nonce(nonce);
835 }
836
837 Ok(self.converter().tx_env(request, evm_env)?)
838 }
839
840 #[expect(clippy::type_complexity)]
854 fn prepare_call_env<DB>(
855 &self,
856 mut evm_env: EvmEnvFor<Self::Evm>,
857 mut request: RpcTxReq<<Self::RpcConvert as RpcConvert>::Network>,
858 db: &mut DB,
859 overrides: EvmOverrides,
860 ) -> Result<(EvmEnvFor<Self::Evm>, TxEnvFor<Self::Evm>), Self::Error>
861 where
862 DB: Database + DatabaseCommit + OverrideBlockHashes,
863 EthApiError: From<<DB as Database>::Error>,
864 {
865 let request_has_gas_limit = request.as_ref().gas_limit().is_some();
867
868 if let Some(requested_gas) = request.as_ref().gas_limit() {
869 let global_gas_cap = self.call_gas_limit();
870 if global_gas_cap != 0 && global_gas_cap < requested_gas {
871 debug!(target: "rpc::eth::call", requested_gas, global_gas_cap, "Capping gas limit to global gas cap");
874 request.as_mut().set_gas_limit(global_gas_cap);
875 }
876 } else {
877 request.as_mut().set_gas_limit(self.call_gas_limit());
879 }
880
881 evm_env.cfg_env.disable_block_gas_limit = true;
884
885 evm_env.cfg_env.disable_eip3607 = true;
888
889 evm_env.cfg_env.disable_base_fee = true;
893
894 if !evm_env.cfg_env.is_amsterdam_eip8037_enabled() {
898 evm_env.cfg_env.tx_gas_limit_cap = Some(u64::MAX);
899 }
900
901 evm_env.cfg_env.disable_fee_charge = true;
905
906 evm_env.cfg_env.memory_limit = self.evm_memory_limit();
907
908 request.as_mut().take_nonce();
910
911 if let Some(block_overrides) = overrides.block {
912 apply_block_overrides(*block_overrides, db, evm_env.block_env.inner_mut());
913 }
914 if let Some(state_overrides) = overrides.state {
915 apply_state_overrides(state_overrides, db)
916 .map_err(EthApiError::from_state_overrides_err)?;
917 }
918
919 let mut tx_env = self.create_txn_env(&evm_env, request, &mut *db)?;
920
921 if tx_env.gas_price() == 0 {
923 evm_env.block_env.inner_mut().basefee = 0;
924 }
925
926 if !request_has_gas_limit {
927 if tx_env.gas_price() > 0 {
929 trace!(target: "rpc::eth::call", ?tx_env, "Applying gas limit cap with caller allowance");
931 let mut cap = self.caller_gas_allowance(db, &evm_env, &tx_env)?;
932 if self.call_gas_limit() != 0 {
934 cap = cap.min(tx_env.gas_limit());
935 }
936 tx_env.set_gas_limit(cap.min(evm_env.block_env.gas_limit()));
938 }
939 }
940
941 Ok((evm_env, tx_env))
942 }
943}