arb_precompiles/
arbstatistics.rs

1use alloy_evm::precompiles::{DynPrecompile, PrecompileInput};
2use alloy_primitives::{Address, U256};
3use alloy_sol_types::SolInterface;
4use revm::precompile::{PrecompileId, PrecompileOutput, PrecompileResult};
5
6use crate::interfaces::IArbStatistics;
7
8/// ArbStatistics precompile address (0x6f).
9pub const ARBSTATISTICS_ADDRESS: Address = Address::new([
10    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
11    0x00, 0x00, 0x00, 0x6f,
12]);
13
14const COPY_GAS: u64 = 3;
15const SLOAD_GAS: u64 = 800;
16
17pub fn create_arbstatistics_precompile() -> DynPrecompile {
18    DynPrecompile::new_stateful(PrecompileId::custom("arbstatistics"), handler)
19}
20
21fn handler(input: PrecompileInput<'_>) -> PrecompileResult {
22    let gas_limit = input.gas;
23    crate::init_precompile_gas(input.data.len());
24
25    let call = match IArbStatistics::ArbStatisticsCalls::abi_decode(input.data) {
26        Ok(c) => c,
27        Err(_) => return crate::burn_all_revert(gas_limit),
28    };
29
30    use IArbStatistics::ArbStatisticsCalls;
31    let result = match call {
32        ArbStatisticsCalls::getStats(_) => handle_get_stats(&input),
33    };
34    crate::gas_check(gas_limit, result)
35}
36
37fn handle_get_stats(input: &PrecompileInput<'_>) -> PrecompileResult {
38    // Five Classic-era stats stay zero post-migration; only block number is live.
39    let block_number = U256::from(crate::arbsys::get_current_l2_block());
40    let mut out = Vec::with_capacity(192);
41    out.extend_from_slice(&block_number.to_be_bytes::<32>());
42    for _ in 0..5 {
43        out.extend_from_slice(&U256::ZERO.to_be_bytes::<32>());
44    }
45    let gas_cost = (SLOAD_GAS + 6 * COPY_GAS).min(input.gas);
46    Ok(PrecompileOutput::new(gas_cost, out.into()))
47}