diff --git a/crates/anvil/src/eth/backend/mem/mod.rs b/crates/anvil/src/eth/backend/mem/mod.rs index 804ef74f41fa..40baa8e1fa1b 100644 --- a/crates/anvil/src/eth/backend/mem/mod.rs +++ b/crates/anvil/src/eth/backend/mem/mod.rs @@ -67,6 +67,7 @@ use anvil_core::eth::{ }; use anvil_rpc::error::RpcError; +use alloy_chains::NamedChain; use flate2::{read::GzDecoder, write::GzEncoder, Compression}; use foundry_evm::{ backend::{DatabaseError, DatabaseResult, RevertSnapshotAction}, @@ -1640,7 +1641,7 @@ impl Backend { Some(block.into_full_block(transactions.into_iter().map(|t| t.inner).collect())) } - /// Takes a block as it's stored internally and returns the eth api conform block format + /// Takes a block as it's stored internally and returns the eth api conform block format. pub fn convert_block(&self, block: Block) -> AlloyBlock { let size = U256::from(alloy_rlp::encode(&block).len() as u32); @@ -1671,7 +1672,7 @@ impl Backend { parent_beacon_block_root, } = header; - AlloyBlock { + let mut block = AlloyBlock { header: AlloyHeader { hash: Some(hash), parent_hash, @@ -1704,7 +1705,23 @@ impl Backend { uncles: vec![], withdrawals: None, other: Default::default(), - } + }; + + // If Arbitrum, apply chain specifics to converted block. + if let Ok( + NamedChain::Arbitrum | + NamedChain::ArbitrumGoerli | + NamedChain::ArbitrumNova | + NamedChain::ArbitrumTestnet, + ) = NamedChain::try_from(self.env.read().env.cfg.chain_id) + { + // Block number is the best number. + block.header.number = Some(self.best_number()); + // Set `l1BlockNumber` field. + block.other.insert("l1BlockNumber".to_string(), number.into()); + } + + block } /// Converts the `BlockNumber` into a numeric value diff --git a/crates/anvil/tests/it/fork.rs b/crates/anvil/tests/it/fork.rs index b27b361b26e7..8a4542b488d8 100644 --- a/crates/anvil/tests/it/fork.rs +++ b/crates/anvil/tests/it/fork.rs @@ -1165,6 +1165,11 @@ async fn test_arbitrum_fork_block_number() { let block_number = api.block_number().unwrap().to::(); assert_eq!(block_number, initial_block_number + 1); + // test block by number API call returns proper block number and `l1BlockNumber` is set + let block_by_number = api.block_by_number(BlockNumberOrTag::Latest).await.unwrap().unwrap(); + assert_eq!(block_by_number.header.number.unwrap(), initial_block_number + 1); + assert!(block_by_number.other.get("l1BlockNumber").is_some()); + // revert to recorded snapshot and check block number assert!(api.evm_revert(snapshot).await.unwrap()); let block_number = api.block_number().unwrap().to::();