# AGENTS.md

## OVERVIEW
System contract integration layer with canonical addresses, deployment transactions, and frame-init interception logic.

## STRUCTURE
- `oracle.rs`: oracle contract address, code constants, deployment helper.
- `keyless_deploy.rs`: keyless deploy address, code constants, deployment helper.
- `control.rs`: MegaAccessControl address, selectors, deployment helper, revert payload builders.
- `limit_control.rs`: MegaLimitControl address and deployment helper.
- `intercept.rs`: interceptor dispatch and synthetic frame-result handling.
- `tx.rs`: helpers for system/deposit-like transaction construction.

## KEY PATTERNS
- Deployment helpers are idempotent and keyed by code hash equality.
- Hardfork gating happens in each deployment helper.
- Interceptors return `None` to fall through to on-chain bytecode on unknown selectors.
- View/control interceptors reject non-zero transfer values with `NonZeroTransfer()`.
- Synthetic interceptor results bypass normal child-frame init and require empty tracking frame push by caller.
- Keep selector constants and ABI encode/decode paths aligned with `mega-system-contracts` interfaces.
- Pre-block helpers (`transact_deploy_*`, `transact_apply_pending_changes`, etc.) return `Option<EvmState>` and let the block executor commit. They never call `db.commit(...)` directly — the executor fires `system_caller.on_state(source, &state)` between collection and commit, and that hook feeds the stateless witness generator. See `PRE-BLOCK STATE CHANGE CONTRACT` below.

## PRE-BLOCK STATE CHANGE CONTRACT

Pre-block helpers in this module participate in the `pre_execution_changes` → `commit_system_call_outcomes` pipeline on `MegaBlockExecutor`. The contract for a new or modified helper:

- **Never call `db.commit(...)` inside the helper.** Return the prepared state; let the executor commit.
- **Return `Ok(None)` only when the step is gated out entirely** — wrong hardfork, feature disabled, etc. Not as an "already up to date" shortcut.
- **On an idempotent no-change path** (e.g., the contract is already deployed with the correct code hash), return `Some(EvmState)` that carries the observed account as a read-only entry: `Account { info, ..Default::default() }` with no `touched`/`created` flags. Returning `None` here is a bug — the account disappears from the stateless witness read set and the generated proof is incomplete.
- **On a real-change path**, include every account and storage slot the helper touched, including slots read in preparation for the change. The witness recorder must see the complete set.

The returned `EvmState` serves two purposes, both load-bearing:

1. **Commit** — `db.commit(state)` applies the writes.
2. **Witness recording** — `system_caller.on_state(source, &state)` runs before commit and feeds the stateless witness generator with the full read/write set for that outcome. Without this, a stateless client cannot verify the block against its pre-state.

The counterpart block-executor side (collection, `on_state`, commit order) is documented in `crates/mega-evm/src/block/AGENTS.md`.

## ANTI-PATTERNS
- Do not intercept unknown selectors with a synthetic revert unless spec requires it.
- Preserve on-chain-bytecode fallback for unknown calls.
- Do not accept value transfers for view/control interceptors unless explicitly specified and tested.
- Do not deploy system bytecode by raw literals in this crate.
- Reuse constants generated by `mega-system-contracts`.
- Do not call `db.commit(...)` inside a helper that participates in `pre_execution_changes`. It bypasses the `on_state` witness-recorder hook and silently produces incomplete stateless proofs.
- Do not return `None` from a helper on a "no change needed" path. Return `Some(EvmState)` with the account entries observed, even when nothing is written.

## WHERE TO LOOK
- Add a new system contract deployment: new `<name>.rs` + hook call in `block/executor.rs::pre_execution_changes`.
- Add interceptor method behavior: `intercept.rs` for decode/dispatch and revert policy.
- Change access-control volatile disable semantics: `control.rs` + `intercept.rs` + `access/tracker.rs`.
- Change keyless deploy interception entrypoint: `intercept.rs` and `keyless_deploy.rs`.
- Update system contract address or code hash references: corresponding module constant definitions.
