1use super::{
2 backend::{
3 db::MaybeFullDatabase,
4 mem::{BlockRequest, State, state},
5 },
6 sign::build_typed_transaction,
7};
8use crate::{
9 ClientFork, LoggingManager, Miner, MiningMode, StorageInfo,
10 eth::{
11 backend::{
12 self,
13 db::SerializableState,
14 mem::{MIN_CREATE_GAS, MIN_TRANSACTION_GAS},
15 notifications::NewBlockNotifications,
16 validate::TransactionValidator,
17 },
18 error::{
19 BlockchainError, FeeHistoryError, InvalidTransactionError, Result, ToRpcResponseResult,
20 },
21 fees::{FeeDetails, FeeHistoryCache, MIN_SUGGESTED_PRIORITY_FEE},
22 macros::node_info,
23 miner::FixedBlockTimeMiner,
24 pool::{
25 Pool,
26 transactions::{
27 PoolTransaction, TransactionOrder, TransactionPriority, TxMarker, to_marker,
28 },
29 },
30 sign::{self, Signer},
31 },
32 filter::{EthFilter, Filters, LogsFilter},
33 mem::transaction_build,
34};
35use alloy_consensus::{
36 Account, Blob,
37 transaction::{Recovered, eip4844::TxEip4844Variant},
38};
39use alloy_dyn_abi::TypedData;
40use alloy_eips::eip2718::Encodable2718;
41use alloy_network::{
42 AnyRpcBlock, AnyRpcTransaction, BlockResponse, Ethereum, NetworkWallet, TransactionBuilder,
43 TransactionResponse, eip2718::Decodable2718,
44};
45use alloy_primitives::{
46 Address, B64, B256, Bytes, Signature, TxHash, TxKind, U64, U256,
47 map::{HashMap, HashSet},
48};
49use alloy_provider::utils::{
50 EIP1559_FEE_ESTIMATION_PAST_BLOCKS, EIP1559_FEE_ESTIMATION_REWARD_PERCENTILE,
51 eip1559_default_estimator,
52};
53use alloy_rpc_types::{
54 AccessList, AccessListResult, BlockId, BlockNumberOrTag as BlockNumber, BlockTransactions,
55 EIP1186AccountProofResponse, FeeHistory, Filter, FilteredParams, Index, Log, Work,
56 anvil::{
57 ForkedNetwork, Forking, Metadata, MineOptions, NodeEnvironment, NodeForkConfig, NodeInfo,
58 },
59 request::TransactionRequest,
60 simulate::{SimulatePayload, SimulatedBlock},
61 state::{AccountOverride, EvmOverrides, StateOverridesBuilder},
62 trace::{
63 filter::TraceFilter,
64 geth::{GethDebugTracingCallOptions, GethDebugTracingOptions, GethTrace},
65 parity::LocalizedTransactionTrace,
66 },
67 txpool::{TxpoolContent, TxpoolInspect, TxpoolInspectSummary, TxpoolStatus},
68};
69use alloy_serde::WithOtherFields;
70use alloy_sol_types::{SolCall, SolValue, sol};
71use alloy_transport::TransportErrorKind;
72use anvil_core::{
73 eth::{
74 EthRequest,
75 block::BlockInfo,
76 transaction::{
77 PendingTransaction, ReceiptResponse, TypedTransaction, TypedTransactionRequest,
78 transaction_request_to_typed,
79 },
80 wallet::{WalletCapabilities, WalletError},
81 },
82 types::{ReorgOptions, TransactionData},
83};
84use anvil_rpc::{error::RpcError, response::ResponseResult};
85use foundry_common::provider::ProviderBuilder;
86use foundry_evm::{backend::DatabaseError, decode::RevertDecoder};
87use futures::{
88 StreamExt,
89 channel::{mpsc::Receiver, oneshot},
90};
91use parking_lot::RwLock;
92use revm::{
93 bytecode::Bytecode,
94 context::BlockEnv,
95 context_interface::{block::BlobExcessGasAndPrice, result::Output},
96 database::{CacheDB, DatabaseRef},
97 interpreter::{InstructionResult, return_ok, return_revert},
98 primitives::eip7702::PER_EMPTY_ACCOUNT_COST,
99};
100use std::{sync::Arc, time::Duration};
101use tokio::sync::mpsc::{UnboundedReceiver, unbounded_channel};
102
103pub const CLIENT_VERSION: &str = concat!("anvil/v", env!("CARGO_PKG_VERSION"));
105
106#[derive(Clone)]
110pub struct EthApi {
111 pool: Arc<Pool>,
113 pub backend: Arc<backend::mem::Backend>,
116 is_mining: bool,
118 signers: Arc<Vec<Box<dyn Signer>>>,
120 fee_history_cache: FeeHistoryCache,
122 fee_history_limit: u64,
124 miner: Miner,
129 logger: LoggingManager,
131 filters: Filters,
133 transaction_order: Arc<RwLock<TransactionOrder>>,
135 net_listening: bool,
137 instance_id: Arc<RwLock<B256>>,
139}
140
141impl EthApi {
142 #[expect(clippy::too_many_arguments)]
144 pub fn new(
145 pool: Arc<Pool>,
146 backend: Arc<backend::mem::Backend>,
147 signers: Arc<Vec<Box<dyn Signer>>>,
148 fee_history_cache: FeeHistoryCache,
149 fee_history_limit: u64,
150 miner: Miner,
151 logger: LoggingManager,
152 filters: Filters,
153 transactions_order: TransactionOrder,
154 ) -> Self {
155 Self {
156 pool,
157 backend,
158 is_mining: true,
159 signers,
160 fee_history_cache,
161 fee_history_limit,
162 miner,
163 logger,
164 filters,
165 net_listening: true,
166 transaction_order: Arc::new(RwLock::new(transactions_order)),
167 instance_id: Arc::new(RwLock::new(B256::random())),
168 }
169 }
170
171 pub async fn execute(&self, request: EthRequest) -> ResponseResult {
173 trace!(target: "rpc::api", "executing eth request");
174 let response = match request.clone() {
175 EthRequest::Web3ClientVersion(()) => self.client_version().to_rpc_result(),
176 EthRequest::Web3Sha3(content) => self.sha3(content).to_rpc_result(),
177 EthRequest::EthGetAccount(addr, block) => {
178 self.get_account(addr, block).await.to_rpc_result()
179 }
180 EthRequest::EthGetAccountInfo(addr, block) => {
181 self.get_account_info(addr, block).await.to_rpc_result()
182 }
183 EthRequest::EthGetBalance(addr, block) => {
184 self.balance(addr, block).await.to_rpc_result()
185 }
186 EthRequest::EthGetTransactionByHash(hash) => {
187 self.transaction_by_hash(hash).await.to_rpc_result()
188 }
189 EthRequest::EthSendTransaction(request) => {
190 self.send_transaction(*request).await.to_rpc_result()
191 }
192 EthRequest::EthSendTransactionSync(request) => {
193 self.send_transaction_sync(*request).await.to_rpc_result()
194 }
195 EthRequest::EthChainId(_) => self.eth_chain_id().to_rpc_result(),
196 EthRequest::EthNetworkId(_) => self.network_id().to_rpc_result(),
197 EthRequest::NetListening(_) => self.net_listening().to_rpc_result(),
198 EthRequest::EthGasPrice(_) => self.eth_gas_price().to_rpc_result(),
199 EthRequest::EthMaxPriorityFeePerGas(_) => {
200 self.gas_max_priority_fee_per_gas().to_rpc_result()
201 }
202 EthRequest::EthBlobBaseFee(_) => self.blob_base_fee().to_rpc_result(),
203 EthRequest::EthAccounts(_) => self.accounts().to_rpc_result(),
204 EthRequest::EthBlockNumber(_) => self.block_number().to_rpc_result(),
205 EthRequest::EthGetStorageAt(addr, slot, block) => {
206 self.storage_at(addr, slot, block).await.to_rpc_result()
207 }
208 EthRequest::EthGetBlockByHash(hash, full) => {
209 if full {
210 self.block_by_hash_full(hash).await.to_rpc_result()
211 } else {
212 self.block_by_hash(hash).await.to_rpc_result()
213 }
214 }
215 EthRequest::EthGetBlockByNumber(num, full) => {
216 if full {
217 self.block_by_number_full(num).await.to_rpc_result()
218 } else {
219 self.block_by_number(num).await.to_rpc_result()
220 }
221 }
222 EthRequest::EthGetTransactionCount(addr, block) => {
223 self.transaction_count(addr, block).await.to_rpc_result()
224 }
225 EthRequest::EthGetTransactionCountByHash(hash) => {
226 self.block_transaction_count_by_hash(hash).await.to_rpc_result()
227 }
228 EthRequest::EthGetTransactionCountByNumber(num) => {
229 self.block_transaction_count_by_number(num).await.to_rpc_result()
230 }
231 EthRequest::EthGetUnclesCountByHash(hash) => {
232 self.block_uncles_count_by_hash(hash).await.to_rpc_result()
233 }
234 EthRequest::EthGetUnclesCountByNumber(num) => {
235 self.block_uncles_count_by_number(num).await.to_rpc_result()
236 }
237 EthRequest::EthGetCodeAt(addr, block) => {
238 self.get_code(addr, block).await.to_rpc_result()
239 }
240 EthRequest::EthGetProof(addr, keys, block) => {
241 self.get_proof(addr, keys, block).await.to_rpc_result()
242 }
243 EthRequest::EthSign(addr, content) => self.sign(addr, content).await.to_rpc_result(),
244 EthRequest::PersonalSign(content, addr) => {
245 self.sign(addr, content).await.to_rpc_result()
246 }
247 EthRequest::EthSignTransaction(request) => {
248 self.sign_transaction(*request).await.to_rpc_result()
249 }
250 EthRequest::EthSignTypedData(addr, data) => {
251 self.sign_typed_data(addr, data).await.to_rpc_result()
252 }
253 EthRequest::EthSignTypedDataV3(addr, data) => {
254 self.sign_typed_data_v3(addr, data).await.to_rpc_result()
255 }
256 EthRequest::EthSignTypedDataV4(addr, data) => {
257 self.sign_typed_data_v4(addr, &data).await.to_rpc_result()
258 }
259 EthRequest::EthSendRawTransaction(tx) => {
260 self.send_raw_transaction(tx).await.to_rpc_result()
261 }
262 EthRequest::EthSendRawTransactionSync(tx) => {
263 self.send_raw_transaction_sync(tx).await.to_rpc_result()
264 }
265 EthRequest::EthCall(call, block, state_override, block_overrides) => self
266 .call(call, block, EvmOverrides::new(state_override, block_overrides))
267 .await
268 .to_rpc_result(),
269 EthRequest::EthSimulateV1(simulation, block) => {
270 self.simulate_v1(simulation, block).await.to_rpc_result()
271 }
272 EthRequest::EthCreateAccessList(call, block) => {
273 self.create_access_list(call, block).await.to_rpc_result()
274 }
275 EthRequest::EthEstimateGas(call, block, state_override, block_overrides) => self
276 .estimate_gas(call, block, EvmOverrides::new(state_override, block_overrides))
277 .await
278 .to_rpc_result(),
279 EthRequest::EthGetRawTransactionByHash(hash) => {
280 self.raw_transaction(hash).await.to_rpc_result()
281 }
282 EthRequest::GetBlobByHash(hash) => {
283 self.anvil_get_blob_by_versioned_hash(hash).to_rpc_result()
284 }
285 EthRequest::GetBlobByTransactionHash(hash) => {
286 self.anvil_get_blob_by_tx_hash(hash).to_rpc_result()
287 }
288 EthRequest::EthGetRawTransactionByBlockHashAndIndex(hash, index) => {
289 self.raw_transaction_by_block_hash_and_index(hash, index).await.to_rpc_result()
290 }
291 EthRequest::EthGetRawTransactionByBlockNumberAndIndex(num, index) => {
292 self.raw_transaction_by_block_number_and_index(num, index).await.to_rpc_result()
293 }
294 EthRequest::EthGetTransactionByBlockHashAndIndex(hash, index) => {
295 self.transaction_by_block_hash_and_index(hash, index).await.to_rpc_result()
296 }
297 EthRequest::EthGetTransactionByBlockNumberAndIndex(num, index) => {
298 self.transaction_by_block_number_and_index(num, index).await.to_rpc_result()
299 }
300 EthRequest::EthGetTransactionReceipt(tx) => {
301 self.transaction_receipt(tx).await.to_rpc_result()
302 }
303 EthRequest::EthGetBlockReceipts(number) => {
304 self.block_receipts(number).await.to_rpc_result()
305 }
306 EthRequest::EthGetUncleByBlockHashAndIndex(hash, index) => {
307 self.uncle_by_block_hash_and_index(hash, index).await.to_rpc_result()
308 }
309 EthRequest::EthGetUncleByBlockNumberAndIndex(num, index) => {
310 self.uncle_by_block_number_and_index(num, index).await.to_rpc_result()
311 }
312 EthRequest::EthGetLogs(filter) => self.logs(filter).await.to_rpc_result(),
313 EthRequest::EthGetWork(_) => self.work().to_rpc_result(),
314 EthRequest::EthSyncing(_) => self.syncing().to_rpc_result(),
315 EthRequest::EthSubmitWork(nonce, pow, digest) => {
316 self.submit_work(nonce, pow, digest).to_rpc_result()
317 }
318 EthRequest::EthSubmitHashRate(rate, id) => {
319 self.submit_hashrate(rate, id).to_rpc_result()
320 }
321 EthRequest::EthFeeHistory(count, newest, reward_percentiles) => {
322 self.fee_history(count, newest, reward_percentiles).await.to_rpc_result()
323 }
324 EthRequest::DebugGetRawTransaction(hash) => {
326 self.raw_transaction(hash).await.to_rpc_result()
327 }
328 EthRequest::DebugTraceTransaction(tx, opts) => {
330 self.debug_trace_transaction(tx, opts).await.to_rpc_result()
331 }
332 EthRequest::DebugTraceCall(tx, block, opts) => {
334 self.debug_trace_call(tx, block, opts).await.to_rpc_result()
335 }
336 EthRequest::TraceTransaction(tx) => self.trace_transaction(tx).await.to_rpc_result(),
337 EthRequest::TraceBlock(block) => self.trace_block(block).await.to_rpc_result(),
338 EthRequest::TraceFilter(filter) => self.trace_filter(filter).await.to_rpc_result(),
339 EthRequest::ImpersonateAccount(addr) => {
340 self.anvil_impersonate_account(addr).await.to_rpc_result()
341 }
342 EthRequest::StopImpersonatingAccount(addr) => {
343 self.anvil_stop_impersonating_account(addr).await.to_rpc_result()
344 }
345 EthRequest::AutoImpersonateAccount(enable) => {
346 self.anvil_auto_impersonate_account(enable).await.to_rpc_result()
347 }
348 EthRequest::GetAutoMine(()) => self.anvil_get_auto_mine().to_rpc_result(),
349 EthRequest::Mine(blocks, interval) => {
350 self.anvil_mine(blocks, interval).await.to_rpc_result()
351 }
352 EthRequest::SetAutomine(enabled) => {
353 self.anvil_set_auto_mine(enabled).await.to_rpc_result()
354 }
355 EthRequest::SetIntervalMining(interval) => {
356 self.anvil_set_interval_mining(interval).to_rpc_result()
357 }
358 EthRequest::GetIntervalMining(()) => self.anvil_get_interval_mining().to_rpc_result(),
359 EthRequest::DropTransaction(tx) => {
360 self.anvil_drop_transaction(tx).await.to_rpc_result()
361 }
362 EthRequest::DropAllTransactions() => {
363 self.anvil_drop_all_transactions().await.to_rpc_result()
364 }
365 EthRequest::Reset(fork) => {
366 self.anvil_reset(fork.and_then(|p| p.params)).await.to_rpc_result()
367 }
368 EthRequest::SetBalance(addr, val) => {
369 self.anvil_set_balance(addr, val).await.to_rpc_result()
370 }
371 EthRequest::AddBalance(addr, val) => {
372 self.anvil_add_balance(addr, val).await.to_rpc_result()
373 }
374 EthRequest::DealERC20(addr, token_addr, val) => {
375 self.anvil_deal_erc20(addr, token_addr, val).await.to_rpc_result()
376 }
377 EthRequest::SetERC20Allowance(owner, spender, token_addr, val) => self
378 .anvil_set_erc20_allowance(owner, spender, token_addr, val)
379 .await
380 .to_rpc_result(),
381 EthRequest::SetCode(addr, code) => {
382 self.anvil_set_code(addr, code).await.to_rpc_result()
383 }
384 EthRequest::SetNonce(addr, nonce) => {
385 self.anvil_set_nonce(addr, nonce).await.to_rpc_result()
386 }
387 EthRequest::SetStorageAt(addr, slot, val) => {
388 self.anvil_set_storage_at(addr, slot, val).await.to_rpc_result()
389 }
390 EthRequest::SetCoinbase(addr) => self.anvil_set_coinbase(addr).await.to_rpc_result(),
391 EthRequest::SetChainId(id) => self.anvil_set_chain_id(id).await.to_rpc_result(),
392 EthRequest::SetLogging(log) => self.anvil_set_logging(log).await.to_rpc_result(),
393 EthRequest::SetMinGasPrice(gas) => {
394 self.anvil_set_min_gas_price(gas).await.to_rpc_result()
395 }
396 EthRequest::SetNextBlockBaseFeePerGas(gas) => {
397 self.anvil_set_next_block_base_fee_per_gas(gas).await.to_rpc_result()
398 }
399 EthRequest::DumpState(preserve_historical_states) => self
400 .anvil_dump_state(preserve_historical_states.and_then(|s| s.params))
401 .await
402 .to_rpc_result(),
403 EthRequest::LoadState(buf) => self.anvil_load_state(buf).await.to_rpc_result(),
404 EthRequest::NodeInfo(_) => self.anvil_node_info().await.to_rpc_result(),
405 EthRequest::AnvilMetadata(_) => self.anvil_metadata().await.to_rpc_result(),
406 EthRequest::EvmSnapshot(_) => self.evm_snapshot().await.to_rpc_result(),
407 EthRequest::EvmRevert(id) => self.evm_revert(id).await.to_rpc_result(),
408 EthRequest::EvmIncreaseTime(time) => self.evm_increase_time(time).await.to_rpc_result(),
409 EthRequest::EvmSetNextBlockTimeStamp(time) => {
410 if time >= U256::from(u64::MAX) {
411 return ResponseResult::Error(RpcError::invalid_params(
412 "The timestamp is too big",
413 ));
414 }
415 let time = time.to::<u64>();
416 self.evm_set_next_block_timestamp(time).to_rpc_result()
417 }
418 EthRequest::EvmSetTime(timestamp) => {
419 if timestamp >= U256::from(u64::MAX) {
420 return ResponseResult::Error(RpcError::invalid_params(
421 "The timestamp is too big",
422 ));
423 }
424 let time = timestamp.to::<u64>();
425 self.evm_set_time(time).to_rpc_result()
426 }
427 EthRequest::EvmSetBlockGasLimit(gas_limit) => {
428 self.evm_set_block_gas_limit(gas_limit).to_rpc_result()
429 }
430 EthRequest::EvmSetBlockTimeStampInterval(time) => {
431 self.evm_set_block_timestamp_interval(time).to_rpc_result()
432 }
433 EthRequest::EvmRemoveBlockTimeStampInterval(()) => {
434 self.evm_remove_block_timestamp_interval().to_rpc_result()
435 }
436 EthRequest::EvmMine(mine) => {
437 self.evm_mine(mine.and_then(|p| p.params)).await.to_rpc_result()
438 }
439 EthRequest::EvmMineDetailed(mine) => {
440 self.evm_mine_detailed(mine.and_then(|p| p.params)).await.to_rpc_result()
441 }
442 EthRequest::SetRpcUrl(url) => self.anvil_set_rpc_url(url).to_rpc_result(),
443 EthRequest::EthSendUnsignedTransaction(tx) => {
444 self.eth_send_unsigned_transaction(*tx).await.to_rpc_result()
445 }
446 EthRequest::EnableTraces(_) => self.anvil_enable_traces().await.to_rpc_result(),
447 EthRequest::EthNewFilter(filter) => self.new_filter(filter).await.to_rpc_result(),
448 EthRequest::EthGetFilterChanges(id) => self.get_filter_changes(&id).await,
449 EthRequest::EthNewBlockFilter(_) => self.new_block_filter().await.to_rpc_result(),
450 EthRequest::EthNewPendingTransactionFilter(_) => {
451 self.new_pending_transaction_filter().await.to_rpc_result()
452 }
453 EthRequest::EthGetFilterLogs(id) => self.get_filter_logs(&id).await.to_rpc_result(),
454 EthRequest::EthUninstallFilter(id) => self.uninstall_filter(&id).await.to_rpc_result(),
455 EthRequest::TxPoolStatus(_) => self.txpool_status().await.to_rpc_result(),
456 EthRequest::TxPoolInspect(_) => self.txpool_inspect().await.to_rpc_result(),
457 EthRequest::TxPoolContent(_) => self.txpool_content().await.to_rpc_result(),
458 EthRequest::ErigonGetHeaderByNumber(num) => {
459 self.erigon_get_header_by_number(num).await.to_rpc_result()
460 }
461 EthRequest::OtsGetApiLevel(_) => self.ots_get_api_level().await.to_rpc_result(),
462 EthRequest::OtsGetInternalOperations(hash) => {
463 self.ots_get_internal_operations(hash).await.to_rpc_result()
464 }
465 EthRequest::OtsHasCode(addr, num) => self.ots_has_code(addr, num).await.to_rpc_result(),
466 EthRequest::OtsTraceTransaction(hash) => {
467 self.ots_trace_transaction(hash).await.to_rpc_result()
468 }
469 EthRequest::OtsGetTransactionError(hash) => {
470 self.ots_get_transaction_error(hash).await.to_rpc_result()
471 }
472 EthRequest::OtsGetBlockDetails(num) => {
473 self.ots_get_block_details(num).await.to_rpc_result()
474 }
475 EthRequest::OtsGetBlockDetailsByHash(hash) => {
476 self.ots_get_block_details_by_hash(hash).await.to_rpc_result()
477 }
478 EthRequest::OtsGetBlockTransactions(num, page, page_size) => {
479 self.ots_get_block_transactions(num, page, page_size).await.to_rpc_result()
480 }
481 EthRequest::OtsSearchTransactionsBefore(address, num, page_size) => {
482 self.ots_search_transactions_before(address, num, page_size).await.to_rpc_result()
483 }
484 EthRequest::OtsSearchTransactionsAfter(address, num, page_size) => {
485 self.ots_search_transactions_after(address, num, page_size).await.to_rpc_result()
486 }
487 EthRequest::OtsGetTransactionBySenderAndNonce(address, nonce) => {
488 self.ots_get_transaction_by_sender_and_nonce(address, nonce).await.to_rpc_result()
489 }
490 EthRequest::OtsGetContractCreator(address) => {
491 self.ots_get_contract_creator(address).await.to_rpc_result()
492 }
493 EthRequest::RemovePoolTransactions(address) => {
494 self.anvil_remove_pool_transactions(address).await.to_rpc_result()
495 }
496 EthRequest::Reorg(reorg_options) => {
497 self.anvil_reorg(reorg_options).await.to_rpc_result()
498 }
499 EthRequest::Rollback(depth) => self.anvil_rollback(depth).await.to_rpc_result(),
500 EthRequest::WalletGetCapabilities(()) => self.get_capabilities().to_rpc_result(),
501 EthRequest::WalletSendTransaction(tx) => {
502 self.wallet_send_transaction(*tx).await.to_rpc_result()
503 }
504 EthRequest::AnvilAddCapability(addr) => self.anvil_add_capability(addr).to_rpc_result(),
505 EthRequest::AnvilSetExecutor(executor_pk) => {
506 self.anvil_set_executor(executor_pk).to_rpc_result()
507 }
508 };
509
510 if let ResponseResult::Error(err) = &response {
511 node_info!("\nRPC request failed:");
512 node_info!(" Request: {:?}", request);
513 node_info!(" Error: {}\n", err);
514 }
515
516 response
517 }
518
519 fn sign_request(
520 &self,
521 from: &Address,
522 request: TypedTransactionRequest,
523 ) -> Result<TypedTransaction> {
524 match request {
525 TypedTransactionRequest::Deposit(_) => {
526 let nil_signature = Signature::from_scalars_and_parity(
527 B256::with_last_byte(1),
528 B256::with_last_byte(1),
529 false,
530 );
531 return build_typed_transaction(request, nil_signature);
532 }
533 _ => {
534 for signer in self.signers.iter() {
535 if signer.accounts().contains(from) {
536 let signature = signer.sign_transaction(request.clone(), from)?;
537 return build_typed_transaction(request, signature);
538 }
539 }
540 }
541 }
542 Err(BlockchainError::NoSignerAvailable)
543 }
544
545 async fn block_request(&self, block_number: Option<BlockId>) -> Result<BlockRequest> {
546 let block_request = match block_number {
547 Some(BlockId::Number(BlockNumber::Pending)) => {
548 let pending_txs = self.pool.ready_transactions().collect();
549 BlockRequest::Pending(pending_txs)
550 }
551 _ => {
552 let number = self.backend.ensure_block_number(block_number).await?;
553 BlockRequest::Number(number)
554 }
555 };
556 Ok(block_request)
557 }
558
559 async fn inner_raw_transaction(&self, hash: B256) -> Result<Option<Bytes>> {
560 match self.pool.get_transaction(hash) {
561 Some(tx) => Ok(Some(tx.transaction.encoded_2718().into())),
562 None => match self.backend.transaction_by_hash(hash).await? {
563 Some(tx) => Ok(Some(tx.inner.inner.encoded_2718().into())),
564 None => Ok(None),
565 },
566 }
567 }
568
569 pub fn client_version(&self) -> Result<String> {
573 node_info!("web3_clientVersion");
574 Ok(CLIENT_VERSION.to_string())
575 }
576
577 pub fn sha3(&self, bytes: Bytes) -> Result<String> {
581 node_info!("web3_sha3");
582 let hash = alloy_primitives::keccak256(bytes.as_ref());
583 Ok(alloy_primitives::hex::encode_prefixed(&hash[..]))
584 }
585
586 pub fn protocol_version(&self) -> Result<u64> {
590 node_info!("eth_protocolVersion");
591 Ok(1)
592 }
593
594 pub fn hashrate(&self) -> Result<U256> {
598 node_info!("eth_hashrate");
599 Ok(U256::ZERO)
600 }
601
602 pub fn author(&self) -> Result<Address> {
606 node_info!("eth_coinbase");
607 Ok(self.backend.coinbase())
608 }
609
610 pub fn is_mining(&self) -> Result<bool> {
614 node_info!("eth_mining");
615 Ok(self.is_mining)
616 }
617
618 pub fn eth_chain_id(&self) -> Result<Option<U64>> {
624 node_info!("eth_chainId");
625 Ok(Some(self.backend.chain_id().to::<U64>()))
626 }
627
628 pub fn network_id(&self) -> Result<Option<String>> {
632 node_info!("eth_networkId");
633 let chain_id = self.backend.chain_id().to::<u64>();
634 Ok(Some(format!("{chain_id}")))
635 }
636
637 pub fn net_listening(&self) -> Result<bool> {
641 node_info!("net_listening");
642 Ok(self.net_listening)
643 }
644
645 fn eth_gas_price(&self) -> Result<U256> {
647 node_info!("eth_gasPrice");
648 Ok(U256::from(self.gas_price()))
649 }
650
651 pub fn gas_price(&self) -> u128 {
653 if self.backend.is_eip1559() {
654 if self.backend.is_min_priority_fee_enforced() {
655 (self.backend.base_fee() as u128).saturating_add(self.lowest_suggestion_tip())
656 } else {
657 self.backend.base_fee() as u128
658 }
659 } else {
660 self.backend.fees().raw_gas_price()
661 }
662 }
663
664 pub fn excess_blob_gas_and_price(&self) -> Result<Option<BlobExcessGasAndPrice>> {
666 Ok(self.backend.excess_blob_gas_and_price())
667 }
668
669 pub fn gas_max_priority_fee_per_gas(&self) -> Result<U256> {
674 self.max_priority_fee_per_gas()
675 }
676
677 pub fn blob_base_fee(&self) -> Result<U256> {
681 Ok(U256::from(self.backend.fees().base_fee_per_blob_gas()))
682 }
683
684 pub fn gas_limit(&self) -> U256 {
686 U256::from(self.backend.gas_limit())
687 }
688
689 pub fn accounts(&self) -> Result<Vec<Address>> {
693 node_info!("eth_accounts");
694 let mut unique = HashSet::new();
695 let mut accounts: Vec<Address> = Vec::new();
696 for signer in self.signers.iter() {
697 accounts.extend(signer.accounts().into_iter().filter(|acc| unique.insert(*acc)));
698 }
699 accounts.extend(
700 self.backend
701 .cheats()
702 .impersonated_accounts()
703 .into_iter()
704 .filter(|acc| unique.insert(*acc)),
705 );
706 Ok(accounts.into_iter().collect())
707 }
708
709 pub fn block_number(&self) -> Result<U256> {
713 node_info!("eth_blockNumber");
714 Ok(U256::from(self.backend.best_number()))
715 }
716
717 pub async fn balance(&self, address: Address, block_number: Option<BlockId>) -> Result<U256> {
721 node_info!("eth_getBalance");
722 let block_request = self.block_request(block_number).await?;
723
724 if let BlockRequest::Number(number) = block_request
726 && let Some(fork) = self.get_fork()
727 && fork.predates_fork(number)
728 {
729 return Ok(fork.get_balance(address, number).await?);
730 }
731
732 self.backend.get_balance(address, Some(block_request)).await
733 }
734
735 pub async fn get_account(
739 &self,
740 address: Address,
741 block_number: Option<BlockId>,
742 ) -> Result<Account> {
743 node_info!("eth_getAccount");
744 let block_request = self.block_request(block_number).await?;
745
746 if let BlockRequest::Number(number) = block_request
748 && let Some(fork) = self.get_fork()
749 && fork.predates_fork(number)
750 {
751 return Ok(fork.get_account(address, number).await?);
752 }
753
754 self.backend.get_account_at_block(address, Some(block_request)).await
755 }
756
757 pub async fn get_account_info(
759 &self,
760 address: Address,
761 block_number: Option<BlockId>,
762 ) -> Result<alloy_rpc_types::eth::AccountInfo> {
763 node_info!("eth_getAccountInfo");
764 let account = self
765 .backend
766 .get_account_at_block(address, Some(self.block_request(block_number).await?))
767 .await?;
768 let code =
769 self.backend.get_code(address, Some(self.block_request(block_number).await?)).await?;
770 Ok(alloy_rpc_types::eth::AccountInfo {
771 balance: account.balance,
772 nonce: account.nonce,
773 code,
774 })
775 }
776 pub async fn storage_at(
780 &self,
781 address: Address,
782 index: U256,
783 block_number: Option<BlockId>,
784 ) -> Result<B256> {
785 node_info!("eth_getStorageAt");
786 let block_request = self.block_request(block_number).await?;
787
788 if let BlockRequest::Number(number) = block_request
790 && let Some(fork) = self.get_fork()
791 && fork.predates_fork(number)
792 {
793 return Ok(B256::from(
794 fork.storage_at(address, index, Some(BlockNumber::Number(number))).await?,
795 ));
796 }
797
798 self.backend.storage_at(address, index, Some(block_request)).await
799 }
800
801 pub async fn block_by_hash(&self, hash: B256) -> Result<Option<AnyRpcBlock>> {
805 node_info!("eth_getBlockByHash");
806 self.backend.block_by_hash(hash).await
807 }
808
809 pub async fn block_by_hash_full(&self, hash: B256) -> Result<Option<AnyRpcBlock>> {
813 node_info!("eth_getBlockByHash");
814 self.backend.block_by_hash_full(hash).await
815 }
816
817 pub async fn block_by_number(&self, number: BlockNumber) -> Result<Option<AnyRpcBlock>> {
821 node_info!("eth_getBlockByNumber");
822 if number == BlockNumber::Pending {
823 return Ok(Some(self.pending_block().await));
824 }
825
826 self.backend.block_by_number(number).await
827 }
828
829 pub async fn block_by_number_full(&self, number: BlockNumber) -> Result<Option<AnyRpcBlock>> {
833 node_info!("eth_getBlockByNumber");
834 if number == BlockNumber::Pending {
835 return Ok(self.pending_block_full().await);
836 }
837 self.backend.block_by_number_full(number).await
838 }
839
840 pub async fn transaction_count(
847 &self,
848 address: Address,
849 block_number: Option<BlockId>,
850 ) -> Result<U256> {
851 node_info!("eth_getTransactionCount");
852 self.get_transaction_count(address, block_number).await.map(U256::from)
853 }
854
855 pub async fn block_transaction_count_by_hash(&self, hash: B256) -> Result<Option<U256>> {
859 node_info!("eth_getBlockTransactionCountByHash");
860 let block = self.backend.block_by_hash(hash).await?;
861 let txs = block.map(|b| match b.transactions() {
862 BlockTransactions::Full(txs) => U256::from(txs.len()),
863 BlockTransactions::Hashes(txs) => U256::from(txs.len()),
864 BlockTransactions::Uncle => U256::from(0),
865 });
866 Ok(txs)
867 }
868
869 pub async fn block_transaction_count_by_number(
873 &self,
874 block_number: BlockNumber,
875 ) -> Result<Option<U256>> {
876 node_info!("eth_getBlockTransactionCountByNumber");
877 let block_request = self.block_request(Some(block_number.into())).await?;
878 if let BlockRequest::Pending(txs) = block_request {
879 let block = self.backend.pending_block(txs).await;
880 return Ok(Some(U256::from(block.transactions.len())));
881 }
882 let block = self.backend.block_by_number(block_number).await?;
883 let txs = block.map(|b| match b.transactions() {
884 BlockTransactions::Full(txs) => U256::from(txs.len()),
885 BlockTransactions::Hashes(txs) => U256::from(txs.len()),
886 BlockTransactions::Uncle => U256::from(0),
887 });
888 Ok(txs)
889 }
890
891 pub async fn block_uncles_count_by_hash(&self, hash: B256) -> Result<U256> {
895 node_info!("eth_getUncleCountByBlockHash");
896 let block =
897 self.backend.block_by_hash(hash).await?.ok_or(BlockchainError::BlockNotFound)?;
898 Ok(U256::from(block.uncles.len()))
899 }
900
901 pub async fn block_uncles_count_by_number(&self, block_number: BlockNumber) -> Result<U256> {
905 node_info!("eth_getUncleCountByBlockNumber");
906 let block = self
907 .backend
908 .block_by_number(block_number)
909 .await?
910 .ok_or(BlockchainError::BlockNotFound)?;
911 Ok(U256::from(block.uncles.len()))
912 }
913
914 pub async fn get_code(&self, address: Address, block_number: Option<BlockId>) -> Result<Bytes> {
918 node_info!("eth_getCode");
919 let block_request = self.block_request(block_number).await?;
920 if let BlockRequest::Number(number) = block_request
922 && let Some(fork) = self.get_fork()
923 && fork.predates_fork(number)
924 {
925 return Ok(fork.get_code(address, number).await?);
926 }
927 self.backend.get_code(address, Some(block_request)).await
928 }
929
930 pub async fn get_proof(
935 &self,
936 address: Address,
937 keys: Vec<B256>,
938 block_number: Option<BlockId>,
939 ) -> Result<EIP1186AccountProofResponse> {
940 node_info!("eth_getProof");
941 let block_request = self.block_request(block_number).await?;
942
943 if let BlockRequest::Number(number) = block_request
946 && let Some(fork) = self.get_fork()
947 && fork.predates_fork_inclusive(number)
948 {
949 return Ok(fork.get_proof(address, keys, Some(number.into())).await?);
950 }
951
952 let proof = self.backend.prove_account_at(address, keys, Some(block_request)).await?;
953 Ok(proof)
954 }
955
956 pub async fn sign_typed_data(
960 &self,
961 _address: Address,
962 _data: serde_json::Value,
963 ) -> Result<String> {
964 node_info!("eth_signTypedData");
965 Err(BlockchainError::RpcUnimplemented)
966 }
967
968 pub async fn sign_typed_data_v3(
972 &self,
973 _address: Address,
974 _data: serde_json::Value,
975 ) -> Result<String> {
976 node_info!("eth_signTypedData_v3");
977 Err(BlockchainError::RpcUnimplemented)
978 }
979
980 pub async fn sign_typed_data_v4(&self, address: Address, data: &TypedData) -> Result<String> {
984 node_info!("eth_signTypedData_v4");
985 let signer = self.get_signer(address).ok_or(BlockchainError::NoSignerAvailable)?;
986 let signature = signer.sign_typed_data(address, data).await?;
987 let signature = alloy_primitives::hex::encode(signature.as_bytes());
988 Ok(format!("0x{signature}"))
989 }
990
991 pub async fn sign(&self, address: Address, content: impl AsRef<[u8]>) -> Result<String> {
995 node_info!("eth_sign");
996 let signer = self.get_signer(address).ok_or(BlockchainError::NoSignerAvailable)?;
997 let signature =
998 alloy_primitives::hex::encode(signer.sign(address, content.as_ref()).await?.as_bytes());
999 Ok(format!("0x{signature}"))
1000 }
1001
1002 pub async fn sign_transaction(
1006 &self,
1007 mut request: WithOtherFields<TransactionRequest>,
1008 ) -> Result<String> {
1009 node_info!("eth_signTransaction");
1010
1011 let from = request.from.map(Ok).unwrap_or_else(|| {
1012 self.accounts()?.first().copied().ok_or(BlockchainError::NoSignerAvailable)
1013 })?;
1014
1015 let (nonce, _) = self.request_nonce(&request, from).await?;
1016
1017 if request.gas.is_none() {
1018 if let Ok(gas) = self.estimate_gas(request.clone(), None, EvmOverrides::default()).await
1020 {
1021 request.gas = Some(gas.to());
1022 }
1023 }
1024
1025 let request = self.build_typed_tx_request(request, nonce)?;
1026
1027 let signed_transaction = self.sign_request(&from, request)?.encoded_2718();
1028 Ok(alloy_primitives::hex::encode_prefixed(signed_transaction))
1029 }
1030
1031 pub async fn send_transaction(
1035 &self,
1036 mut request: WithOtherFields<TransactionRequest>,
1037 ) -> Result<TxHash> {
1038 node_info!("eth_sendTransaction");
1039
1040 let from = request.from.map(Ok).unwrap_or_else(|| {
1041 self.accounts()?.first().copied().ok_or(BlockchainError::NoSignerAvailable)
1042 })?;
1043 let (nonce, on_chain_nonce) = self.request_nonce(&request, from).await?;
1044
1045 if request.gas.is_none() {
1046 if let Ok(gas) = self.estimate_gas(request.clone(), None, EvmOverrides::default()).await
1048 {
1049 request.gas = Some(gas.to());
1050 }
1051 }
1052
1053 let request = self.build_typed_tx_request(request, nonce)?;
1054
1055 let pending_transaction = if self.is_impersonated(from) {
1057 let bypass_signature = self.impersonated_signature(&request);
1058 let transaction = sign::build_typed_transaction(request, bypass_signature)?;
1059 self.ensure_typed_transaction_supported(&transaction)?;
1060 trace!(target : "node", ?from, "eth_sendTransaction: impersonating");
1061 PendingTransaction::with_impersonated(transaction, from)
1062 } else {
1063 let transaction = self.sign_request(&from, request)?;
1064 self.ensure_typed_transaction_supported(&transaction)?;
1065 PendingTransaction::new(transaction)?
1066 };
1067 self.backend.validate_pool_transaction(&pending_transaction).await?;
1069
1070 let requires = required_marker(nonce, on_chain_nonce, from);
1071 let provides = vec![to_marker(nonce, from)];
1072 debug_assert!(requires != provides);
1073
1074 self.add_pending_transaction(pending_transaction, requires, provides)
1075 }
1076
1077 async fn await_transaction_inclusion(&self, hash: TxHash) -> Result<ReceiptResponse> {
1079 let mut stream = self.new_block_notifications();
1080 if let Some(receipt) = self.backend.transaction_receipt(hash).await? {
1082 return Ok(receipt);
1083 }
1084 while let Some(notification) = stream.next().await {
1085 if let Some(block) = self.backend.get_block_by_hash(notification.hash)
1086 && block.transactions.iter().any(|tx| tx.hash() == hash)
1087 && let Some(receipt) = self.backend.transaction_receipt(hash).await?
1088 {
1089 return Ok(receipt);
1090 }
1091 }
1092
1093 Err(BlockchainError::Message("Failed to await transaction inclusion".to_string()))
1094 }
1095
1096 async fn check_transaction_inclusion(&self, hash: TxHash) -> Result<ReceiptResponse> {
1098 const TIMEOUT_DURATION: Duration = Duration::from_secs(30);
1099 tokio::time::timeout(TIMEOUT_DURATION, self.await_transaction_inclusion(hash))
1100 .await
1101 .unwrap_or_else(|_elapsed| {
1102 Err(BlockchainError::TransactionConfirmationTimeout {
1103 hash,
1104 duration: TIMEOUT_DURATION,
1105 })
1106 })
1107 }
1108
1109 pub async fn send_transaction_sync(
1113 &self,
1114 request: WithOtherFields<TransactionRequest>,
1115 ) -> Result<ReceiptResponse> {
1116 node_info!("eth_sendTransactionSync");
1117 let hash = self.send_transaction(request).await?;
1118
1119 let receipt = self.check_transaction_inclusion(hash).await?;
1120
1121 Ok(ReceiptResponse::from(receipt))
1122 }
1123
1124 pub async fn send_raw_transaction(&self, tx: Bytes) -> Result<TxHash> {
1128 node_info!("eth_sendRawTransaction");
1129 let mut data = tx.as_ref();
1130 if data.is_empty() {
1131 return Err(BlockchainError::EmptyRawTransactionData);
1132 }
1133
1134 let transaction = TypedTransaction::decode_2718(&mut data)
1135 .map_err(|_| BlockchainError::FailedToDecodeSignedTransaction)?;
1136
1137 self.ensure_typed_transaction_supported(&transaction)?;
1138
1139 let pending_transaction = PendingTransaction::new(transaction)?;
1140
1141 self.backend.validate_pool_transaction(&pending_transaction).await?;
1143
1144 let on_chain_nonce = self.backend.current_nonce(*pending_transaction.sender()).await?;
1145 let from = *pending_transaction.sender();
1146 let nonce = pending_transaction.transaction.nonce();
1147 let requires = required_marker(nonce, on_chain_nonce, from);
1148
1149 let priority = self.transaction_priority(&pending_transaction.transaction);
1150 let pool_transaction = PoolTransaction {
1151 requires,
1152 provides: vec![to_marker(nonce, *pending_transaction.sender())],
1153 pending_transaction,
1154 priority,
1155 };
1156
1157 let tx = self.pool.add_transaction(pool_transaction)?;
1158 trace!(target: "node", "Added transaction: [{:?}] sender={:?}", tx.hash(), from);
1159 Ok(*tx.hash())
1160 }
1161
1162 pub async fn send_raw_transaction_sync(&self, tx: Bytes) -> Result<ReceiptResponse> {
1166 node_info!("eth_sendRawTransactionSync");
1167
1168 let hash = self.send_raw_transaction(tx).await?;
1169 let receipt = self.check_transaction_inclusion(hash).await?;
1170
1171 Ok(ReceiptResponse::from(receipt))
1172 }
1173
1174 pub async fn call(
1178 &self,
1179 request: WithOtherFields<TransactionRequest>,
1180 block_number: Option<BlockId>,
1181 overrides: EvmOverrides,
1182 ) -> Result<Bytes> {
1183 node_info!("eth_call");
1184 let block_request = self.block_request(block_number).await?;
1185 if let BlockRequest::Number(number) = block_request
1187 && let Some(fork) = self.get_fork()
1188 && fork.predates_fork(number)
1189 {
1190 if overrides.has_state() || overrides.has_block() {
1191 return Err(BlockchainError::EvmOverrideError(
1192 "not available on past forked blocks".to_string(),
1193 ));
1194 }
1195 return Ok(fork.call(&request, Some(number.into())).await?);
1196 }
1197
1198 let fees = FeeDetails::new(
1199 request.gas_price,
1200 request.max_fee_per_gas,
1201 request.max_priority_fee_per_gas,
1202 request.max_fee_per_blob_gas,
1203 )?
1204 .or_zero_fees();
1205 self.on_blocking_task(|this| async move {
1208 let (exit, out, gas, _) =
1209 this.backend.call(request, fees, Some(block_request), overrides).await?;
1210 trace!(target : "node", "Call status {:?}, gas {}", exit, gas);
1211
1212 ensure_return_ok(exit, &out)
1213 })
1214 .await
1215 }
1216
1217 pub async fn simulate_v1(
1218 &self,
1219 request: SimulatePayload,
1220 block_number: Option<BlockId>,
1221 ) -> Result<Vec<SimulatedBlock<AnyRpcBlock>>> {
1222 node_info!("eth_simulateV1");
1223 let block_request = self.block_request(block_number).await?;
1224 if let BlockRequest::Number(number) = block_request
1226 && let Some(fork) = self.get_fork()
1227 && fork.predates_fork(number)
1228 {
1229 return Ok(fork.simulate_v1(&request, Some(number.into())).await?);
1230 }
1231
1232 self.on_blocking_task(|this| async move {
1235 let simulated_blocks = this.backend.simulate(request, Some(block_request)).await?;
1236 trace!(target : "node", "Simulate status {:?}", simulated_blocks);
1237
1238 Ok(simulated_blocks)
1239 })
1240 .await
1241 }
1242
1243 pub async fn create_access_list(
1257 &self,
1258 mut request: WithOtherFields<TransactionRequest>,
1259 block_number: Option<BlockId>,
1260 ) -> Result<AccessListResult> {
1261 node_info!("eth_createAccessList");
1262 let block_request = self.block_request(block_number).await?;
1263 if let BlockRequest::Number(number) = block_request
1265 && let Some(fork) = self.get_fork()
1266 && fork.predates_fork(number)
1267 {
1268 return Ok(fork.create_access_list(&request, Some(number.into())).await?);
1269 }
1270
1271 self.backend
1272 .with_database_at(Some(block_request), |state, block_env| {
1273 let (exit, out, _, access_list) = self.backend.build_access_list_with_state(
1274 &state,
1275 request.clone(),
1276 FeeDetails::zero(),
1277 block_env.clone(),
1278 )?;
1279 ensure_return_ok(exit, &out)?;
1280
1281 request.access_list = Some(access_list.clone());
1283
1284 let (exit, out, gas_used, _) = self.backend.call_with_state(
1285 &state,
1286 request.clone(),
1287 FeeDetails::zero(),
1288 block_env,
1289 )?;
1290 ensure_return_ok(exit, &out)?;
1291
1292 Ok(AccessListResult {
1293 access_list: AccessList(access_list.0),
1294 gas_used: U256::from(gas_used),
1295 error: None,
1296 })
1297 })
1298 .await?
1299 }
1300
1301 pub async fn estimate_gas(
1306 &self,
1307 request: WithOtherFields<TransactionRequest>,
1308 block_number: Option<BlockId>,
1309 overrides: EvmOverrides,
1310 ) -> Result<U256> {
1311 node_info!("eth_estimateGas");
1312 self.do_estimate_gas(
1313 request,
1314 block_number.or_else(|| Some(BlockNumber::Pending.into())),
1315 overrides,
1316 )
1317 .await
1318 .map(U256::from)
1319 }
1320
1321 pub fn anvil_get_blob_by_versioned_hash(
1323 &self,
1324 hash: B256,
1325 ) -> Result<Option<alloy_consensus::Blob>> {
1326 node_info!("anvil_getBlobByHash");
1327 Ok(self.backend.get_blob_by_versioned_hash(hash)?)
1328 }
1329
1330 pub fn anvil_get_blob_by_tx_hash(&self, hash: B256) -> Result<Option<Vec<Blob>>> {
1332 node_info!("anvil_getBlobsByTransactionHash");
1333 Ok(self.backend.get_blob_by_tx_hash(hash)?)
1334 }
1335
1336 pub async fn transaction_by_hash(&self, hash: B256) -> Result<Option<AnyRpcTransaction>> {
1343 node_info!("eth_getTransactionByHash");
1344 let mut tx = self.pool.get_transaction(hash).map(|pending| {
1345 let from = *pending.sender();
1346 let tx = transaction_build(
1347 Some(*pending.hash()),
1348 pending.transaction,
1349 None,
1350 None,
1351 Some(self.backend.base_fee()),
1352 );
1353
1354 let WithOtherFields { inner: mut tx, other } = tx.0;
1355 tx.inner = Recovered::new_unchecked(tx.inner.into_inner(), from);
1358
1359 AnyRpcTransaction(WithOtherFields { inner: tx, other })
1360 });
1361 if tx.is_none() {
1362 tx = self.backend.transaction_by_hash(hash).await?
1363 }
1364
1365 Ok(tx)
1366 }
1367
1368 pub async fn transaction_by_block_hash_and_index(
1372 &self,
1373 hash: B256,
1374 index: Index,
1375 ) -> Result<Option<AnyRpcTransaction>> {
1376 node_info!("eth_getTransactionByBlockHashAndIndex");
1377 self.backend.transaction_by_block_hash_and_index(hash, index).await
1378 }
1379
1380 pub async fn transaction_by_block_number_and_index(
1384 &self,
1385 block: BlockNumber,
1386 idx: Index,
1387 ) -> Result<Option<AnyRpcTransaction>> {
1388 node_info!("eth_getTransactionByBlockNumberAndIndex");
1389 self.backend.transaction_by_block_number_and_index(block, idx).await
1390 }
1391
1392 pub async fn transaction_receipt(&self, hash: B256) -> Result<Option<ReceiptResponse>> {
1396 node_info!("eth_getTransactionReceipt");
1397 self.backend.transaction_receipt(hash).await
1398 }
1399
1400 pub async fn block_receipts(&self, number: BlockId) -> Result<Option<Vec<ReceiptResponse>>> {
1404 node_info!("eth_getBlockReceipts");
1405 self.backend.block_receipts(number).await
1406 }
1407
1408 pub async fn uncle_by_block_hash_and_index(
1412 &self,
1413 block_hash: B256,
1414 idx: Index,
1415 ) -> Result<Option<AnyRpcBlock>> {
1416 node_info!("eth_getUncleByBlockHashAndIndex");
1417 let number =
1418 self.backend.ensure_block_number(Some(BlockId::Hash(block_hash.into()))).await?;
1419 if let Some(fork) = self.get_fork()
1420 && fork.predates_fork_inclusive(number)
1421 {
1422 return Ok(fork.uncle_by_block_hash_and_index(block_hash, idx.into()).await?);
1423 }
1424 Ok(None)
1426 }
1427
1428 pub async fn uncle_by_block_number_and_index(
1432 &self,
1433 block_number: BlockNumber,
1434 idx: Index,
1435 ) -> Result<Option<AnyRpcBlock>> {
1436 node_info!("eth_getUncleByBlockNumberAndIndex");
1437 let number = self.backend.ensure_block_number(Some(BlockId::Number(block_number))).await?;
1438 if let Some(fork) = self.get_fork()
1439 && fork.predates_fork_inclusive(number)
1440 {
1441 return Ok(fork.uncle_by_block_number_and_index(number, idx.into()).await?);
1442 }
1443 Ok(None)
1445 }
1446
1447 pub async fn logs(&self, filter: Filter) -> Result<Vec<Log>> {
1451 node_info!("eth_getLogs");
1452 self.backend.logs(filter).await
1453 }
1454
1455 pub fn work(&self) -> Result<Work> {
1459 node_info!("eth_getWork");
1460 Err(BlockchainError::RpcUnimplemented)
1461 }
1462
1463 pub fn syncing(&self) -> Result<bool> {
1467 node_info!("eth_syncing");
1468 Ok(false)
1469 }
1470
1471 pub fn submit_work(&self, _: B64, _: B256, _: B256) -> Result<bool> {
1475 node_info!("eth_submitWork");
1476 Err(BlockchainError::RpcUnimplemented)
1477 }
1478
1479 pub fn submit_hashrate(&self, _: U256, _: B256) -> Result<bool> {
1483 node_info!("eth_submitHashrate");
1484 Err(BlockchainError::RpcUnimplemented)
1485 }
1486
1487 pub async fn fee_history(
1491 &self,
1492 block_count: U256,
1493 newest_block: BlockNumber,
1494 reward_percentiles: Vec<f64>,
1495 ) -> Result<FeeHistory> {
1496 node_info!("eth_feeHistory");
1497 let current = self.backend.best_number();
1500 let slots_in_an_epoch = 32u64;
1501
1502 let number = match newest_block {
1503 BlockNumber::Latest | BlockNumber::Pending => current,
1504 BlockNumber::Earliest => 0,
1505 BlockNumber::Number(n) => n,
1506 BlockNumber::Safe => current.saturating_sub(slots_in_an_epoch),
1507 BlockNumber::Finalized => current.saturating_sub(slots_in_an_epoch * 2),
1508 };
1509
1510 if let Some(fork) = self.get_fork() {
1512 if fork.predates_fork_inclusive(number) {
1515 return fork
1516 .fee_history(block_count.to(), BlockNumber::Number(number), &reward_percentiles)
1517 .await
1518 .map_err(BlockchainError::AlloyForkProvider);
1519 }
1520 }
1521
1522 const MAX_BLOCK_COUNT: u64 = 1024u64;
1523 let block_count = block_count.to::<u64>().min(MAX_BLOCK_COUNT);
1524
1525 let highest = number;
1527 let lowest = highest.saturating_sub(block_count.saturating_sub(1));
1528
1529 if lowest < self.backend.best_number().saturating_sub(self.fee_history_limit) {
1531 return Err(FeeHistoryError::InvalidBlockRange.into());
1532 }
1533
1534 let mut response = FeeHistory {
1535 oldest_block: lowest,
1536 base_fee_per_gas: Vec::new(),
1537 gas_used_ratio: Vec::new(),
1538 reward: Some(Default::default()),
1539 base_fee_per_blob_gas: Default::default(),
1540 blob_gas_used_ratio: Default::default(),
1541 };
1542 let mut rewards = Vec::new();
1543
1544 {
1545 let fee_history = self.fee_history_cache.lock();
1546
1547 for n in lowest..=highest {
1549 if let Some(block) = fee_history.get(&n) {
1551 response.base_fee_per_gas.push(block.base_fee);
1552 response.base_fee_per_blob_gas.push(block.base_fee_per_blob_gas.unwrap_or(0));
1553 response.blob_gas_used_ratio.push(block.blob_gas_used_ratio);
1554 response.gas_used_ratio.push(block.gas_used_ratio);
1555
1556 if !reward_percentiles.is_empty() {
1558 let mut block_rewards = Vec::new();
1559 let resolution_per_percentile: f64 = 2.0;
1560 for p in &reward_percentiles {
1561 let p = p.clamp(0.0, 100.0);
1562 let index = ((p.round() / 2f64) * 2f64) * resolution_per_percentile;
1563 let reward = block.rewards.get(index as usize).map_or(0, |r| *r);
1564 block_rewards.push(reward);
1565 }
1566 rewards.push(block_rewards);
1567 }
1568 }
1569 }
1570 }
1571
1572 response.reward = Some(rewards);
1573
1574 response.base_fee_per_gas.push(self.backend.fees().base_fee() as u128);
1579
1580 response.base_fee_per_blob_gas.push(self.backend.fees().base_fee_per_blob_gas());
1584
1585 Ok(response)
1586 }
1587
1588 pub fn max_priority_fee_per_gas(&self) -> Result<U256> {
1595 node_info!("eth_maxPriorityFeePerGas");
1596 Ok(U256::from(self.lowest_suggestion_tip()))
1597 }
1598
1599 fn lowest_suggestion_tip(&self) -> u128 {
1603 let block_number = self.backend.best_number();
1604 let latest_cached_block = self.fee_history_cache.lock().get(&block_number).cloned();
1605
1606 match latest_cached_block {
1607 Some(block) => block.rewards.iter().copied().min(),
1608 None => self.fee_history_cache.lock().values().flat_map(|b| b.rewards.clone()).min(),
1609 }
1610 .map(|fee| fee.max(MIN_SUGGESTED_PRIORITY_FEE))
1611 .unwrap_or(MIN_SUGGESTED_PRIORITY_FEE)
1612 }
1613
1614 pub async fn new_filter(&self, filter: Filter) -> Result<String> {
1618 node_info!("eth_newFilter");
1619 let historic = if filter.block_option.get_from_block().is_some() {
1622 self.backend.logs(filter.clone()).await?
1623 } else {
1624 vec![]
1625 };
1626 let filter = EthFilter::Logs(Box::new(LogsFilter {
1627 blocks: self.new_block_notifications(),
1628 storage: self.storage_info(),
1629 filter: FilteredParams::new(Some(filter)),
1630 historic: Some(historic),
1631 }));
1632 Ok(self.filters.add_filter(filter).await)
1633 }
1634
1635 pub async fn new_block_filter(&self) -> Result<String> {
1639 node_info!("eth_newBlockFilter");
1640 let filter = EthFilter::Blocks(self.new_block_notifications());
1641 Ok(self.filters.add_filter(filter).await)
1642 }
1643
1644 pub async fn new_pending_transaction_filter(&self) -> Result<String> {
1648 node_info!("eth_newPendingTransactionFilter");
1649 let filter = EthFilter::PendingTransactions(self.new_ready_transactions());
1650 Ok(self.filters.add_filter(filter).await)
1651 }
1652
1653 pub async fn get_filter_changes(&self, id: &str) -> ResponseResult {
1657 node_info!("eth_getFilterChanges");
1658 self.filters.get_filter_changes(id).await
1659 }
1660
1661 pub async fn get_filter_logs(&self, id: &str) -> Result<Vec<Log>> {
1665 node_info!("eth_getFilterLogs");
1666 if let Some(filter) = self.filters.get_log_filter(id).await {
1667 self.backend.logs(filter).await
1668 } else {
1669 Ok(Vec::new())
1670 }
1671 }
1672
1673 pub async fn uninstall_filter(&self, id: &str) -> Result<bool> {
1675 node_info!("eth_uninstallFilter");
1676 Ok(self.filters.uninstall_filter(id).await.is_some())
1677 }
1678
1679 pub async fn raw_transaction(&self, hash: B256) -> Result<Option<Bytes>> {
1683 node_info!("debug_getRawTransaction");
1684 self.inner_raw_transaction(hash).await
1685 }
1686
1687 pub async fn raw_transaction_by_block_hash_and_index(
1691 &self,
1692 block_hash: B256,
1693 index: Index,
1694 ) -> Result<Option<Bytes>> {
1695 node_info!("eth_getRawTransactionByBlockHashAndIndex");
1696 match self.backend.transaction_by_block_hash_and_index(block_hash, index).await? {
1697 Some(tx) => self.inner_raw_transaction(tx.tx_hash()).await,
1698 None => Ok(None),
1699 }
1700 }
1701
1702 pub async fn raw_transaction_by_block_number_and_index(
1706 &self,
1707 block_number: BlockNumber,
1708 index: Index,
1709 ) -> Result<Option<Bytes>> {
1710 node_info!("eth_getRawTransactionByBlockNumberAndIndex");
1711 match self.backend.transaction_by_block_number_and_index(block_number, index).await? {
1712 Some(tx) => self.inner_raw_transaction(tx.tx_hash()).await,
1713 None => Ok(None),
1714 }
1715 }
1716
1717 pub async fn debug_trace_transaction(
1721 &self,
1722 tx_hash: B256,
1723 opts: GethDebugTracingOptions,
1724 ) -> Result<GethTrace> {
1725 node_info!("debug_traceTransaction");
1726 self.backend.debug_trace_transaction(tx_hash, opts).await
1727 }
1728
1729 pub async fn debug_trace_call(
1733 &self,
1734 request: WithOtherFields<TransactionRequest>,
1735 block_number: Option<BlockId>,
1736 opts: GethDebugTracingCallOptions,
1737 ) -> Result<GethTrace> {
1738 node_info!("debug_traceCall");
1739 let block_request = self.block_request(block_number).await?;
1740 let fees = FeeDetails::new(
1741 request.gas_price,
1742 request.max_fee_per_gas,
1743 request.max_priority_fee_per_gas,
1744 request.max_fee_per_blob_gas,
1745 )?
1746 .or_zero_fees();
1747
1748 let result: std::result::Result<GethTrace, BlockchainError> =
1749 self.backend.call_with_tracing(request, fees, Some(block_request), opts).await;
1750 result
1751 }
1752
1753 pub async fn trace_transaction(&self, tx_hash: B256) -> Result<Vec<LocalizedTransactionTrace>> {
1757 node_info!("trace_transaction");
1758 self.backend.trace_transaction(tx_hash).await
1759 }
1760
1761 pub async fn trace_block(&self, block: BlockNumber) -> Result<Vec<LocalizedTransactionTrace>> {
1765 node_info!("trace_block");
1766 self.backend.trace_block(block).await
1767 }
1768
1769 pub async fn trace_filter(
1773 &self,
1774 filter: TraceFilter,
1775 ) -> Result<Vec<LocalizedTransactionTrace>> {
1776 node_info!("trace_filter");
1777 self.backend.trace_filter(filter).await
1778 }
1779}
1780
1781impl EthApi {
1784 pub async fn anvil_impersonate_account(&self, address: Address) -> Result<()> {
1788 node_info!("anvil_impersonateAccount");
1789 self.backend.impersonate(address);
1790 Ok(())
1791 }
1792
1793 pub async fn anvil_stop_impersonating_account(&self, address: Address) -> Result<()> {
1797 node_info!("anvil_stopImpersonatingAccount");
1798 self.backend.stop_impersonating(address);
1799 Ok(())
1800 }
1801
1802 pub async fn anvil_auto_impersonate_account(&self, enabled: bool) -> Result<()> {
1806 node_info!("anvil_autoImpersonateAccount");
1807 self.backend.auto_impersonate_account(enabled);
1808 Ok(())
1809 }
1810
1811 pub fn anvil_get_auto_mine(&self) -> Result<bool> {
1815 node_info!("anvil_getAutomine");
1816 Ok(self.miner.is_auto_mine())
1817 }
1818
1819 pub fn anvil_get_interval_mining(&self) -> Result<Option<u64>> {
1823 node_info!("anvil_getIntervalMining");
1824 Ok(self.miner.get_interval())
1825 }
1826
1827 pub async fn anvil_set_auto_mine(&self, enable_automine: bool) -> Result<()> {
1832 node_info!("evm_setAutomine");
1833 if self.miner.is_auto_mine() {
1834 if enable_automine {
1835 return Ok(());
1836 }
1837 self.miner.set_mining_mode(MiningMode::None);
1838 } else if enable_automine {
1839 let listener = self.pool.add_ready_listener();
1840 let mode = MiningMode::instant(1_000, listener);
1841 self.miner.set_mining_mode(mode);
1842 }
1843 Ok(())
1844 }
1845
1846 pub async fn anvil_mine(&self, num_blocks: Option<U256>, interval: Option<U256>) -> Result<()> {
1850 node_info!("anvil_mine");
1851 let interval = interval.map(|i| i.to::<u64>());
1852 let blocks = num_blocks.unwrap_or(U256::from(1));
1853 if blocks.is_zero() {
1854 return Ok(());
1855 }
1856
1857 self.on_blocking_task(|this| async move {
1858 for _ in 0..blocks.to::<u64>() {
1860 if let Some(interval) = interval {
1862 this.backend.time().increase_time(interval);
1863 }
1864 this.mine_one().await;
1865 }
1866 Ok(())
1867 })
1868 .await?;
1869
1870 Ok(())
1871 }
1872
1873 pub fn anvil_set_interval_mining(&self, secs: u64) -> Result<()> {
1877 node_info!("evm_setIntervalMining");
1878 let mining_mode = if secs == 0 {
1879 MiningMode::None
1880 } else {
1881 let block_time = Duration::from_secs(secs);
1882
1883 self.backend.update_interval_mine_block_time(block_time);
1885
1886 MiningMode::FixedBlockTime(FixedBlockTimeMiner::new(block_time))
1887 };
1888 self.miner.set_mining_mode(mining_mode);
1889 Ok(())
1890 }
1891
1892 pub async fn anvil_drop_transaction(&self, tx_hash: B256) -> Result<Option<B256>> {
1896 node_info!("anvil_dropTransaction");
1897 Ok(self.pool.drop_transaction(tx_hash).map(|tx| tx.hash()))
1898 }
1899
1900 pub async fn anvil_drop_all_transactions(&self) -> Result<()> {
1904 node_info!("anvil_dropAllTransactions");
1905 self.pool.clear();
1906 Ok(())
1907 }
1908
1909 pub async fn anvil_reset(&self, forking: Option<Forking>) -> Result<()> {
1915 self.reset_instance_id();
1916 node_info!("anvil_reset");
1917 if let Some(forking) = forking {
1918 self.backend.reset_fork(forking).await
1920 } else {
1921 self.backend.reset_to_in_mem().await
1924 }
1925 }
1926
1927 pub async fn anvil_set_chain_id(&self, chain_id: u64) -> Result<()> {
1928 node_info!("anvil_setChainId");
1929 self.backend.set_chain_id(chain_id);
1930 Ok(())
1931 }
1932
1933 pub async fn anvil_set_balance(&self, address: Address, balance: U256) -> Result<()> {
1937 node_info!("anvil_setBalance");
1938 self.backend.set_balance(address, balance).await?;
1939 Ok(())
1940 }
1941
1942 pub async fn anvil_add_balance(&self, address: Address, balance: U256) -> Result<()> {
1946 node_info!("anvil_addBalance");
1947 let current_balance = self.backend.get_balance(address, None).await?;
1948 self.backend.set_balance(address, current_balance + balance).await?;
1949 Ok(())
1950 }
1951
1952 async fn find_erc20_storage_slot(
1969 &self,
1970 token_address: Address,
1971 calldata: Bytes,
1972 expected_value: U256,
1973 ) -> Result<B256> {
1974 let tx = TransactionRequest::default().with_to(token_address).with_input(calldata.clone());
1975
1976 let access_list_result =
1978 self.create_access_list(WithOtherFields::new(tx.clone()), None).await?;
1979 let access_list = access_list_result.access_list;
1980
1981 for item in access_list.0 {
1984 if item.address != token_address {
1985 continue;
1986 };
1987 for slot in &item.storage_keys {
1988 let account_override = AccountOverride::default().with_state_diff(std::iter::once(
1989 (*slot, B256::from(expected_value.to_be_bytes())),
1990 ));
1991
1992 let state_override = StateOverridesBuilder::default()
1993 .append(token_address, account_override)
1994 .build();
1995
1996 let evm_override = EvmOverrides::state(Some(state_override));
1997
1998 let Ok(result) =
1999 self.call(WithOtherFields::new(tx.clone()), None, evm_override).await
2000 else {
2001 continue;
2003 };
2004
2005 let Ok(result_value) = U256::abi_decode(&result) else {
2006 continue;
2008 };
2009
2010 if result_value == expected_value {
2011 return Ok(*slot);
2012 }
2013 }
2014 }
2015
2016 Err(BlockchainError::Message("Unable to find storage slot".to_string()))
2017 }
2018
2019 pub async fn anvil_deal_erc20(
2023 &self,
2024 address: Address,
2025 token_address: Address,
2026 balance: U256,
2027 ) -> Result<()> {
2028 node_info!("anvil_dealERC20");
2029
2030 sol! {
2031 #[sol(rpc)]
2032 contract IERC20 {
2033 function balanceOf(address target) external view returns (uint256);
2034 }
2035 }
2036
2037 let calldata = IERC20::balanceOfCall { target: address }.abi_encode().into();
2038
2039 let slot =
2041 self.find_erc20_storage_slot(token_address, calldata, balance).await.map_err(|_| {
2042 BlockchainError::Message("Unable to set ERC20 balance, no slot found".to_string())
2043 })?;
2044
2045 self.anvil_set_storage_at(
2047 token_address,
2048 U256::from_be_bytes(slot.0),
2049 B256::from(balance.to_be_bytes()),
2050 )
2051 .await?;
2052
2053 Ok(())
2054 }
2055
2056 pub async fn anvil_set_erc20_allowance(
2060 &self,
2061 owner: Address,
2062 spender: Address,
2063 token_address: Address,
2064 amount: U256,
2065 ) -> Result<()> {
2066 node_info!("anvil_setERC20Allowance");
2067
2068 sol! {
2069 #[sol(rpc)]
2070 contract IERC20 {
2071 function allowance(address owner, address spender) external view returns (uint256);
2072 }
2073 }
2074
2075 let calldata = IERC20::allowanceCall { owner, spender }.abi_encode().into();
2076
2077 let slot =
2079 self.find_erc20_storage_slot(token_address, calldata, amount).await.map_err(|_| {
2080 BlockchainError::Message("Unable to set ERC20 allowance, no slot found".to_string())
2081 })?;
2082
2083 self.anvil_set_storage_at(
2085 token_address,
2086 U256::from_be_bytes(slot.0),
2087 B256::from(amount.to_be_bytes()),
2088 )
2089 .await?;
2090
2091 Ok(())
2092 }
2093
2094 pub async fn anvil_set_code(&self, address: Address, code: Bytes) -> Result<()> {
2098 node_info!("anvil_setCode");
2099 self.backend.set_code(address, code).await?;
2100 Ok(())
2101 }
2102
2103 pub async fn anvil_set_nonce(&self, address: Address, nonce: U256) -> Result<()> {
2107 node_info!("anvil_setNonce");
2108 self.backend.set_nonce(address, nonce).await?;
2109 Ok(())
2110 }
2111
2112 pub async fn anvil_set_storage_at(
2116 &self,
2117 address: Address,
2118 slot: U256,
2119 val: B256,
2120 ) -> Result<bool> {
2121 node_info!("anvil_setStorageAt");
2122 self.backend.set_storage_at(address, slot, val).await?;
2123 Ok(true)
2124 }
2125
2126 pub async fn anvil_set_logging(&self, enable: bool) -> Result<()> {
2130 node_info!("anvil_setLoggingEnabled");
2131 self.logger.set_enabled(enable);
2132 Ok(())
2133 }
2134
2135 pub async fn anvil_set_min_gas_price(&self, gas: U256) -> Result<()> {
2139 node_info!("anvil_setMinGasPrice");
2140 if self.backend.is_eip1559() {
2141 return Err(RpcError::invalid_params(
2142 "anvil_setMinGasPrice is not supported when EIP-1559 is active",
2143 )
2144 .into());
2145 }
2146 self.backend.set_gas_price(gas.to());
2147 Ok(())
2148 }
2149
2150 pub async fn anvil_set_next_block_base_fee_per_gas(&self, basefee: U256) -> Result<()> {
2154 node_info!("anvil_setNextBlockBaseFeePerGas");
2155 if !self.backend.is_eip1559() {
2156 return Err(RpcError::invalid_params(
2157 "anvil_setNextBlockBaseFeePerGas is only supported when EIP-1559 is active",
2158 )
2159 .into());
2160 }
2161 self.backend.set_base_fee(basefee.to());
2162 Ok(())
2163 }
2164
2165 pub async fn anvil_set_coinbase(&self, address: Address) -> Result<()> {
2169 node_info!("anvil_setCoinbase");
2170 self.backend.set_coinbase(address);
2171 Ok(())
2172 }
2173
2174 pub async fn anvil_dump_state(
2179 &self,
2180 preserve_historical_states: Option<bool>,
2181 ) -> Result<Bytes> {
2182 node_info!("anvil_dumpState");
2183 self.backend.dump_state(preserve_historical_states.unwrap_or(false)).await
2184 }
2185
2186 pub async fn serialized_state(
2188 &self,
2189 preserve_historical_states: bool,
2190 ) -> Result<SerializableState> {
2191 self.backend.serialized_state(preserve_historical_states).await
2192 }
2193
2194 pub async fn anvil_load_state(&self, buf: Bytes) -> Result<bool> {
2199 node_info!("anvil_loadState");
2200 self.backend.load_state_bytes(buf).await
2201 }
2202
2203 pub async fn anvil_node_info(&self) -> Result<NodeInfo> {
2207 node_info!("anvil_nodeInfo");
2208
2209 let env = self.backend.env().read();
2210 let fork_config = self.backend.get_fork();
2211 let tx_order = self.transaction_order.read();
2212 let hard_fork: &str = env.evm_env.cfg_env.spec.into();
2213
2214 Ok(NodeInfo {
2215 current_block_number: self.backend.best_number(),
2216 current_block_timestamp: env.evm_env.block_env.timestamp,
2217 current_block_hash: self.backend.best_hash(),
2218 hard_fork: hard_fork.to_string(),
2219 transaction_order: match *tx_order {
2220 TransactionOrder::Fifo => "fifo".to_string(),
2221 TransactionOrder::Fees => "fees".to_string(),
2222 },
2223 environment: NodeEnvironment {
2224 base_fee: self.backend.base_fee() as u128,
2225 chain_id: self.backend.chain_id().to::<u64>(),
2226 gas_limit: self.backend.gas_limit(),
2227 gas_price: self.gas_price(),
2228 },
2229 fork_config: fork_config
2230 .map(|fork| {
2231 let config = fork.config.read();
2232
2233 NodeForkConfig {
2234 fork_url: Some(config.eth_rpc_url.clone()),
2235 fork_block_number: Some(config.block_number),
2236 fork_retry_backoff: Some(config.backoff.as_millis()),
2237 }
2238 })
2239 .unwrap_or_default(),
2240 })
2241 }
2242
2243 pub async fn anvil_metadata(&self) -> Result<Metadata> {
2247 node_info!("anvil_metadata");
2248 let fork_config = self.backend.get_fork();
2249
2250 Ok(Metadata {
2251 client_version: CLIENT_VERSION.to_string(),
2252 chain_id: self.backend.chain_id().to::<u64>(),
2253 latest_block_hash: self.backend.best_hash(),
2254 latest_block_number: self.backend.best_number(),
2255 instance_id: *self.instance_id.read(),
2256 forked_network: fork_config.map(|cfg| ForkedNetwork {
2257 chain_id: cfg.chain_id(),
2258 fork_block_number: cfg.block_number(),
2259 fork_block_hash: cfg.block_hash(),
2260 }),
2261 snapshots: self.backend.list_state_snapshots(),
2262 })
2263 }
2264
2265 pub async fn anvil_remove_pool_transactions(&self, address: Address) -> Result<()> {
2266 node_info!("anvil_removePoolTransactions");
2267 self.pool.remove_transactions_by_address(address);
2268 Ok(())
2269 }
2270
2271 pub async fn anvil_reorg(&self, options: ReorgOptions) -> Result<()> {
2285 node_info!("anvil_reorg");
2286 let depth = options.depth;
2287 let tx_block_pairs = options.tx_block_pairs;
2288
2289 let current_height = self.backend.best_number();
2291 let common_height = current_height.checked_sub(depth).ok_or(BlockchainError::RpcError(
2292 RpcError::invalid_params(format!(
2293 "Reorg depth must not exceed current chain height: current height {current_height}, depth {depth}"
2294 )),
2295 ))?;
2296
2297 let common_block =
2299 self.backend.get_block(common_height).ok_or(BlockchainError::BlockNotFound)?;
2300
2301 let block_pool_txs = if tx_block_pairs.is_empty() {
2304 HashMap::default()
2305 } else {
2306 let mut pairs = tx_block_pairs;
2307
2308 if let Some((_, num)) = pairs.iter().find(|(_, num)| *num >= depth) {
2310 return Err(BlockchainError::RpcError(RpcError::invalid_params(format!(
2311 "Block number for reorg tx will exceed the reorged chain height. Block number {num} must not exceed (depth-1) {}",
2312 depth - 1
2313 ))));
2314 }
2315
2316 pairs.sort_by_key(|a| a.1);
2318
2319 let mut nonces: HashMap<Address, u64> = HashMap::default();
2322
2323 let mut txs: HashMap<u64, Vec<Arc<PoolTransaction>>> = HashMap::default();
2324 for pair in pairs {
2325 let (tx_data, block_index) = pair;
2326
2327 let pending = match tx_data {
2328 TransactionData::Raw(bytes) => {
2329 let mut data = bytes.as_ref();
2330 let decoded = TypedTransaction::decode_2718(&mut data)
2331 .map_err(|_| BlockchainError::FailedToDecodeSignedTransaction)?;
2332 PendingTransaction::new(decoded)?
2333 }
2334
2335 TransactionData::JSON(req) => {
2336 let mut tx_req = WithOtherFields::new(req);
2337 let from = tx_req.from.map(Ok).unwrap_or_else(|| {
2338 self.accounts()?
2339 .first()
2340 .copied()
2341 .ok_or(BlockchainError::NoSignerAvailable)
2342 })?;
2343
2344 let curr_nonce = nonces.entry(from).or_insert(
2346 self.get_transaction_count(
2347 from,
2348 Some(common_block.header.number.into()),
2349 )
2350 .await?,
2351 );
2352
2353 if tx_req.gas.is_none()
2355 && let Ok(gas) = self
2356 .estimate_gas(tx_req.clone(), None, EvmOverrides::default())
2357 .await
2358 {
2359 tx_req.gas = Some(gas.to());
2360 }
2361
2362 let typed = self.build_typed_tx_request(tx_req, *curr_nonce)?;
2364
2365 *curr_nonce += 1;
2367
2368 if self.is_impersonated(from) {
2370 let bypass_signature = self.impersonated_signature(&typed);
2371 let transaction =
2372 sign::build_typed_transaction(typed, bypass_signature)?;
2373 self.ensure_typed_transaction_supported(&transaction)?;
2374 PendingTransaction::with_impersonated(transaction, from)
2375 } else {
2376 let transaction = self.sign_request(&from, typed)?;
2377 self.ensure_typed_transaction_supported(&transaction)?;
2378 PendingTransaction::new(transaction)?
2379 }
2380 }
2381 };
2382
2383 let pooled = PoolTransaction::new(pending);
2384 txs.entry(block_index).or_default().push(Arc::new(pooled));
2385 }
2386
2387 txs
2388 };
2389
2390 self.backend.reorg(depth, block_pool_txs, common_block).await?;
2391 Ok(())
2392 }
2393
2394 pub async fn anvil_rollback(&self, depth: Option<u64>) -> Result<()> {
2405 node_info!("anvil_rollback");
2406 let depth = depth.unwrap_or(1);
2407
2408 let current_height = self.backend.best_number();
2410 let common_height = current_height.checked_sub(depth).ok_or(BlockchainError::RpcError(
2411 RpcError::invalid_params(format!(
2412 "Rollback depth must not exceed current chain height: current height {current_height}, depth {depth}"
2413 )),
2414 ))?;
2415
2416 let common_block =
2418 self.backend.get_block(common_height).ok_or(BlockchainError::BlockNotFound)?;
2419
2420 self.backend.rollback(common_block).await?;
2421 Ok(())
2422 }
2423
2424 pub async fn evm_snapshot(&self) -> Result<U256> {
2428 node_info!("evm_snapshot");
2429 Ok(self.backend.create_state_snapshot().await)
2430 }
2431
2432 pub async fn evm_revert(&self, id: U256) -> Result<bool> {
2437 node_info!("evm_revert");
2438 self.backend.revert_state_snapshot(id).await
2439 }
2440
2441 pub async fn evm_increase_time(&self, seconds: U256) -> Result<i64> {
2445 node_info!("evm_increaseTime");
2446 Ok(self.backend.time().increase_time(seconds.try_into().unwrap_or(u64::MAX)) as i64)
2447 }
2448
2449 pub fn evm_set_next_block_timestamp(&self, seconds: u64) -> Result<()> {
2453 node_info!("evm_setNextBlockTimestamp");
2454 self.backend.time().set_next_block_timestamp(seconds)
2455 }
2456
2457 pub fn evm_set_time(&self, timestamp: u64) -> Result<u64> {
2462 node_info!("evm_setTime");
2463 let now = self.backend.time().current_call_timestamp();
2464 self.backend.time().reset(timestamp);
2465
2466 let offset = timestamp.saturating_sub(now);
2468 Ok(Duration::from_millis(offset).as_secs())
2469 }
2470
2471 pub fn evm_set_block_gas_limit(&self, gas_limit: U256) -> Result<bool> {
2475 node_info!("evm_setBlockGasLimit");
2476 self.backend.set_gas_limit(gas_limit.to());
2477 Ok(true)
2478 }
2479
2480 pub fn evm_set_block_timestamp_interval(&self, seconds: u64) -> Result<()> {
2484 node_info!("anvil_setBlockTimestampInterval");
2485 self.backend.time().set_block_timestamp_interval(seconds);
2486 Ok(())
2487 }
2488
2489 pub fn evm_remove_block_timestamp_interval(&self) -> Result<bool> {
2493 node_info!("anvil_removeBlockTimestampInterval");
2494 Ok(self.backend.time().remove_block_timestamp_interval())
2495 }
2496
2497 pub async fn evm_mine(&self, opts: Option<MineOptions>) -> Result<String> {
2504 node_info!("evm_mine");
2505
2506 self.do_evm_mine(opts).await?;
2507
2508 Ok("0x0".to_string())
2509 }
2510
2511 pub async fn evm_mine_detailed(&self, opts: Option<MineOptions>) -> Result<Vec<AnyRpcBlock>> {
2521 node_info!("evm_mine_detailed");
2522
2523 let mined_blocks = self.do_evm_mine(opts).await?;
2524
2525 let mut blocks = Vec::with_capacity(mined_blocks as usize);
2526
2527 let latest = self.backend.best_number();
2528 for offset in (0..mined_blocks).rev() {
2529 let block_num = latest - offset;
2530 if let Some(mut block) =
2531 self.backend.block_by_number_full(BlockNumber::Number(block_num)).await?
2532 {
2533 let block_txs = match block.transactions_mut() {
2534 BlockTransactions::Full(txs) => txs,
2535 BlockTransactions::Hashes(_) | BlockTransactions::Uncle => unreachable!(),
2536 };
2537 for tx in block_txs.iter_mut() {
2538 if let Some(receipt) = self.backend.mined_transaction_receipt(tx.tx_hash())
2539 && let Some(output) = receipt.out
2540 {
2541 if !receipt
2543 .inner
2544 .inner
2545 .as_receipt_with_bloom()
2546 .receipt
2547 .status
2548 .coerce_status()
2549 && let Some(reason) = RevertDecoder::new().maybe_decode(&output, None)
2550 {
2551 tx.other.insert(
2552 "revertReason".to_string(),
2553 serde_json::to_value(reason).expect("Infallible"),
2554 );
2555 }
2556 tx.other.insert(
2557 "output".to_string(),
2558 serde_json::to_value(output).expect("Infallible"),
2559 );
2560 }
2561 }
2562 block.transactions = BlockTransactions::Full(block_txs.to_vec());
2563 blocks.push(block);
2564 }
2565 }
2566
2567 Ok(blocks)
2568 }
2569
2570 pub fn anvil_set_block(&self, block_number: u64) -> Result<()> {
2574 node_info!("anvil_setBlock");
2575 self.backend.set_block_number(block_number);
2576 Ok(())
2577 }
2578
2579 pub fn anvil_set_rpc_url(&self, url: String) -> Result<()> {
2583 node_info!("anvil_setRpcUrl");
2584 if let Some(fork) = self.backend.get_fork() {
2585 let mut config = fork.config.write();
2586 let new_provider = Arc::new(
2588 ProviderBuilder::new(&url).max_retry(10).initial_backoff(1000).build().map_err(
2589 |_| {
2590 TransportErrorKind::custom_str(
2591 format!("Failed to parse invalid url {url}").as_str(),
2592 )
2593 },
2594 )?, );
2597 config.provider = new_provider;
2598 trace!(target: "backend", "Updated fork rpc from \"{}\" to \"{}\"", config.eth_rpc_url, url);
2599 config.eth_rpc_url = url;
2600 }
2601 Ok(())
2602 }
2603
2604 pub async fn anvil_enable_traces(&self) -> Result<()> {
2609 node_info!("anvil_enableTraces");
2610 Err(BlockchainError::RpcUnimplemented)
2611 }
2612
2613 pub async fn eth_send_unsigned_transaction(
2617 &self,
2618 request: WithOtherFields<TransactionRequest>,
2619 ) -> Result<TxHash> {
2620 node_info!("eth_sendUnsignedTransaction");
2621 let from = request.from.ok_or(BlockchainError::NoSignerAvailable)?;
2623
2624 let (nonce, on_chain_nonce) = self.request_nonce(&request, from).await?;
2625
2626 let request = self.build_typed_tx_request(request, nonce)?;
2627
2628 let bypass_signature = self.impersonated_signature(&request);
2629 let transaction = sign::build_typed_transaction(request, bypass_signature)?;
2630
2631 self.ensure_typed_transaction_supported(&transaction)?;
2632
2633 let pending_transaction = PendingTransaction::with_impersonated(transaction, from);
2634
2635 self.backend.validate_pool_transaction(&pending_transaction).await?;
2637
2638 let requires = required_marker(nonce, on_chain_nonce, from);
2639 let provides = vec![to_marker(nonce, from)];
2640
2641 self.add_pending_transaction(pending_transaction, requires, provides)
2642 }
2643
2644 pub async fn txpool_status(&self) -> Result<TxpoolStatus> {
2650 node_info!("txpool_status");
2651 Ok(self.pool.txpool_status())
2652 }
2653
2654 pub async fn txpool_inspect(&self) -> Result<TxpoolInspect> {
2661 node_info!("txpool_inspect");
2662 let mut inspect = TxpoolInspect::default();
2663
2664 fn convert(tx: Arc<PoolTransaction>) -> TxpoolInspectSummary {
2665 let tx = &tx.pending_transaction.transaction;
2666 let to = tx.to();
2667 let gas_price = tx.gas_price();
2668 let value = tx.value();
2669 let gas = tx.gas_limit();
2670 TxpoolInspectSummary { to, value, gas, gas_price }
2671 }
2672
2673 for pending in self.pool.ready_transactions() {
2680 let entry = inspect.pending.entry(*pending.pending_transaction.sender()).or_default();
2681 let key = pending.pending_transaction.nonce().to_string();
2682 entry.insert(key, convert(pending));
2683 }
2684 for queued in self.pool.pending_transactions() {
2685 let entry = inspect.pending.entry(*queued.pending_transaction.sender()).or_default();
2686 let key = queued.pending_transaction.nonce().to_string();
2687 entry.insert(key, convert(queued));
2688 }
2689 Ok(inspect)
2690 }
2691
2692 pub async fn txpool_content(&self) -> Result<TxpoolContent<AnyRpcTransaction>> {
2699 node_info!("txpool_content");
2700 let mut content = TxpoolContent::<AnyRpcTransaction>::default();
2701 fn convert(tx: Arc<PoolTransaction>) -> Result<AnyRpcTransaction> {
2702 let from = *tx.pending_transaction.sender();
2703 let tx = transaction_build(
2704 Some(tx.hash()),
2705 tx.pending_transaction.transaction.clone(),
2706 None,
2707 None,
2708 None,
2709 );
2710
2711 let WithOtherFields { inner: mut tx, other } = tx.0;
2712
2713 tx.inner = Recovered::new_unchecked(tx.inner.into_inner(), from);
2716
2717 let tx = AnyRpcTransaction(WithOtherFields { inner: tx, other });
2718
2719 Ok(tx)
2720 }
2721
2722 for pending in self.pool.ready_transactions() {
2723 let entry = content.pending.entry(*pending.pending_transaction.sender()).or_default();
2724 let key = pending.pending_transaction.nonce().to_string();
2725 entry.insert(key, convert(pending)?);
2726 }
2727 for queued in self.pool.pending_transactions() {
2728 let entry = content.pending.entry(*queued.pending_transaction.sender()).or_default();
2729 let key = queued.pending_transaction.nonce().to_string();
2730 entry.insert(key, convert(queued)?);
2731 }
2732
2733 Ok(content)
2734 }
2735}
2736
2737impl EthApi {
2739 pub fn get_capabilities(&self) -> Result<WalletCapabilities> {
2745 node_info!("wallet_getCapabilities");
2746 Ok(self.backend.get_capabilities())
2747 }
2748
2749 pub async fn wallet_send_transaction(
2750 &self,
2751 mut request: WithOtherFields<TransactionRequest>,
2752 ) -> Result<TxHash> {
2753 node_info!("wallet_sendTransaction");
2754
2755 if request.value.is_some_and(|val| val > U256::ZERO) {
2758 return Err(WalletError::ValueNotZero.into());
2759 }
2760
2761 if request.from.is_some() {
2763 return Err(WalletError::FromSet.into());
2764 }
2765
2766 if request.nonce.is_some() {
2768 return Err(WalletError::NonceSet.into());
2769 }
2770
2771 let capabilities = self.backend.get_capabilities();
2772 let valid_delegations: &[Address] = capabilities
2773 .get(self.chain_id())
2774 .map(|caps| caps.delegation.addresses.as_ref())
2775 .unwrap_or_default();
2776
2777 if let Some(authorizations) = &request.authorization_list
2778 && authorizations.iter().any(|auth| !valid_delegations.contains(&auth.address))
2779 {
2780 return Err(WalletError::InvalidAuthorization.into());
2781 }
2782
2783 match (request.authorization_list.is_some(), request.to) {
2785 (false, Some(TxKind::Call(addr))) => {
2788 let acc = self.backend.get_account(addr).await?;
2789
2790 let delegated_address = acc
2791 .code
2792 .map(|code| match code {
2793 Bytecode::Eip7702(c) => c.address(),
2794 _ => Address::ZERO,
2795 })
2796 .unwrap_or_default();
2797
2798 if delegated_address == Address::ZERO
2800 || !valid_delegations.contains(&delegated_address)
2801 {
2802 return Err(WalletError::IllegalDestination.into());
2803 }
2804 }
2805 (true, _) => (),
2807 _ => return Err(WalletError::IllegalDestination.into()),
2809 }
2810
2811 let wallet = self.backend.executor_wallet().ok_or(WalletError::InternalError)?;
2812
2813 let from = NetworkWallet::<Ethereum>::default_signer_address(&wallet);
2814
2815 let nonce = self.get_transaction_count(from, Some(BlockId::latest())).await?;
2816
2817 request.nonce = Some(nonce);
2818
2819 let chain_id = self.chain_id();
2820
2821 request.chain_id = Some(chain_id);
2822
2823 request.from = Some(from);
2824
2825 let gas_limit_fut =
2826 self.estimate_gas(request.clone(), Some(BlockId::latest()), EvmOverrides::default());
2827
2828 let fees_fut = self.fee_history(
2829 U256::from(EIP1559_FEE_ESTIMATION_PAST_BLOCKS),
2830 BlockNumber::Latest,
2831 vec![EIP1559_FEE_ESTIMATION_REWARD_PERCENTILE],
2832 );
2833
2834 let (gas_limit, fees) = tokio::join!(gas_limit_fut, fees_fut);
2835
2836 let gas_limit = gas_limit?;
2837 let fees = fees?;
2838
2839 request.gas = Some(gas_limit.to());
2840
2841 let base_fee = fees.latest_block_base_fee().unwrap_or_default();
2842
2843 let estimation = eip1559_default_estimator(base_fee, &fees.reward.unwrap_or_default());
2844
2845 request.max_fee_per_gas = Some(estimation.max_fee_per_gas);
2846 request.max_priority_fee_per_gas = Some(estimation.max_priority_fee_per_gas);
2847 request.gas_price = None;
2848
2849 let envelope = request.build(&wallet).await.map_err(|_| WalletError::InternalError)?;
2850
2851 self.send_raw_transaction(envelope.encoded_2718().into()).await
2852 }
2853
2854 pub fn anvil_add_capability(&self, address: Address) -> Result<()> {
2858 node_info!("anvil_addCapability");
2859 self.backend.add_capability(address);
2860 Ok(())
2861 }
2862
2863 pub fn anvil_set_executor(&self, executor_pk: String) -> Result<Address> {
2864 node_info!("anvil_setExecutor");
2865 self.backend.set_executor(executor_pk)
2866 }
2867}
2868
2869impl EthApi {
2870 async fn on_blocking_task<C, F, R>(&self, c: C) -> Result<R>
2872 where
2873 C: FnOnce(Self) -> F,
2874 F: Future<Output = Result<R>> + Send + 'static,
2875 R: Send + 'static,
2876 {
2877 let (tx, rx) = oneshot::channel();
2878 let this = self.clone();
2879 let f = c(this);
2880 tokio::task::spawn_blocking(move || {
2881 tokio::runtime::Handle::current().block_on(async move {
2882 let res = f.await;
2883 let _ = tx.send(res);
2884 })
2885 });
2886 rx.await.map_err(|_| BlockchainError::Internal("blocking task panicked".to_string()))?
2887 }
2888
2889 async fn do_evm_mine(&self, opts: Option<MineOptions>) -> Result<u64> {
2891 let mut blocks_to_mine = 1u64;
2892
2893 if let Some(opts) = opts {
2894 let timestamp = match opts {
2895 MineOptions::Timestamp(timestamp) => timestamp,
2896 MineOptions::Options { timestamp, blocks } => {
2897 if let Some(blocks) = blocks {
2898 blocks_to_mine = blocks;
2899 }
2900 timestamp
2901 }
2902 };
2903 if let Some(timestamp) = timestamp {
2904 self.evm_set_next_block_timestamp(timestamp)?;
2906 }
2907 }
2908
2909 self.on_blocking_task(|this| async move {
2912 for _ in 0..blocks_to_mine {
2914 this.mine_one().await;
2915 }
2916 Ok(())
2917 })
2918 .await?;
2919
2920 Ok(blocks_to_mine)
2921 }
2922
2923 async fn do_estimate_gas(
2924 &self,
2925 request: WithOtherFields<TransactionRequest>,
2926 block_number: Option<BlockId>,
2927 overrides: EvmOverrides,
2928 ) -> Result<u128> {
2929 let block_request = self.block_request(block_number).await?;
2930 if let BlockRequest::Number(number) = block_request
2932 && let Some(fork) = self.get_fork()
2933 && fork.predates_fork(number)
2934 {
2935 if overrides.has_state() || overrides.has_block() {
2936 return Err(BlockchainError::EvmOverrideError(
2937 "not available on past forked blocks".to_string(),
2938 ));
2939 }
2940 return Ok(fork.estimate_gas(&request, Some(number.into())).await?);
2941 }
2942
2943 self.on_blocking_task(|this| async move {
2946 this.backend
2947 .with_database_at(Some(block_request), |state, mut block| {
2948 let mut cache_db = CacheDB::new(state);
2949 if let Some(state_overrides) = overrides.state {
2950 state::apply_state_overrides(
2951 state_overrides.into_iter().collect(),
2952 &mut cache_db,
2953 )?;
2954 }
2955 if let Some(block_overrides) = overrides.block {
2956 state::apply_block_overrides(*block_overrides, &mut cache_db, &mut block);
2957 }
2958 this.do_estimate_gas_with_state(request, cache_db.as_dyn(), block)
2959 })
2960 .await?
2961 })
2962 .await
2963 }
2964
2965 fn do_estimate_gas_with_state(
2969 &self,
2970 mut request: WithOtherFields<TransactionRequest>,
2971 state: &dyn DatabaseRef<Error = DatabaseError>,
2972 block_env: BlockEnv,
2973 ) -> Result<u128> {
2974 let to = request.to.as_ref().and_then(TxKind::to);
2977
2978 let maybe_transfer = (request.input.input().is_none()
2980 || request.input.input().is_some_and(|data| data.is_empty()))
2981 && request.authorization_list.is_none()
2982 && request.access_list.is_none()
2983 && request.blob_versioned_hashes.is_none();
2984
2985 if maybe_transfer
2986 && let Some(to) = to
2987 && let Ok(target_code) = self.backend.get_code_with_state(&state, *to)
2988 && target_code.as_ref().is_empty()
2989 {
2990 return Ok(MIN_TRANSACTION_GAS);
2991 }
2992
2993 let fees = FeeDetails::new(
2994 request.gas_price,
2995 request.max_fee_per_gas,
2996 request.max_priority_fee_per_gas,
2997 request.max_fee_per_blob_gas,
2998 )?
2999 .or_zero_fees();
3000
3001 let mut highest_gas_limit = request.gas.map_or(block_env.gas_limit.into(), |g| g as u128);
3004
3005 let gas_price = fees.gas_price.unwrap_or_default();
3006 if gas_price > 0
3008 && let Some(from) = request.from
3009 {
3010 let mut available_funds = self.backend.get_balance_with_state(state, from)?;
3011 if let Some(value) = request.value {
3012 if value > available_funds {
3013 return Err(InvalidTransactionError::InsufficientFunds.into());
3014 }
3015 available_funds -= value;
3017 }
3018 let allowance = available_funds.checked_div(U256::from(gas_price)).unwrap_or_default();
3020 highest_gas_limit = std::cmp::min(highest_gas_limit, allowance.saturating_to());
3021 }
3022
3023 let mut call_to_estimate = request.clone();
3024 call_to_estimate.gas = Some(highest_gas_limit as u64);
3025
3026 let ethres =
3028 self.backend.call_with_state(&state, call_to_estimate, fees.clone(), block_env.clone());
3029
3030 let gas_used = match ethres.try_into()? {
3031 GasEstimationCallResult::Success(gas) => Ok(gas),
3032 GasEstimationCallResult::OutOfGas => {
3033 Err(InvalidTransactionError::BasicOutOfGas(highest_gas_limit).into())
3034 }
3035 GasEstimationCallResult::Revert(output) => {
3036 Err(InvalidTransactionError::Revert(output).into())
3037 }
3038 GasEstimationCallResult::EvmError(err) => {
3039 warn!(target: "node", "estimation failed due to {:?}", err);
3040 Err(BlockchainError::EvmError(err))
3041 }
3042 }?;
3043
3044 let mut lowest_gas_limit = determine_base_gas_by_kind(&request);
3051
3052 let mut mid_gas_limit =
3054 std::cmp::min(gas_used * 3, (highest_gas_limit + lowest_gas_limit) / 2);
3055
3056 while (highest_gas_limit - lowest_gas_limit) > 1 {
3058 request.gas = Some(mid_gas_limit as u64);
3059 let ethres = self.backend.call_with_state(
3060 &state,
3061 request.clone(),
3062 fees.clone(),
3063 block_env.clone(),
3064 );
3065
3066 match ethres.try_into()? {
3067 GasEstimationCallResult::Success(_) => {
3068 highest_gas_limit = mid_gas_limit;
3072 }
3073 GasEstimationCallResult::OutOfGas
3074 | GasEstimationCallResult::Revert(_)
3075 | GasEstimationCallResult::EvmError(_) => {
3076 lowest_gas_limit = mid_gas_limit;
3083 }
3084 };
3085 mid_gas_limit = (highest_gas_limit + lowest_gas_limit) / 2;
3087 }
3088
3089 trace!(target : "node", "Estimated Gas for call {:?}", highest_gas_limit);
3090
3091 Ok(highest_gas_limit)
3092 }
3093
3094 pub fn set_transaction_order(&self, order: TransactionOrder) {
3096 *self.transaction_order.write() = order;
3097 }
3098
3099 fn transaction_priority(&self, tx: &TypedTransaction) -> TransactionPriority {
3101 self.transaction_order.read().priority(tx)
3102 }
3103
3104 pub fn chain_id(&self) -> u64 {
3106 self.backend.chain_id().to::<u64>()
3107 }
3108
3109 pub fn get_fork(&self) -> Option<ClientFork> {
3111 self.backend.get_fork()
3112 }
3113
3114 pub fn instance_id(&self) -> B256 {
3116 *self.instance_id.read()
3117 }
3118
3119 pub fn reset_instance_id(&self) {
3121 *self.instance_id.write() = B256::random();
3122 }
3123
3124 #[expect(clippy::borrowed_box)]
3126 pub fn get_signer(&self, address: Address) -> Option<&Box<dyn Signer>> {
3127 self.signers.iter().find(|signer| signer.is_signer_for(address))
3128 }
3129
3130 pub fn new_block_notifications(&self) -> NewBlockNotifications {
3132 self.backend.new_block_notifications()
3133 }
3134
3135 pub fn new_ready_transactions(&self) -> Receiver<TxHash> {
3137 self.pool.add_ready_listener()
3138 }
3139
3140 pub fn full_pending_transactions(&self) -> UnboundedReceiver<AnyRpcTransaction> {
3142 let (tx, rx) = unbounded_channel();
3143 let mut hashes = self.new_ready_transactions();
3144
3145 let this = self.clone();
3146
3147 tokio::spawn(async move {
3148 while let Some(hash) = hashes.next().await {
3149 if let Ok(Some(txn)) = this.transaction_by_hash(hash).await
3150 && tx.send(txn).is_err()
3151 {
3152 break;
3153 }
3154 }
3155 });
3156
3157 rx
3158 }
3159
3160 pub fn storage_info(&self) -> StorageInfo {
3162 StorageInfo::new(Arc::clone(&self.backend))
3163 }
3164
3165 pub fn is_fork(&self) -> bool {
3167 self.backend.is_fork()
3168 }
3169
3170 pub async fn mine_one(&self) {
3172 let transactions = self.pool.ready_transactions().collect::<Vec<_>>();
3173 let outcome = self.backend.mine_block(transactions).await;
3174
3175 trace!(target: "node", blocknumber = ?outcome.block_number, "mined block");
3176 self.pool.on_mined_block(outcome);
3177 }
3178
3179 async fn pending_block(&self) -> AnyRpcBlock {
3181 let transactions = self.pool.ready_transactions().collect::<Vec<_>>();
3182 let info = self.backend.pending_block(transactions).await;
3183 self.backend.convert_block(info.block)
3184 }
3185
3186 async fn pending_block_full(&self) -> Option<AnyRpcBlock> {
3188 let transactions = self.pool.ready_transactions().collect::<Vec<_>>();
3189 let BlockInfo { block, transactions, receipts: _ } =
3190 self.backend.pending_block(transactions).await;
3191
3192 let mut partial_block = self.backend.convert_block(block.clone());
3193
3194 let mut block_transactions = Vec::with_capacity(block.transactions.len());
3195 let base_fee = self.backend.base_fee();
3196
3197 for info in transactions {
3198 let tx = block.transactions.get(info.transaction_index as usize)?.clone();
3199
3200 let tx = transaction_build(
3201 Some(info.transaction_hash),
3202 tx,
3203 Some(&block),
3204 Some(info),
3205 Some(base_fee),
3206 );
3207 block_transactions.push(tx);
3208 }
3209
3210 partial_block.transactions = BlockTransactions::from(block_transactions);
3211
3212 Some(partial_block)
3213 }
3214
3215 fn build_typed_tx_request(
3216 &self,
3217 request: WithOtherFields<TransactionRequest>,
3218 nonce: u64,
3219 ) -> Result<TypedTransactionRequest> {
3220 let chain_id = request.chain_id.unwrap_or_else(|| self.chain_id());
3221 let max_fee_per_gas = request.max_fee_per_gas;
3222 let max_fee_per_blob_gas = request.max_fee_per_blob_gas;
3223 let gas_price = request.gas_price;
3224
3225 let gas_limit = request.gas.unwrap_or_else(|| self.backend.gas_limit());
3226 let from = request.from;
3227
3228 let request = match transaction_request_to_typed(request) {
3229 Some(TypedTransactionRequest::Legacy(mut m)) => {
3230 m.nonce = nonce;
3231 m.chain_id = Some(chain_id);
3232 m.gas_limit = gas_limit;
3233 if gas_price.is_none() {
3234 m.gas_price = self.gas_price();
3235 }
3236 TypedTransactionRequest::Legacy(m)
3237 }
3238 Some(TypedTransactionRequest::EIP2930(mut m)) => {
3239 m.nonce = nonce;
3240 m.chain_id = chain_id;
3241 m.gas_limit = gas_limit;
3242 if gas_price.is_none() {
3243 m.gas_price = self.gas_price();
3244 }
3245 TypedTransactionRequest::EIP2930(m)
3246 }
3247 Some(TypedTransactionRequest::EIP1559(mut m)) => {
3248 m.nonce = nonce;
3249 m.chain_id = chain_id;
3250 m.gas_limit = gas_limit;
3251 if max_fee_per_gas.is_none() {
3252 m.max_fee_per_gas = self.gas_price();
3253 }
3254 TypedTransactionRequest::EIP1559(m)
3255 }
3256 Some(TypedTransactionRequest::EIP7702(mut m)) => {
3257 m.nonce = nonce;
3258 m.chain_id = chain_id;
3259 m.gas_limit = gas_limit;
3260 if max_fee_per_gas.is_none() {
3261 m.max_fee_per_gas = self.gas_price();
3262 }
3263 TypedTransactionRequest::EIP7702(m)
3264 }
3265 Some(TypedTransactionRequest::EIP4844(m)) => {
3266 TypedTransactionRequest::EIP4844(match m {
3267 TxEip4844Variant::TxEip4844WithSidecar(mut m) => {
3269 m.tx.nonce = nonce;
3270 m.tx.chain_id = chain_id;
3271 m.tx.gas_limit = gas_limit;
3272 if max_fee_per_gas.is_none() {
3273 m.tx.max_fee_per_gas = self.gas_price();
3274 }
3275 if max_fee_per_blob_gas.is_none() {
3276 m.tx.max_fee_per_blob_gas = self
3277 .excess_blob_gas_and_price()
3278 .unwrap_or_default()
3279 .map_or(0, |g| g.blob_gasprice)
3280 }
3281 TxEip4844Variant::TxEip4844WithSidecar(m)
3282 }
3283 TxEip4844Variant::TxEip4844(mut tx) => {
3284 if !self.backend.skip_blob_validation(from) {
3285 return Err(BlockchainError::FailedToDecodeTransaction);
3286 }
3287
3288 tx.nonce = nonce;
3290 tx.chain_id = chain_id;
3291 tx.gas_limit = gas_limit;
3292 if max_fee_per_gas.is_none() {
3293 tx.max_fee_per_gas = self.gas_price();
3294 }
3295 if max_fee_per_blob_gas.is_none() {
3296 tx.max_fee_per_blob_gas = self
3297 .excess_blob_gas_and_price()
3298 .unwrap_or_default()
3299 .map_or(0, |g| g.blob_gasprice)
3300 }
3301
3302 TxEip4844Variant::TxEip4844(tx)
3303 }
3304 })
3305 }
3306 Some(TypedTransactionRequest::Deposit(mut m)) => {
3307 m.gas_limit = gas_limit;
3308 TypedTransactionRequest::Deposit(m)
3309 }
3310 None => return Err(BlockchainError::FailedToDecodeTransaction),
3311 };
3312 Ok(request)
3313 }
3314
3315 pub fn is_impersonated(&self, addr: Address) -> bool {
3317 self.backend.cheats().is_impersonated(addr)
3318 }
3319
3320 fn impersonated_signature(&self, request: &TypedTransactionRequest) -> Signature {
3322 match request {
3323 TypedTransactionRequest::Legacy(_) => Signature::from_scalars_and_parity(
3326 B256::with_last_byte(1),
3327 B256::with_last_byte(1),
3328 false,
3329 ),
3330 TypedTransactionRequest::EIP2930(_)
3331 | TypedTransactionRequest::EIP1559(_)
3332 | TypedTransactionRequest::EIP7702(_)
3333 | TypedTransactionRequest::EIP4844(_)
3334 | TypedTransactionRequest::Deposit(_) => Signature::from_scalars_and_parity(
3335 B256::with_last_byte(1),
3336 B256::with_last_byte(1),
3337 false,
3338 ),
3339 }
3340 }
3341
3342 async fn get_transaction_count(
3344 &self,
3345 address: Address,
3346 block_number: Option<BlockId>,
3347 ) -> Result<u64> {
3348 let block_request = self.block_request(block_number).await?;
3349
3350 if let BlockRequest::Number(number) = block_request
3351 && let Some(fork) = self.get_fork()
3352 && fork.predates_fork(number)
3353 {
3354 return Ok(fork.get_nonce(address, number).await?);
3355 }
3356
3357 self.backend.get_nonce(address, block_request).await
3358 }
3359
3360 async fn request_nonce(
3368 &self,
3369 request: &TransactionRequest,
3370 from: Address,
3371 ) -> Result<(u64, u64)> {
3372 let highest_nonce =
3373 self.get_transaction_count(from, Some(BlockId::Number(BlockNumber::Pending))).await?;
3374 let nonce = request.nonce.unwrap_or(highest_nonce);
3375
3376 Ok((nonce, highest_nonce))
3377 }
3378
3379 fn add_pending_transaction(
3381 &self,
3382 pending_transaction: PendingTransaction,
3383 requires: Vec<TxMarker>,
3384 provides: Vec<TxMarker>,
3385 ) -> Result<TxHash> {
3386 let from = *pending_transaction.sender();
3387 let priority = self.transaction_priority(&pending_transaction.transaction);
3388 let pool_transaction =
3389 PoolTransaction { requires, provides, pending_transaction, priority };
3390 let tx = self.pool.add_transaction(pool_transaction)?;
3391 trace!(target: "node", "Added transaction: [{:?}] sender={:?}", tx.hash(), from);
3392 Ok(*tx.hash())
3393 }
3394
3395 pub async fn state_root(&self) -> Option<B256> {
3397 self.backend.get_db().read().await.maybe_state_root()
3398 }
3399
3400 fn ensure_typed_transaction_supported(&self, tx: &TypedTransaction) -> Result<()> {
3402 match &tx {
3403 TypedTransaction::EIP2930(_) => self.backend.ensure_eip2930_active(),
3404 TypedTransaction::EIP1559(_) => self.backend.ensure_eip1559_active(),
3405 TypedTransaction::EIP4844(_) => self.backend.ensure_eip4844_active(),
3406 TypedTransaction::EIP7702(_) => self.backend.ensure_eip7702_active(),
3407 TypedTransaction::Deposit(_) => self.backend.ensure_op_deposits_active(),
3408 TypedTransaction::Legacy(_) => Ok(()),
3409 }
3410 }
3411}
3412
3413fn required_marker(provided_nonce: u64, on_chain_nonce: u64, from: Address) -> Vec<TxMarker> {
3414 if provided_nonce == on_chain_nonce {
3415 return Vec::new();
3416 }
3417 let prev_nonce = provided_nonce.saturating_sub(1);
3418 if on_chain_nonce <= prev_nonce { vec![to_marker(prev_nonce, from)] } else { Vec::new() }
3419}
3420
3421fn convert_transact_out(out: &Option<Output>) -> Bytes {
3422 match out {
3423 None => Default::default(),
3424 Some(Output::Call(out)) => out.to_vec().into(),
3425 Some(Output::Create(out, _)) => out.to_vec().into(),
3426 }
3427}
3428
3429fn ensure_return_ok(exit: InstructionResult, out: &Option<Output>) -> Result<Bytes> {
3431 let out = convert_transact_out(out);
3432 match exit {
3433 return_ok!() => Ok(out),
3434 return_revert!() => Err(InvalidTransactionError::Revert(Some(out.0.into())).into()),
3435 reason => Err(BlockchainError::EvmError(reason)),
3436 }
3437}
3438
3439fn determine_base_gas_by_kind(request: &WithOtherFields<TransactionRequest>) -> u128 {
3441 match transaction_request_to_typed(request.clone()) {
3442 Some(request) => match request {
3443 TypedTransactionRequest::Legacy(req) => match req.to {
3444 TxKind::Call(_) => MIN_TRANSACTION_GAS,
3445 TxKind::Create => MIN_CREATE_GAS,
3446 },
3447 TypedTransactionRequest::EIP1559(req) => match req.to {
3448 TxKind::Call(_) => MIN_TRANSACTION_GAS,
3449 TxKind::Create => MIN_CREATE_GAS,
3450 },
3451 TypedTransactionRequest::EIP7702(req) => {
3452 MIN_TRANSACTION_GAS
3453 + req.authorization_list.len() as u128 * PER_EMPTY_ACCOUNT_COST as u128
3454 }
3455 TypedTransactionRequest::EIP2930(req) => match req.to {
3456 TxKind::Call(_) => MIN_TRANSACTION_GAS,
3457 TxKind::Create => MIN_CREATE_GAS,
3458 },
3459 TypedTransactionRequest::EIP4844(_) => MIN_TRANSACTION_GAS,
3460 TypedTransactionRequest::Deposit(req) => match req.to {
3461 TxKind::Call(_) => MIN_TRANSACTION_GAS,
3462 TxKind::Create => MIN_CREATE_GAS,
3463 },
3464 },
3465 _ => MIN_CREATE_GAS,
3468 }
3469}
3470
3471enum GasEstimationCallResult {
3473 Success(u128),
3474 OutOfGas,
3475 Revert(Option<Bytes>),
3476 EvmError(InstructionResult),
3477}
3478
3479impl TryFrom<Result<(InstructionResult, Option<Output>, u128, State)>> for GasEstimationCallResult {
3483 type Error = BlockchainError;
3484
3485 fn try_from(res: Result<(InstructionResult, Option<Output>, u128, State)>) -> Result<Self> {
3486 match res {
3487 Err(BlockchainError::InvalidTransaction(InvalidTransactionError::GasTooHigh(_))) => {
3489 Ok(Self::OutOfGas)
3490 }
3491 Err(err) => Err(err),
3492 Ok((exit, output, gas, _)) => match exit {
3493 return_ok!() | InstructionResult::CallOrCreate => Ok(Self::Success(gas)),
3494
3495 InstructionResult::Revert => Ok(Self::Revert(output.map(|o| o.into_data()))),
3497 InstructionResult::CallTooDeep
3498 | InstructionResult::OutOfFunds
3499 | InstructionResult::CreateInitCodeStartingEF00
3500 | InstructionResult::InvalidEOFInitCode
3501 | InstructionResult::InvalidExtDelegateCallTarget => Ok(Self::EvmError(exit)),
3502
3503 InstructionResult::OutOfGas
3505 | InstructionResult::MemoryOOG
3506 | InstructionResult::MemoryLimitOOG
3507 | InstructionResult::PrecompileOOG
3508 | InstructionResult::InvalidOperandOOG
3509 | InstructionResult::ReentrancySentryOOG => Ok(Self::OutOfGas),
3510
3511 InstructionResult::OpcodeNotFound
3513 | InstructionResult::CallNotAllowedInsideStatic
3514 | InstructionResult::StateChangeDuringStaticCall
3515 | InstructionResult::InvalidFEOpcode
3516 | InstructionResult::InvalidJump
3517 | InstructionResult::NotActivated
3518 | InstructionResult::StackUnderflow
3519 | InstructionResult::StackOverflow
3520 | InstructionResult::OutOfOffset
3521 | InstructionResult::CreateCollision
3522 | InstructionResult::OverflowPayment
3523 | InstructionResult::PrecompileError
3524 | InstructionResult::NonceOverflow
3525 | InstructionResult::CreateContractSizeLimit
3526 | InstructionResult::CreateContractStartingWithEF
3527 | InstructionResult::CreateInitCodeSizeLimit
3528 | InstructionResult::FatalExternalError
3529 | InstructionResult::ReturnContractInNotInitEOF
3530 | InstructionResult::EOFOpcodeDisabledInLegacy
3531 | InstructionResult::SubRoutineStackOverflow
3532 | InstructionResult::EofAuxDataOverflow
3533 | InstructionResult::EofAuxDataTooSmall
3534 | InstructionResult::InvalidEXTCALLTarget => Ok(Self::EvmError(exit)),
3535 },
3536 }
3537 }
3538}