arb_precompiles/
arbosacts.rs

1use std::sync::Arc;
2
3use alloy_evm::precompiles::{DynPrecompile, PrecompileInput};
4use alloy_primitives::Address;
5use alloy_sol_types::{SolError, SolInterface};
6use arb_context::ArbPrecompileCtx;
7use revm::precompile::{PrecompileId, PrecompileResult};
8
9use crate::interfaces::IArbosActs;
10
11/// ArbosActs precompile address (0xa4b05).
12pub const ARBOSACTS_ADDRESS: Address = Address::new([
13    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
14    0x00, 0x0a, 0x4b, 0x05,
15]);
16
17pub fn create_arbosacts_precompile(ctx: Arc<ArbPrecompileCtx>) -> DynPrecompile {
18    DynPrecompile::new_stateful(PrecompileId::custom("arbosacts"), move |input| {
19        handler(input, &ctx)
20    })
21}
22
23/// Every method is invoked by ArbOS internally, never by an EVM caller, so a
24/// valid call reverts with `CallerNotArbOS()`. Unknown selectors, static,
25/// delegated, or value-bearing calls consume all gas and revert empty.
26fn handler(input: PrecompileInput<'_>, ctx: &ArbPrecompileCtx) -> PrecompileResult {
27    let gas_limit = input.gas;
28    let known_method = IArbosActs::ArbosActsCalls::abi_decode(input.data).is_ok();
29    if !known_method
30        || input.is_static
31        || input.target_address != input.bytecode_address
32        || !input.value.is_zero()
33    {
34        return crate::burn_all_revert(gas_limit);
35    }
36
37    let mut gas_used = 0u64;
38    crate::init_precompile_gas(&mut gas_used, ctx, input.data.len());
39    crate::revert_sol_error(
40        &mut gas_used,
41        ctx,
42        IArbosActs::CallerNotArbOS {}.abi_encode(),
43        gas_limit,
44    )
45}