<!-- tempo-docs-context -->
> Source: [/docs/protocol/zones/proving](https://tempo.xyz/developers/docs/protocol/zones/proving.md)
> Section: [Zones](https://tempo.xyz/developers/docs/zones.md). Connect to a Zone and work with private balances, deposits, and withdrawals. Zones is in limited preview; see the introduction for access. Earlier testnet sandbox guides describe a separate integration.
> [Documentation index](https://tempo.xyz/developers/llms.txt) · [Docs skill](https://tempo.xyz/developers/SKILL.md)

> Tempo MCP: Use `search`, `find_pages`, `read_page`, and `code` at `https://mcp.tempo.xyz` for Tempo and related documentation.
> If an indexed page is missing or reflects an older site, read this site’s [documentation index](https://tempo.xyz/developers/llms.txt) and Markdown pages directly.

# Proving and Settlement

Settlement records commitments to private Zone execution on Tempo and queues accepted withdrawals.

## Overview

Zone settlement queues accepted withdrawals for processing on Tempo. The stateless proof function (SPF) validates batch execution. It replays batches against witnessed Zone and Tempo state.

## Implementation Status

This page follows Zones source at [`ac49071f`](https://github.com/tempoxyz/zones/tree/ac49071f) and Tempo source at [`3c4db7f843`](https://github.com/tempoxyz/tempo/tree/3c4db7f843). Source support doesn't establish which runtime a deployed Zone uses.

The Zones Solidity reference verifier still returns `true` without checking execution. Tempo also implements a native Nitro attestation verifier activated by T13. At the reviewed commit, its approved enclave measurements are unset, so it rejects Nitro proofs.

During rollout, T13 also accepts the `NoProof` mode. This mode keeps the quorum and continuity checks but skips attestation. A later upgrade removes it. Check the network's active hardfork, verifier implementation, and approved measurements before relying on execution-proof enforcement.

The sequencer implementation can be configured to wait for a Nitro-attested batch before submitting it. This node-side requirement is separate from onchain enforcement. Forced exits remain unfinished. Withdrawal settlement depends on the operator continuing to process and submit batches.

## Batch Submission

The sequencer calls `ZonePortal.submitBatch` on Tempo. Each batch covers one or more Zone blocks and includes:

| Field | Description |
|-------|-------------|
| `tempoBlockNumber` | Tempo checkpoint committed by the Zone |
| `recentTempoBlockNumber` | Recent anchor for ancestry mode (`0` for direct lookup) |
| `blockTransition` | Zone block hash transition (`prevBlockHash` → `nextBlockHash`) |
| `depositQueueTransition` | Previous and next deposit hashes and deposit numbers |
| `tokenEnablementTransition` | Previous and next processed enabled-token counts (T13) |
| `withdrawalQueueHash` | Hash chain of withdrawals for this batch (`0` if none) |
| `verifierConfig` | `0x01` for the Nitro verifier policy; `0x02` for the temporary T13 `NoProof` fallback, which requires an empty `proof` |
| `proof` | Nitro attestation when a settlement prover is configured; empty on the unconfigured compatibility path |
| `zoneHeight` | Height of the submitted Zone tip |
| `signatures` | Distinct sequencer signatures forming the settlement certificate |

The portal checks these before calling the verifier:

* Continuity with its stored `blockHash`.
* An increasing Zone height.
* Deposit progress.
* Processed token-enablement progress under T13.
* The active sequencer quorum.

The EIP-712 certificate binds the Zone ID, sequencer-set version, batch index, and verifier. It also binds the Tempo anchor, state transitions, withdrawal hash, and verifier configuration. Replacing the sequencer set invalidates certificates from the old configuration.

The portal then calls the configured verifier. On acceptance, it updates the Zone tip and the processed deposit and enabled-token counts. It also updates the Tempo checkpoint and withdrawal batch index, then enqueues any withdrawals. A signature quorum authenticates the submitted commitments. It doesn't independently prove correct execution.

The sequencer prepares a signed batch and waits for Nitro attestation when configured. The portal checks quorum and continuity, then calls the active verifier. The Solidity reference is a stub; the T13 native verifier checks attestations and requires approved enclave measurements.

## Verifier Interface

The T13 portal calls its configured verifier through this interface. Earlier runtimes use older interfaces, so use the ABI for your network:

```solidity
interface IVerifier {
    function verify(
        uint32 zoneId,
        uint64 tempoBlockNumber,
        uint64 anchorBlockNumber,
        bytes32 anchorBlockHash,
        uint64 expectedWithdrawalBatchIndex,
        uint256 nextZoneHeight,
        BlockTransition calldata blockTransition,
        DepositQueueTransition calldata depositQueueTransition,
        TokenEnablementTransition calldata tokenEnablementTransition,
        bytes32 withdrawalQueueHash,
        bytes calldata verifierConfig,
        bytes calldata proof
    ) external view returns (bool);
}
```

The native T13 verifier binds the attested result to the parent chain, canonical portal, Zone ID, verifier, and batch inputs. It checks the Nitro certificate chain, document signature, enclave measurements, and batch digest. The Solidity reference verifier doesn't perform these checks.

## State Transition Function

The SPF is implemented as a Rust verifier. It accepts trusted network configuration separately from the batch witness:

```rust
pub fn prove_zone_batch(
    config: &SpfConfig,
    witness: BatchWitness,
) -> Result<BatchOutput, Error>
```

### Execution Flow

The stateless validator takes trusted configuration and a batch witness, checks and replays state, recomputes roots and queue commitments, validates the Tempo anchor, and returns BatchOutput or an error.

1. **Bind the Starting State:** Validate the Zone chain ID and portal against trusted configuration. Use the parent header's state root for Zone reads. Verify that the initial Tempo witness matches the checkpoint stored in Zone state.
2. **Replay Blocks:** Check parent hashes, block numbers, and timestamps. Execute the supplied system and user transactions through the Zone EVM. This includes deposit processing and withdrawal finalization when present.
3. **Recompute Commitments:** Rebuild state roots and canonical Tempo-format Zone headers. Then read deposit progress, enabled-token progress, and withdrawal batch commitments from the resulting state.
4. **Validate the Anchor:** Match the final Tempo checkpoint to the public inputs, directly or through the supplied ancestry headers.

The SPF can replay an open Zone tip without withdrawal finalization. Settlement policy imposes its batch boundaries separately.

<span id="deployment-modes" />

### Validation Deployment Modes

On a sequencer, `--sequencer.enable-prover` requires `--sequencer.prover-address HOST:PORT`. The sequencer waits for the remote prover's successful batch result and nonempty Nitro attestation before submission. It collects the settlement certificate in parallel.

On an `rpc_only` follower, the same flag enables observational validation. Without a remote address, this runs in-process. A follower's observational results don't control settlement. The unconfigured sequencer compatibility path submits empty proof bytes. It can't satisfy an enforcing verifier.

The remote service runs inside AWS Nitro Enclaves over AF\_VSOCK. After replay, it places the canonical batch digest in a Nitro attestation document's `user_data`. It returns `BatchOutput` with a proof bundle. The bundle sets `verifierConfig = 0x01` and the raw COSE/CBOR document as `proof`.

TCP mode supports local transport testing, but successful replay still requires the Nitro Secure Module. Outside an enclave, the service returns `attestation_unavailable` rather than an unattested success. ZK proof generation isn't implemented.

## Ancestry Proofs

Tempo's EIP-2935 history exposes an 8,191-block lookup window. If a Zone’s checkpoint is older, the submitter chooses a recent Tempo anchor and collects the intervening headers. The SPF validates their consecutive block numbers and parent hashes against that anchor.

| Mode | Condition | Behavior |
|------|-----------|----------|
| Direct | `recentTempoBlockNumber = 0` | Portal reads the `tempoBlockNumber` hash from EIP-2935 |
| Ancestry | `recentTempoBlockNumber > tempoBlockNumber` | Portal reads the recent hash; SPF checks the intervening header chain |

Both modes can carry the Nitro attestation. The SPF validates ancestry during replay. An enforcing verifier must authenticate the resulting attestation and bind it to the submitted anchor. The Solidity stub doesn't enforce that check.

## Tempo State Access

The Zone accesses its finalized Tempo checkpoint through the `TempoState` precompile (`0x1c00...0000`). During execution:

1. `ZoneInbox` calls `TempoState.finalizeTempo(headers)` when advancing the checkpoint.
2. Zone system execution reads Tempo state at that exact checkpoint.
3. SPF replay requires witnessed account and storage proofs for those reads.

The Zone imports finalized Tempo headers in order. Policy updates become visible after the corresponding checkpoint is imported. They don't arrive as unrestricted reads of the latest Tempo state.

## Related

[Architecture](https://tempo.xyz/developers/docs/protocol/zones/architecture): Covers portals, private ledgers, contract roles, and the settlement lifecycle.

[Bridging](https://tempo.xyz/developers/docs/protocol/zones/bridging): Covers deposits, withdrawals, encrypted deposits, and composable withdrawal callbacks.

[Privacy](https://tempo.xyz/developers/docs/zones/privacy): Covers who can see Zone data and the trust assumptions behind it.
