1use super::{
2 backend::mem::{BlockRequest, DatabaseRef, State},
3 sign::build_impersonated,
4};
5use crate::{
6 ClientFork, LoggingManager, Miner, MiningMode, StorageInfo,
7 eth::{
8 backend::{
9 self,
10 db::SerializableState,
11 mem::{MIN_CREATE_GAS, MIN_TRANSACTION_GAS},
12 notifications::NewBlockNotifications,
13 validate::TransactionValidator,
14 },
15 error::{
16 BlockchainError, FeeHistoryError, InvalidTransactionError, Result, ToRpcResponseResult,
17 },
18 fees::{FeeDetails, FeeHistoryCache, MIN_SUGGESTED_PRIORITY_FEE},
19 macros::node_info,
20 miner::FixedBlockTimeMiner,
21 pool::{
22 Pool,
23 transactions::{
24 PoolTransaction, TransactionOrder, TransactionPriority, TxMarker, to_marker,
25 },
26 },
27 sign::{self, Signer},
28 },
29 filter::{EthFilter, Filters, LogsFilter},
30 mem::transaction_build,
31};
32use alloy_consensus::{
33 Blob, BlockHeader, Transaction, TrieAccount, TxEip4844Variant, transaction::Recovered,
34};
35use alloy_dyn_abi::TypedData;
36use alloy_eips::{
37 eip2718::Encodable2718,
38 eip7910::{EthConfig, EthForkConfig},
39};
40use alloy_evm::overrides::{OverrideBlockHashes, apply_state_overrides};
41use alloy_network::{
42 AnyRpcBlock, AnyRpcTransaction, BlockResponse, Network, ReceiptResponse, TransactionBuilder,
43 TransactionBuilder4844, TransactionResponse, eip2718::Decodable2718,
44};
45use alloy_primitives::{
46 Address, B64, B256, Bytes, TxHash, TxKind, U64, U256,
47 map::{HashMap, HashSet},
48};
49use alloy_rpc_types::{
50 AccessList, AccessListResult, BlockId, BlockNumberOrTag as BlockNumber, BlockTransactions,
51 EIP1186AccountProofResponse, FeeHistory, Filter, FilteredParams, Index, Log, Work,
52 anvil::{
53 ForkedNetwork, Forking, Metadata, MineOptions, NodeEnvironment, NodeForkConfig, NodeInfo,
54 },
55 request::TransactionRequest,
56 simulate::{SimulatePayload, SimulatedBlock},
57 state::{AccountOverride, EvmOverrides, StateOverridesBuilder},
58 trace::{
59 filter::TraceFilter,
60 geth::{GethDebugTracingCallOptions, GethDebugTracingOptions, GethTrace},
61 parity::{LocalizedTransactionTrace, TraceResultsWithTransactionHash, TraceType},
62 },
63 txpool::{TxpoolContent, TxpoolInspect, TxpoolInspectSummary, TxpoolStatus},
64};
65use alloy_rpc_types_eth::FillTransaction;
66use alloy_serde::WithOtherFields;
67use alloy_sol_types::{SolCall, SolValue, sol};
68use alloy_transport::TransportErrorKind;
69use anvil_core::{
70 eth::{
71 EthRequest,
72 block::BlockInfo,
73 transaction::{MaybeImpersonatedTransaction, PendingTransaction},
74 },
75 types::{ReorgOptions, TransactionData},
76};
77use anvil_rpc::{error::RpcError, response::ResponseResult};
78use foundry_common::provider::ProviderBuilder;
79use foundry_evm::decode::RevertDecoder;
80use foundry_primitives::{
81 FoundryNetwork, FoundryTransactionRequest, FoundryTxEnvelope, FoundryTxReceipt, FoundryTxType,
82 FoundryTypedTx,
83};
84use futures::{
85 StreamExt, TryFutureExt,
86 channel::{mpsc::Receiver, oneshot},
87};
88use parking_lot::RwLock;
89use revm::{
90 context::BlockEnv,
91 context_interface::{block::BlobExcessGasAndPrice, result::Output},
92 database::CacheDB,
93 interpreter::{InstructionResult, return_ok, return_revert},
94 primitives::eip7702::PER_EMPTY_ACCOUNT_COST,
95};
96use std::{sync::Arc, time::Duration};
97use tokio::{
98 sync::mpsc::{UnboundedReceiver, unbounded_channel},
99 try_join,
100};
101
102pub const CLIENT_VERSION: &str = concat!("anvil/v", env!("CARGO_PKG_VERSION"));
104
105pub struct EthApi<N: Network> {
109 pool: Arc<Pool<N::TxEnvelope>>,
111 pub backend: Arc<backend::mem::Backend<N>>,
114 is_mining: bool,
116 signers: Arc<Vec<Box<dyn Signer<N>>>>,
118 fee_history_cache: FeeHistoryCache,
120 fee_history_limit: u64,
122 miner: Miner<N::TxEnvelope>,
127 logger: LoggingManager,
129 filters: Filters<N>,
131 transaction_order: Arc<RwLock<TransactionOrder>>,
133 net_listening: bool,
135 instance_id: Arc<RwLock<B256>>,
137}
138
139impl<N: Network> Clone for EthApi<N> {
140 fn clone(&self) -> Self {
141 Self {
142 pool: self.pool.clone(),
143 backend: self.backend.clone(),
144 is_mining: self.is_mining,
145 signers: self.signers.clone(),
146 fee_history_cache: self.fee_history_cache.clone(),
147 fee_history_limit: self.fee_history_limit,
148 miner: self.miner.clone(),
149 logger: self.logger.clone(),
150 filters: self.filters.clone(),
151 transaction_order: self.transaction_order.clone(),
152 net_listening: self.net_listening,
153 instance_id: self.instance_id.clone(),
154 }
155 }
156}
157
158impl<N: Network> EthApi<N> {
161 #[expect(clippy::too_many_arguments)]
163 pub fn new(
164 pool: Arc<Pool<N::TxEnvelope>>,
165 backend: Arc<backend::mem::Backend<N>>,
166 signers: Arc<Vec<Box<dyn Signer<N>>>>,
167 fee_history_cache: FeeHistoryCache,
168 fee_history_limit: u64,
169 miner: Miner<N::TxEnvelope>,
170 logger: LoggingManager,
171 filters: Filters<N>,
172 transactions_order: TransactionOrder,
173 ) -> Self {
174 Self {
175 pool,
176 backend,
177 is_mining: true,
178 signers,
179 fee_history_cache,
180 fee_history_limit,
181 miner,
182 logger,
183 filters,
184 net_listening: true,
185 transaction_order: Arc::new(RwLock::new(transactions_order)),
186 instance_id: Arc::new(RwLock::new(B256::random())),
187 }
188 }
189
190 pub fn gas_price(&self) -> u128 {
192 if self.backend.is_eip1559() {
193 if self.backend.is_min_priority_fee_enforced() {
194 (self.backend.base_fee() as u128).saturating_add(self.lowest_suggestion_tip())
195 } else {
196 self.backend.base_fee() as u128
197 }
198 } else {
199 self.backend.fees().raw_gas_price()
200 }
201 }
202
203 fn lowest_suggestion_tip(&self) -> u128 {
207 let block_number = self.backend.best_number();
208 let latest_cached_block = self.fee_history_cache.lock().get(&block_number).cloned();
209
210 match latest_cached_block {
211 Some(block) => block.rewards.iter().copied().min(),
212 None => self.fee_history_cache.lock().values().flat_map(|b| b.rewards.clone()).min(),
213 }
214 .map(|fee| fee.max(MIN_SUGGESTED_PRIORITY_FEE))
215 .unwrap_or(MIN_SUGGESTED_PRIORITY_FEE)
216 }
217
218 pub fn anvil_get_auto_mine(&self) -> Result<bool> {
222 node_info!("anvil_getAutomine");
223 Ok(self.miner.is_auto_mine())
224 }
225
226 pub fn anvil_get_interval_mining(&self) -> Result<Option<u64>> {
230 node_info!("anvil_getIntervalMining");
231 Ok(self.miner.get_interval())
232 }
233
234 pub async fn anvil_set_auto_mine(&self, enable_automine: bool) -> Result<()> {
239 node_info!("evm_setAutomine");
240 if self.miner.is_auto_mine() {
241 if enable_automine {
242 return Ok(());
243 }
244 self.miner.set_mining_mode(MiningMode::None);
245 } else if enable_automine {
246 let listener = self.pool.add_ready_listener();
247 let mode = MiningMode::instant(1_000, listener);
248 self.miner.set_mining_mode(mode);
249 }
250 Ok(())
251 }
252
253 pub fn anvil_set_interval_mining(&self, secs: u64) -> Result<()> {
257 node_info!("evm_setIntervalMining");
258 let mining_mode = if secs == 0 {
259 MiningMode::None
260 } else {
261 let block_time = Duration::from_secs(secs);
262
263 self.backend.update_interval_mine_block_time(block_time);
265
266 MiningMode::FixedBlockTime(FixedBlockTimeMiner::new(block_time))
267 };
268 self.miner.set_mining_mode(mining_mode);
269 Ok(())
270 }
271
272 pub async fn anvil_drop_transaction(&self, tx_hash: B256) -> Result<Option<B256>> {
276 node_info!("anvil_dropTransaction");
277 Ok(self.pool.drop_transaction(tx_hash).map(|tx| tx.hash()))
278 }
279
280 pub async fn anvil_drop_all_transactions(&self) -> Result<()> {
284 node_info!("anvil_dropAllTransactions");
285 self.pool.clear();
286 Ok(())
287 }
288
289 pub async fn anvil_set_chain_id(&self, chain_id: u64) -> Result<()> {
290 node_info!("anvil_setChainId");
291 self.backend.set_chain_id(chain_id);
292 Ok(())
293 }
294
295 pub async fn anvil_set_balance(&self, address: Address, balance: U256) -> Result<()> {
299 node_info!("anvil_setBalance");
300 self.backend.set_balance(address, balance).await?;
301 Ok(())
302 }
303
304 pub async fn anvil_set_code(&self, address: Address, code: Bytes) -> Result<()> {
308 node_info!("anvil_setCode");
309 self.backend.set_code(address, code).await?;
310 Ok(())
311 }
312
313 pub async fn anvil_set_nonce(&self, address: Address, nonce: U256) -> Result<()> {
317 node_info!("anvil_setNonce");
318 self.backend.set_nonce(address, nonce).await?;
319 Ok(())
320 }
321
322 pub async fn anvil_set_storage_at(
326 &self,
327 address: Address,
328 slot: U256,
329 val: B256,
330 ) -> Result<bool> {
331 node_info!("anvil_setStorageAt");
332 self.backend.set_storage_at(address, slot, val).await?;
333 Ok(true)
334 }
335
336 pub async fn anvil_set_logging(&self, enable: bool) -> Result<()> {
340 node_info!("anvil_setLoggingEnabled");
341 self.logger.set_enabled(enable);
342 Ok(())
343 }
344
345 pub async fn anvil_set_min_gas_price(&self, gas: U256) -> Result<()> {
349 node_info!("anvil_setMinGasPrice");
350 if self.backend.is_eip1559() {
351 return Err(RpcError::invalid_params(
352 "anvil_setMinGasPrice is not supported when EIP-1559 is active",
353 )
354 .into());
355 }
356 self.backend.set_gas_price(gas.to());
357 Ok(())
358 }
359
360 pub async fn anvil_set_next_block_base_fee_per_gas(&self, basefee: U256) -> Result<()> {
364 node_info!("anvil_setNextBlockBaseFeePerGas");
365 if !self.backend.is_eip1559() {
366 return Err(RpcError::invalid_params(
367 "anvil_setNextBlockBaseFeePerGas is only supported when EIP-1559 is active",
368 )
369 .into());
370 }
371 self.backend.set_base_fee(basefee.to());
372 Ok(())
373 }
374
375 pub async fn anvil_set_coinbase(&self, address: Address) -> Result<()> {
379 node_info!("anvil_setCoinbase");
380 self.backend.set_coinbase(address);
381 Ok(())
382 }
383
384 pub async fn anvil_node_info(&self) -> Result<NodeInfo> {
388 node_info!("anvil_nodeInfo");
389
390 let env = self.backend.env().read();
391 let fork_config = self.backend.get_fork();
392 let tx_order = self.transaction_order.read();
393 let hard_fork: &str = env.evm_env.cfg_env.spec.into();
394
395 Ok(NodeInfo {
396 current_block_number: self.backend.best_number(),
397 current_block_timestamp: env.evm_env.block_env.timestamp.saturating_to(),
398 current_block_hash: self.backend.best_hash(),
399 hard_fork: hard_fork.to_string(),
400 transaction_order: match *tx_order {
401 TransactionOrder::Fifo => "fifo".to_string(),
402 TransactionOrder::Fees => "fees".to_string(),
403 },
404 environment: NodeEnvironment {
405 base_fee: self.backend.base_fee() as u128,
406 chain_id: self.backend.chain_id().to::<u64>(),
407 gas_limit: self.backend.gas_limit(),
408 gas_price: self.gas_price(),
409 },
410 fork_config: fork_config
411 .map(|fork| {
412 let config = fork.config.read();
413
414 NodeForkConfig {
415 fork_url: Some(config.eth_rpc_url.clone()),
416 fork_block_number: Some(config.block_number),
417 fork_retry_backoff: Some(config.backoff.as_millis()),
418 }
419 })
420 .unwrap_or_default(),
421 })
422 }
423
424 pub async fn anvil_metadata(&self) -> Result<Metadata> {
428 node_info!("anvil_metadata");
429 let fork_config = self.backend.get_fork();
430
431 Ok(Metadata {
432 client_version: CLIENT_VERSION.to_string(),
433 chain_id: self.backend.chain_id().to::<u64>(),
434 latest_block_hash: self.backend.best_hash(),
435 latest_block_number: self.backend.best_number(),
436 instance_id: *self.instance_id.read(),
437 forked_network: fork_config.map(|cfg| ForkedNetwork {
438 chain_id: cfg.chain_id(),
439 fork_block_number: cfg.block_number(),
440 fork_block_hash: cfg.block_hash(),
441 }),
442 snapshots: self.backend.list_state_snapshots(),
443 })
444 }
445
446 pub async fn anvil_remove_pool_transactions(&self, address: Address) -> Result<()> {
447 node_info!("anvil_removePoolTransactions");
448 self.pool.remove_transactions_by_address(address);
449 Ok(())
450 }
451
452 pub async fn evm_snapshot(&self) -> Result<U256> {
456 node_info!("evm_snapshot");
457 Ok(self.backend.create_state_snapshot().await)
458 }
459
460 pub async fn evm_increase_time(&self, seconds: U256) -> Result<i64> {
464 node_info!("evm_increaseTime");
465 Ok(self.backend.time().increase_time(seconds.try_into().unwrap_or(u64::MAX)) as i64)
466 }
467
468 pub fn evm_set_next_block_timestamp(&self, seconds: u64) -> Result<()> {
472 node_info!("evm_setNextBlockTimestamp");
473 self.backend.time().set_next_block_timestamp(seconds)
474 }
475
476 pub fn evm_set_time(&self, timestamp: u64) -> Result<u64> {
481 node_info!("evm_setTime");
482 let now = self.backend.time().current_call_timestamp();
483 self.backend.time().reset(timestamp);
484
485 let offset = timestamp.saturating_sub(now);
487 Ok(Duration::from_millis(offset).as_secs())
488 }
489
490 pub fn evm_set_block_gas_limit(&self, gas_limit: U256) -> Result<bool> {
494 node_info!("evm_setBlockGasLimit");
495 self.backend.set_gas_limit(gas_limit.to());
496 Ok(true)
497 }
498
499 pub fn evm_set_block_timestamp_interval(&self, seconds: u64) -> Result<()> {
503 node_info!("anvil_setBlockTimestampInterval");
504 self.backend.time().set_block_timestamp_interval(seconds);
505 Ok(())
506 }
507
508 pub fn evm_remove_block_timestamp_interval(&self) -> Result<bool> {
512 node_info!("anvil_removeBlockTimestampInterval");
513 Ok(self.backend.time().remove_block_timestamp_interval())
514 }
515
516 pub fn anvil_set_rpc_url(&self, url: String) -> Result<()> {
520 node_info!("anvil_setRpcUrl");
521 if let Some(fork) = self.backend.get_fork() {
522 let mut config = fork.config.write();
523 let new_provider = Arc::new(
525 ProviderBuilder::new(&url).max_retry(10).initial_backoff(1000).build().map_err(
526 |_| {
527 TransportErrorKind::custom_str(
528 format!("Failed to parse invalid url {url}").as_str(),
529 )
530 },
531 )?, );
534 config.provider = new_provider;
535 trace!(target: "backend", "Updated fork rpc from \"{}\" to \"{}\"", config.eth_rpc_url, url);
536 config.eth_rpc_url = url;
537 }
538 Ok(())
539 }
540
541 pub async fn txpool_status(&self) -> Result<TxpoolStatus> {
547 node_info!("txpool_status");
548 Ok(self.pool.txpool_status())
549 }
550
551 async fn on_blocking_task<C, F, R>(&self, c: C) -> Result<R>
553 where
554 C: FnOnce(Self) -> F,
555 F: Future<Output = Result<R>> + Send + 'static,
556 R: Send + 'static,
557 {
558 let (tx, rx) = oneshot::channel();
559 let this = self.clone();
560 let f = c(this);
561 tokio::task::spawn_blocking(move || {
562 tokio::runtime::Handle::current().block_on(async move {
563 let res = f.await;
564 let _ = tx.send(res);
565 })
566 });
567 rx.await.map_err(|_| BlockchainError::Internal("blocking task panicked".to_string()))?
568 }
569
570 pub fn set_transaction_order(&self, order: TransactionOrder) {
572 *self.transaction_order.write() = order;
573 }
574
575 pub fn chain_id(&self) -> u64 {
577 self.backend.chain_id().to::<u64>()
578 }
579
580 pub fn get_fork(&self) -> Option<ClientFork> {
582 self.backend.get_fork()
583 }
584
585 pub fn instance_id(&self) -> B256 {
587 *self.instance_id.read()
588 }
589
590 pub fn reset_instance_id(&self) {
592 *self.instance_id.write() = B256::random();
593 }
594
595 #[expect(clippy::borrowed_box)]
597 pub fn get_signer(&self, address: Address) -> Option<&Box<dyn Signer<N>>> {
598 self.signers.iter().find(|signer| signer.is_signer_for(address))
599 }
600
601 pub fn new_ready_transactions(&self) -> Receiver<TxHash> {
603 self.pool.add_ready_listener()
604 }
605
606 pub fn is_fork(&self) -> bool {
608 self.backend.is_fork()
609 }
610
611 pub async fn state_root(&self) -> Option<B256> {
613 self.backend.get_db().read().await.maybe_state_root()
614 }
615
616 pub fn is_impersonated(&self, addr: Address) -> bool {
618 self.backend.cheats().is_impersonated(addr)
619 }
620
621 pub fn storage_info(&self) -> StorageInfo<N> {
623 StorageInfo::new(Arc::clone(&self.backend))
624 }
625}
626
627impl EthApi<FoundryNetwork> {
630 pub async fn anvil_reset(&self, forking: Option<Forking>) -> Result<()> {
636 self.reset_instance_id();
637 node_info!("anvil_reset");
638 if let Some(forking) = forking {
639 self.backend.reset_fork(forking).await?;
641 } else {
642 self.backend.reset_to_in_mem().await?;
644 }
645 self.pool.clear();
647 Ok(())
648 }
649
650 pub async fn anvil_dump_state(
655 &self,
656 preserve_historical_states: Option<bool>,
657 ) -> Result<Bytes> {
658 node_info!("anvil_dumpState");
659 self.backend.dump_state(preserve_historical_states.unwrap_or(false)).await
660 }
661
662 pub async fn serialized_state(
664 &self,
665 preserve_historical_states: bool,
666 ) -> Result<SerializableState> {
667 self.backend.serialized_state(preserve_historical_states).await
668 }
669
670 pub async fn anvil_load_state(&self, buf: Bytes) -> Result<bool> {
675 node_info!("anvil_loadState");
676 self.backend.load_state_bytes(buf).await
677 }
678
679 pub async fn evm_revert(&self, id: U256) -> Result<bool> {
684 node_info!("evm_revert");
685 self.backend.revert_state_snapshot(id).await
686 }
687
688 async fn block_request(
689 &self,
690 block_number: Option<BlockId>,
691 ) -> Result<BlockRequest<FoundryTxEnvelope>> {
692 let block_request = match block_number {
693 Some(BlockId::Number(BlockNumber::Pending)) => {
694 let pending_txs = self.pool.ready_transactions().collect();
695 BlockRequest::Pending(pending_txs)
696 }
697 _ => {
698 let number = self.backend.ensure_block_number(block_number).await?;
699 BlockRequest::Number(number)
700 }
701 };
702 Ok(block_request)
703 }
704
705 pub async fn anvil_add_balance(&self, address: Address, balance: U256) -> Result<()> {
709 node_info!("anvil_addBalance");
710 let current_balance = self.backend.get_balance(address, None).await?;
711 self.backend.set_balance(address, current_balance.saturating_add(balance)).await?;
712 Ok(())
713 }
714
715 pub async fn anvil_rollback(&self, depth: Option<u64>) -> Result<()> {
726 node_info!("anvil_rollback");
727 let depth = depth.unwrap_or(1);
728
729 let current_height = self.backend.best_number();
731 let common_height = current_height.checked_sub(depth).ok_or(BlockchainError::RpcError(
732 RpcError::invalid_params(format!(
733 "Rollback depth must not exceed current chain height: current height {current_height}, depth {depth}"
734 )),
735 ))?;
736
737 let common_block =
739 self.backend.get_block(common_height).ok_or(BlockchainError::BlockNotFound)?;
740
741 self.backend.rollback(common_block).await?;
742 Ok(())
743 }
744
745 fn do_estimate_gas_with_state(
749 &self,
750 mut request: WithOtherFields<TransactionRequest>,
751 state: &dyn DatabaseRef,
752 block_env: BlockEnv,
753 ) -> Result<u128> {
754 let to = request.to.as_ref().and_then(TxKind::to);
757
758 let maybe_transfer = (request.input.input().is_none()
760 || request.input.input().is_some_and(|data| data.is_empty()))
761 && request.authorization_list.is_none()
762 && request.access_list.is_none()
763 && request.blob_versioned_hashes.is_none();
764
765 if maybe_transfer
766 && let Some(to) = to
767 && let Ok(target_code) = self.backend.get_code_with_state(&state, *to)
768 && target_code.as_ref().is_empty()
769 {
770 return Ok(MIN_TRANSACTION_GAS);
771 }
772
773 let fees = FeeDetails::new(
774 request.gas_price,
775 request.max_fee_per_gas,
776 request.max_priority_fee_per_gas,
777 request.max_fee_per_blob_gas,
778 )?
779 .or_zero_fees();
780
781 let mut highest_gas_limit = request.gas.map_or(block_env.gas_limit.into(), |g| g as u128);
784
785 let gas_price = fees.gas_price.unwrap_or_default();
786 if gas_price > 0
788 && let Some(from) = request.from
789 {
790 let mut available_funds = self.backend.get_balance_with_state(state, from)?;
791 if let Some(value) = request.value {
792 if value > available_funds {
793 return Err(InvalidTransactionError::InsufficientFunds.into());
794 }
795 available_funds -= value;
797 }
798 let allowance = available_funds.checked_div(U256::from(gas_price)).unwrap_or_default();
800 highest_gas_limit = std::cmp::min(highest_gas_limit, allowance.saturating_to());
801 }
802
803 let mut call_to_estimate = request.clone();
804 call_to_estimate.gas = Some(highest_gas_limit as u64);
805
806 let ethres =
808 self.backend.call_with_state(&state, call_to_estimate, fees.clone(), block_env.clone());
809
810 let gas_used = match ethres.try_into()? {
811 GasEstimationCallResult::Success(gas) => Ok(gas),
812 GasEstimationCallResult::OutOfGas => {
813 Err(InvalidTransactionError::BasicOutOfGas(highest_gas_limit).into())
814 }
815 GasEstimationCallResult::Revert(output) => {
816 Err(InvalidTransactionError::Revert(output).into())
817 }
818 GasEstimationCallResult::EvmError(err) => {
819 warn!(target: "node", "estimation failed due to {:?}", err);
820 Err(BlockchainError::EvmError(err))
821 }
822 }?;
823
824 let mut lowest_gas_limit = determine_base_gas_by_kind(&request);
831
832 let mut mid_gas_limit =
834 std::cmp::min(gas_used * 3, (highest_gas_limit + lowest_gas_limit) / 2);
835
836 while (highest_gas_limit - lowest_gas_limit) > 1 {
838 request.gas = Some(mid_gas_limit as u64);
839 let ethres = self.backend.call_with_state(
840 &state,
841 request.clone(),
842 fees.clone(),
843 block_env.clone(),
844 );
845
846 match ethres.try_into()? {
847 GasEstimationCallResult::Success(_) => {
848 highest_gas_limit = mid_gas_limit;
852 }
853 GasEstimationCallResult::OutOfGas
854 | GasEstimationCallResult::Revert(_)
855 | GasEstimationCallResult::EvmError(_) => {
856 lowest_gas_limit = mid_gas_limit;
863 }
864 };
865 mid_gas_limit = (highest_gas_limit + lowest_gas_limit) / 2;
867 }
868
869 trace!(target : "node", "Estimated Gas for call {:?}", highest_gas_limit);
870
871 Ok(highest_gas_limit)
872 }
873
874 pub fn new_block_notifications(&self) -> NewBlockNotifications {
876 self.backend.new_block_notifications()
877 }
878
879 pub async fn execute(&self, request: EthRequest) -> ResponseResult {
881 trace!(target: "rpc::api", "executing eth request");
882 let response = match request.clone() {
883 EthRequest::EthProtocolVersion(()) => self.protocol_version().to_rpc_result(),
884 EthRequest::Web3ClientVersion(()) => self.client_version().to_rpc_result(),
885 EthRequest::Web3Sha3(content) => self.sha3(content).to_rpc_result(),
886 EthRequest::EthGetAccount(addr, block) => {
887 self.get_account(addr, block).await.to_rpc_result()
888 }
889 EthRequest::EthGetAccountInfo(addr, block) => {
890 self.get_account_info(addr, block).await.to_rpc_result()
891 }
892 EthRequest::EthGetBalance(addr, block) => {
893 self.balance(addr, block).await.to_rpc_result()
894 }
895 EthRequest::EthGetTransactionByHash(hash) => {
896 self.transaction_by_hash(hash).await.to_rpc_result()
897 }
898 EthRequest::EthSendTransaction(request) => {
899 self.send_transaction(*request).await.to_rpc_result()
900 }
901 EthRequest::EthSendTransactionSync(request) => {
902 self.send_transaction_sync(*request).await.to_rpc_result()
903 }
904 EthRequest::EthChainId(_) => self.eth_chain_id().to_rpc_result(),
905 EthRequest::EthNetworkId(_) => self.network_id().to_rpc_result(),
906 EthRequest::NetListening(_) => self.net_listening().to_rpc_result(),
907 EthRequest::EthHashrate(()) => self.hashrate().to_rpc_result(),
908 EthRequest::EthGasPrice(_) => self.eth_gas_price().to_rpc_result(),
909 EthRequest::EthMaxPriorityFeePerGas(_) => {
910 self.gas_max_priority_fee_per_gas().to_rpc_result()
911 }
912 EthRequest::EthBlobBaseFee(_) => self.blob_base_fee().to_rpc_result(),
913 EthRequest::EthAccounts(_) => self.accounts().to_rpc_result(),
914 EthRequest::EthBlockNumber(_) => self.block_number().to_rpc_result(),
915 EthRequest::EthCoinbase(()) => self.author().to_rpc_result(),
916 EthRequest::EthGetStorageAt(addr, slot, block) => {
917 self.storage_at(addr, slot, block).await.to_rpc_result()
918 }
919 EthRequest::EthGetBlockByHash(hash, full) => {
920 if full {
921 self.block_by_hash_full(hash).await.to_rpc_result()
922 } else {
923 self.block_by_hash(hash).await.to_rpc_result()
924 }
925 }
926 EthRequest::EthGetBlockByNumber(num, full) => {
927 if full {
928 self.block_by_number_full(num).await.to_rpc_result()
929 } else {
930 self.block_by_number(num).await.to_rpc_result()
931 }
932 }
933 EthRequest::EthGetTransactionCount(addr, block) => {
934 self.transaction_count(addr, block).await.to_rpc_result()
935 }
936 EthRequest::EthGetTransactionCountByHash(hash) => {
937 self.block_transaction_count_by_hash(hash).await.to_rpc_result()
938 }
939 EthRequest::EthGetTransactionCountByNumber(num) => {
940 self.block_transaction_count_by_number(num).await.to_rpc_result()
941 }
942 EthRequest::EthGetUnclesCountByHash(hash) => {
943 self.block_uncles_count_by_hash(hash).await.to_rpc_result()
944 }
945 EthRequest::EthGetUnclesCountByNumber(num) => {
946 self.block_uncles_count_by_number(num).await.to_rpc_result()
947 }
948 EthRequest::EthGetCodeAt(addr, block) => {
949 self.get_code(addr, block).await.to_rpc_result()
950 }
951 EthRequest::EthGetProof(addr, keys, block) => {
952 self.get_proof(addr, keys, block).await.to_rpc_result()
953 }
954 EthRequest::EthSign(addr, content) => self.sign(addr, content).await.to_rpc_result(),
955 EthRequest::PersonalSign(content, addr) => {
956 self.sign(addr, content).await.to_rpc_result()
957 }
958 EthRequest::EthSignTransaction(request) => {
959 self.sign_transaction(*request).await.to_rpc_result()
960 }
961 EthRequest::EthSignTypedData(addr, data) => {
962 self.sign_typed_data(addr, data).await.to_rpc_result()
963 }
964 EthRequest::EthSignTypedDataV3(addr, data) => {
965 self.sign_typed_data_v3(addr, data).await.to_rpc_result()
966 }
967 EthRequest::EthSignTypedDataV4(addr, data) => {
968 self.sign_typed_data_v4(addr, &data).await.to_rpc_result()
969 }
970 EthRequest::EthSendRawTransaction(tx) => {
971 self.send_raw_transaction(tx).await.to_rpc_result()
972 }
973 EthRequest::EthSendRawTransactionSync(tx) => {
974 self.send_raw_transaction_sync(tx).await.to_rpc_result()
975 }
976 EthRequest::EthCall(call, block, state_override, block_overrides) => self
977 .call(call, block, EvmOverrides::new(state_override, block_overrides))
978 .await
979 .to_rpc_result(),
980 EthRequest::EthSimulateV1(simulation, block) => {
981 self.simulate_v1(simulation, block).await.to_rpc_result()
982 }
983 EthRequest::EthCreateAccessList(call, block) => {
984 self.create_access_list(call, block).await.to_rpc_result()
985 }
986 EthRequest::EthEstimateGas(call, block, state_override, block_overrides) => self
987 .estimate_gas(call, block, EvmOverrides::new(state_override, block_overrides))
988 .await
989 .to_rpc_result(),
990 EthRequest::EthFillTransaction(request) => {
991 self.fill_transaction(request).await.to_rpc_result()
992 }
993 EthRequest::EthGetRawTransactionByHash(hash) => {
994 self.raw_transaction(hash).await.to_rpc_result()
995 }
996 EthRequest::GetBlobByHash(hash) => {
997 self.anvil_get_blob_by_versioned_hash(hash).to_rpc_result()
998 }
999 EthRequest::GetBlobByTransactionHash(hash) => {
1000 self.anvil_get_blob_by_tx_hash(hash).to_rpc_result()
1001 }
1002 EthRequest::GetGenesisTime(()) => self.anvil_get_genesis_time().to_rpc_result(),
1003 EthRequest::EthGetRawTransactionByBlockHashAndIndex(hash, index) => {
1004 self.raw_transaction_by_block_hash_and_index(hash, index).await.to_rpc_result()
1005 }
1006 EthRequest::EthGetRawTransactionByBlockNumberAndIndex(num, index) => {
1007 self.raw_transaction_by_block_number_and_index(num, index).await.to_rpc_result()
1008 }
1009 EthRequest::EthGetTransactionByBlockHashAndIndex(hash, index) => {
1010 self.transaction_by_block_hash_and_index(hash, index).await.to_rpc_result()
1011 }
1012 EthRequest::EthGetTransactionByBlockNumberAndIndex(num, index) => {
1013 self.transaction_by_block_number_and_index(num, index).await.to_rpc_result()
1014 }
1015 EthRequest::EthGetTransactionReceipt(tx) => {
1016 self.transaction_receipt(tx).await.to_rpc_result()
1017 }
1018 EthRequest::EthGetBlockReceipts(number) => {
1019 self.block_receipts(number).await.to_rpc_result()
1020 }
1021 EthRequest::EthGetUncleByBlockHashAndIndex(hash, index) => {
1022 self.uncle_by_block_hash_and_index(hash, index).await.to_rpc_result()
1023 }
1024 EthRequest::EthGetUncleByBlockNumberAndIndex(num, index) => {
1025 self.uncle_by_block_number_and_index(num, index).await.to_rpc_result()
1026 }
1027 EthRequest::EthGetLogs(filter) => self.logs(filter).await.to_rpc_result(),
1028 EthRequest::EthGetWork(_) => self.work().to_rpc_result(),
1029 EthRequest::EthSyncing(_) => self.syncing().to_rpc_result(),
1030 EthRequest::EthConfig(_) => self.config().to_rpc_result(),
1031 EthRequest::EthSubmitWork(nonce, pow, digest) => {
1032 self.submit_work(nonce, pow, digest).to_rpc_result()
1033 }
1034 EthRequest::EthSubmitHashRate(rate, id) => {
1035 self.submit_hashrate(rate, id).to_rpc_result()
1036 }
1037 EthRequest::EthFeeHistory(count, newest, reward_percentiles) => {
1038 self.fee_history(count, newest, reward_percentiles).await.to_rpc_result()
1039 }
1040 EthRequest::DebugGetRawTransaction(hash) => {
1042 self.raw_transaction(hash).await.to_rpc_result()
1043 }
1044 EthRequest::DebugTraceTransaction(tx, opts) => {
1046 self.debug_trace_transaction(tx, opts).await.to_rpc_result()
1047 }
1048 EthRequest::DebugTraceCall(tx, block, opts) => {
1050 self.debug_trace_call(tx, block, opts).await.to_rpc_result()
1051 }
1052 EthRequest::DebugCodeByHash(hash, block) => {
1053 self.debug_code_by_hash(hash, block).await.to_rpc_result()
1054 }
1055 EthRequest::DebugDbGet(key) => self.debug_db_get(key).await.to_rpc_result(),
1056 EthRequest::TraceTransaction(tx) => self.trace_transaction(tx).await.to_rpc_result(),
1057 EthRequest::TraceBlock(block) => self.trace_block(block).await.to_rpc_result(),
1058 EthRequest::TraceFilter(filter) => self.trace_filter(filter).await.to_rpc_result(),
1059 EthRequest::TraceReplayBlockTransactions(block, trace_types) => {
1060 self.trace_replay_block_transactions(block, trace_types).await.to_rpc_result()
1061 }
1062 EthRequest::ImpersonateAccount(addr) => {
1063 self.anvil_impersonate_account(addr).await.to_rpc_result()
1064 }
1065 EthRequest::StopImpersonatingAccount(addr) => {
1066 self.anvil_stop_impersonating_account(addr).await.to_rpc_result()
1067 }
1068 EthRequest::AutoImpersonateAccount(enable) => {
1069 self.anvil_auto_impersonate_account(enable).await.to_rpc_result()
1070 }
1071 EthRequest::ImpersonateSignature(signature, address) => {
1072 self.anvil_impersonate_signature(signature, address).await.to_rpc_result()
1073 }
1074 EthRequest::GetAutoMine(()) => self.anvil_get_auto_mine().to_rpc_result(),
1075 EthRequest::Mine(blocks, interval) => {
1076 self.anvil_mine(blocks, interval).await.to_rpc_result()
1077 }
1078 EthRequest::SetAutomine(enabled) => {
1079 self.anvil_set_auto_mine(enabled).await.to_rpc_result()
1080 }
1081 EthRequest::SetIntervalMining(interval) => {
1082 self.anvil_set_interval_mining(interval).to_rpc_result()
1083 }
1084 EthRequest::GetIntervalMining(()) => self.anvil_get_interval_mining().to_rpc_result(),
1085 EthRequest::DropTransaction(tx) => {
1086 self.anvil_drop_transaction(tx).await.to_rpc_result()
1087 }
1088 EthRequest::DropAllTransactions() => {
1089 self.anvil_drop_all_transactions().await.to_rpc_result()
1090 }
1091 EthRequest::Reset(fork) => {
1092 self.anvil_reset(fork.and_then(|p| p.params)).await.to_rpc_result()
1093 }
1094 EthRequest::SetBalance(addr, val) => {
1095 self.anvil_set_balance(addr, val).await.to_rpc_result()
1096 }
1097 EthRequest::AddBalance(addr, val) => {
1098 self.anvil_add_balance(addr, val).await.to_rpc_result()
1099 }
1100 EthRequest::DealERC20(addr, token_addr, val) => {
1101 self.anvil_deal_erc20(addr, token_addr, val).await.to_rpc_result()
1102 }
1103 EthRequest::SetERC20Allowance(owner, spender, token_addr, val) => self
1104 .anvil_set_erc20_allowance(owner, spender, token_addr, val)
1105 .await
1106 .to_rpc_result(),
1107 EthRequest::SetCode(addr, code) => {
1108 self.anvil_set_code(addr, code).await.to_rpc_result()
1109 }
1110 EthRequest::SetNonce(addr, nonce) => {
1111 self.anvil_set_nonce(addr, nonce).await.to_rpc_result()
1112 }
1113 EthRequest::SetStorageAt(addr, slot, val) => {
1114 self.anvil_set_storage_at(addr, slot, val).await.to_rpc_result()
1115 }
1116 EthRequest::SetCoinbase(addr) => self.anvil_set_coinbase(addr).await.to_rpc_result(),
1117 EthRequest::SetChainId(id) => self.anvil_set_chain_id(id).await.to_rpc_result(),
1118 EthRequest::SetLogging(log) => self.anvil_set_logging(log).await.to_rpc_result(),
1119 EthRequest::SetMinGasPrice(gas) => {
1120 self.anvil_set_min_gas_price(gas).await.to_rpc_result()
1121 }
1122 EthRequest::SetNextBlockBaseFeePerGas(gas) => {
1123 self.anvil_set_next_block_base_fee_per_gas(gas).await.to_rpc_result()
1124 }
1125 EthRequest::DumpState(preserve_historical_states) => self
1126 .anvil_dump_state(preserve_historical_states.and_then(|s| s.params))
1127 .await
1128 .to_rpc_result(),
1129 EthRequest::LoadState(buf) => self.anvil_load_state(buf).await.to_rpc_result(),
1130 EthRequest::NodeInfo(_) => self.anvil_node_info().await.to_rpc_result(),
1131 EthRequest::AnvilMetadata(_) => self.anvil_metadata().await.to_rpc_result(),
1132 EthRequest::EvmSnapshot(_) => self.evm_snapshot().await.to_rpc_result(),
1133 EthRequest::EvmRevert(id) => self.evm_revert(id).await.to_rpc_result(),
1134 EthRequest::EvmIncreaseTime(time) => self.evm_increase_time(time).await.to_rpc_result(),
1135 EthRequest::EvmSetNextBlockTimeStamp(time) => {
1136 if time >= U256::from(u64::MAX) {
1137 return ResponseResult::Error(RpcError::invalid_params(
1138 "The timestamp is too big",
1139 ));
1140 }
1141 let time = time.to::<u64>();
1142 self.evm_set_next_block_timestamp(time).to_rpc_result()
1143 }
1144 EthRequest::EvmSetTime(timestamp) => {
1145 if timestamp >= U256::from(u64::MAX) {
1146 return ResponseResult::Error(RpcError::invalid_params(
1147 "The timestamp is too big",
1148 ));
1149 }
1150 let time = timestamp.to::<u64>();
1151 self.evm_set_time(time).to_rpc_result()
1152 }
1153 EthRequest::EvmSetBlockGasLimit(gas_limit) => {
1154 self.evm_set_block_gas_limit(gas_limit).to_rpc_result()
1155 }
1156 EthRequest::EvmSetBlockTimeStampInterval(time) => {
1157 self.evm_set_block_timestamp_interval(time).to_rpc_result()
1158 }
1159 EthRequest::EvmRemoveBlockTimeStampInterval(()) => {
1160 self.evm_remove_block_timestamp_interval().to_rpc_result()
1161 }
1162 EthRequest::EvmMine(mine) => {
1163 self.evm_mine(mine.and_then(|p| p.params)).await.to_rpc_result()
1164 }
1165 EthRequest::EvmMineDetailed(mine) => {
1166 self.evm_mine_detailed(mine.and_then(|p| p.params)).await.to_rpc_result()
1167 }
1168 EthRequest::SetRpcUrl(url) => self.anvil_set_rpc_url(url).to_rpc_result(),
1169 EthRequest::EthSendUnsignedTransaction(tx) => {
1170 self.eth_send_unsigned_transaction(*tx).await.to_rpc_result()
1171 }
1172 EthRequest::EthNewFilter(filter) => self.new_filter(filter).await.to_rpc_result(),
1173 EthRequest::EthGetFilterChanges(id) => self.get_filter_changes(&id).await,
1174 EthRequest::EthNewBlockFilter(_) => self.new_block_filter().await.to_rpc_result(),
1175 EthRequest::EthNewPendingTransactionFilter(_) => {
1176 self.new_pending_transaction_filter().await.to_rpc_result()
1177 }
1178 EthRequest::EthGetFilterLogs(id) => self.get_filter_logs(&id).await.to_rpc_result(),
1179 EthRequest::EthUninstallFilter(id) => self.uninstall_filter(&id).await.to_rpc_result(),
1180 EthRequest::TxPoolStatus(_) => self.txpool_status().await.to_rpc_result(),
1181 EthRequest::TxPoolInspect(_) => self.txpool_inspect().await.to_rpc_result(),
1182 EthRequest::TxPoolContent(_) => self.txpool_content().await.to_rpc_result(),
1183 EthRequest::ErigonGetHeaderByNumber(num) => {
1184 self.erigon_get_header_by_number(num).await.to_rpc_result()
1185 }
1186 EthRequest::OtsGetApiLevel(_) => self.ots_get_api_level().await.to_rpc_result(),
1187 EthRequest::OtsGetInternalOperations(hash) => {
1188 self.ots_get_internal_operations(hash).await.to_rpc_result()
1189 }
1190 EthRequest::OtsHasCode(addr, num) => self.ots_has_code(addr, num).await.to_rpc_result(),
1191 EthRequest::OtsTraceTransaction(hash) => {
1192 self.ots_trace_transaction(hash).await.to_rpc_result()
1193 }
1194 EthRequest::OtsGetTransactionError(hash) => {
1195 self.ots_get_transaction_error(hash).await.to_rpc_result()
1196 }
1197 EthRequest::OtsGetBlockDetails(num) => {
1198 self.ots_get_block_details(num).await.to_rpc_result()
1199 }
1200 EthRequest::OtsGetBlockDetailsByHash(hash) => {
1201 self.ots_get_block_details_by_hash(hash).await.to_rpc_result()
1202 }
1203 EthRequest::OtsGetBlockTransactions(num, page, page_size) => {
1204 self.ots_get_block_transactions(num, page, page_size).await.to_rpc_result()
1205 }
1206 EthRequest::OtsSearchTransactionsBefore(address, num, page_size) => {
1207 self.ots_search_transactions_before(address, num, page_size).await.to_rpc_result()
1208 }
1209 EthRequest::OtsSearchTransactionsAfter(address, num, page_size) => {
1210 self.ots_search_transactions_after(address, num, page_size).await.to_rpc_result()
1211 }
1212 EthRequest::OtsGetTransactionBySenderAndNonce(address, nonce) => {
1213 self.ots_get_transaction_by_sender_and_nonce(address, nonce).await.to_rpc_result()
1214 }
1215 EthRequest::EthGetTransactionBySenderAndNonce(sender, nonce) => {
1216 self.transaction_by_sender_and_nonce(sender, nonce).await.to_rpc_result()
1217 }
1218 EthRequest::OtsGetContractCreator(address) => {
1219 self.ots_get_contract_creator(address).await.to_rpc_result()
1220 }
1221 EthRequest::RemovePoolTransactions(address) => {
1222 self.anvil_remove_pool_transactions(address).await.to_rpc_result()
1223 }
1224 EthRequest::Reorg(reorg_options) => {
1225 self.anvil_reorg(reorg_options).await.to_rpc_result()
1226 }
1227 EthRequest::Rollback(depth) => self.anvil_rollback(depth).await.to_rpc_result(),
1228 };
1229
1230 if let ResponseResult::Error(err) = &response {
1231 node_info!("\nRPC request failed:");
1232 node_info!(" Request: {:?}", request);
1233 node_info!(" Error: {}\n", err);
1234 }
1235
1236 response
1237 }
1238
1239 fn sign_request(&self, from: &Address, typed_tx: FoundryTypedTx) -> Result<FoundryTxEnvelope> {
1240 match typed_tx {
1241 FoundryTypedTx::Deposit(_) => return Ok(build_impersonated(typed_tx)),
1242 _ => {
1243 for signer in self.signers.iter() {
1244 if signer.accounts().contains(from) {
1245 return signer.sign_transaction_from(from, typed_tx);
1246 }
1247 }
1248 }
1249 }
1250 Err(BlockchainError::NoSignerAvailable)
1251 }
1252
1253 async fn inner_raw_transaction(&self, hash: B256) -> Result<Option<Bytes>> {
1254 match self.pool.get_transaction(hash) {
1255 Some(tx) => Ok(Some(tx.transaction.encoded_2718().into())),
1256 None => match self.backend.transaction_by_hash(hash).await? {
1257 Some(tx) => Ok(Some(tx.as_ref().encoded_2718().into())),
1258 None => Ok(None),
1259 },
1260 }
1261 }
1262
1263 pub fn client_version(&self) -> Result<String> {
1267 node_info!("web3_clientVersion");
1268 Ok(CLIENT_VERSION.to_string())
1269 }
1270
1271 pub fn sha3(&self, bytes: Bytes) -> Result<String> {
1275 node_info!("web3_sha3");
1276 let hash = alloy_primitives::keccak256(bytes.as_ref());
1277 Ok(alloy_primitives::hex::encode_prefixed(&hash[..]))
1278 }
1279
1280 pub fn protocol_version(&self) -> Result<u64> {
1284 node_info!("eth_protocolVersion");
1285 Ok(1)
1286 }
1287
1288 pub fn hashrate(&self) -> Result<U256> {
1292 node_info!("eth_hashrate");
1293 Ok(U256::ZERO)
1294 }
1295
1296 pub fn author(&self) -> Result<Address> {
1300 node_info!("eth_coinbase");
1301 Ok(self.backend.coinbase())
1302 }
1303
1304 pub fn is_mining(&self) -> Result<bool> {
1308 node_info!("eth_mining");
1309 Ok(self.is_mining)
1310 }
1311
1312 pub fn eth_chain_id(&self) -> Result<Option<U64>> {
1318 node_info!("eth_chainId");
1319 Ok(Some(self.backend.chain_id().to::<U64>()))
1320 }
1321
1322 pub fn network_id(&self) -> Result<Option<String>> {
1326 node_info!("eth_networkId");
1327 let chain_id = self.backend.chain_id().to::<u64>();
1328 Ok(Some(format!("{chain_id}")))
1329 }
1330
1331 pub fn net_listening(&self) -> Result<bool> {
1335 node_info!("net_listening");
1336 Ok(self.net_listening)
1337 }
1338
1339 fn eth_gas_price(&self) -> Result<U256> {
1341 node_info!("eth_gasPrice");
1342 Ok(U256::from(self.gas_price()))
1343 }
1344
1345 pub fn excess_blob_gas_and_price(&self) -> Result<Option<BlobExcessGasAndPrice>> {
1347 Ok(self.backend.excess_blob_gas_and_price())
1348 }
1349
1350 pub fn gas_max_priority_fee_per_gas(&self) -> Result<U256> {
1355 self.max_priority_fee_per_gas()
1356 }
1357
1358 pub fn blob_base_fee(&self) -> Result<U256> {
1362 Ok(U256::from(self.backend.fees().base_fee_per_blob_gas()))
1363 }
1364
1365 pub fn gas_limit(&self) -> U256 {
1367 U256::from(self.backend.gas_limit())
1368 }
1369
1370 pub fn accounts(&self) -> Result<Vec<Address>> {
1374 node_info!("eth_accounts");
1375 let mut unique = HashSet::new();
1376 let mut accounts: Vec<Address> = Vec::new();
1377 for signer in self.signers.iter() {
1378 accounts.extend(signer.accounts().into_iter().filter(|acc| unique.insert(*acc)));
1379 }
1380 accounts.extend(
1381 self.backend
1382 .cheats()
1383 .impersonated_accounts()
1384 .into_iter()
1385 .filter(|acc| unique.insert(*acc)),
1386 );
1387 Ok(accounts.into_iter().collect())
1388 }
1389
1390 pub fn block_number(&self) -> Result<U256> {
1394 node_info!("eth_blockNumber");
1395 Ok(U256::from(self.backend.best_number()))
1396 }
1397
1398 pub async fn balance(&self, address: Address, block_number: Option<BlockId>) -> Result<U256> {
1402 node_info!("eth_getBalance");
1403 let block_request = self.block_request(block_number).await?;
1404
1405 if let BlockRequest::Number(number) = block_request
1407 && let Some(fork) = self.get_fork()
1408 && fork.predates_fork(number)
1409 {
1410 return Ok(fork.get_balance(address, number).await?);
1411 }
1412
1413 self.backend.get_balance(address, Some(block_request)).await
1414 }
1415
1416 pub async fn get_account(
1420 &self,
1421 address: Address,
1422 block_number: Option<BlockId>,
1423 ) -> Result<TrieAccount> {
1424 node_info!("eth_getAccount");
1425 let block_request = self.block_request(block_number).await?;
1426
1427 if let BlockRequest::Number(number) = block_request
1429 && let Some(fork) = self.get_fork()
1430 && fork.predates_fork(number)
1431 {
1432 return Ok(fork.get_account(address, number).await?);
1433 }
1434
1435 self.backend.get_account_at_block(address, Some(block_request)).await
1436 }
1437
1438 pub async fn get_account_info(
1442 &self,
1443 address: Address,
1444 block_number: Option<BlockId>,
1445 ) -> Result<alloy_rpc_types::eth::AccountInfo> {
1446 node_info!("eth_getAccountInfo");
1447
1448 if let Some(fork) = self.get_fork() {
1449 let block_request = self.block_request(block_number).await?;
1450 if let BlockRequest::Number(number) = block_request {
1452 trace!(target: "node", "get_account_info: fork block {}, requested block {number}", fork.block_number());
1453 return if fork.predates_fork(number) {
1454 let balance = fork.get_balance(address, number).map_err(BlockchainError::from);
1457 let code = fork.get_code(address, number).map_err(BlockchainError::from);
1458 let nonce = self.get_transaction_count(address, Some(number.into()));
1459 let (balance, code, nonce) = try_join!(balance, code, nonce)?;
1460
1461 Ok(alloy_rpc_types::eth::AccountInfo { balance, nonce, code })
1462 } else {
1463 let account_info = self.backend.get_account(address).await?;
1466 let code = self.backend.get_code(address, Some(block_request)).await?;
1467 Ok(alloy_rpc_types::eth::AccountInfo {
1468 balance: account_info.balance,
1469 nonce: account_info.nonce,
1470 code,
1471 })
1472 };
1473 }
1474 }
1475
1476 let account = self.get_account(address, block_number);
1477 let code = self.get_code(address, block_number);
1478 let (account, code) = try_join!(account, code)?;
1479 Ok(alloy_rpc_types::eth::AccountInfo {
1480 balance: account.balance,
1481 nonce: account.nonce,
1482 code,
1483 })
1484 }
1485 pub async fn storage_at(
1489 &self,
1490 address: Address,
1491 index: U256,
1492 block_number: Option<BlockId>,
1493 ) -> Result<B256> {
1494 node_info!("eth_getStorageAt");
1495 let block_request = self.block_request(block_number).await?;
1496
1497 if let BlockRequest::Number(number) = block_request
1499 && let Some(fork) = self.get_fork()
1500 && fork.predates_fork(number)
1501 {
1502 return Ok(B256::from(
1503 fork.storage_at(address, index, Some(BlockNumber::Number(number))).await?,
1504 ));
1505 }
1506
1507 self.backend.storage_at(address, index, Some(block_request)).await
1508 }
1509
1510 pub async fn block_by_hash(&self, hash: B256) -> Result<Option<AnyRpcBlock>> {
1514 node_info!("eth_getBlockByHash");
1515 self.backend.block_by_hash(hash).await
1516 }
1517
1518 pub async fn block_by_hash_full(&self, hash: B256) -> Result<Option<AnyRpcBlock>> {
1522 node_info!("eth_getBlockByHash");
1523 self.backend.block_by_hash_full(hash).await
1524 }
1525
1526 pub async fn block_by_number(&self, number: BlockNumber) -> Result<Option<AnyRpcBlock>> {
1530 node_info!("eth_getBlockByNumber");
1531 if number == BlockNumber::Pending {
1532 return Ok(Some(self.pending_block().await));
1533 }
1534
1535 self.backend.block_by_number(number).await
1536 }
1537
1538 pub async fn block_by_number_full(&self, number: BlockNumber) -> Result<Option<AnyRpcBlock>> {
1542 node_info!("eth_getBlockByNumber");
1543 if number == BlockNumber::Pending {
1544 return Ok(self.pending_block_full().await);
1545 }
1546 self.backend.block_by_number_full(number).await
1547 }
1548
1549 pub async fn transaction_count(
1556 &self,
1557 address: Address,
1558 block_number: Option<BlockId>,
1559 ) -> Result<U256> {
1560 node_info!("eth_getTransactionCount");
1561 self.get_transaction_count(address, block_number).await.map(U256::from)
1562 }
1563
1564 pub async fn block_transaction_count_by_hash(&self, hash: B256) -> Result<Option<U256>> {
1568 node_info!("eth_getBlockTransactionCountByHash");
1569 let block = self.backend.block_by_hash(hash).await?;
1570 let txs = block.map(|b| match b.transactions() {
1571 BlockTransactions::Full(txs) => U256::from(txs.len()),
1572 BlockTransactions::Hashes(txs) => U256::from(txs.len()),
1573 BlockTransactions::Uncle => U256::from(0),
1574 });
1575 Ok(txs)
1576 }
1577
1578 pub async fn block_transaction_count_by_number(
1582 &self,
1583 block_number: BlockNumber,
1584 ) -> Result<Option<U256>> {
1585 node_info!("eth_getBlockTransactionCountByNumber");
1586 let block_request = self.block_request(Some(block_number.into())).await?;
1587 if let BlockRequest::Pending(txs) = block_request {
1588 let block = self.backend.pending_block(txs).await;
1589 return Ok(Some(U256::from(block.block.body.transactions.len())));
1590 }
1591 let block = self.backend.block_by_number(block_number).await?;
1592 let txs = block.map(|b| match b.transactions() {
1593 BlockTransactions::Full(txs) => U256::from(txs.len()),
1594 BlockTransactions::Hashes(txs) => U256::from(txs.len()),
1595 BlockTransactions::Uncle => U256::from(0),
1596 });
1597 Ok(txs)
1598 }
1599
1600 pub async fn block_uncles_count_by_hash(&self, hash: B256) -> Result<U256> {
1604 node_info!("eth_getUncleCountByBlockHash");
1605 let block =
1606 self.backend.block_by_hash(hash).await?.ok_or(BlockchainError::BlockNotFound)?;
1607 Ok(U256::from(block.uncles.len()))
1608 }
1609
1610 pub async fn block_uncles_count_by_number(&self, block_number: BlockNumber) -> Result<U256> {
1614 node_info!("eth_getUncleCountByBlockNumber");
1615 let block = self
1616 .backend
1617 .block_by_number(block_number)
1618 .await?
1619 .ok_or(BlockchainError::BlockNotFound)?;
1620 Ok(U256::from(block.uncles.len()))
1621 }
1622
1623 pub async fn get_code(&self, address: Address, block_number: Option<BlockId>) -> Result<Bytes> {
1627 node_info!("eth_getCode");
1628 let block_request = self.block_request(block_number).await?;
1629 if let BlockRequest::Number(number) = block_request
1631 && let Some(fork) = self.get_fork()
1632 && fork.predates_fork(number)
1633 {
1634 return Ok(fork.get_code(address, number).await?);
1635 }
1636 self.backend.get_code(address, Some(block_request)).await
1637 }
1638
1639 pub async fn get_proof(
1644 &self,
1645 address: Address,
1646 keys: Vec<B256>,
1647 block_number: Option<BlockId>,
1648 ) -> Result<EIP1186AccountProofResponse> {
1649 node_info!("eth_getProof");
1650 let block_request = self.block_request(block_number).await?;
1651
1652 if let BlockRequest::Number(number) = block_request
1655 && let Some(fork) = self.get_fork()
1656 && fork.predates_fork_inclusive(number)
1657 {
1658 return Ok(fork.get_proof(address, keys, Some(number.into())).await?);
1659 }
1660
1661 let proof = self.backend.prove_account_at(address, keys, Some(block_request)).await?;
1662 Ok(proof)
1663 }
1664
1665 pub async fn sign_typed_data(
1669 &self,
1670 _address: Address,
1671 _data: serde_json::Value,
1672 ) -> Result<String> {
1673 node_info!("eth_signTypedData");
1674 Err(BlockchainError::RpcUnimplemented)
1675 }
1676
1677 pub async fn sign_typed_data_v3(
1681 &self,
1682 _address: Address,
1683 _data: serde_json::Value,
1684 ) -> Result<String> {
1685 node_info!("eth_signTypedData_v3");
1686 Err(BlockchainError::RpcUnimplemented)
1687 }
1688
1689 pub async fn sign_typed_data_v4(&self, address: Address, data: &TypedData) -> Result<String> {
1693 node_info!("eth_signTypedData_v4");
1694 let signer = self.get_signer(address).ok_or(BlockchainError::NoSignerAvailable)?;
1695 let signature = signer.sign_typed_data(address, data).await?;
1696 let signature = alloy_primitives::hex::encode(signature.as_bytes());
1697 Ok(format!("0x{signature}"))
1698 }
1699
1700 pub async fn sign(&self, address: Address, content: impl AsRef<[u8]>) -> Result<String> {
1704 node_info!("eth_sign");
1705 let signer = self.get_signer(address).ok_or(BlockchainError::NoSignerAvailable)?;
1706 let signature =
1707 alloy_primitives::hex::encode(signer.sign(address, content.as_ref()).await?.as_bytes());
1708 Ok(format!("0x{signature}"))
1709 }
1710
1711 pub async fn sign_transaction(
1715 &self,
1716 request: WithOtherFields<TransactionRequest>,
1717 ) -> Result<String> {
1718 node_info!("eth_signTransaction");
1719
1720 let from = request.from.map(Ok).unwrap_or_else(|| {
1721 self.accounts()?.first().copied().ok_or(BlockchainError::NoSignerAvailable)
1722 })?;
1723
1724 let (nonce, _) = self.request_nonce(&request, from).await?;
1725
1726 let request = self.build_tx_request(request, nonce).await?;
1727
1728 let signed_transaction = self.sign_request(&from, request)?.encoded_2718();
1729 Ok(alloy_primitives::hex::encode_prefixed(signed_transaction))
1730 }
1731
1732 pub async fn send_transaction(
1736 &self,
1737 request: WithOtherFields<TransactionRequest>,
1738 ) -> Result<TxHash> {
1739 node_info!("eth_sendTransaction");
1740
1741 let from = request.from.map(Ok).unwrap_or_else(|| {
1742 self.accounts()?.first().copied().ok_or(BlockchainError::NoSignerAvailable)
1743 })?;
1744 let (nonce, on_chain_nonce) = self.request_nonce(&request, from).await?;
1745
1746 let typed_tx = self.build_tx_request(request, nonce).await?;
1747
1748 let pending_transaction = if self.is_impersonated(from) {
1750 let transaction = sign::build_impersonated(typed_tx);
1751 self.ensure_typed_transaction_supported(&transaction)?;
1752 trace!(target : "node", ?from, "eth_sendTransaction: impersonating");
1753 PendingTransaction::with_impersonated(transaction, from)
1754 } else {
1755 let transaction = self.sign_request(&from, typed_tx)?;
1756 self.ensure_typed_transaction_supported(&transaction)?;
1757 PendingTransaction::new(transaction)?
1758 };
1759 self.backend.validate_pool_transaction(&pending_transaction).await?;
1761
1762 let requires = required_marker(nonce, on_chain_nonce, from);
1763 let provides = vec![to_marker(nonce, from)];
1764 debug_assert!(requires != provides);
1765
1766 self.add_pending_transaction(pending_transaction, requires, provides)
1767 }
1768
1769 async fn await_transaction_inclusion(&self, hash: TxHash) -> Result<FoundryTxReceipt> {
1771 let mut stream = self.new_block_notifications();
1772 if let Some(receipt) = self.backend.transaction_receipt(hash).await? {
1774 return Ok(receipt);
1775 }
1776 while let Some(notification) = stream.next().await {
1777 if let Some(block) = self.backend.get_block_by_hash(notification.hash)
1778 && block.body.transactions.iter().any(|tx| tx.hash() == hash)
1779 && let Some(receipt) = self.backend.transaction_receipt(hash).await?
1780 {
1781 return Ok(receipt);
1782 }
1783 }
1784
1785 Err(BlockchainError::Message("Failed to await transaction inclusion".to_string()))
1786 }
1787
1788 async fn check_transaction_inclusion(&self, hash: TxHash) -> Result<FoundryTxReceipt> {
1790 const TIMEOUT_DURATION: Duration = Duration::from_secs(30);
1791 tokio::time::timeout(TIMEOUT_DURATION, self.await_transaction_inclusion(hash))
1792 .await
1793 .unwrap_or_else(|_elapsed| {
1794 Err(BlockchainError::TransactionConfirmationTimeout {
1795 hash,
1796 duration: TIMEOUT_DURATION,
1797 })
1798 })
1799 }
1800
1801 pub async fn send_transaction_sync(
1805 &self,
1806 request: WithOtherFields<TransactionRequest>,
1807 ) -> Result<FoundryTxReceipt> {
1808 node_info!("eth_sendTransactionSync");
1809 let hash = self.send_transaction(request).await?;
1810
1811 let receipt = self.check_transaction_inclusion(hash).await?;
1812
1813 Ok(receipt)
1814 }
1815
1816 pub async fn send_raw_transaction(&self, tx: Bytes) -> Result<TxHash> {
1820 node_info!("eth_sendRawTransaction");
1821 let mut data = tx.as_ref();
1822 if data.is_empty() {
1823 return Err(BlockchainError::EmptyRawTransactionData);
1824 }
1825
1826 let transaction = FoundryTxEnvelope::decode_2718(&mut data)
1827 .map_err(|_| BlockchainError::FailedToDecodeSignedTransaction)?;
1828
1829 self.ensure_typed_transaction_supported(&transaction)?;
1830
1831 let pending_transaction = PendingTransaction::new(transaction)?;
1832
1833 self.backend.validate_pool_transaction(&pending_transaction).await?;
1835
1836 let on_chain_nonce = self.backend.current_nonce(*pending_transaction.sender()).await?;
1837 let from = *pending_transaction.sender();
1838 let nonce = pending_transaction.transaction.nonce();
1839 let requires = required_marker(nonce, on_chain_nonce, from);
1840
1841 let priority = self.transaction_priority(&pending_transaction.transaction);
1842 let pool_transaction = PoolTransaction {
1843 requires,
1844 provides: vec![to_marker(nonce, *pending_transaction.sender())],
1845 pending_transaction,
1846 priority,
1847 };
1848
1849 let tx = self.pool.add_transaction(pool_transaction)?;
1850 trace!(target: "node", "Added transaction: [{:?}] sender={:?}", tx.hash(), from);
1851 Ok(*tx.hash())
1852 }
1853
1854 pub async fn send_raw_transaction_sync(&self, tx: Bytes) -> Result<FoundryTxReceipt> {
1858 node_info!("eth_sendRawTransactionSync");
1859
1860 let hash = self.send_raw_transaction(tx).await?;
1861 let receipt = self.check_transaction_inclusion(hash).await?;
1862
1863 Ok(receipt)
1864 }
1865
1866 pub async fn call(
1870 &self,
1871 request: WithOtherFields<TransactionRequest>,
1872 block_number: Option<BlockId>,
1873 overrides: EvmOverrides,
1874 ) -> Result<Bytes> {
1875 node_info!("eth_call");
1876 let block_request = self.block_request(block_number).await?;
1877 if let BlockRequest::Number(number) = block_request
1879 && let Some(fork) = self.get_fork()
1880 && fork.predates_fork(number)
1881 {
1882 if overrides.has_state() || overrides.has_block() {
1883 return Err(BlockchainError::EvmOverrideError(
1884 "not available on past forked blocks".to_string(),
1885 ));
1886 }
1887 return Ok(fork.call(&request, Some(number.into())).await?);
1888 }
1889
1890 let fees = FeeDetails::new(
1891 request.gas_price,
1892 request.max_fee_per_gas,
1893 request.max_priority_fee_per_gas,
1894 request.max_fee_per_blob_gas,
1895 )?
1896 .or_zero_fees();
1897 self.on_blocking_task(|this| async move {
1900 let (exit, out, gas, _) =
1901 this.backend.call(request, fees, Some(block_request), overrides).await?;
1902 trace!(target : "node", "Call status {:?}, gas {}", exit, gas);
1903
1904 ensure_return_ok(exit, &out)
1905 })
1906 .await
1907 }
1908
1909 pub async fn simulate_v1(
1910 &self,
1911 request: SimulatePayload,
1912 block_number: Option<BlockId>,
1913 ) -> Result<Vec<SimulatedBlock<AnyRpcBlock>>> {
1914 node_info!("eth_simulateV1");
1915 let block_request = self.block_request(block_number).await?;
1916 if let BlockRequest::Number(number) = block_request
1918 && let Some(fork) = self.get_fork()
1919 && fork.predates_fork(number)
1920 {
1921 return Ok(fork.simulate_v1(&request, Some(number.into())).await?);
1922 }
1923
1924 self.on_blocking_task(|this| async move {
1927 let simulated_blocks = this.backend.simulate(request, Some(block_request)).await?;
1928 trace!(target : "node", "Simulate status {:?}", simulated_blocks);
1929
1930 Ok(simulated_blocks)
1931 })
1932 .await
1933 }
1934
1935 pub async fn create_access_list(
1949 &self,
1950 mut request: WithOtherFields<TransactionRequest>,
1951 block_number: Option<BlockId>,
1952 ) -> Result<AccessListResult> {
1953 node_info!("eth_createAccessList");
1954 let block_request = self.block_request(block_number).await?;
1955 if let BlockRequest::Number(number) = block_request
1957 && let Some(fork) = self.get_fork()
1958 && fork.predates_fork(number)
1959 {
1960 return Ok(fork.create_access_list(&request, Some(number.into())).await?);
1961 }
1962
1963 self.backend
1964 .with_database_at(Some(block_request), |state, block_env| {
1965 let (exit, out, _, access_list) = self.backend.build_access_list_with_state(
1966 &state,
1967 request.clone(),
1968 FeeDetails::zero(),
1969 block_env.clone(),
1970 )?;
1971 ensure_return_ok(exit, &out)?;
1972
1973 request.access_list = Some(access_list.clone());
1975
1976 let (exit, out, gas_used, _) = self.backend.call_with_state(
1977 &state,
1978 request.clone(),
1979 FeeDetails::zero(),
1980 block_env,
1981 )?;
1982 ensure_return_ok(exit, &out)?;
1983
1984 Ok(AccessListResult {
1985 access_list: AccessList(access_list.0),
1986 gas_used: U256::from(gas_used),
1987 error: None,
1988 })
1989 })
1990 .await?
1991 }
1992
1993 pub async fn estimate_gas(
1998 &self,
1999 request: WithOtherFields<TransactionRequest>,
2000 block_number: Option<BlockId>,
2001 overrides: EvmOverrides,
2002 ) -> Result<U256> {
2003 node_info!("eth_estimateGas");
2004 self.do_estimate_gas(
2005 request,
2006 block_number.or_else(|| Some(BlockNumber::Pending.into())),
2007 overrides,
2008 )
2009 .await
2010 .map(U256::from)
2011 }
2012
2013 pub async fn fill_transaction(
2020 &self,
2021 mut request: WithOtherFields<TransactionRequest>,
2022 ) -> Result<FillTransaction<AnyRpcTransaction>> {
2023 node_info!("eth_fillTransaction");
2024
2025 let from = match request.as_ref().from() {
2026 Some(from) => from,
2027 None => self.accounts()?.first().copied().ok_or(BlockchainError::NoSignerAvailable)?,
2028 };
2029
2030 let nonce = if let Some(nonce) = request.as_ref().nonce() {
2031 nonce
2032 } else {
2033 self.request_nonce(&request, from).await?.0
2034 };
2035
2036 if request.as_ref().gas_limit().is_none() {
2040 let estimated_gas =
2041 self.estimate_gas(request.clone(), None, EvmOverrides::default()).await?;
2042 request.as_mut().set_gas_limit(estimated_gas.to());
2043 }
2044
2045 let typed_tx = self.build_tx_request(request, nonce).await?;
2046 let tx = build_impersonated(typed_tx);
2047
2048 let raw = tx.encoded_2718().to_vec().into();
2049
2050 let mut tx =
2051 transaction_build(None, MaybeImpersonatedTransaction::new(tx), None, None, None);
2052
2053 tx.0.inner.inner = Recovered::new_unchecked(tx.0.inner.inner.into_inner(), from);
2056
2057 Ok(FillTransaction { raw, tx })
2058 }
2059
2060 pub fn anvil_get_blob_by_versioned_hash(
2062 &self,
2063 hash: B256,
2064 ) -> Result<Option<alloy_consensus::Blob>> {
2065 node_info!("anvil_getBlobByHash");
2066 Ok(self.backend.get_blob_by_versioned_hash(hash)?)
2067 }
2068
2069 pub fn anvil_get_blob_by_tx_hash(&self, hash: B256) -> Result<Option<Vec<Blob>>> {
2071 node_info!("anvil_getBlobsByTransactionHash");
2072 Ok(self.backend.get_blob_by_tx_hash(hash)?)
2073 }
2074
2075 pub fn anvil_get_blobs_by_block_id(
2077 &self,
2078 block_id: impl Into<BlockId>,
2079 versioned_hashes: Vec<B256>,
2080 ) -> Result<Option<Vec<Blob>>> {
2081 node_info!("anvil_getBlobsByBlockId");
2082 Ok(self.backend.get_blobs_by_block_id(block_id, versioned_hashes)?)
2083 }
2084
2085 pub fn anvil_get_genesis_time(&self) -> Result<u64> {
2089 node_info!("anvil_getGenesisTime");
2090 Ok(self.backend.genesis_time())
2091 }
2092
2093 pub async fn transaction_by_hash(&self, hash: B256) -> Result<Option<AnyRpcTransaction>> {
2100 node_info!("eth_getTransactionByHash");
2101 let mut tx = self.pool.get_transaction(hash).map(|pending| {
2102 let from = *pending.sender();
2103 let tx = transaction_build(
2104 Some(*pending.hash()),
2105 pending.transaction,
2106 None,
2107 None,
2108 Some(self.backend.base_fee()),
2109 );
2110
2111 let WithOtherFields { inner: mut tx, other } = tx.0;
2112 tx.inner = Recovered::new_unchecked(tx.inner.into_inner(), from);
2115
2116 AnyRpcTransaction(WithOtherFields { inner: tx, other })
2117 });
2118 if tx.is_none() {
2119 tx = self.backend.transaction_by_hash(hash).await?
2120 }
2121
2122 Ok(tx)
2123 }
2124
2125 pub async fn transaction_by_block_hash_and_index(
2129 &self,
2130 hash: B256,
2131 index: Index,
2132 ) -> Result<Option<AnyRpcTransaction>> {
2133 node_info!("eth_getTransactionByBlockHashAndIndex");
2134 self.backend.transaction_by_block_hash_and_index(hash, index).await
2135 }
2136
2137 pub async fn transaction_by_block_number_and_index(
2141 &self,
2142 block: BlockNumber,
2143 idx: Index,
2144 ) -> Result<Option<AnyRpcTransaction>> {
2145 node_info!("eth_getTransactionByBlockNumberAndIndex");
2146 self.backend.transaction_by_block_number_and_index(block, idx).await
2147 }
2148
2149 pub async fn transaction_by_sender_and_nonce(
2156 &self,
2157 sender: Address,
2158 nonce: U256,
2159 ) -> Result<Option<AnyRpcTransaction>> {
2160 node_info!("eth_getTransactionBySenderAndNonce");
2161
2162 for pending_tx in self.pool.ready_transactions().chain(self.pool.pending_transactions()) {
2164 if U256::from(pending_tx.pending_transaction.nonce()) == nonce
2165 && *pending_tx.pending_transaction.sender() == sender
2166 {
2167 let tx = transaction_build(
2168 Some(*pending_tx.pending_transaction.hash()),
2169 pending_tx.pending_transaction.transaction.clone(),
2170 None,
2171 None,
2172 Some(self.backend.base_fee()),
2173 );
2174
2175 let WithOtherFields { inner: mut tx, other } = tx.0;
2176 let from = *pending_tx.pending_transaction.sender();
2179 tx.inner = Recovered::new_unchecked(tx.inner.into_inner(), from);
2180
2181 return Ok(Some(AnyRpcTransaction(WithOtherFields { inner: tx, other })));
2182 }
2183 }
2184
2185 let highest_nonce = self.transaction_count(sender, None).await?.saturating_to::<u64>();
2186 let target_nonce = nonce.saturating_to::<u64>();
2187
2188 if target_nonce >= highest_nonce {
2190 return Ok(None);
2191 }
2192
2193 let latest_block = self.backend.best_number();
2195 if latest_block == 0 {
2196 return Ok(None);
2197 }
2198
2199 let mut low = 1u64;
2201 let mut high = latest_block;
2202
2203 while low <= high {
2204 let mid = low + (high - low) / 2;
2205 let mid_nonce =
2206 self.transaction_count(sender, Some(mid.into())).await?.saturating_to::<u64>();
2207
2208 if mid_nonce > target_nonce {
2209 high = mid - 1;
2210 } else {
2211 low = mid + 1;
2212 }
2213 }
2214
2215 let target_block = low;
2217 if target_block <= latest_block
2218 && let Some(txs) =
2219 self.backend.mined_transactions_by_block_number(target_block.into()).await
2220 {
2221 for tx in txs {
2222 if tx.from() == sender && tx.nonce() == target_nonce {
2223 return Ok(Some(tx));
2224 }
2225 }
2226 }
2227
2228 Ok(None)
2229 }
2230
2231 pub async fn transaction_receipt(&self, hash: B256) -> Result<Option<FoundryTxReceipt>> {
2235 node_info!("eth_getTransactionReceipt");
2236 self.backend.transaction_receipt(hash).await
2237 }
2238
2239 pub async fn block_receipts(&self, number: BlockId) -> Result<Option<Vec<FoundryTxReceipt>>> {
2243 node_info!("eth_getBlockReceipts");
2244 self.backend.block_receipts(number).await
2245 }
2246
2247 pub async fn uncle_by_block_hash_and_index(
2251 &self,
2252 block_hash: B256,
2253 idx: Index,
2254 ) -> Result<Option<AnyRpcBlock>> {
2255 node_info!("eth_getUncleByBlockHashAndIndex");
2256 let number =
2257 self.backend.ensure_block_number(Some(BlockId::Hash(block_hash.into()))).await?;
2258 if let Some(fork) = self.get_fork()
2259 && fork.predates_fork_inclusive(number)
2260 {
2261 return Ok(fork.uncle_by_block_hash_and_index(block_hash, idx.into()).await?);
2262 }
2263 Ok(None)
2265 }
2266
2267 pub async fn uncle_by_block_number_and_index(
2271 &self,
2272 block_number: BlockNumber,
2273 idx: Index,
2274 ) -> Result<Option<AnyRpcBlock>> {
2275 node_info!("eth_getUncleByBlockNumberAndIndex");
2276 let number = self.backend.ensure_block_number(Some(BlockId::Number(block_number))).await?;
2277 if let Some(fork) = self.get_fork()
2278 && fork.predates_fork_inclusive(number)
2279 {
2280 return Ok(fork.uncle_by_block_number_and_index(number, idx.into()).await?);
2281 }
2282 Ok(None)
2284 }
2285
2286 pub async fn logs(&self, filter: Filter) -> Result<Vec<Log>> {
2290 node_info!("eth_getLogs");
2291 self.backend.logs(filter).await
2292 }
2293
2294 pub fn work(&self) -> Result<Work> {
2298 node_info!("eth_getWork");
2299 Err(BlockchainError::RpcUnimplemented)
2300 }
2301
2302 pub fn syncing(&self) -> Result<bool> {
2306 node_info!("eth_syncing");
2307 Ok(false)
2308 }
2309
2310 pub fn config(&self) -> Result<EthConfig> {
2321 node_info!("eth_config");
2322 Ok(EthConfig {
2323 current: EthForkConfig {
2324 activation_time: 0,
2325 blob_schedule: self.backend.blob_params(),
2326 chain_id: self.backend.env().read().evm_env.cfg_env.chain_id,
2327 fork_id: Bytes::from_static(&[0; 4]),
2328 precompiles: self.backend.precompiles(),
2329 system_contracts: self.backend.system_contracts(),
2330 },
2331 next: None,
2332 last: None,
2333 })
2334 }
2335
2336 pub fn submit_work(&self, _: B64, _: B256, _: B256) -> Result<bool> {
2340 node_info!("eth_submitWork");
2341 Err(BlockchainError::RpcUnimplemented)
2342 }
2343
2344 pub fn submit_hashrate(&self, _: U256, _: B256) -> Result<bool> {
2348 node_info!("eth_submitHashrate");
2349 Err(BlockchainError::RpcUnimplemented)
2350 }
2351
2352 pub async fn fee_history(
2356 &self,
2357 block_count: U256,
2358 newest_block: BlockNumber,
2359 reward_percentiles: Vec<f64>,
2360 ) -> Result<FeeHistory> {
2361 node_info!("eth_feeHistory");
2362 let current = self.backend.best_number();
2365 let slots_in_an_epoch = 32u64;
2366
2367 let number = match newest_block {
2368 BlockNumber::Latest | BlockNumber::Pending => current,
2369 BlockNumber::Earliest => 0,
2370 BlockNumber::Number(n) => n,
2371 BlockNumber::Safe => current.saturating_sub(slots_in_an_epoch),
2372 BlockNumber::Finalized => current.saturating_sub(slots_in_an_epoch * 2),
2373 };
2374
2375 if let Some(fork) = self.get_fork() {
2377 if fork.predates_fork_inclusive(number) {
2380 return fork
2381 .fee_history(block_count.to(), BlockNumber::Number(number), &reward_percentiles)
2382 .await
2383 .map_err(BlockchainError::AlloyForkProvider);
2384 }
2385 }
2386
2387 const MAX_BLOCK_COUNT: u64 = 1024u64;
2388 let block_count = block_count.to::<u64>().min(MAX_BLOCK_COUNT);
2389
2390 let highest = number;
2392 let lowest = highest.saturating_sub(block_count.saturating_sub(1));
2393
2394 if lowest < self.backend.best_number().saturating_sub(self.fee_history_limit) {
2396 return Err(FeeHistoryError::InvalidBlockRange.into());
2397 }
2398
2399 let mut response = FeeHistory {
2400 oldest_block: lowest,
2401 base_fee_per_gas: Vec::new(),
2402 gas_used_ratio: Vec::new(),
2403 reward: Some(Default::default()),
2404 base_fee_per_blob_gas: Default::default(),
2405 blob_gas_used_ratio: Default::default(),
2406 };
2407 let mut rewards = Vec::new();
2408
2409 {
2410 let fee_history = self.fee_history_cache.lock();
2411
2412 for n in lowest..=highest {
2414 if let Some(block) = fee_history.get(&n) {
2416 response.base_fee_per_gas.push(block.base_fee);
2417 response.base_fee_per_blob_gas.push(block.base_fee_per_blob_gas.unwrap_or(0));
2418 response.blob_gas_used_ratio.push(block.blob_gas_used_ratio);
2419 response.gas_used_ratio.push(block.gas_used_ratio);
2420
2421 if !reward_percentiles.is_empty() {
2423 let mut block_rewards = Vec::new();
2424 let resolution_per_percentile: f64 = 2.0;
2425 for p in &reward_percentiles {
2426 let p = p.clamp(0.0, 100.0);
2427 let index = ((p.round() / 2f64) * 2f64) * resolution_per_percentile;
2428 let reward = block.rewards.get(index as usize).map_or(0, |r| *r);
2429 block_rewards.push(reward);
2430 }
2431 rewards.push(block_rewards);
2432 }
2433 }
2434 }
2435 }
2436
2437 response.reward = Some(rewards);
2438
2439 response.base_fee_per_gas.push(self.backend.fees().base_fee() as u128);
2444
2445 response.base_fee_per_blob_gas.push(self.backend.fees().base_fee_per_blob_gas());
2449
2450 Ok(response)
2451 }
2452
2453 pub fn max_priority_fee_per_gas(&self) -> Result<U256> {
2460 node_info!("eth_maxPriorityFeePerGas");
2461 Ok(U256::from(self.lowest_suggestion_tip()))
2462 }
2463
2464 pub async fn new_filter(&self, filter: Filter) -> Result<String> {
2468 node_info!("eth_newFilter");
2469 let historic = if filter.block_option.get_from_block().is_some() {
2472 self.backend.logs(filter.clone()).await?
2473 } else {
2474 vec![]
2475 };
2476 let filter = EthFilter::Logs(Box::new(LogsFilter {
2477 blocks: self.new_block_notifications(),
2478 storage: self.storage_info(),
2479 filter: FilteredParams::new(Some(filter)),
2480 historic: Some(historic),
2481 }));
2482 Ok(self.filters.add_filter(filter).await)
2483 }
2484
2485 pub async fn new_block_filter(&self) -> Result<String> {
2489 node_info!("eth_newBlockFilter");
2490 let filter = EthFilter::Blocks(self.new_block_notifications());
2491 Ok(self.filters.add_filter(filter).await)
2492 }
2493
2494 pub async fn new_pending_transaction_filter(&self) -> Result<String> {
2498 node_info!("eth_newPendingTransactionFilter");
2499 let filter = EthFilter::PendingTransactions(self.new_ready_transactions());
2500 Ok(self.filters.add_filter(filter).await)
2501 }
2502
2503 pub async fn get_filter_changes(&self, id: &str) -> ResponseResult {
2507 node_info!("eth_getFilterChanges");
2508 self.filters.get_filter_changes(id).await
2509 }
2510
2511 pub async fn get_filter_logs(&self, id: &str) -> Result<Vec<Log>> {
2515 node_info!("eth_getFilterLogs");
2516 if let Some(filter) = self.filters.get_log_filter(id).await {
2517 self.backend.logs(filter).await
2518 } else {
2519 Err(BlockchainError::FilterNotFound)
2520 }
2521 }
2522
2523 pub async fn uninstall_filter(&self, id: &str) -> Result<bool> {
2525 node_info!("eth_uninstallFilter");
2526 Ok(self.filters.uninstall_filter(id).await.is_some())
2527 }
2528
2529 pub async fn raw_transaction(&self, hash: B256) -> Result<Option<Bytes>> {
2533 node_info!("debug_getRawTransaction");
2534 self.inner_raw_transaction(hash).await
2535 }
2536
2537 pub async fn raw_transaction_by_block_hash_and_index(
2541 &self,
2542 block_hash: B256,
2543 index: Index,
2544 ) -> Result<Option<Bytes>> {
2545 node_info!("eth_getRawTransactionByBlockHashAndIndex");
2546 match self.backend.transaction_by_block_hash_and_index(block_hash, index).await? {
2547 Some(tx) => self.inner_raw_transaction(tx.tx_hash()).await,
2548 None => Ok(None),
2549 }
2550 }
2551
2552 pub async fn raw_transaction_by_block_number_and_index(
2556 &self,
2557 block_number: BlockNumber,
2558 index: Index,
2559 ) -> Result<Option<Bytes>> {
2560 node_info!("eth_getRawTransactionByBlockNumberAndIndex");
2561 match self.backend.transaction_by_block_number_and_index(block_number, index).await? {
2562 Some(tx) => self.inner_raw_transaction(tx.tx_hash()).await,
2563 None => Ok(None),
2564 }
2565 }
2566
2567 pub async fn debug_trace_transaction(
2571 &self,
2572 tx_hash: B256,
2573 opts: GethDebugTracingOptions,
2574 ) -> Result<GethTrace> {
2575 node_info!("debug_traceTransaction");
2576 self.backend.debug_trace_transaction(tx_hash, opts).await
2577 }
2578
2579 pub async fn debug_trace_call(
2583 &self,
2584 request: WithOtherFields<TransactionRequest>,
2585 block_number: Option<BlockId>,
2586 opts: GethDebugTracingCallOptions,
2587 ) -> Result<GethTrace> {
2588 node_info!("debug_traceCall");
2589 let block_request = self.block_request(block_number).await?;
2590 let fees = FeeDetails::new(
2591 request.gas_price,
2592 request.max_fee_per_gas,
2593 request.max_priority_fee_per_gas,
2594 request.max_fee_per_blob_gas,
2595 )?
2596 .or_zero_fees();
2597
2598 let result: std::result::Result<GethTrace, BlockchainError> =
2599 self.backend.call_with_tracing(request, fees, Some(block_request), opts).await;
2600 result
2601 }
2602
2603 pub async fn debug_code_by_hash(
2607 &self,
2608 hash: B256,
2609 block_id: Option<BlockId>,
2610 ) -> Result<Option<Bytes>> {
2611 node_info!("debug_codeByHash");
2612 self.backend.debug_code_by_hash(hash, block_id).await
2613 }
2614
2615 pub async fn debug_db_get(&self, key: String) -> Result<Option<Bytes>> {
2620 node_info!("debug_dbGet");
2621 self.backend.debug_db_get(key).await
2622 }
2623
2624 pub async fn trace_transaction(&self, tx_hash: B256) -> Result<Vec<LocalizedTransactionTrace>> {
2628 node_info!("trace_transaction");
2629 self.backend.trace_transaction(tx_hash).await
2630 }
2631
2632 pub async fn trace_block(&self, block: BlockNumber) -> Result<Vec<LocalizedTransactionTrace>> {
2636 node_info!("trace_block");
2637 self.backend.trace_block(block).await
2638 }
2639
2640 pub async fn trace_filter(
2644 &self,
2645 filter: TraceFilter,
2646 ) -> Result<Vec<LocalizedTransactionTrace>> {
2647 node_info!("trace_filter");
2648 self.backend.trace_filter(filter).await
2649 }
2650
2651 pub async fn trace_replay_block_transactions(
2655 &self,
2656 block: BlockNumber,
2657 trace_types: HashSet<TraceType>,
2658 ) -> Result<Vec<TraceResultsWithTransactionHash>> {
2659 node_info!("trace_replayBlockTransactions");
2660 self.backend.trace_replay_block_transactions(block, trace_types).await
2661 }
2662}
2663
2664impl EthApi<FoundryNetwork> {
2667 pub async fn anvil_impersonate_account(&self, address: Address) -> Result<()> {
2671 node_info!("anvil_impersonateAccount");
2672 self.backend.impersonate(address);
2673 Ok(())
2674 }
2675
2676 pub async fn anvil_stop_impersonating_account(&self, address: Address) -> Result<()> {
2680 node_info!("anvil_stopImpersonatingAccount");
2681 self.backend.stop_impersonating(address);
2682 Ok(())
2683 }
2684
2685 pub async fn anvil_auto_impersonate_account(&self, enabled: bool) -> Result<()> {
2689 node_info!("anvil_autoImpersonateAccount");
2690 self.backend.auto_impersonate_account(enabled);
2691 Ok(())
2692 }
2693
2694 pub async fn anvil_impersonate_signature(
2696 &self,
2697 signature: Bytes,
2698 address: Address,
2699 ) -> Result<()> {
2700 node_info!("anvil_impersonateSignature");
2701 self.backend.impersonate_signature(signature, address).await
2702 }
2703
2704 pub async fn anvil_mine(&self, num_blocks: Option<U256>, interval: Option<U256>) -> Result<()> {
2708 node_info!("anvil_mine");
2709 let interval = interval.map(|i| i.to::<u64>());
2710 let blocks = num_blocks.unwrap_or(U256::from(1));
2711 if blocks.is_zero() {
2712 return Ok(());
2713 }
2714
2715 self.on_blocking_task(|this| async move {
2716 for _ in 0..blocks.to::<u64>() {
2718 if let Some(interval) = interval {
2720 this.backend.time().increase_time(interval);
2721 }
2722 this.mine_one().await;
2723 }
2724 Ok(())
2725 })
2726 .await?;
2727
2728 Ok(())
2729 }
2730
2731 async fn find_erc20_storage_slot(
2748 &self,
2749 token_address: Address,
2750 calldata: Bytes,
2751 expected_value: U256,
2752 ) -> Result<B256> {
2753 let tx = TransactionRequest::default().with_to(token_address).with_input(calldata.clone());
2754
2755 let access_list_result =
2757 self.create_access_list(WithOtherFields::new(tx.clone()), None).await?;
2758 let access_list = access_list_result.access_list;
2759
2760 for item in access_list.0 {
2763 if item.address != token_address {
2764 continue;
2765 };
2766 for slot in &item.storage_keys {
2767 let account_override = AccountOverride::default().with_state_diff(std::iter::once(
2768 (*slot, B256::from(expected_value.to_be_bytes())),
2769 ));
2770
2771 let state_override = StateOverridesBuilder::default()
2772 .append(token_address, account_override)
2773 .build();
2774
2775 let evm_override = EvmOverrides::state(Some(state_override));
2776
2777 let Ok(result) =
2778 self.call(WithOtherFields::new(tx.clone()), None, evm_override).await
2779 else {
2780 continue;
2782 };
2783
2784 let Ok(result_value) = U256::abi_decode(&result) else {
2785 continue;
2787 };
2788
2789 if result_value == expected_value {
2790 return Ok(*slot);
2791 }
2792 }
2793 }
2794
2795 Err(BlockchainError::Message("Unable to find storage slot".to_string()))
2796 }
2797
2798 pub async fn anvil_deal_erc20(
2802 &self,
2803 address: Address,
2804 token_address: Address,
2805 balance: U256,
2806 ) -> Result<()> {
2807 node_info!("anvil_dealERC20");
2808
2809 sol! {
2810 #[sol(rpc)]
2811 contract IERC20 {
2812 function balanceOf(address target) external view returns (uint256);
2813 }
2814 }
2815
2816 let calldata = IERC20::balanceOfCall { target: address }.abi_encode().into();
2817
2818 let slot =
2820 self.find_erc20_storage_slot(token_address, calldata, balance).await.map_err(|_| {
2821 BlockchainError::Message("Unable to set ERC20 balance, no slot found".to_string())
2822 })?;
2823
2824 self.anvil_set_storage_at(
2826 token_address,
2827 U256::from_be_bytes(slot.0),
2828 B256::from(balance.to_be_bytes()),
2829 )
2830 .await?;
2831
2832 Ok(())
2833 }
2834
2835 pub async fn anvil_set_erc20_allowance(
2839 &self,
2840 owner: Address,
2841 spender: Address,
2842 token_address: Address,
2843 amount: U256,
2844 ) -> Result<()> {
2845 node_info!("anvil_setERC20Allowance");
2846
2847 sol! {
2848 #[sol(rpc)]
2849 contract IERC20 {
2850 function allowance(address owner, address spender) external view returns (uint256);
2851 }
2852 }
2853
2854 let calldata = IERC20::allowanceCall { owner, spender }.abi_encode().into();
2855
2856 let slot =
2858 self.find_erc20_storage_slot(token_address, calldata, amount).await.map_err(|_| {
2859 BlockchainError::Message("Unable to set ERC20 allowance, no slot found".to_string())
2860 })?;
2861
2862 self.anvil_set_storage_at(
2864 token_address,
2865 U256::from_be_bytes(slot.0),
2866 B256::from(amount.to_be_bytes()),
2867 )
2868 .await?;
2869
2870 Ok(())
2871 }
2872
2873 pub async fn anvil_reorg(&self, options: ReorgOptions) -> Result<()> {
2887 node_info!("anvil_reorg");
2888 let depth = options.depth;
2889 let tx_block_pairs = options.tx_block_pairs;
2890
2891 let current_height = self.backend.best_number();
2893 let common_height = current_height.checked_sub(depth).ok_or(BlockchainError::RpcError(
2894 RpcError::invalid_params(format!(
2895 "Reorg depth must not exceed current chain height: current height {current_height}, depth {depth}"
2896 )),
2897 ))?;
2898
2899 let common_block =
2901 self.backend.get_block(common_height).ok_or(BlockchainError::BlockNotFound)?;
2902
2903 let block_pool_txs = if tx_block_pairs.is_empty() {
2906 HashMap::default()
2907 } else {
2908 let mut pairs = tx_block_pairs;
2909
2910 if let Some((_, num)) = pairs.iter().find(|(_, num)| *num >= depth) {
2912 return Err(BlockchainError::RpcError(RpcError::invalid_params(format!(
2913 "Block number for reorg tx will exceed the reorged chain height. Block number {num} must not exceed (depth-1) {}",
2914 depth - 1
2915 ))));
2916 }
2917
2918 pairs.sort_by_key(|a| a.1);
2920
2921 let mut nonces: HashMap<Address, u64> = HashMap::default();
2924
2925 let mut txs: HashMap<u64, Vec<Arc<PoolTransaction<FoundryTxEnvelope>>>> =
2926 HashMap::default();
2927 for pair in pairs {
2928 let (tx_data, block_index) = pair;
2929
2930 let pending = match tx_data {
2931 TransactionData::Raw(bytes) => {
2932 let mut data = bytes.as_ref();
2933 let decoded = FoundryTxEnvelope::decode_2718(&mut data)
2934 .map_err(|_| BlockchainError::FailedToDecodeSignedTransaction)?;
2935 PendingTransaction::new(decoded)?
2936 }
2937
2938 TransactionData::JSON(request) => {
2939 let from = request.from.map(Ok).unwrap_or_else(|| {
2940 self.accounts()?
2941 .first()
2942 .copied()
2943 .ok_or(BlockchainError::NoSignerAvailable)
2944 })?;
2945
2946 let curr_nonce = nonces.entry(from).or_insert(
2948 self.get_transaction_count(
2949 from,
2950 Some(common_block.header.number().into()),
2951 )
2952 .await?,
2953 );
2954
2955 let typed_tx = self.build_tx_request(request.into(), *curr_nonce).await?;
2957
2958 *curr_nonce += 1;
2960
2961 if self.is_impersonated(from) {
2963 let transaction = sign::build_impersonated(typed_tx);
2964 self.ensure_typed_transaction_supported(&transaction)?;
2965 PendingTransaction::with_impersonated(transaction, from)
2966 } else {
2967 let transaction = self.sign_request(&from, typed_tx)?;
2968 self.ensure_typed_transaction_supported(&transaction)?;
2969 PendingTransaction::new(transaction)?
2970 }
2971 }
2972 };
2973
2974 let pooled = PoolTransaction::new(pending);
2975 txs.entry(block_index).or_default().push(Arc::new(pooled));
2976 }
2977
2978 txs
2979 };
2980
2981 self.backend.reorg(depth, block_pool_txs, common_block).await?;
2982 Ok(())
2983 }
2984
2985 pub async fn evm_mine(&self, opts: Option<MineOptions>) -> Result<String> {
2992 node_info!("evm_mine");
2993
2994 self.do_evm_mine(opts).await?;
2995
2996 Ok("0x0".to_string())
2997 }
2998
2999 pub async fn evm_mine_detailed(&self, opts: Option<MineOptions>) -> Result<Vec<AnyRpcBlock>> {
3009 node_info!("evm_mine_detailed");
3010
3011 let mined_blocks = self.do_evm_mine(opts).await?;
3012
3013 let mut blocks = Vec::with_capacity(mined_blocks as usize);
3014
3015 let latest = self.backend.best_number();
3016 for offset in (0..mined_blocks).rev() {
3017 let block_num = latest - offset;
3018 if let Some(mut block) =
3019 self.backend.block_by_number_full(BlockNumber::Number(block_num)).await?
3020 {
3021 let block_txs = match block.transactions_mut() {
3022 BlockTransactions::Full(txs) => txs,
3023 BlockTransactions::Hashes(_) | BlockTransactions::Uncle => unreachable!(),
3024 };
3025 for tx in block_txs.iter_mut() {
3026 if let Some(receipt) = self.backend.mined_transaction_receipt(tx.tx_hash())
3027 && let Some(output) = receipt.out
3028 {
3029 if !receipt.inner.as_ref().status()
3031 && let Some(reason) = RevertDecoder::new().maybe_decode(&output, None)
3032 {
3033 tx.other.insert(
3034 "revertReason".to_string(),
3035 serde_json::to_value(reason).expect("Infallible"),
3036 );
3037 }
3038 tx.other.insert(
3039 "output".to_string(),
3040 serde_json::to_value(output).expect("Infallible"),
3041 );
3042 }
3043 }
3044 block.transactions = BlockTransactions::Full(block_txs.to_vec());
3045 blocks.push(block);
3046 }
3047 }
3048
3049 Ok(blocks)
3050 }
3051
3052 pub async fn eth_send_unsigned_transaction(
3056 &self,
3057 request: WithOtherFields<TransactionRequest>,
3058 ) -> Result<TxHash> {
3059 node_info!("eth_sendUnsignedTransaction");
3060 let from = request.from.ok_or(BlockchainError::NoSignerAvailable)?;
3062
3063 let (nonce, on_chain_nonce) = self.request_nonce(&request, from).await?;
3064
3065 let typed_tx = self.build_tx_request(request, nonce).await?;
3066
3067 let transaction = sign::build_impersonated(typed_tx);
3068
3069 self.ensure_typed_transaction_supported(&transaction)?;
3070
3071 let pending_transaction = PendingTransaction::with_impersonated(transaction, from);
3072
3073 self.backend.validate_pool_transaction(&pending_transaction).await?;
3075
3076 let requires = required_marker(nonce, on_chain_nonce, from);
3077 let provides = vec![to_marker(nonce, from)];
3078
3079 self.add_pending_transaction(pending_transaction, requires, provides)
3080 }
3081
3082 pub async fn txpool_inspect(&self) -> Result<TxpoolInspect> {
3089 node_info!("txpool_inspect");
3090 let mut inspect = TxpoolInspect::default();
3091
3092 fn convert(tx: Arc<PoolTransaction<FoundryTxEnvelope>>) -> TxpoolInspectSummary {
3093 let tx = &tx.pending_transaction.transaction;
3094 let to = tx.to();
3095 let gas_price = tx.max_fee_per_gas();
3096 let value = tx.value();
3097 let gas = tx.gas_limit();
3098 TxpoolInspectSummary { to, value, gas, gas_price }
3099 }
3100
3101 for pending in self.pool.ready_transactions() {
3108 let entry = inspect.pending.entry(*pending.pending_transaction.sender()).or_default();
3109 let key = pending.pending_transaction.nonce().to_string();
3110 entry.insert(key, convert(pending));
3111 }
3112 for queued in self.pool.pending_transactions() {
3113 let entry = inspect.pending.entry(*queued.pending_transaction.sender()).or_default();
3114 let key = queued.pending_transaction.nonce().to_string();
3115 entry.insert(key, convert(queued));
3116 }
3117 Ok(inspect)
3118 }
3119
3120 pub async fn txpool_content(&self) -> Result<TxpoolContent<AnyRpcTransaction>> {
3127 node_info!("txpool_content");
3128 let mut content = TxpoolContent::<AnyRpcTransaction>::default();
3129 fn convert(tx: Arc<PoolTransaction<FoundryTxEnvelope>>) -> Result<AnyRpcTransaction> {
3130 let from = *tx.pending_transaction.sender();
3131 let tx = transaction_build(
3132 Some(tx.hash()),
3133 tx.pending_transaction.transaction.clone(),
3134 None,
3135 None,
3136 None,
3137 );
3138
3139 let WithOtherFields { inner: mut tx, other } = tx.0;
3140
3141 tx.inner = Recovered::new_unchecked(tx.inner.into_inner(), from);
3144
3145 let tx = AnyRpcTransaction(WithOtherFields { inner: tx, other });
3146
3147 Ok(tx)
3148 }
3149
3150 for pending in self.pool.ready_transactions() {
3151 let entry = content.pending.entry(*pending.pending_transaction.sender()).or_default();
3152 let key = pending.pending_transaction.nonce().to_string();
3153 entry.insert(key, convert(pending)?);
3154 }
3155 for queued in self.pool.pending_transactions() {
3156 let entry = content.pending.entry(*queued.pending_transaction.sender()).or_default();
3157 let key = queued.pending_transaction.nonce().to_string();
3158 entry.insert(key, convert(queued)?);
3159 }
3160
3161 Ok(content)
3162 }
3163}
3164
3165impl EthApi<FoundryNetwork> {
3166 async fn do_evm_mine(&self, opts: Option<MineOptions>) -> Result<u64> {
3168 let mut blocks_to_mine = 1u64;
3169
3170 if let Some(opts) = opts {
3171 let timestamp = match opts {
3172 MineOptions::Timestamp(timestamp) => timestamp,
3173 MineOptions::Options { timestamp, blocks } => {
3174 if let Some(blocks) = blocks {
3175 blocks_to_mine = blocks;
3176 }
3177 timestamp
3178 }
3179 };
3180 if let Some(timestamp) = timestamp {
3181 self.evm_set_next_block_timestamp(timestamp)?;
3183 }
3184 }
3185
3186 self.on_blocking_task(|this| async move {
3189 for _ in 0..blocks_to_mine {
3191 this.mine_one().await;
3192 }
3193 Ok(())
3194 })
3195 .await?;
3196
3197 Ok(blocks_to_mine)
3198 }
3199
3200 async fn do_estimate_gas(
3201 &self,
3202 request: WithOtherFields<TransactionRequest>,
3203 block_number: Option<BlockId>,
3204 overrides: EvmOverrides,
3205 ) -> Result<u128> {
3206 let block_request = self.block_request(block_number).await?;
3207 if let BlockRequest::Number(number) = block_request
3209 && let Some(fork) = self.get_fork()
3210 && fork.predates_fork(number)
3211 {
3212 if overrides.has_state() || overrides.has_block() {
3213 return Err(BlockchainError::EvmOverrideError(
3214 "not available on past forked blocks".to_string(),
3215 ));
3216 }
3217 return Ok(fork.estimate_gas(&request, Some(number.into())).await?);
3218 }
3219
3220 self.on_blocking_task(|this| async move {
3223 this.backend
3224 .with_database_at(Some(block_request), |state, mut block| {
3225 let mut cache_db = CacheDB::new(state);
3226 if let Some(state_overrides) = overrides.state {
3227 apply_state_overrides(
3228 state_overrides.into_iter().collect(),
3229 &mut cache_db,
3230 )?;
3231 }
3232 if let Some(block_overrides) = overrides.block {
3233 cache_db.apply_block_overrides(*block_overrides, &mut block);
3234 }
3235 this.do_estimate_gas_with_state(request, &cache_db, block)
3236 })
3237 .await?
3238 })
3239 .await
3240 }
3241
3242 fn transaction_priority(&self, tx: &FoundryTxEnvelope) -> TransactionPriority {
3244 self.transaction_order.read().priority(tx)
3245 }
3246
3247 pub fn full_pending_transactions(&self) -> UnboundedReceiver<AnyRpcTransaction> {
3249 let (tx, rx) = unbounded_channel();
3250 let mut hashes = self.new_ready_transactions();
3251
3252 let this = self.clone();
3253
3254 tokio::spawn(async move {
3255 while let Some(hash) = hashes.next().await {
3256 if let Ok(Some(txn)) = this.transaction_by_hash(hash).await
3257 && tx.send(txn).is_err()
3258 {
3259 break;
3260 }
3261 }
3262 });
3263
3264 rx
3265 }
3266
3267 pub async fn mine_one(&self) {
3269 let transactions = self.pool.ready_transactions().collect::<Vec<_>>();
3270 let outcome = self.backend.mine_block(transactions).await;
3271
3272 trace!(target: "node", blocknumber = ?outcome.block_number, "mined block");
3273 self.pool.on_mined_block(outcome);
3274 }
3275
3276 async fn pending_block(&self) -> AnyRpcBlock {
3278 let transactions = self.pool.ready_transactions().collect::<Vec<_>>();
3279 let info = self.backend.pending_block(transactions).await;
3280 self.backend.convert_block(info.block)
3281 }
3282
3283 async fn pending_block_full(&self) -> Option<AnyRpcBlock> {
3285 let transactions = self.pool.ready_transactions().collect::<Vec<_>>();
3286 let BlockInfo { block, transactions, receipts: _ } =
3287 self.backend.pending_block(transactions).await;
3288
3289 let mut partial_block = self.backend.convert_block(block.clone());
3290
3291 let mut block_transactions = Vec::with_capacity(block.body.transactions.len());
3292 let base_fee = self.backend.base_fee();
3293
3294 for info in transactions {
3295 let tx = block.body.transactions.get(info.transaction_index as usize)?.clone();
3296
3297 let tx = transaction_build(
3298 Some(info.transaction_hash),
3299 tx,
3300 Some(&block),
3301 Some(info),
3302 Some(base_fee),
3303 );
3304 block_transactions.push(tx);
3305 }
3306
3307 partial_block.transactions = BlockTransactions::from(block_transactions);
3308
3309 Some(partial_block)
3310 }
3311
3312 async fn build_tx_request(
3315 &self,
3316 request: WithOtherFields<TransactionRequest>,
3317 nonce: u64,
3318 ) -> Result<FoundryTypedTx> {
3319 let mut request = Into::<FoundryTransactionRequest>::into(request);
3320 let from = request.from().or(self.accounts()?.first().copied());
3321
3322 request.chain_id().is_none().then(|| request.set_chain_id(self.chain_id()));
3324 request.nonce().is_none().then(|| request.set_nonce(nonce));
3325 request.kind().is_none().then(|| request.set_kind(TxKind::default()));
3326 if request.gas_limit().is_none() {
3327 request.set_gas_limit(
3328 self.do_estimate_gas(
3329 request.as_ref().clone().into(),
3330 None,
3331 EvmOverrides::default(),
3332 )
3333 .await
3334 .map(|v| v as u64)
3335 .unwrap_or(self.backend.gas_limit()),
3336 );
3337 }
3338
3339 if let Err((tx_type, _)) = request.missing_keys() {
3341 if matches!(tx_type, FoundryTxType::Legacy | FoundryTxType::Eip2930) {
3342 request.gas_price().is_none().then(|| request.set_gas_price(self.gas_price()));
3343 }
3344 if tx_type == FoundryTxType::Eip2930 {
3345 request
3346 .access_list()
3347 .is_none()
3348 .then(|| request.set_access_list(Default::default()));
3349 }
3350 if matches!(
3351 tx_type,
3352 FoundryTxType::Eip1559 | FoundryTxType::Eip4844 | FoundryTxType::Eip7702
3353 ) {
3354 request
3355 .max_fee_per_gas()
3356 .is_none()
3357 .then(|| request.set_max_fee_per_gas(self.gas_price()));
3358 request
3359 .max_priority_fee_per_gas()
3360 .is_none()
3361 .then(|| request.set_max_priority_fee_per_gas(MIN_SUGGESTED_PRIORITY_FEE));
3362 }
3363 if tx_type == FoundryTxType::Eip4844 {
3364 request.as_ref().max_fee_per_blob_gas().is_none().then(|| {
3365 request.as_mut().set_max_fee_per_blob_gas(
3366 self.backend.fees().get_next_block_blob_base_fee_per_gas(),
3367 )
3368 });
3369 }
3370 }
3371
3372 match request
3373 .build_unsigned()
3374 .map_err(|e| BlockchainError::InvalidTransactionRequest(e.to_string()))?
3375 {
3376 FoundryTypedTx::Eip4844(TxEip4844Variant::TxEip4844(_))
3377 if !self.backend.skip_blob_validation(from) =>
3378 {
3379 Err(BlockchainError::FailedToDecodeTransaction)
3381 }
3382 res => Ok(res),
3383 }
3384 }
3385
3386 async fn get_transaction_count(
3388 &self,
3389 address: Address,
3390 block_number: Option<BlockId>,
3391 ) -> Result<u64> {
3392 let block_request = self.block_request(block_number).await?;
3393
3394 if let BlockRequest::Number(number) = block_request
3395 && let Some(fork) = self.get_fork()
3396 && fork.predates_fork(number)
3397 {
3398 return Ok(fork.get_nonce(address, number).await?);
3399 }
3400
3401 self.backend.get_nonce(address, block_request).await
3402 }
3403
3404 async fn request_nonce(
3412 &self,
3413 request: &TransactionRequest,
3414 from: Address,
3415 ) -> Result<(u64, u64)> {
3416 let highest_nonce =
3417 self.get_transaction_count(from, Some(BlockId::Number(BlockNumber::Pending))).await?;
3418 let nonce = request.nonce.unwrap_or(highest_nonce);
3419
3420 Ok((nonce, highest_nonce))
3421 }
3422
3423 fn add_pending_transaction(
3425 &self,
3426 pending_transaction: PendingTransaction<FoundryTxEnvelope>,
3427 requires: Vec<TxMarker>,
3428 provides: Vec<TxMarker>,
3429 ) -> Result<TxHash> {
3430 let from = *pending_transaction.sender();
3431 let priority = self.transaction_priority(&pending_transaction.transaction);
3432 let pool_transaction =
3433 PoolTransaction { requires, provides, pending_transaction, priority };
3434 let tx = self.pool.add_transaction(pool_transaction)?;
3435 trace!(target: "node", "Added transaction: [{:?}] sender={:?}", tx.hash(), from);
3436 Ok(*tx.hash())
3437 }
3438
3439 fn ensure_typed_transaction_supported(&self, tx: &FoundryTxEnvelope) -> Result<()> {
3441 match &tx {
3442 FoundryTxEnvelope::Eip2930(_) => self.backend.ensure_eip2930_active(),
3443 FoundryTxEnvelope::Eip1559(_) => self.backend.ensure_eip1559_active(),
3444 FoundryTxEnvelope::Eip4844(_) => self.backend.ensure_eip4844_active(),
3445 FoundryTxEnvelope::Eip7702(_) => self.backend.ensure_eip7702_active(),
3446 FoundryTxEnvelope::Deposit(_) => self.backend.ensure_op_deposits_active(),
3447 FoundryTxEnvelope::Legacy(_) => Ok(()),
3448 FoundryTxEnvelope::Tempo(_) => todo!(),
3450 }
3451 }
3452}
3453
3454fn required_marker(provided_nonce: u64, on_chain_nonce: u64, from: Address) -> Vec<TxMarker> {
3455 if provided_nonce == on_chain_nonce {
3456 return Vec::new();
3457 }
3458 let prev_nonce = provided_nonce.saturating_sub(1);
3459 if on_chain_nonce <= prev_nonce { vec![to_marker(prev_nonce, from)] } else { Vec::new() }
3460}
3461
3462fn convert_transact_out(out: &Option<Output>) -> Bytes {
3463 match out {
3464 None => Default::default(),
3465 Some(Output::Call(out)) => out.to_vec().into(),
3466 Some(Output::Create(out, _)) => out.to_vec().into(),
3467 }
3468}
3469
3470fn ensure_return_ok(exit: InstructionResult, out: &Option<Output>) -> Result<Bytes> {
3472 let out = convert_transact_out(out);
3473 match exit {
3474 return_ok!() => Ok(out),
3475 return_revert!() => Err(InvalidTransactionError::Revert(Some(out)).into()),
3476 reason => Err(BlockchainError::EvmError(reason)),
3477 }
3478}
3479
3480fn determine_base_gas_by_kind(request: &WithOtherFields<TransactionRequest>) -> u128 {
3482 match request.kind() {
3483 Some(TxKind::Call(_)) => {
3484 MIN_TRANSACTION_GAS
3485 + request.inner().authorization_list.as_ref().map_or(0, |auths_list| {
3486 auths_list.len() as u128 * PER_EMPTY_ACCOUNT_COST as u128
3487 })
3488 }
3489 Some(TxKind::Create) => MIN_CREATE_GAS,
3490 None => MIN_CREATE_GAS,
3492 }
3493}
3494
3495enum GasEstimationCallResult {
3497 Success(u128),
3498 OutOfGas,
3499 Revert(Option<Bytes>),
3500 EvmError(InstructionResult),
3501}
3502
3503impl TryFrom<Result<(InstructionResult, Option<Output>, u128, State)>> for GasEstimationCallResult {
3507 type Error = BlockchainError;
3508
3509 fn try_from(res: Result<(InstructionResult, Option<Output>, u128, State)>) -> Result<Self> {
3510 match res {
3511 Err(BlockchainError::InvalidTransaction(InvalidTransactionError::GasTooHigh(_))) => {
3513 Ok(Self::OutOfGas)
3514 }
3515 Err(err) => Err(err),
3516 Ok((exit, output, gas, _)) => match exit {
3517 return_ok!() => Ok(Self::Success(gas)),
3518
3519 InstructionResult::Revert => Ok(Self::Revert(output.map(|o| o.into_data()))),
3521 InstructionResult::CallTooDeep
3522 | InstructionResult::OutOfFunds
3523 | InstructionResult::CreateInitCodeStartingEF00
3524 | InstructionResult::InvalidEOFInitCode
3525 | InstructionResult::InvalidExtDelegateCallTarget => Ok(Self::EvmError(exit)),
3526
3527 InstructionResult::OutOfGas
3529 | InstructionResult::MemoryOOG
3530 | InstructionResult::MemoryLimitOOG
3531 | InstructionResult::PrecompileOOG
3532 | InstructionResult::InvalidOperandOOG
3533 | InstructionResult::ReentrancySentryOOG => Ok(Self::OutOfGas),
3534
3535 InstructionResult::OpcodeNotFound
3537 | InstructionResult::CallNotAllowedInsideStatic
3538 | InstructionResult::StateChangeDuringStaticCall
3539 | InstructionResult::InvalidFEOpcode
3540 | InstructionResult::InvalidJump
3541 | InstructionResult::NotActivated
3542 | InstructionResult::StackUnderflow
3543 | InstructionResult::StackOverflow
3544 | InstructionResult::OutOfOffset
3545 | InstructionResult::CreateCollision
3546 | InstructionResult::OverflowPayment
3547 | InstructionResult::PrecompileError
3548 | InstructionResult::NonceOverflow
3549 | InstructionResult::CreateContractSizeLimit
3550 | InstructionResult::CreateContractStartingWithEF
3551 | InstructionResult::CreateInitCodeSizeLimit
3552 | InstructionResult::FatalExternalError => Ok(Self::EvmError(exit)),
3553 },
3554 }
3555 }
3556}