1use crate::{
2 api_server::{
3 ApiRequest,
4 error::{Error, Result, ToRpcResponseResult},
5 filters::{
6 BlockFilter, BlockNotifications, EthFilter, Filters, LogsFilter,
7 PendingTransactionsFilter, eviction_task,
8 },
9 revive_conversions::{
10 AlloyU256, ReviveAddress, ReviveBlockId, ReviveBlockNumberOrTag, ReviveBytes,
11 ReviveFilter, ReviveTrace, ReviveTracerType, SubstrateU256,
12 convert_to_generic_transaction,
13 },
14 signer::DevSigner,
15 trace_helpers::{parity_block_trace_builder, parity_transaction_trace_builder},
16 txpool_helpers::{
17 TxpoolTransactionInfo, extract_sender, extract_tx_info, extract_tx_summary,
18 transaction_matches_eth_hash,
19 },
20 },
21 logging::LoggingManager,
22 macros::node_info,
23 substrate_node::{
24 host::recover_maybe_impersonated_address,
25 impersonation::ImpersonationManager,
26 in_mem_rpc::InMemoryRpcClient,
27 mining_engine::MiningEngine,
28 revert::{RevertInfo, RevertManager},
29 service::{
30 BackendError, BackendWithOverlay, Client, Service, TransactionPoolHandle,
31 storage::{
32 AccountType, BytecodeType, CodeInfo, ContractInfo, ReviveAccountInfo,
33 SystemAccountInfo,
34 },
35 },
36 },
37};
38use alloy_dyn_abi::TypedData;
39use alloy_eips::{BlockId, BlockNumberOrTag};
40use alloy_primitives::{Address, B256, U64, U256};
41use alloy_rpc_types::{
42 Filter, TransactionRequest,
43 anvil::{Forking, Metadata as AnvilMetadata, MineOptions, NodeEnvironment, NodeInfo},
44 trace::{
45 geth::{GethDebugTracingCallOptions, GethDebugTracingOptions, GethTrace, TraceResult},
46 parity::LocalizedTransactionTrace,
47 },
48 txpool::{TxpoolContent, TxpoolInspect, TxpoolStatus},
49};
50use alloy_serde::WithOtherFields;
51use alloy_trie::{EMPTY_ROOT_HASH, KECCAK_EMPTY, TrieAccount};
52use anvil_core::eth::{EthRequest, Params as AnvilCoreParams};
53use anvil_rpc::response::ResponseResult;
54use chrono::{DateTime, Datelike, Utc};
55use codec::{Decode, Encode};
56use futures::{StreamExt, channel::mpsc};
57use indexmap::IndexMap;
58use pallet_revive_eth_rpc::{
59 BlockInfoProvider, EthRpcError, ReceiptExtractor, ReceiptProvider, SubxtBlockInfoProvider,
60 client::{Client as EthRpcClient, ClientError, SubscriptionType},
61 subxt_client::{
62 self, SrcChainConfig, runtime_types::bounded_collections::bounded_vec::BoundedVec,
63 },
64};
65use polkadot_sdk::{
66 pallet_revive::{
67 ReviveApi,
68 evm::{
69 self, Block, BlockNumberOrTagOrHash, BlockTag, Bytes, CallTracerConfig,
70 FeeHistoryResult, FilterResults, Log, ReceiptInfo, TracerType, TransactionInfo,
71 TransactionSigned,
72 },
73 },
74 parachains_common::{AccountId, Hash, Nonce},
75 polkadot_sdk_frame::runtime::types_common::OpaqueBlock,
76 sc_client_api::HeaderBackend,
77 sc_service::{InPoolTransaction, SpawnTaskHandle, TransactionPool},
78 sp_api::{Metadata as _, ProvideRuntimeApi},
79 sp_blockchain::Info,
80 sp_core::{self, Hasher, keccak_256},
81 sp_runtime::{FixedU128, traits::BlakeTwo256},
82};
83use revm::primitives::hardfork::SpecId;
84use sqlx::sqlite::SqlitePoolOptions;
85use std::{collections::BTreeSet, sync::Arc, time::Duration};
86use substrate_runtime::{Balance, constants::NATIVE_TO_ETH_RATIO};
87use subxt::{
88 Metadata as SubxtMetadata, OnlineClient, backend::rpc::RpcClient,
89 client::RuntimeVersion as SubxtRuntimeVersion, config::substrate::H256,
90 ext::subxt_rpcs::LegacyRpcMethods, utils::H160,
91};
92use subxt_signer::eth::Keypair;
93use tokio::try_join;
94
95pub const CLIENT_VERSION: &str = concat!("anvil-polkadot/v", env!("CARGO_PKG_VERSION"));
96const TIMEOUT_DURATION: Duration = Duration::from_secs(30);
97
98pub struct ApiServer {
99 eth_rpc_client: EthRpcClient,
100 req_receiver: mpsc::Receiver<ApiRequest>,
101 backend: BackendWithOverlay,
102 logging_manager: LoggingManager,
103 client: Arc<Client>,
104 mining_engine: Arc<MiningEngine>,
105 wallet: DevSigner,
106 block_provider: SubxtBlockInfoProvider,
107 revert_manager: RevertManager,
108 impersonation_manager: ImpersonationManager,
109 tx_pool: Arc<TransactionPoolHandle>,
110 instance_id: B256,
111 filters: Filters,
113}
114
115impl ApiServer {
116 #[allow(clippy::too_many_arguments)]
117 pub async fn new(
118 substrate_service: Service,
119 req_receiver: mpsc::Receiver<ApiRequest>,
120 logging_manager: LoggingManager,
121 revert_manager: RevertManager,
122 impersonation_manager: ImpersonationManager,
123 signers: Vec<Keypair>,
124 filters: Filters,
125 revive_rpc_block_limit: Option<usize>,
126 ) -> Result<Self> {
127 let rpc_client = RpcClient::new(InMemoryRpcClient(substrate_service.rpc_handlers.clone()));
128 let api = create_online_client(&substrate_service, rpc_client.clone()).await?;
129 let rpc = LegacyRpcMethods::<SrcChainConfig>::new(rpc_client.clone());
130 let block_provider = SubxtBlockInfoProvider::new(api.clone(), rpc.clone()).await?;
131 let eth_rpc_client = create_revive_rpc_client(
132 api.clone(),
133 rpc_client.clone(),
134 rpc,
135 block_provider.clone(),
136 substrate_service.spawn_handle.clone(),
137 revive_rpc_block_limit,
138 )
139 .await?;
140
141 let filters_clone = filters.clone();
142 substrate_service.spawn_handle.spawn("filter-eviction-task", "None", async move {
143 eviction_task(filters_clone).await;
144 });
145 Ok(Self {
146 block_provider,
147 req_receiver,
148 logging_manager,
149 backend: BackendWithOverlay::new(
150 substrate_service.backend.clone(),
151 substrate_service.storage_overrides.clone(),
152 ),
153 client: substrate_service.client.clone(),
154 mining_engine: substrate_service.mining_engine.clone(),
155 eth_rpc_client,
156 revert_manager,
157 impersonation_manager,
158 tx_pool: substrate_service.tx_pool.clone(),
159 wallet: DevSigner::new(signers)?,
160 instance_id: B256::random(),
161 filters,
162 })
163 }
164
165 pub async fn run(mut self) {
166 while let Some(msg) = self.req_receiver.next().await {
167 let resp = self.execute(msg.req).await;
168
169 if let Err(resp) = msg.resp_sender.send(resp) {
170 node_info!("Request was cancelled before sending the response: {:?}", resp);
171 }
172 }
173 }
174
175 pub async fn execute(&mut self, req: EthRequest) -> ResponseResult {
176 let res = match req.clone() {
177 EthRequest::SetLogging(enabled) => self.set_logging(enabled).to_rpc_result(),
178 EthRequest::SetNextBlockBaseFeePerGas(base_fee) => {
180 node_info!("evm_setNextBlockBaseFeePerGas");
181 let latest_block = self.latest_block();
182 self.backend.inject_next_fee_multiplier(
185 latest_block,
186 FixedU128::from_rational(base_fee.to::<u128>(), NATIVE_TO_ETH_RATIO.into()),
187 );
188 Ok(()).to_rpc_result()
189 }
190
191 EthRequest::Mine(blocks, interval) => self.mine(blocks, interval).await.to_rpc_result(),
193 EthRequest::SetIntervalMining(interval) => {
194 self.set_interval_mining(interval).to_rpc_result()
195 }
196 EthRequest::GetIntervalMining(_) => self.get_interval_mining().to_rpc_result(),
197 EthRequest::GetAutoMine(_) => self.get_auto_mine().to_rpc_result(),
198 EthRequest::SetAutomine(enabled) => self.set_auto_mine(enabled).to_rpc_result(),
199 EthRequest::EvmMine(mine) => self.evm_mine(mine).await.to_rpc_result(),
200 EthRequest::EvmMineDetailed(mine) => self.evm_mine_detailed(mine).await.to_rpc_result(),
201
202 EthRequest::SetCoinbase(address) => {
204 node_info!("anvil_setCoinbase");
205 let latest_block = self.latest_block();
206 let account_id = self
207 .client
208 .runtime_api()
209 .account_id(latest_block, H160::from_slice(address.as_slice()))
210 .map_err(Error::RuntimeApi);
211 account_id
212 .map(|inner| self.backend.inject_aura_authority(latest_block, inner))
213 .to_rpc_result()
214 }
215 EthRequest::EthCoinbase(()) => {
216 node_info!("eth_coinbase");
217 let latest_block = self.latest_block();
218 let authority =
219 self.backend.read_aura_authority(latest_block).map_err(Error::Backend);
220 authority
221 .and_then(|inner| {
222 self.client
223 .runtime_api()
224 .address(latest_block, inner)
225 .map_err(Error::RuntimeApi)
226 })
227 .map(|inner| Address::from(inner.to_fixed_bytes()))
228 .to_rpc_result()
229 }
230
231 EthRequest::EvmSetBlockTimeStampInterval(time) => {
233 self.set_block_timestamp_interval(time).to_rpc_result()
234 }
235 EthRequest::EvmRemoveBlockTimeStampInterval(_) => {
236 self.remove_block_timestamp_interval().to_rpc_result()
237 }
238 EthRequest::EvmSetNextBlockTimeStamp(time) => {
239 self.set_next_block_timestamp(time).to_rpc_result()
240 }
241 EthRequest::EvmIncreaseTime(time) => self.increase_time(time).to_rpc_result(),
242 EthRequest::EvmSetTime(timestamp) => self.set_time(timestamp).to_rpc_result(),
243
244 EthRequest::ImpersonateAccount(addr) => {
246 self.impersonate_account(H160::from_slice(addr.0.as_ref())).to_rpc_result()
247 }
248 EthRequest::StopImpersonatingAccount(addr) => {
249 self.stop_impersonating_account(&H160::from_slice(addr.0.as_ref())).to_rpc_result()
250 }
251 EthRequest::AutoImpersonateAccount(enable) => {
252 self.auto_impersonate_account(enable).to_rpc_result()
253 }
254 EthRequest::EthSendUnsignedTransaction(request) => {
255 node_info!("eth_sendUnsignedTransaction");
256 self.send_transaction(*request.clone(), true).await.to_rpc_result()
257 }
258
259 EthRequest::EthChainId(_) => self.eth_chain_id().to_rpc_result(),
261 EthRequest::EthNetworkId(_) => self.network_id().to_rpc_result(),
262 EthRequest::NetListening(_) => self.net_listening().to_rpc_result(),
263 EthRequest::EthSyncing(_) => self.syncing().to_rpc_result(),
264 EthRequest::EthGetTransactionReceipt(tx_hash) => {
265 self.transaction_receipt(tx_hash).await.to_rpc_result()
266 }
267 EthRequest::EthGetBalance(addr, block) => {
268 self.get_balance(addr, block).await.to_rpc_result()
269 }
270 EthRequest::EthGetStorageAt(addr, slot, block) => {
271 self.get_storage_at(addr, slot, block).await.to_rpc_result()
272 }
273 EthRequest::EthGetCodeAt(addr, block) => {
274 self.get_code(addr, block).await.to_rpc_result()
275 }
276 EthRequest::EthGetBlockByHash(hash, full) => {
277 self.get_block_by_hash(hash, full).await.to_rpc_result()
278 }
279 EthRequest::EthEstimateGas(call, block, _overrides, _block_overrides) => {
280 self.estimate_gas(call, block).await.to_rpc_result()
281 }
282 EthRequest::EthCall(call, block, _, _) => self.call(call, block).await.to_rpc_result(),
283 EthRequest::EthSendTransaction(request) => {
284 self.send_transaction(*request.clone(), false).await.to_rpc_result()
285 }
286 EthRequest::EthSendTransactionSync(request) => {
287 self.send_transaction_sync(*request).await.to_rpc_result()
288 }
289 EthRequest::EthGasPrice(()) => self.gas_price().await.to_rpc_result(),
290 EthRequest::EthGetBlockByNumber(num, hydrated) => {
291 node_info!("eth_getBlockByNumber");
292 self.get_block_by_number(num, hydrated).await.to_rpc_result()
293 }
294 EthRequest::EthGetTransactionCount(addr, block) => self
295 .get_transaction_count(ReviveAddress::from(addr).inner(), block)
296 .await
297 .map(|val| AlloyU256::from(val).inner())
298 .to_rpc_result(),
299 EthRequest::EthBlockNumber(()) => {
300 node_info!("eth_blockNumber");
301 Ok(U256::from(self.client.info().best_number)).to_rpc_result()
302 }
303 EthRequest::EthGetTransactionCountByHash(hash) => {
304 node_info!("eth_getBlockTransactionCountByHash");
305 self.get_block_transaction_count_by_hash(hash).await.to_rpc_result()
306 }
307 EthRequest::EthGetTransactionCountByNumber(num) => {
308 node_info!("eth_getBlockTransactionCountByNumber");
309 self.get_block_transaction_count_by_number(num).await.to_rpc_result()
310 }
311 EthRequest::EthGetTransactionByBlockHashAndIndex(hash, index) => {
312 node_info!("eth_getTransactionByBlockHashAndIndex");
313 self.get_transaction_by_block_hash_and_index(hash, index.into())
314 .await
315 .to_rpc_result()
316 }
317 EthRequest::EthGetTransactionByBlockNumberAndIndex(num, index) => {
318 node_info!("eth_getTransactionByBlockNumberAndIndex");
319 self.get_transaction_by_block_number_and_index(num, index.into())
320 .await
321 .to_rpc_result()
322 }
323 EthRequest::EthGetTransactionByHash(hash) => {
324 node_info!("eth_getTransactionByHash");
325 self.get_transaction_by_hash(hash).await.to_rpc_result()
326 }
327 EthRequest::Web3ClientVersion(()) => {
328 node_info!("web3_clientVersion");
329 Ok(CLIENT_VERSION.to_string()).to_rpc_result()
330 }
331 EthRequest::EthFeeHistory(count, newest, reward_percentiles) => {
332 node_info!("eth_feeHistory");
333 self.fee_history(count, newest, Some(reward_percentiles)).await.to_rpc_result()
334 }
335 EthRequest::EthMaxPriorityFeePerGas(_) => {
336 node_info!("eth_maxPriorityFeePerGas");
337 self.max_priority_fee_per_gas().await.to_rpc_result()
338 }
339 EthRequest::EthSendRawTransaction(tx) => {
340 node_info!("eth_sendRawTransaction");
341 self.send_raw_transaction(ReviveBytes::from(tx).inner()).await.to_rpc_result()
342 }
343 EthRequest::EthSendRawTransactionSync(tx) => {
344 self.send_raw_transaction_sync(ReviveBytes::from(tx).inner()).await.to_rpc_result()
345 }
346 EthRequest::EthGetLogs(filter) => {
347 node_info!("eth_getLogs");
348 self.get_logs(filter).await.to_rpc_result()
349 }
350 EthRequest::EthAccounts(_) => {
351 node_info!("eth_accounts");
352 self.accounts().to_rpc_result()
353 }
354 EthRequest::SetBalance(address, value) => {
356 self.set_balance(address, value).to_rpc_result()
357 }
358 EthRequest::SetNonce(address, value) => self.set_nonce(address, value).to_rpc_result(),
359 EthRequest::SetCode(address, bytes) => self.set_code(address, bytes).to_rpc_result(),
360 EthRequest::SetStorageAt(address, key, value) => {
361 self.set_storage_at(address, key, value).to_rpc_result()
362 }
363 EthRequest::SetImmutableStorageAt(address, data) => {
364 self.set_immutable_storage_at(address, data).to_rpc_result()
365 }
366 EthRequest::SetChainId(chain_id) => self.set_chain_id(chain_id).to_rpc_result(),
367 EthRequest::EvmSnapshot(()) => self.snapshot().await.to_rpc_result(),
369 EthRequest::Rollback(depth) => self.rollback(depth).await.to_rpc_result(),
370 EthRequest::EvmRevert(id) => self.revert(id).await.to_rpc_result(),
371 EthRequest::Reset(params) => {
372 self.reset(params.and_then(|p| p.params)).await.to_rpc_result()
373 }
374 EthRequest::EthSign(addr, content) => {
376 node_info!("eth_sign");
377 self.sign(addr, content).await.to_rpc_result()
378 }
379 EthRequest::EthSignTypedDataV4(addr, data) => {
380 self.sign_typed_data_v4(addr, data).await.to_rpc_result()
381 }
382 EthRequest::EthSignTypedData(addr, data) => {
383 self.sign_typed_data(addr, data).to_rpc_result()
384 }
385 EthRequest::EthSignTypedDataV3(addr, data) => {
386 self.sign_typed_data_v3(addr, data).to_rpc_result()
387 }
388 EthRequest::EthSignTransaction(request) => {
389 self.sign_transaction(*request).await.to_rpc_result()
390 }
391 EthRequest::PersonalSign(content, addr) => {
392 node_info!("personal_sign");
393 self.sign(addr, content).await.to_rpc_result()
394 }
395 EthRequest::EthGetAccount(addr, block) => {
396 self.get_account(addr, block).await.to_rpc_result()
397 }
398 EthRequest::EthGetAccountInfo(addr, block) => {
399 self.get_account_info(addr, block).await.to_rpc_result()
400 }
401 EthRequest::TxPoolStatus(_) => self.txpool_status().await.to_rpc_result(),
403 EthRequest::TxPoolInspect(_) => self.txpool_inspect().await.to_rpc_result(),
404 EthRequest::TxPoolContent(_) => self.txpool_content().await.to_rpc_result(),
405 EthRequest::DropAllTransactions() => {
406 self.anvil_drop_all_transactions().await.to_rpc_result()
407 }
408 EthRequest::DropTransaction(eth_hash) => {
409 self.anvil_drop_transaction(eth_hash).await.to_rpc_result()
410 }
411 EthRequest::RemovePoolTransactions(address) => {
412 self.anvil_remove_pool_transactions(address).await.to_rpc_result()
413 }
414 EthRequest::NodeInfo(_) => self.anvil_node_info().await.to_rpc_result(),
416 EthRequest::AnvilMetadata(_) => self.anvil_metadata().await.to_rpc_result(),
417 EthRequest::DebugTraceTransaction(tx_hash, geth_tracer_options) => {
419 self.debug_trace_transaction(tx_hash, geth_tracer_options).await.to_rpc_result()
420 }
421 EthRequest::DebugTraceCall(request, block_number, geth_tracer_options) => self
422 .debug_trace_call(request, block_number, geth_tracer_options)
423 .await
424 .to_rpc_result(),
425 EthRequest::DebugTraceBlockByNumber(block_number, geth_tracer_options) => self
427 .debug_trace_block_by_number(block_number, geth_tracer_options)
428 .await
429 .to_rpc_result(),
430 EthRequest::TraceTransaction(tx_hash) => {
431 self.trace_transaction(tx_hash).await.to_rpc_result()
432 }
433 EthRequest::TraceBlock(block_number) => {
434 self.trace_block(block_number).await.to_rpc_result()
435 }
436 EthRequest::EthNewFilter(filter) => {
438 self.new_filter(ReviveFilter::from(filter).into_inner()).await.to_rpc_result()
439 }
440 EthRequest::EthGetFilterLogs(id) => self.get_filter_logs(&id).await.to_rpc_result(),
441 EthRequest::EthGetFilterChanges(id) => self.get_filter_changes(&id).await,
442 EthRequest::EthNewBlockFilter(_) => self.new_block_filter().await.to_rpc_result(),
443 EthRequest::EthNewPendingTransactionFilter(_) => {
444 self.new_pending_transactions_filter().await.to_rpc_result()
445 }
446 EthRequest::EthUninstallFilter(id) => self.uninstall_filter(&id).await.to_rpc_result(),
447 _ => Err::<(), _>(Error::RpcUnimplemented).to_rpc_result(),
448 };
449
450 if let ResponseResult::Error(err) = &res {
451 node_info!("\nRPC request failed:");
452 node_info!(" Request: {:?}", req);
453 node_info!(" Error: {}\n", err);
454 }
455
456 res
457 }
458
459 fn set_logging(&self, enabled: bool) -> Result<()> {
460 node_info!("anvil_setLoggingEnabled");
461
462 self.logging_manager.set_enabled(enabled);
463 Ok(())
464 }
465
466 async fn mine(&self, blocks: Option<U256>, interval: Option<U256>) -> Result<()> {
468 node_info!("anvil_mine");
469
470 if blocks.is_some_and(|b| u64::try_from(b).is_err()) {
471 return Err(Error::InvalidParams("The number of blocks is too large".to_string()));
472 }
473 if interval.is_some_and(|i| u64::try_from(i).is_err()) {
474 return Err(Error::InvalidParams(
475 "The interval between blocks is too large".to_string(),
476 ));
477 }
478
479 let receiver = self.eth_rpc_client.block_notifier().map(|sender| sender.subscribe());
481
482 let awaited_hash = self
483 .mining_engine
484 .mine(blocks.map(|b| b.to()), interval.map(|i| Duration::from_secs(i.to())))
485 .await
486 .map_err(Error::Mining)?;
487 self.wait_for_hash(receiver, awaited_hash).await?;
488 Ok(())
489 }
490
491 fn set_interval_mining(&self, interval: u64) -> Result<()> {
492 node_info!("evm_setIntervalMining");
493
494 self.mining_engine.set_interval_mining(Duration::from_secs(interval));
495 Ok(())
496 }
497
498 fn get_interval_mining(&self) -> Result<Option<u64>> {
499 node_info!("anvil_getIntervalMining");
500
501 Ok(self.mining_engine.get_interval_mining())
502 }
503
504 fn get_auto_mine(&self) -> Result<bool> {
505 node_info!("anvil_getAutomine");
506
507 Ok(self.mining_engine.is_automine())
508 }
509
510 fn set_auto_mine(&self, enabled: bool) -> Result<()> {
511 node_info!("evm_setAutomine");
512
513 self.mining_engine.set_auto_mine(enabled);
514 Ok(())
515 }
516
517 async fn evm_mine(&self, mine: Option<AnvilCoreParams<Option<MineOptions>>>) -> Result<String> {
518 node_info!("evm_mine");
519
520 let receiver = self.eth_rpc_client.block_notifier().map(|sender| sender.subscribe());
522 let awaited_hash = self.mining_engine.evm_mine(mine.and_then(|p| p.params)).await?;
523 self.wait_for_hash(receiver, awaited_hash).await?;
524 Ok("0x0".to_string())
525 }
526
527 async fn evm_mine_detailed(
528 &self,
529 mine: Option<AnvilCoreParams<Option<MineOptions>>>,
530 ) -> Result<Vec<Block>> {
531 node_info!("evm_mineDetailed");
532
533 let receiver = self.eth_rpc_client.block_notifier().map(|sender| sender.subscribe());
535
536 let (mined_blocks, awaited_hash) =
537 self.mining_engine.do_evm_mine(mine.and_then(|p| p.params)).await?;
538
539 self.wait_for_hash(receiver, awaited_hash).await?;
540
541 let mut blocks = Vec::with_capacity(mined_blocks as usize);
542 let last_block = self.client.info().best_number as u64;
543 let starting = last_block - mined_blocks + 1;
544 for block_number in starting..=last_block {
545 if let Some(block) =
546 self.get_block_by_number(BlockNumberOrTag::Number(block_number), true).await?
547 {
548 blocks.push(block);
549 }
550 }
551 Ok(blocks)
552 }
553
554 fn set_block_timestamp_interval(&self, time: u64) -> Result<()> {
556 node_info!("anvil_setBlockTimestampInterval");
557
558 self.mining_engine.set_block_timestamp_interval(Duration::from_secs(time));
559 Ok(())
560 }
561
562 fn remove_block_timestamp_interval(&self) -> Result<bool> {
563 node_info!("anvil_removeBlockTimestampInterval");
564
565 Ok(self.mining_engine.remove_block_timestamp_interval())
566 }
567
568 fn set_next_block_timestamp(&self, time: U256) -> Result<()> {
569 node_info!("evm_setNextBlockTimeStamp");
570
571 if time >= U256::from(u64::MAX) {
572 return Err(Error::InvalidParams("The timestamp is too big".to_string()));
573 }
574 let time = time.to::<u64>();
575 self.mining_engine
576 .set_next_block_timestamp(Duration::from_secs(time))
577 .map_err(Error::Mining)
578 }
579
580 fn increase_time(&self, time: U256) -> Result<i64> {
581 node_info!("evm_increaseTime");
582
583 Ok(self.mining_engine.increase_time(Duration::from_secs(time.try_into().unwrap_or(0))))
584 }
585
586 fn set_time(&self, timestamp: U256) -> Result<u64> {
587 node_info!("evm_setTime");
588
589 if timestamp >= U256::from(u64::MAX) {
590 return Err(Error::InvalidParams("The timestamp is too big".to_string()));
591 }
592 let time = timestamp.to::<u64>();
593 let time_ms = time.saturating_mul(1000);
594 let latest_block = self.latest_block();
596 let last_block_timestamp = self.backend.read_timestamp(latest_block)?;
597 if time_ms < last_block_timestamp {
599 self.backend.inject_timestamp(latest_block, time_ms);
600 }
601 Ok(self.mining_engine.set_time(Duration::from_secs(time)))
602 }
603
604 fn impersonate_account(&mut self, addr: H160) -> Result<()> {
606 node_info!("anvil_impersonateAccount");
607 self.impersonation_manager.impersonate(addr);
608 Ok(())
609 }
610
611 fn auto_impersonate_account(&mut self, enable: bool) -> Result<()> {
612 node_info!("anvil_autoImpersonateAccount");
613 self.impersonation_manager.set_auto_impersonate_account(enable);
614 Ok(())
615 }
616
617 fn stop_impersonating_account(&mut self, addr: &H160) -> Result<()> {
618 node_info!("anvil_stopImpersonatingAccount");
619 self.impersonation_manager.stop_impersonating(addr);
620 Ok(())
621 }
622
623 fn chain_id(&self, at: Hash) -> u64 {
624 self.backend.read_chain_id(at).expect("Chain ID is populated on genesis")
625 }
626
627 fn eth_chain_id(&self) -> Result<U64> {
629 node_info!("eth_chainId");
630 let latest_block = self.latest_block();
631
632 Ok(U256::from(self.chain_id(latest_block)).to::<U64>())
633 }
634
635 fn network_id(&self) -> Result<u64> {
636 node_info!("eth_networkId");
637 let latest_block = self.latest_block();
638
639 Ok(self.chain_id(latest_block))
640 }
641
642 fn net_listening(&self) -> Result<bool> {
643 node_info!("net_listening");
644 Ok(true)
645 }
646
647 fn syncing(&self) -> Result<bool> {
648 node_info!("eth_syncing");
649 Ok(false)
650 }
651
652 async fn transaction_receipt(&self, tx_hash: B256) -> Result<Option<ReceiptInfo>> {
653 node_info!("eth_getTransactionReceipt");
654 Ok(self.eth_rpc_client.receipt(&(tx_hash.0.into())).await)
655 }
656
657 async fn get_balance(&self, addr: Address, block: Option<BlockId>) -> Result<U256> {
658 node_info!("eth_getBalance");
659 let hash = self.get_block_hash_for_tag(block).await?;
660
661 let runtime_api = self.eth_rpc_client.runtime_api(hash);
662 let balance = runtime_api.balance(ReviveAddress::from(addr).inner()).await?;
663 Ok(AlloyU256::from(balance).inner())
664 }
665
666 async fn get_storage_at(
667 &self,
668 addr: Address,
669 slot: U256,
670 block: Option<BlockId>,
671 ) -> Result<B256> {
672 node_info!("eth_getStorageAt");
673 let hash = self.get_block_hash_for_tag(block).await?;
674 let runtime_api = self.eth_rpc_client.runtime_api(hash);
675 let bytes: B256 = match runtime_api
676 .get_storage(ReviveAddress::from(addr).inner(), slot.to_be_bytes())
677 .await
678 {
679 Ok(Some(bytes)) => bytes.as_slice().try_into().map_err(|_| {
680 Error::InternalError("Unable to convert value to 32-byte value".to_string())
681 })?,
682 Ok(None) | Err(ClientError::ContractNotFound) => Default::default(),
683 Err(err) => return Err(Error::ReviveRpc(EthRpcError::ClientError(err))),
684 };
685 Ok(bytes)
686 }
687
688 async fn get_code(&self, address: Address, block: Option<BlockId>) -> Result<Bytes> {
689 node_info!("eth_getCode");
690
691 let hash = self.get_block_hash_for_tag(block).await?;
692 let code = self
693 .eth_rpc_client
694 .runtime_api(hash)
695 .code(ReviveAddress::from(address).inner())
696 .await?;
697 Ok(code.into())
698 }
699
700 async fn get_block_by_hash(
702 &self,
703 block_hash: B256,
704 hydrated_transactions: bool,
705 ) -> Result<Option<Block>> {
706 node_info!("eth_getBlockByHash");
707 let Some(block) = self
708 .eth_rpc_client
709 .block_by_ethereum_hash(&H256::from_slice(block_hash.as_slice()))
710 .await?
711 else {
712 return Ok(None);
713 };
714 let block = self.eth_rpc_client.evm_block(block, hydrated_transactions).await;
715 Ok(block)
716 }
717
718 async fn estimate_gas(
719 &self,
720 request: WithOtherFields<TransactionRequest>,
721 block: Option<BlockId>,
722 ) -> Result<sp_core::U256> {
723 node_info!("eth_estimateGas");
724
725 let hash = self.get_block_hash_for_tag(block).await?;
726 let runtime_api = self.eth_rpc_client.runtime_api(hash);
727 let dry_run = runtime_api
728 .dry_run(
729 convert_to_generic_transaction(request.into_inner()),
730 ReviveBlockId::from(block).inner(),
731 )
732 .await?;
733 Ok(dry_run.eth_gas)
734 }
735
736 async fn call(
737 &self,
738 request: WithOtherFields<TransactionRequest>,
739 block: Option<BlockId>,
740 ) -> Result<Bytes> {
741 node_info!("eth_call");
742
743 let hash = self.get_block_hash_for_tag(block).await?;
744
745 let runtime_api = self.eth_rpc_client.runtime_api(hash);
746 let dry_run = runtime_api
747 .dry_run(
748 convert_to_generic_transaction(request.into_inner()),
749 ReviveBlockId::from(block).inner(),
750 )
751 .await?;
752
753 Ok(dry_run.data.into())
754 }
755
756 async fn gas_price(&self) -> Result<sp_core::U256> {
757 node_info!("eth_gasPrice");
758
759 let hash = self.latest_block();
760
761 let runtime_api = self.eth_rpc_client.runtime_api(hash);
762 runtime_api.gas_price().await.map_err(Error::from)
763 }
764
765 async fn get_transaction_count(
766 &self,
767 address: H160,
768 block: Option<BlockId>,
769 ) -> Result<sp_core::U256> {
770 node_info!("eth_getTransactionCount");
771 let hash = self.get_block_hash_for_tag(block).await?;
772 let runtime_api = self.eth_rpc_client.runtime_api(hash);
773 let nonce = runtime_api.nonce(address).await?;
774 Ok(nonce)
775 }
776
777 async fn send_raw_transaction(&self, transaction: Bytes) -> Result<H256> {
778 let hash = H256(keccak_256(&transaction.0));
779 let call = subxt_client::tx().revive().eth_transact(transaction.0);
780 self.eth_rpc_client.submit(call).await?;
781 Ok(hash)
782 }
783
784 pub async fn send_raw_transaction_sync(&self, tx: Bytes) -> Result<ReceiptInfo> {
785 node_info!("eth_sendRawTransactionSync");
786 let receiver = self
788 .eth_rpc_client
789 .block_notifier()
790 .ok_or_else(|| {
791 Error::InternalError("Invalid receiver. Unable to wait for receipt".to_string())
792 })?
793 .subscribe();
794 let hash = B256::from_slice(self.send_raw_transaction(tx).await?.as_ref());
795 self.wait_for_receipt(hash, receiver).await
796 }
797
798 async fn send_transaction(
799 &self,
800 transaction_req: WithOtherFields<TransactionRequest>,
801 unsigned_tx: bool,
802 ) -> Result<H256> {
803 node_info!("eth_sendTransaction");
804 let mut transaction = convert_to_generic_transaction(transaction_req.clone().into_inner());
805 let Some(from) = transaction.from else {
806 return Err(Error::ReviveRpc(EthRpcError::InvalidTransaction));
807 };
808
809 let best_hash = self.latest_block();
810 let best_eth_hash =
811 self.eth_rpc_client.resolve_ethereum_hash(&best_hash).await.ok_or_else(|| {
812 Error::InternalError("Ethereum block hash of latest block not found".to_string())
813 })?;
814 let latest_block_id = Some(BlockId::hash(B256::from_slice(best_eth_hash.as_ref())));
815 let account = if self.impersonation_manager.is_impersonated(from) || unsigned_tx {
816 None
817 } else {
818 Some(
819 *self
820 .accounts()?
821 .iter()
822 .find(|account| **account == from)
823 .ok_or(Error::ReviveRpc(EthRpcError::AccountNotFound(from)))?,
824 )
825 };
826
827 if transaction.gas.is_none() {
828 transaction.gas =
829 Some(self.estimate_gas(transaction_req.clone(), latest_block_id).await?);
830 }
831
832 if transaction.gas_price.is_none() {
833 transaction.gas_price = Some(self.gas_price().await?);
834 }
835
836 if transaction.nonce.is_none() {
837 transaction.nonce = Some(self.get_transaction_count(from, latest_block_id).await?);
838 }
839
840 if transaction.chain_id.is_none() {
841 transaction.chain_id =
842 Some(sp_core::U256::from_big_endian(&self.chain_id(best_hash).to_be_bytes()));
843 }
844
845 let tx = transaction
846 .try_into_unsigned()
847 .map_err(|_| Error::ReviveRpc(EthRpcError::InvalidTransaction))?;
848
849 let payload = match account {
850 Some(addr) => self
851 .wallet
852 .sign_transaction(Address::from(ReviveAddress::new(addr)), tx)?
853 .signed_payload(),
854 None => {
855 use crate::substrate_node::host::IMPERSONATION_MARKER;
859 let mut fake_signature = [IMPERSONATION_MARKER; 65];
860 fake_signature[..12].fill(0);
861 fake_signature[12..32].copy_from_slice(from.as_bytes());
862 fake_signature[64] = 0; tx.with_signature(fake_signature).signed_payload()
864 }
865 };
866
867 self.send_raw_transaction(Bytes(payload)).await
868 }
869
870 async fn send_transaction_sync(
871 &self,
872 request: WithOtherFields<TransactionRequest>,
873 ) -> Result<ReceiptInfo> {
874 node_info!("eth_sendTransactionSync");
875 let receiver = self
877 .eth_rpc_client
878 .block_notifier()
879 .ok_or_else(|| {
880 Error::InternalError("Invalid receiver. Unable to wait for receipt".to_string())
881 })?
882 .subscribe();
883 let hash = B256::from_slice(self.send_transaction(request, false).await?.as_ref());
884 self.wait_for_receipt(hash, receiver).await
885 }
886
887 async fn get_block_by_number(
888 &self,
889 block_number: BlockNumberOrTag,
890 hydrated_transactions: bool,
891 ) -> Result<Option<Block>> {
892 let Some(block) = self
893 .eth_rpc_client
894 .block_by_number_or_tag(&ReviveBlockNumberOrTag::from(block_number).inner())
895 .await?
896 else {
897 return Ok(None);
898 };
899 let block = self.eth_rpc_client.evm_block(block, hydrated_transactions).await;
900 Ok(block)
901 }
902
903 pub(crate) async fn snapshot(&mut self) -> Result<U256> {
904 node_info!("evm_snapshot");
905 Ok(self.revert_manager.snapshot())
906 }
907
908 pub(crate) async fn revert(&mut self, id: U256) -> Result<bool> {
909 node_info!("evm_revert");
910 let res = self
911 .revert_manager
912 .revert(id)
913 .map_err(|err| Error::Backend(BackendError::Client(err)))?;
914 let Some(res) = res else { return Ok(false) };
915
916 self.on_revert_update(res).await?;
917
918 Ok(true)
919 }
920
921 pub(crate) async fn reset(&mut self, forking: Option<Forking>) -> Result<()> {
927 self.instance_id = B256::random();
928 node_info!("anvil_reset");
929 if forking.is_some() {
932 return Err(Error::RpcUnimplemented);
933 }
934
935 let res = self
936 .revert_manager
937 .reset_to_genesis()
938 .map_err(|err| Error::Backend(BackendError::Client(err)))?;
939
940 self.on_revert_update(res).await
941 }
942
943 pub(crate) async fn rollback(&mut self, depth: Option<u64>) -> Result<()> {
944 node_info!("anvil_rollback");
945 let res = self
946 .revert_manager
947 .rollback(depth)
948 .map_err(|err| Error::Backend(BackendError::Client(err)))?;
949
950 self.on_revert_update(res).await?;
951
952 Ok(())
953 }
954
955 async fn anvil_node_info(&self) -> Result<NodeInfo> {
956 node_info!("anvil_nodeInfo");
957
958 let best_hash = self.latest_block();
959 let Some(latest_evm_block) = self.get_block_by_substrate_hash(best_hash).await? else {
960 return Err(Error::InternalError("Latest block not found".to_string()));
961 };
962 let current_block_number: u64 =
963 latest_evm_block.number.try_into().map_err(|_| EthRpcError::ConversionError)?;
964 let current_block_timestamp: u64 =
965 latest_evm_block.timestamp.try_into().map_err(|_| EthRpcError::ConversionError)?;
966 let base_fee: u128 = latest_evm_block
969 .base_fee_per_gas
970 .try_into()
971 .map_err(|_| EthRpcError::ConversionError)?;
972 let gas_limit: u64 = latest_evm_block.gas_limit.try_into().unwrap_or(u64::MAX);
973 let hard_fork: &str = SpecId::PRAGUE.into();
975
976 Ok(NodeInfo {
977 current_block_number,
978 current_block_timestamp,
979 current_block_hash: B256::from_slice(latest_evm_block.hash.as_ref()),
980 hard_fork: hard_fork.to_string(),
981 transaction_order: "fifo".to_string(),
983 environment: NodeEnvironment {
984 base_fee,
985 chain_id: self.chain_id(best_hash),
986 gas_limit,
987 gas_price: base_fee,
988 },
989 fork_config: Default::default(),
991 })
992 }
993
994 async fn anvil_metadata(&self) -> Result<AnvilMetadata> {
995 node_info!("anvil_metadata");
996
997 let best_hash = self.latest_block();
998 let Some(latest_evm_block) = self.get_block_by_substrate_hash(best_hash).await? else {
999 return Err(Error::InternalError("Latest block not found".to_string()));
1000 };
1001 let latest_block_number: u64 =
1002 latest_evm_block.number.try_into().map_err(|_| EthRpcError::ConversionError)?;
1003
1004 Ok(AnvilMetadata {
1005 client_version: CLIENT_VERSION.to_string(),
1006 chain_id: self.chain_id(best_hash),
1007 latest_block_hash: B256::from_slice(latest_evm_block.hash.as_ref()),
1008 latest_block_number,
1009 instance_id: self.instance_id,
1010 forked_network: None,
1012 snapshots: self.revert_manager.list_snapshots(),
1013 })
1014 }
1015
1016 async fn get_block_transaction_count_by_hash(&self, block_hash: B256) -> Result<Option<U256>> {
1017 let block_hash = H256::from_slice(block_hash.as_slice());
1018 Ok(self.eth_rpc_client.receipts_count_per_block(&block_hash).await.map(U256::from))
1019 }
1020
1021 async fn get_block_transaction_count_by_number(
1022 &self,
1023 block_number: BlockNumberOrTag,
1024 ) -> Result<Option<U256>> {
1025 let Some(hash) =
1026 self.maybe_get_block_hash_for_tag(Some(BlockId::Number(block_number))).await?
1027 else {
1028 return Ok(None);
1029 };
1030
1031 Ok(self.eth_rpc_client.receipts_count_per_block(&hash).await.map(U256::from))
1032 }
1033
1034 async fn get_transaction_by_block_hash_and_index(
1035 &self,
1036 block_hash: B256,
1037 transaction_index: U256,
1038 ) -> Result<Option<TransactionInfo>> {
1039 let Some(receipt) = self
1040 .eth_rpc_client
1041 .receipt_by_hash_and_index(
1042 &H256::from_slice(block_hash.as_ref()),
1043 transaction_index.try_into().map_err(|_| EthRpcError::ConversionError)?,
1044 )
1045 .await
1046 else {
1047 return Ok(None);
1048 };
1049
1050 let Some(signed_tx) =
1051 self.eth_rpc_client.signed_tx_by_hash(&receipt.transaction_hash).await
1052 else {
1053 return Ok(None);
1054 };
1055
1056 Ok(Some(TransactionInfo::new(&receipt, signed_tx)))
1057 }
1058
1059 async fn get_transaction_by_block_number_and_index(
1060 &self,
1061 block: BlockNumberOrTag,
1062 transaction_index: U256,
1063 ) -> Result<Option<TransactionInfo>> {
1064 let Some(block) = self
1065 .eth_rpc_client
1066 .block_by_number_or_tag(&ReviveBlockNumberOrTag::from(block).inner())
1067 .await?
1068 else {
1069 return Ok(None);
1070 };
1071 self.get_transaction_by_block_hash_and_index(
1072 B256::from_slice(block.hash().as_ref()),
1073 transaction_index,
1074 )
1075 .await
1076 }
1077
1078 async fn get_transaction_by_hash(
1079 &self,
1080 transaction_hash: B256,
1081 ) -> Result<Option<TransactionInfo>> {
1082 let tx_hash = H256::from_slice(transaction_hash.as_ref());
1083 let receipt = self.eth_rpc_client.receipt(&tx_hash).await;
1084 let signed_tx = self.eth_rpc_client.signed_tx_by_hash(&tx_hash).await;
1085 if let (Some(receipt), Some(signed_tx)) = (receipt, signed_tx) {
1086 return Ok(Some(TransactionInfo::new(&receipt, signed_tx)));
1087 }
1088
1089 Ok(None)
1090 }
1091
1092 async fn fee_history(
1093 &self,
1094 block_count: U256,
1095 newest_block: BlockNumberOrTag,
1096 reward_percentiles: Option<Vec<f64>>,
1097 ) -> Result<FeeHistoryResult> {
1098 let block_count: u32 = block_count.try_into().map_err(|_| EthRpcError::ConversionError)?;
1099 let result = self
1100 .eth_rpc_client
1101 .fee_history(
1102 block_count,
1103 ReviveBlockNumberOrTag::from(newest_block).inner(),
1104 reward_percentiles,
1105 )
1106 .await?;
1107 Ok(result)
1108 }
1109
1110 async fn max_priority_fee_per_gas(&self) -> Result<sp_core::U256> {
1111 Ok(Default::default())
1114 }
1115
1116 pub fn accounts(&self) -> Result<Vec<H160>> {
1117 node_info!("eth_accounts");
1118 let mut accounts = BTreeSet::new();
1120
1121 accounts.extend(self.wallet.accounts());
1122 accounts.extend(self.impersonation_manager.impersonated_accounts.clone());
1123 Ok(accounts.into_iter().collect())
1124 }
1125
1126 async fn get_logs(&self, filter: Filter) -> Result<FilterResults> {
1127 let logs = self.eth_rpc_client.logs(Some(ReviveFilter::from(filter).into_inner())).await?;
1128 Ok(FilterResults::Logs(logs))
1129 }
1130
1131 fn set_chain_id(&self, chain_id: u64) -> Result<()> {
1133 node_info!("anvil_setChainId");
1134
1135 let latest_block = self.latest_block();
1136 self.backend.inject_chain_id(latest_block, chain_id);
1137
1138 Ok(())
1139 }
1140
1141 fn set_balance(&self, address: Address, value: U256) -> Result<()> {
1142 node_info!("anvil_setBalance");
1143
1144 let latest_block = self.latest_block();
1145
1146 let (new_balance, dust) = self.construct_balance_with_dust(latest_block, value)?;
1147
1148 let account_id = self.get_account_id(latest_block, address)?;
1149 self.set_frame_system_balance(latest_block, account_id, new_balance)?;
1150
1151 let mut revive_account_info = self
1152 .backend
1153 .read_revive_account_info(latest_block, address)?
1154 .unwrap_or(ReviveAccountInfo { account_type: AccountType::EOA, dust: 0 });
1155
1156 if revive_account_info.dust != dust {
1157 revive_account_info.dust = dust;
1158
1159 self.backend.inject_revive_account_info(latest_block, address, revive_account_info);
1160 }
1161
1162 Ok(())
1163 }
1164
1165 fn set_nonce(&self, address: Address, value: U256) -> Result<()> {
1166 node_info!("anvil_setNonce");
1167
1168 let latest_block = self.latest_block();
1169
1170 let account_id = self.get_account_id(latest_block, address)?;
1171
1172 let mut account_info = self
1173 .backend
1174 .read_system_account_info(latest_block, account_id.clone())?
1175 .unwrap_or_else(|| SystemAccountInfo { providers: 1, ..Default::default() });
1176
1177 account_info.nonce = value.try_into().map_err(|_| Error::NonceOverflow)?;
1178
1179 self.backend.inject_system_account_info(latest_block, account_id, account_info);
1180
1181 Ok(())
1182 }
1183
1184 fn set_storage_at(&self, address: Address, key: U256, value: B256) -> Result<()> {
1185 node_info!("anvil_setStorageAt");
1186
1187 let latest_block = self.latest_block();
1188
1189 let account_id = self.get_account_id(latest_block, address)?;
1190
1191 let maybe_system_account_info =
1192 self.backend.read_system_account_info(latest_block, account_id.clone())?;
1193 let nonce = maybe_system_account_info.as_ref().map(|info| info.nonce).unwrap_or_default();
1194
1195 if maybe_system_account_info.is_none() {
1196 self.set_frame_system_balance(
1197 latest_block,
1198 account_id,
1199 substrate_runtime::currency::DOLLARS,
1200 )?;
1201 }
1202
1203 let trie_id = match self.backend.read_revive_account_info(latest_block, address)? {
1204 None => {
1206 let contract_info = new_contract_info(&address, (*KECCAK_EMPTY).into(), nonce);
1207 let trie_id = contract_info.trie_id.0.clone();
1208
1209 self.backend.inject_revive_account_info(
1210 latest_block,
1211 address,
1212 ReviveAccountInfo {
1213 account_type: AccountType::Contract(contract_info),
1214 dust: 0,
1215 },
1216 );
1217
1218 trie_id
1219 }
1220 Some(ReviveAccountInfo { account_type: AccountType::EOA, dust }) => {
1222 let contract_info = new_contract_info(&address, (*KECCAK_EMPTY).into(), nonce);
1223 let trie_id = contract_info.trie_id.0.clone();
1224
1225 self.backend.inject_revive_account_info(
1226 latest_block,
1227 address,
1228 ReviveAccountInfo { account_type: AccountType::Contract(contract_info), dust },
1229 );
1230
1231 trie_id
1232 }
1233 Some(ReviveAccountInfo {
1234 account_type: AccountType::Contract(contract_info), ..
1235 }) => contract_info.trie_id.0,
1236 };
1237
1238 self.backend.inject_child_storage(
1239 latest_block,
1240 trie_id,
1241 key.to_be_bytes_vec(),
1242 value.to_vec(),
1243 );
1244
1245 Ok(())
1246 }
1247
1248 fn set_code(&self, address: Address, bytes: alloy_primitives::Bytes) -> Result<()> {
1249 node_info!("anvil_setCode");
1250
1251 let latest_block = self.latest_block();
1252
1253 let account_id = self.get_account_id(latest_block, address)?;
1254
1255 let code_hash = H256(keccak_256(&bytes));
1256
1257 let maybe_system_account_info =
1258 self.backend.read_system_account_info(latest_block, account_id.clone())?;
1259 let nonce = maybe_system_account_info.as_ref().map(|info| info.nonce).unwrap_or_default();
1260
1261 if maybe_system_account_info.is_none() {
1262 self.set_frame_system_balance(
1263 latest_block,
1264 account_id.clone(),
1265 substrate_runtime::currency::DOLLARS,
1266 )?;
1267 }
1268
1269 let mut old_code_info = None;
1270 let revive_account_info = match self
1271 .backend
1272 .read_revive_account_info(latest_block, address)?
1273 {
1274 None => {
1275 let contract_info = new_contract_info(&address, code_hash, nonce);
1276
1277 ReviveAccountInfo { account_type: AccountType::Contract(contract_info), dust: 0 }
1278 }
1279 Some(ReviveAccountInfo { account_type: AccountType::EOA, dust }) => {
1280 let contract_info = new_contract_info(&address, code_hash, nonce);
1281
1282 ReviveAccountInfo { account_type: AccountType::Contract(contract_info), dust }
1283 }
1284 Some(ReviveAccountInfo {
1285 account_type: AccountType::Contract(mut contract_info),
1286 dust,
1287 }) => {
1288 if let Some(code_info) =
1289 self.backend.read_code_info(latest_block, contract_info.code_hash)?
1290 {
1291 if code_info.refcount == 1 && contract_info.code_hash != code_hash {
1292 self.backend.inject_pristine_code(
1294 latest_block,
1295 contract_info.code_hash,
1296 None,
1297 );
1298 self.backend.inject_code_info(latest_block, contract_info.code_hash, None);
1299 }
1300
1301 old_code_info = Some(code_info);
1302 }
1303
1304 contract_info.code_hash = code_hash;
1305
1306 ReviveAccountInfo { account_type: AccountType::Contract(contract_info), dust }
1307 }
1308 };
1309
1310 self.backend.inject_revive_account_info(latest_block, address, revive_account_info);
1311
1312 let code_info = old_code_info
1313 .map(|mut code_info| {
1314 code_info.code_len = bytes.len() as u32;
1315 code_info.code_type = BytecodeType::Evm;
1316 code_info
1317 })
1318 .unwrap_or_else(|| CodeInfo {
1319 owner: <[u8; 32]>::from(account_id).into(),
1320 deposit: Default::default(),
1321 refcount: 1,
1322 code_len: bytes.len() as u32,
1323 behaviour_version: 0,
1324 code_type: BytecodeType::Evm,
1325 });
1326
1327 self.backend.inject_pristine_code(latest_block, code_hash, Some(bytes));
1328 self.backend.inject_code_info(latest_block, code_hash, Some(code_info));
1329
1330 Ok(())
1331 }
1332
1333 fn set_immutable_storage_at(
1334 &self,
1335 address: Address,
1336 immutables: Vec<alloy_primitives::Bytes>,
1337 ) -> Result<()> {
1338 node_info!("anvil_setImmutableStorageAt");
1339
1340 let latest_block = self.latest_block();
1341
1342 let pvm_data: Vec<u8> = immutables
1361 .into_iter()
1362 .flat_map(|immutable| {
1363 let mut word = [0u8; 32];
1364 let len = immutable.len().min(32);
1365 word[..len].copy_from_slice(&immutable[..len]);
1366 word.reverse();
1367 word
1368 })
1369 .collect();
1370
1371 self.backend.inject_immutable_data(latest_block, address, pvm_data);
1372
1373 Ok(())
1374 }
1375
1376 async fn sign(&self, address: Address, content: impl AsRef<[u8]>) -> Result<String> {
1378 Ok(alloy_primitives::hex::encode_prefixed(self.wallet.sign(address, content.as_ref())?))
1379 }
1380
1381 fn sign_typed_data(&self, _address: Address, _data: serde_json::Value) -> Result<String> {
1382 node_info!("eth_signTypedData");
1383 Err(Error::RpcUnimplemented)
1384 }
1385
1386 fn sign_typed_data_v3(&self, _address: Address, _data: serde_json::Value) -> Result<String> {
1387 node_info!("eth_signTypedData_v3");
1388 Err(Error::RpcUnimplemented)
1389 }
1390
1391 async fn sign_transaction(
1392 &self,
1393 tx: WithOtherFields<TransactionRequest>,
1394 ) -> Result<TransactionSigned> {
1395 node_info!("eth_signTransaction");
1396 let from = tx.inner().from.ok_or(Error::ReviveRpc(EthRpcError::InvalidTransaction))?;
1397 let generic_transaction = convert_to_generic_transaction(tx.into_inner());
1398 let unsigned_transaction = generic_transaction
1399 .try_into_unsigned()
1400 .map_err(|_| Error::ReviveRpc(EthRpcError::InvalidTransaction))?;
1401 self.wallet.sign_transaction(from, unsigned_transaction)
1402 }
1403
1404 async fn sign_typed_data_v4(&self, address: Address, data: TypedData) -> Result<String> {
1405 node_info!("eth_signTypedData_v4");
1406 Ok(alloy_primitives::hex::encode_prefixed(self.wallet.sign_typed_data(address, &data)?))
1407 }
1408
1409 async fn get_account(
1410 &self,
1411 address: Address,
1412 block_number: Option<BlockId>,
1413 ) -> Result<TrieAccount> {
1414 node_info!("eth_getAccount");
1415 let addr = ReviveAddress::from(address).inner();
1416 let nonce = self.get_transaction_count(addr, block_number).await?;
1417 let balance = self.get_balance(address, block_number).await?;
1418 let code = self.get_code(address, block_number).await?;
1419 let code_hash =
1420 if code.is_empty() { KECCAK_EMPTY } else { B256::from(keccak_256(&code.0)) };
1421 let storage_root = EMPTY_ROOT_HASH;
1423
1424 Ok(TrieAccount { nonce: nonce.as_u64(), balance, storage_root, code_hash })
1425 }
1426
1427 async fn get_account_info(
1428 &self,
1429 address: Address,
1430 block_number: Option<BlockId>,
1431 ) -> Result<alloy_rpc_types::eth::AccountInfo> {
1432 node_info!("eth_getAccountInfo");
1433 let account = self.get_account(address, block_number);
1434 let code = self.get_code(address, block_number);
1435 let (account, code) = try_join!(account, code)?;
1436 Ok(alloy_rpc_types::eth::AccountInfo {
1437 balance: account.balance,
1438 nonce: account.nonce,
1439 code: alloy_primitives::Bytes::from(code.0),
1440 })
1441 }
1442
1443 async fn new_block_filter(&self) -> Result<String> {
1447 node_info!("eth_newBlockFilter");
1448 let filter = EthFilter::Blocks(BlockFilter::new(BlockNotifications::new(
1449 self.new_block_notifications()?,
1450 )));
1451 Ok(self.filters.add_filter(filter).await)
1452 }
1453
1454 async fn uninstall_filter(&self, id: &str) -> Result<bool> {
1456 node_info!("eth_uninstallFilter");
1457 Ok(self.filters.uninstall_filter(id).await.is_some())
1458 }
1459
1460 async fn get_filter_changes(&self, id: &str) -> ResponseResult {
1462 node_info!("eth_getFilterChanges");
1463 self.filters.get_filter_changes(id).await
1464 }
1465
1466 async fn new_pending_transactions_filter(&self) -> Result<String> {
1467 node_info!("eth_newPendingTransactionFilter");
1468 let filter = EthFilter::PendingTransactions(PendingTransactionsFilter::new(
1469 BlockNotifications::new(self.new_block_notifications()?),
1470 self.tx_pool.clone(),
1471 self.eth_rpc_client.clone(),
1472 ));
1473 Ok(self.filters.add_filter(filter).await)
1474 }
1475
1476 async fn new_filter(&self, filter: evm::Filter) -> Result<String> {
1477 node_info!("eth_newFilter");
1478 let eth_filter = EthFilter::Logs(
1479 LogsFilter::new(
1480 BlockNotifications::new(self.new_block_notifications()?),
1481 self.eth_rpc_client.clone(),
1482 filter,
1483 )
1484 .await?,
1485 );
1486 Ok(self.filters.add_filter(eth_filter).await)
1487 }
1488
1489 async fn get_filter_logs(&self, id: &str) -> Result<Vec<Log>> {
1490 node_info!("eth_getFilterLogs");
1491 if let Some(filter) = self.filters.get_log_filter(id).await {
1492 Ok(self.eth_rpc_client.logs(Some(filter)).await?)
1493 } else {
1494 Ok(Vec::new())
1495 }
1496 }
1497
1498 async fn update_block_provider_on_revert(&self, info: &Info<OpaqueBlock>) -> Result<()> {
1500 let best_block = self.block_provider.block_by_number(info.best_number).await?.ok_or(
1501 Error::InternalError(format!(
1502 "Could not find best block with number {}",
1503 info.best_number
1504 )),
1505 )?;
1506 self.block_provider.update_latest(best_block, SubscriptionType::BestBlocks).await;
1507
1508 let finalized_block =
1509 self.block_provider.block_by_number(info.finalized_number).await?.ok_or(
1510 Error::InternalError(format!(
1511 "Could not find finalized block with number {}",
1512 info.finalized_number
1513 )),
1514 )?;
1515 self.block_provider.update_latest(finalized_block, SubscriptionType::FinalizedBlocks).await;
1516
1517 Ok(())
1518 }
1519
1520 async fn update_time_on_revert(&self, best_hash: Hash) -> Result<()> {
1521 let timestamp = self.backend.read_timestamp(best_hash)?;
1522 self.mining_engine.set_time(Duration::from_millis(timestamp));
1523 Ok(())
1524 }
1525
1526 async fn on_revert_update(&self, revert_info: RevertInfo) -> Result<()> {
1527 if revert_info.reverted > 0 {
1528 self.update_block_provider_on_revert(&revert_info.info).await?;
1529 }
1530
1531 self.update_time_on_revert(revert_info.info.best_hash).await?;
1532
1533 Ok(())
1534 }
1535
1536 async fn maybe_get_block_hash_for_tag(
1538 &self,
1539 block_id: Option<BlockId>,
1540 ) -> Result<Option<H256>> {
1541 match ReviveBlockId::from(block_id).inner() {
1542 BlockNumberOrTagOrHash::BlockHash(hash) => {
1543 Ok(Some(self.eth_rpc_client.resolve_substrate_hash(&hash).await.ok_or(
1545 Error::ReviveRpc(EthRpcError::ClientError(ClientError::EthereumBlockNotFound)),
1546 )?))
1547 }
1548 BlockNumberOrTagOrHash::BlockNumber(block_number) => {
1549 let n = block_number.try_into().map_err(|_| {
1550 Error::InvalidParams("Block number conversion failed".to_string())
1551 })?;
1552 Ok(self.eth_rpc_client.get_block_hash(n).await?)
1553 }
1554 BlockNumberOrTagOrHash::BlockTag(BlockTag::Finalized | BlockTag::Safe) => {
1555 let block = self.eth_rpc_client.latest_finalized_block().await;
1556 Ok(Some(block.hash()))
1557 }
1558 BlockNumberOrTagOrHash::BlockTag(_) => {
1559 let block = self.eth_rpc_client.latest_block().await;
1560 Ok(Some(block.hash()))
1561 }
1562 }
1563 }
1564
1565 async fn get_block_hash_for_tag(&self, block_id: Option<BlockId>) -> Result<H256> {
1567 self.maybe_get_block_hash_for_tag(block_id)
1568 .await?
1569 .ok_or(Error::InvalidParams("Block number not found".to_string()))
1570 }
1571
1572 fn get_account_id(&self, block: Hash, address: Address) -> Result<AccountId> {
1573 Ok(self.client.runtime_api().account_id(block, ReviveAddress::from(address).inner())?)
1574 }
1575
1576 fn construct_balance_with_dust(&self, block: Hash, value: U256) -> Result<(Balance, u32)> {
1577 self.client
1578 .runtime_api()
1579 .new_balance_with_dust(block, SubstrateU256::from(value).inner())?
1580 .map_err(|_| Error::BalanceConversion)
1581 }
1582
1583 fn latest_block(&self) -> H256 {
1584 self.backend.blockchain().info().best_hash
1585 }
1586
1587 async fn get_block_by_substrate_hash(&self, block_hash: H256) -> Result<Option<Block>> {
1589 let Some(substrate_block) = self.eth_rpc_client.block_by_hash(&block_hash).await? else {
1590 return Ok(None);
1591 };
1592 let Some(evm_block) = self.eth_rpc_client.evm_block(substrate_block, false).await else {
1593 return Err(Error::InternalError(
1594 "EVM block not found for substrate block".to_string(),
1595 ));
1596 };
1597 Ok(Some(evm_block))
1598 }
1599
1600 fn set_frame_system_balance(
1601 &self,
1602 latest_block: H256,
1603 account_id: AccountId,
1604 balance: Balance,
1605 ) -> Result<()> {
1606 let mut total_issuance = self.backend.read_total_issuance(latest_block)?;
1607
1608 let mut system_account_info = self
1609 .backend
1610 .read_system_account_info(latest_block, account_id.clone())?
1611 .unwrap_or_else(|| SystemAccountInfo { providers: 1, ..Default::default() });
1612
1613 if let Some(diff) = balance.checked_sub(system_account_info.data.free) {
1614 total_issuance = total_issuance.saturating_add(diff);
1615 } else {
1616 total_issuance = total_issuance.saturating_sub(system_account_info.data.free - balance);
1617 }
1618
1619 system_account_info.data.free = balance;
1620
1621 self.backend.inject_system_account_info(latest_block, account_id, system_account_info);
1622 self.backend.inject_total_issuance(latest_block, total_issuance);
1623
1624 Ok(())
1625 }
1626
1627 async fn txpool_status(&self) -> Result<TxpoolStatus> {
1629 node_info!("txpool_status");
1630 let pool_status = self.tx_pool.status();
1631 Ok(TxpoolStatus { pending: pool_status.ready as u64, queued: pool_status.future as u64 })
1632 }
1633
1634 async fn txpool_inspect(&self) -> Result<TxpoolInspect> {
1636 node_info!("txpool_inspect");
1637 let mut inspect = TxpoolInspect::default();
1638
1639 for tx in self.tx_pool.ready() {
1640 if let Some((sender, nonce, summary)) = extract_tx_summary(tx.data()) {
1641 let entry = inspect.pending.entry(sender).or_default();
1642 entry.insert(nonce.to_string(), summary);
1643 }
1644 }
1645
1646 for tx in self.tx_pool.futures() {
1647 if let Some((sender, nonce, summary)) = extract_tx_summary(tx.data()) {
1648 let entry = inspect.queued.entry(sender).or_default();
1649 entry.insert(nonce.to_string(), summary);
1650 }
1651 }
1652
1653 Ok(inspect)
1654 }
1655
1656 async fn txpool_content(&self) -> Result<TxpoolContent<TxpoolTransactionInfo>> {
1658 node_info!("txpool_content");
1659 let mut content = TxpoolContent::default();
1660
1661 for tx in self.tx_pool.ready() {
1662 if let Some((sender, nonce, tx_info)) = extract_tx_info(tx.data()) {
1663 let entry = content.pending.entry(sender).or_default();
1664 entry.insert(nonce.to_string(), tx_info);
1665 }
1666 }
1667
1668 for tx in self.tx_pool.futures() {
1669 if let Some((sender, nonce, tx_info)) = extract_tx_info(tx.data()) {
1670 let entry = content.queued.entry(sender).or_default();
1671 entry.insert(nonce.to_string(), tx_info);
1672 }
1673 }
1674
1675 Ok(content)
1676 }
1677
1678 async fn anvil_drop_all_transactions(&self) -> Result<()> {
1680 node_info!("anvil_dropAllTransactions");
1681 let ready_txs = self.tx_pool.ready();
1682 let future_txs = self.tx_pool.futures();
1683
1684 let mut invalid_txs = IndexMap::new();
1685
1686 for tx in ready_txs {
1687 invalid_txs.insert(*tx.hash(), None);
1688 }
1689
1690 for tx in future_txs {
1691 invalid_txs.insert(*tx.hash(), None);
1692 }
1693
1694 self.tx_pool.report_invalid(None, invalid_txs).await;
1695
1696 Ok(())
1697 }
1698
1699 async fn anvil_drop_transaction(&self, eth_hash: B256) -> Result<Option<B256>> {
1701 node_info!("anvil_dropTransaction");
1702 for tx in self.tx_pool.ready() {
1703 if transaction_matches_eth_hash(tx.data(), eth_hash) {
1704 let mut invalid_txs = IndexMap::new();
1705 invalid_txs.insert(*tx.hash(), None);
1706 self.tx_pool.report_invalid(None, invalid_txs).await;
1707 return Ok(Some(eth_hash));
1708 }
1709 }
1710
1711 for tx in self.tx_pool.futures() {
1712 if transaction_matches_eth_hash(tx.data(), eth_hash) {
1713 let mut invalid_txs = IndexMap::new();
1714 invalid_txs.insert(*tx.hash(), None);
1715 self.tx_pool.report_invalid(None, invalid_txs).await;
1716 return Ok(Some(eth_hash));
1717 }
1718 }
1719
1720 Ok(None)
1722 }
1723
1724 async fn anvil_remove_pool_transactions(&self, address: Address) -> Result<()> {
1726 node_info!("anvil_removePoolTransactions");
1727 let mut invalid_txs = IndexMap::new();
1728
1729 for tx in self.tx_pool.ready() {
1730 if let Some(sender) = extract_sender(tx.data())
1731 && sender == address
1732 {
1733 invalid_txs.insert(*tx.hash(), None);
1734 }
1735 }
1736
1737 for tx in self.tx_pool.futures() {
1738 if let Some(sender) = extract_sender(tx.data())
1739 && sender == address
1740 {
1741 invalid_txs.insert(*tx.hash(), None);
1742 }
1743 }
1744
1745 if !invalid_txs.is_empty() {
1746 self.tx_pool.report_invalid(None, invalid_txs).await;
1747 }
1748
1749 Ok(())
1750 }
1751
1752 async fn debug_trace_transaction(
1753 &self,
1754 tx_hash: B256,
1755 geth_tracer_options: GethDebugTracingOptions,
1756 ) -> Result<GethTrace> {
1757 node_info!("debug_traceTransaction");
1758 let trace = self
1759 .eth_rpc_client
1760 .trace_transaction(
1761 H256::from_slice(tx_hash.as_ref()),
1762 ReviveTracerType::from(geth_tracer_options).inner(),
1763 )
1764 .await?;
1765 Ok(ReviveTrace::new(trace).into())
1766 }
1767
1768 async fn debug_trace_call(
1769 &self,
1770 request: WithOtherFields<TransactionRequest>,
1771 block_number: Option<BlockId>,
1772 geth_tracer_options: GethDebugTracingCallOptions,
1773 ) -> Result<GethTrace> {
1774 node_info!("debug_traceCall");
1775 let hash = self.get_block_hash_for_tag(block_number).await?;
1776 let runtime_api = self.eth_rpc_client.runtime_api(hash);
1777 let transaction = convert_to_generic_transaction(request.into_inner());
1778 let trace = runtime_api
1779 .trace_call(transaction, ReviveTracerType::from(geth_tracer_options).inner())
1780 .await?;
1781 Ok(ReviveTrace::new(trace).into())
1782 }
1783
1784 async fn debug_trace_block_by_number(
1785 &self,
1786 block_number: BlockNumberOrTag,
1787 geth_tracer_options: GethDebugTracingOptions,
1788 ) -> Result<Vec<TraceResult>> {
1789 node_info!("debug_traceBlockByNumber");
1790
1791 Ok(self
1792 .eth_rpc_client
1793 .trace_block_by_number(
1794 ReviveBlockNumberOrTag::from(block_number).inner(),
1795 ReviveTracerType::from(geth_tracer_options).inner(),
1796 )
1797 .await?
1798 .into_iter()
1799 .map(|tx_trace| TraceResult::Success {
1800 result: ReviveTrace::new(tx_trace.trace).into(),
1801 tx_hash: Some(B256::from_slice(tx_trace.tx_hash.as_ref())),
1802 })
1803 .collect::<Vec<_>>())
1804 }
1805
1806 async fn trace_transaction(&self, tx_hash: B256) -> Result<Vec<LocalizedTransactionTrace>> {
1807 node_info!("trace_transaction");
1808 let trace = self
1809 .eth_rpc_client
1810 .trace_transaction(
1811 H256::from_slice(tx_hash.as_ref()),
1812 TracerType::CallTracer(Some(CallTracerConfig::default())),
1813 )
1814 .await?;
1815 let tx_info = self.get_transaction_by_hash(tx_hash).await?;
1816 parity_transaction_trace_builder(trace, tx_info)
1817 }
1818
1819 async fn trace_block(
1820 &self,
1821 block_number: BlockNumberOrTag,
1822 ) -> Result<Vec<LocalizedTransactionTrace>> {
1823 node_info!("trace_block");
1824 let Some(block) = self.get_block_by_number(block_number, true).await? else {
1826 return Ok(vec![]);
1827 };
1828 let traces = self
1829 .eth_rpc_client
1830 .trace_block_by_number(
1831 ReviveBlockNumberOrTag::from(block_number).inner(),
1832 TracerType::CallTracer(Some(CallTracerConfig::default())),
1833 )
1834 .await?;
1835
1836 parity_block_trace_builder(traces, block)
1837 }
1838
1839 async fn wait_for_receipt(
1842 &self,
1843 hash: B256,
1844 mut receiver: tokio::sync::broadcast::Receiver<H256>,
1845 ) -> Result<ReceiptInfo> {
1846 tokio::time::timeout(TIMEOUT_DURATION, async {
1847 while let Ok(_block_hash) = receiver.recv().await {
1848 if let Some(receipt) = self.transaction_receipt(hash).await? {
1849 return Ok(receipt);
1850 }
1851 }
1852 Err(Error::TransactionConfirmationTimeout { hash, duration: TIMEOUT_DURATION })
1853 })
1854 .await
1855 .unwrap_or_else(|_| {
1856 Err(Error::TransactionConfirmationTimeout { hash, duration: TIMEOUT_DURATION })
1857 })
1858 }
1859
1860 async fn wait_for_hash(
1861 &self,
1862 receiver: Option<tokio::sync::broadcast::Receiver<H256>>,
1863 awaited_hash: H256,
1864 ) -> Result<()> {
1865 if let Some(mut receiver) = receiver {
1866 tokio::time::timeout(Duration::from_secs(3), async {
1867 loop {
1868 if let Ok(block_hash) = receiver.recv().await {
1869 if let Err(e) = self.log_mined_block(block_hash).await {
1870 node_info!("Failed to log mined block {block_hash:?}: {e:?}");
1871 }
1872 if block_hash == awaited_hash {
1873 break;
1874 }
1875 }
1876 }
1877 })
1878 .await
1879 .map_err(|e| {
1880 Error::InternalError(format!(
1881 "Was not notified about the new best block in time {e:?}."
1882 ))
1883 })?;
1884 }
1885 Ok(())
1886 }
1887
1888 fn new_block_notifications(&self) -> Result<tokio::sync::broadcast::Receiver<H256>> {
1889 self.eth_rpc_client
1890 .block_notifier()
1891 .map(|sender| sender.subscribe())
1892 .ok_or(Error::InternalError("Could not subscribe to new blocks. 😢".to_string()))
1893 }
1894
1895 async fn log_mined_block(&self, block_hash: H256) -> Result<()> {
1896 let block_timestamp = self.backend.read_timestamp(block_hash)?;
1897 let block_number = self.backend.read_block_number(block_hash)?;
1898 let timestamp = utc_from_millis(block_timestamp)?;
1899 node_info!(" Block Number: {}", block_number);
1900 node_info!(" Block Hash: {:?}", block_hash);
1901 if timestamp.year() > 9999 {
1902 node_info!(" Block Time: {:?}\n", timestamp.to_rfc3339());
1904 } else {
1905 node_info!(" Block Time: {:?}\n", timestamp.to_rfc2822());
1906 }
1907 Ok(())
1908 }
1909}
1910
1911fn utc_from_millis(millis: u64) -> Result<DateTime<Utc>> {
1913 DateTime::from_timestamp_millis(
1914 millis.try_into().map_err(|err| {
1915 Error::InvalidParams(format!("Could not convert the timestamp: {err:?}"))
1916 })?,
1917 )
1918 .ok_or(Error::InvalidParams("Could not get the utc datetime ðŸ˜".to_string()))
1919}
1920
1921fn new_contract_info(address: &Address, code_hash: H256, nonce: Nonce) -> ContractInfo {
1922 let address = H160::from_slice(address.as_slice());
1923
1924 let trie_id =
1925 ("bcontract_trie_v1", address, nonce).using_encoded(BlakeTwo256::hash).as_ref().to_vec();
1926
1927 ContractInfo {
1928 trie_id: BoundedVec(trie_id),
1929 code_hash,
1930 storage_bytes: 0,
1931 storage_items: 0,
1932 storage_byte_deposit: 0,
1933 storage_item_deposit: 0,
1934 storage_base_deposit: 0,
1935 immutable_data_len: 0,
1936 }
1937}
1938
1939async fn create_online_client(
1940 substrate_service: &Service,
1941 rpc_client: RpcClient,
1942) -> Result<OnlineClient<SrcChainConfig>> {
1943 let genesis_block_number = substrate_service.genesis_block_number.try_into().map_err(|_| {
1944 Error::InternalError(format!(
1945 "Genesis block number {} is too large for u32 (max: {})",
1946 substrate_service.genesis_block_number,
1947 u32::MAX
1948 ))
1949 })?;
1950
1951 let Some(genesis_hash) = substrate_service.client.hash(genesis_block_number).ok().flatten()
1952 else {
1953 return Err(Error::InternalError(format!(
1954 "Genesis hash not found for genesis block number {}",
1955 substrate_service.genesis_block_number
1956 )));
1957 };
1958
1959 let Ok(runtime_version) = substrate_service.client.runtime_version_at(genesis_hash) else {
1960 return Err(Error::InternalError(
1961 "Runtime version not found for given genesis hash".to_string(),
1962 ));
1963 };
1964
1965 let subxt_runtime_version = SubxtRuntimeVersion {
1966 spec_version: runtime_version.spec_version,
1967 transaction_version: runtime_version.transaction_version,
1968 };
1969
1970 let Ok(supported_metadata_versions) =
1971 substrate_service.client.runtime_api().metadata_versions(genesis_hash)
1972 else {
1973 return Err(Error::InternalError("Unable to fetch metadata versions".to_string()));
1974 };
1975
1976 let Some(latest_metadata_version) = supported_metadata_versions.into_iter().max() else {
1977 return Err(Error::InternalError("No stable metadata versions supported".to_string()));
1978 };
1979
1980 let opaque_metadata = substrate_service
1981 .client
1982 .runtime_api()
1983 .metadata_at_version(genesis_hash, latest_metadata_version)
1984 .map_err(|_| {
1985 Error::InternalError("Failed to get runtime API for genesis hash".to_string())
1986 })?
1987 .ok_or_else(|| {
1988 Error::InternalError(format!(
1989 "Metadata not found for version {latest_metadata_version} at genesis hash"
1990 ))
1991 })?;
1992 let subxt_metadata = SubxtMetadata::decode(&mut (*opaque_metadata).as_slice())
1993 .map_err(|_| Error::InternalError("Unable to decode metadata".to_string()))?;
1994
1995 OnlineClient::<SrcChainConfig>::from_rpc_client_with(
1996 genesis_hash,
1997 subxt_runtime_version,
1998 subxt_metadata,
1999 rpc_client,
2000 )
2001 .map_err(|err| {
2002 Error::InternalError(format!("Failed to initialize the subxt online client: {err}"))
2003 })
2004}
2005
2006async fn create_revive_rpc_client(
2007 api: OnlineClient<SrcChainConfig>,
2008 rpc_client: RpcClient,
2009 rpc: LegacyRpcMethods<SrcChainConfig>,
2010 block_provider: SubxtBlockInfoProvider,
2011 task_spawn_handle: SpawnTaskHandle,
2012 keep_latest_n_blocks: Option<usize>,
2013) -> Result<EthRpcClient> {
2014 let pool = SqlitePoolOptions::new()
2015 .max_connections(1)
2016 .idle_timeout(None)
2018 .max_lifetime(None)
2019 .connect("sqlite::memory:")
2020 .await
2021 .map_err(|err| Error::ReviveRpc(EthRpcError::ClientError(ClientError::SqlxError(err))))?;
2022
2023 let receipt_extractor = ReceiptExtractor::new_with_custom_address_recovery(
2024 api.clone(),
2025 None,
2026 Arc::new(recover_maybe_impersonated_address),
2027 )
2028 .await
2029 .map_err(|err| Error::ReviveRpc(EthRpcError::ClientError(err)))?;
2030
2031 let receipt_provider =
2032 ReceiptProvider::new(pool, block_provider.clone(), receipt_extractor, keep_latest_n_blocks)
2033 .await
2034 .map_err(|err| {
2035 Error::ReviveRpc(EthRpcError::ClientError(ClientError::SqlxError(err)))
2036 })?;
2037
2038 let mut eth_rpc_client =
2039 EthRpcClient::new(api, rpc_client, rpc, block_provider, receipt_provider)
2040 .await
2041 .map_err(Error::from)?;
2042 let _ = eth_rpc_client.subscribe_and_cache_blocks(1).await;
2045
2046 eth_rpc_client.set_block_notifier(Some(tokio::sync::broadcast::channel::<H256>(50).0));
2048 let eth_rpc_client_clone = eth_rpc_client.clone();
2049 task_spawn_handle.spawn("block-subscription", "None", async move {
2050 let eth_rpc_client = eth_rpc_client_clone;
2051 let best_future =
2052 eth_rpc_client.subscribe_and_cache_new_blocks(SubscriptionType::BestBlocks);
2053 let finalized_future =
2054 eth_rpc_client.subscribe_and_cache_new_blocks(SubscriptionType::FinalizedBlocks);
2055 let res = tokio::try_join!(best_future, finalized_future).map(|_| ());
2056 if let Err(err) = res {
2057 panic!("Block subscription task failed: {err:?}")
2058 }
2059 });
2060
2061 Ok(eth_rpc_client)
2062}