arb_precompiles/
arbstatistics.rs

1use std::sync::Arc;
2
3use alloy_evm::precompiles::{DynPrecompile, PrecompileInput};
4use alloy_primitives::{Address, U256};
5use alloy_sol_types::SolInterface;
6use arb_context::ArbPrecompileCtx;
7use revm::precompile::{PrecompileId, PrecompileOutput, PrecompileResult};
8
9use crate::interfaces::IArbStatistics;
10
11/// ArbStatistics precompile address (0x6f).
12pub const ARBSTATISTICS_ADDRESS: Address = Address::new([
13    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
14    0x00, 0x00, 0x00, 0x6f,
15]);
16
17const COPY_GAS: u64 = 3;
18
19pub fn create_arbstatistics_precompile(ctx: Arc<ArbPrecompileCtx>) -> DynPrecompile {
20    DynPrecompile::new_stateful(PrecompileId::custom("arbstatistics"), move |input| {
21        handler(input, &ctx)
22    })
23}
24
25fn handler(input: PrecompileInput<'_>, ctx: &ArbPrecompileCtx) -> PrecompileResult {
26    let mut gas_used = 0u64;
27    let gas_limit = input.gas;
28    crate::init_precompile_gas(&mut gas_used, ctx, input.data.len());
29
30    let call = match IArbStatistics::ArbStatisticsCalls::abi_decode(input.data) {
31        Ok(c) => c,
32        Err(_) => return crate::burn_all_revert(gas_limit),
33    };
34    if let Some(r) = crate::reject_nonpayable_value(input.value, input.data, gas_limit, &[]) {
35        return r;
36    }
37    if let Some(r) = crate::reject_delegate_nonpure(
38        input.target_address != input.bytecode_address,
39        input.data,
40        gas_limit,
41        &[],
42    ) {
43        return r;
44    }
45
46    use IArbStatistics::ArbStatisticsCalls;
47    let result = match call {
48        ArbStatisticsCalls::getStats(_) => handle_get_stats(&input, &mut gas_used, ctx),
49    };
50    crate::gas_check(ctx, gas_limit, gas_used, result)
51}
52
53fn handle_get_stats(
54    input: &PrecompileInput<'_>,
55    gas_used: &mut u64,
56    ctx: &ArbPrecompileCtx,
57) -> PrecompileResult {
58    // Five Classic-era stats stay zero post-migration; only block number is live.
59    let block_number = U256::from(ctx.block.l2_block_number);
60    let mut out = Vec::with_capacity(192);
61    out.extend_from_slice(&block_number.to_be_bytes::<32>());
62    for _ in 0..5 {
63        out.extend_from_slice(&U256::ZERO.to_be_bytes::<32>());
64    }
65    crate::charge_computation(gas_used, ctx, 6 * COPY_GAS);
66    Ok(PrecompileOutput::new(
67        (*gas_used).min(input.gas),
68        out.into(),
69    ))
70}