arb_precompiles/
nodeinterface_debug.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::INodeInterfaceDebug;
10
11/// NodeInterfaceDebug virtual contract address (0xc9).
12pub const NODE_INTERFACE_DEBUG_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, 0xc9,
15]);
16
17const COPY_GAS: u64 = 3;
18
19pub fn create_nodeinterface_debug_precompile(ctx: Arc<ArbPrecompileCtx>) -> DynPrecompile {
20    DynPrecompile::new_stateful(PrecompileId::custom("nodeinterfacedebug"), 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 INodeInterfaceDebug::NodeInterfaceDebugCalls::abi_decode(input.data) {
31        Ok(c) => c,
32        Err(_) => return crate::burn_all_revert(gas_limit),
33    };
34
35    use INodeInterfaceDebug::NodeInterfaceDebugCalls;
36    let result = match call {
37        NodeInterfaceDebugCalls::getRetryable(_) => handle_get_retryable(&input),
38    };
39    crate::gas_check(ctx, gas_limit, gas_used, result)
40}
41
42/// Returns a well-formed empty `RetryableInfo` — bridge tooling gets a valid
43/// ABI response; populating it requires RPC-layer state access.
44fn handle_get_retryable(input: &PrecompileInput<'_>) -> PrecompileResult {
45    let mut out = vec![0u8; 7 * 32 + 32];
46    U256::from(7u64 * 32)
47        .to_be_bytes::<32>()
48        .iter()
49        .enumerate()
50        .for_each(|(i, b)| out[6 * 32 + i] = *b);
51    Ok(PrecompileOutput::new(COPY_GAS.min(input.gas), out.into()))
52}