---
id: TIP-1154
title: Configurable Accounts on Zones
description: Zones read each account's configuration commitment from Tempo, so configurable accounts work on zones with the same owners as on Tempo.
authors: Tanishk Goyal (@legion2002)
status: Draft
related: TIP-1107, TIP-1111, TIP-1113
protocolVersion: T14
---

# TIP-1154: Configurable Accounts on Zones

## Abstract

This TIP brings configurable accounts to Zones. A configurable account lets its owners change which keys control it while keeping the same address. Under this TIP, a change made on Tempo reaches each zone once the zone imports the Tempo block that contains it: the account works on any zone with the same address and the same owners as on Tempo.

Each zone reads it from the latest Tempo block the zone has imported, and the zone's prover checks every read against that block.

## Motivation

[Configurable accounts](./tip-1107.md) let owners change the keys behind an account without moving its funds to a new address. They can add an owner, change the signing policy, or replace a key that was lost or stolen. This TIP enables the same changes to propagate to any zone on which the account has funds without any direct action by the user. 

As motivation, suppose Acme's treasury is a 2-of-3 configurable account. Acme pays staff from it on one zone and pays suppliers on another, and receives funds on a third. An executive's owner key is compromised, so Acme replaces it on Tempo. Without this TIP, Acme would have to repeat the change on each zone it had funds. Until it did, the stolen key would still count toward the 2-of-3 on any zone it missed.

With this TIP, Acme makes the change once, on Tempo, and each zone applies it once it imports that block. New accounts need no setup on a zone. A new configurable account works on any zone from its first transaction, at the same address as on Tempo.

## Assumptions

- Zones already read Tempo state at a finalized, proven Tempo block (the **anchor**, kept by the `TempoState` precompile), as they do for TIP-403 policies. This TIP adds one more kind of read through that same path.
- Address derivation ([TIP-1107](./tip-1107.md#address-derivation)) hashes only the initial configuration, with no chain ID, so a derived address is the same on Tempo and its zones.
- This TIP activates together with the other T14 configurable account components.

---

# Specification

## Overview

On a zone, an account's **commitment** means its [TIP-1107 configuration commitment](./tip-1107.md#commitment-storage), read at the zone's anchor. It is the configuration hash in the fifth field of the account's leaf in Tempo's state trie. A zero commitment means the account is unregistered. Zone state never stores a commitment.

A [configurable account](./tip-1107.md) keeps its owners and signing policy in a configuration that this commitment hashes. Its owners authorize with a configurable-account signature, type byte `0x05`. A derived account's address comes from its initial configuration. An ordinary key whose address happens to equal it is the account's [colliding key](./tip-1107.md#address-derivation).

| Operation | Tempo | Zone under this TIP |
|---|---|---|
| Authorize with `0x05` (direct, access key, key authorization) | Allowed | Allowed, checked against Tempo's commitment at the anchor |
| Initial registration | Writes the version-zero hash and retires the [colliding key](./tip-1107.md#address-derivation) | No write. An unregistered account is checked by derivation, exactly as on Tempo. The colliding key is retired on the zone only once the account registers on Tempo and the anchor includes it |
| `updateConfig`, `upgradeAccount` | Allowed | Revert with `UnsupportedOnZone()` |
| Original-key retirement (TIP-1113) | Uses the local commitment | Uses Tempo's commitment at the anchor |

Owners register, rotate keys and migrate accounts only on Tempo. Zones apply those changes once their anchor reaches the Tempo block that contains them. An account used only on a zone keeps its colliding key live there until it registers on Tempo. Users who want the key retired on a zone register on Tempo first.

## Mechanics

The subsections follow a zone transaction from start to finish. First the zone reads Tempo state at the anchor and authorizes the transaction against it. Then it executes and pays for each read, and the prover proves the reads in the batch. Last, the zone applies owner changes as its anchor advances.

### Reading Tempo state

1. The anchor is fixed for each transaction, as it is for TIP-403 reads. Every transaction in a zone block reads Tempo at the anchor set by that block's opening [`advanceTempo`](../zones/specs/spec.md#block-structure) system transaction (a block has exactly one).
2. Zones read Tempo only for an **eligible** address, meaning one whose zone code is empty and that isn't zero, a virtual address, an address with the TIP-20 prefix (`0x20C0` followed by ten zero bytes) or the ZonePortal prefix (`0x5AD0` followed by ten zero bytes), a precompile active on the zone, or a zone system contract. Eligibility depends only on the address and zone state, never on Tempo state, so every zone node charges the same gas. It excludes everything TIP-1107 excludes, since an address with either prefix can never be a configurable account. Zones reject EIP-7702 and Tempo authorization lists, so no zone account has a delegation. Contract creation is disabled too, so every address with zone code is a contract the zone predeployed and has no commitment. Loading it reads nothing from Tempo.
3. Every read of an account's commitment during zone execution returns Tempo's commitment for that address at the anchor. This includes transaction authorization, TIP-1113 retirement checks, `verifyConfigurableAccount`, `getConfigCommitment`, TIP-20 `permit`, keychain helpers (`verifyKeychain`, `verifyKeychainAdmin`, `isAdminKey`) and payment channel `open` and `topUp`.
4. The commitment is read when execution first loads the account in a transaction, including when a precompile reads the commitment of an address, whether passed to it or recovered from a signature. It is priced through the account's cold access, as described in [Gas](#gas).
5. If Tempo state at the anchor can't be read, execution fails closed. The sequencer stops building rather than treating the commitment as zero.

### Transaction authorization

With these reads, the [TIP-1107 authorization](./tip-1107.md#authorization) rules and the [TIP-1113 retirement](./tip-1113.md#retirement-check) rules apply on zones without changes:

- An account unregistered on Tempo validates a version-zero configuration by derivation.
- A registered or migrated account must match Tempo's commitment.
- A primitive signature from an address with a nonzero commitment is rejected as a retired root.

### Transaction execution

#### Account code

An eligible account whose Tempo commitment at the anchor is nonzero has the [account code marker](./tip-1107.md#account-code) (`0xef`) as its code on the zone, read from Tempo like the commitment and never written to zone state. When such an account changes on the zone, for example when its nonce advances, the zone stores it with its local code and no commitment. Authorization's code-hash check, `EXTCODESIZE`, `EXTCODEHASH`, `EXTCODECOPY`, calls to the account and ERC-1271 then behave as on Tempo, so verifiers that check for code reject the retired original key.

Such an account exists on the zone even without a zone leaf. `EXTCODEHASH` returns `keccak256(0xef)`, not zero, and EIP-161 doesn't treat it as empty. Loading or touching it writes no zone leaf. The zone writes one only when the account's balance or nonce changes.

#### Configuration writes

Zones never write a commitment. Tempo stays the only chain that does.

- Zones skip initial registration and do not charge its intrinsic gas (the TIP-1107 registration cost or TIP-1000 new-account cost).
- The configurable account precompile is active on zones for its read function `getConfigCommitment`. `verifyConfigurableAccount` lives on TIP-1020's `SignatureVerifier` precompile, as in [TIP-1107](./tip-1107.md#interfaces), and zones run it there (see [Signature verification](#signature-verification)). Calls to `updateConfig` ([TIP-1107](./tip-1107.md#owner-updates)) and `upgradeAccount` ([TIP-1113](./tip-1113.md)) explicitly revert with `UnsupportedOnZone()`.
- Zone account leaves keep the four-field encoding and their local code. A state transition that would write a commitment or the account marker into zone state is invalid.

#### Signature verification

Zones enable TIP-1020's `SignatureVerifier` precompile, at the same address as on Tempo, which zones don't run today. A configurable account's owners sign with a `0x05` signature that only `verifyConfigurableAccount` can check, and that function lives on `SignatureVerifier`. Contracts check these signatures through ERC-1271: a registered account carries the `0xef` code marker, whose `isValidSignature` calls `verifyConfigurableAccount`. Without `SignatureVerifier` on the zone, that call has nothing to run, so Permit2 and other ERC-1271 verifiers would reject every configurable-account signature on a zone even though the same signature passes on Tempo. On zones, `verifyConfigurableAccount` checks the signature against Tempo's commitment at the anchor, like every other commitment read, and charges `L1_COMMITMENT_READ_GAS` as described in [Gas](#gas). `SignatureVerifier`'s other functions behave as on Tempo.

#### Gas

`L1_COMMITMENT_READ_GAS` (10,000) is the cost of reading an account's commitment from Tempo, because each read adds a Tempo account proof to the batch witness. A zone reads Tempo when it loads an account from its database, which happens on the account's first [EIP-2929](https://eips.ethereum.org/EIPS/eip-2929) cold access in a transaction. So zones charge the read through the cold access itself. From T14, a zone's gas schedule adds `L1_COMMITMENT_READ_GAS` to the cold account access cost, which becomes 12,600, and to the access-list address cost, which becomes 12,400. Tempo's gas schedule is unchanged.

- **Execution.** Every cold account access pays the zone's cold cost. This covers `CALL*`, `EXTCODE*`, `BALANCE` and `SELFDESTRUCT`, and the accounts precompiles load through their storage provider. These include the address whose commitment `verifyConfigurableAccount`, `getConfigCommitment`, TIP-20 `permit`, `verifyKeychain`, `verifyKeychainAdmin`, `isAdminKey` and payment channel `open` and `topUp` read, whether passed in their arguments or recovered from a signature. An opcode or precompile access to a warm account pays nothing extra. A zone charges TIP-20 `transfer`, `transferFrom`, `transferWithMemo`, `transferFromWithMemo`, `approve` and `permit` a fixed 100,000 gas, which hides storage-dependent costs. That fixed charge replaces every access cost inside the call, including the cold access of a `permit` owner whose commitment it reads. It is above any cold access, so the bound below still holds.
- **Intrinsic gas.** A transaction warms its sender and first call target without a cold access, so intrinsic gas charges their reads. The sender pays a full cold access (12,600) on every zone transaction at T14, whatever its signature. The first call target pays `L1_COMMITMENT_READ_GAS` unless it is the sender, a precompile or an address that can't be an account. From T14, a later call in a batch pays a cold access in intrinsic gas only when its target is outside the transaction's warm set (the sender, the first call target, precompiles, access-list addresses and the coinbase) and no earlier call targeted it. On a zone that cold access is 12,600, so each distinct cold target pays its read once. Every other later call pays a warm access (100). This batch rule is the same on Tempo from T14, where a cold access stays 2,600, so only the cold access cost differs on a zone. A separate fee payer, key-authorization signer or access key pays the zone's cold access when it is cold.
- **Coinbase.** The coinbase stays warm ([EIP-3651](https://eips.ethereum.org/EIPS/eip-3651)). Its read is unpaid, but it is one account per block.
- **Exempt.** System transactions (`advanceTempo`, `advanceTempoHeaders`, `finalizeWithdrawalBatch`), which pay no gas and make no commitment reads.

The cold cost doesn't depend on whether an account is [eligible](#reading-tempo-state), so some accesses pay `L1_COMMITMENT_READ_GAS` for a read that never happens. These are cold accesses to TIP-20 tokens and other precompiles that EIP-2929 doesn't pre-warm, precompile addresses in an access list, and cold accesses to zone predeploys. Each pays at most once per transaction, so a batch of transfers on one TIP-20 token pays it once. The first call target is the only exception, since intrinsic gas prices it separately. See [Rationale](#rationale).

`L1_COMMITMENT_READ_GAS` keeps a batch's Tempo witness inside the prover's budget when every block is filled with reads of fresh addresses. A Tempo account proof is about 2.6 KB. A batch has 120 zone blocks of 30M gas each, and the witness limit is about 1.1 GB, so a block can carry at most about 3,500 reads, which needs at least about 8,500 gas per read. The cheapest repeatable read is an access-list entry at 12,400 gas (a cold access costs 12,600), so a 30M block carries at most about 2,420 reads, about 0.76 GB per batch, leaving about 30% of the limit for the rest of the witness. The value assumes today's Tempo state size. Each 10× growth in Tempo accounts adds about 0.45 KB per proof, and the constant should be revisited with it. It also assumes the default batch of 120 zone blocks at a 30M block gas limit. If operators run longer batches or raise the gas limit, `L1_COMMITMENT_READ_GAS` may need to rise with them.

### Batch verification

The prover's Tempo witness includes an account proof for each address whose commitment execution read, at each anchor used. For an unregistered address it proves the leaf has no fifth field, or that the account doesn't exist. Account-leaf decoding accepts the optional [TIP-1107](./tip-1107.md#commitment-storage) fifth field with the same rules as Tempo. The tag is `0x00`, the hash is nonzero, and there are no extra fields. A missing or invalid proof invalidates the batch.

Witness size grows with distinct eligible accounts read × anchors. The first proof of an account is about 2.6 KB, and the same account at another anchor in the batch adds about 0.45 KB, since most trie nodes are shared. A 60-second batch with 6,000 distinct senders adds about 16 MB. Reaching the 1.1 GB limit would take about 400,000 distinct senders in one batch, which [Gas](#gas) prices out. The sequencer collects each zone block's Tempo witness before the block becomes canonical, with one `eth_getMultiProof` call at that block's anchor, so a canonical block always has its witness stored. Fetching 1,000 proofs from a Tempo node takes about 200 ms, so a block at the [Gas](#gas) worst case of about 2,420 reads takes about 0.48 s to collect, against about 0.5 s of block time. Collection adds to each block's time, so sustained worst-case load stretches zone blocks to about 1 s while it lasts. This slows the zone but doesn't affect proving or settlement. `L1_COMMITMENT_READ_GAS` is sized for witness size, and it also prices this slowdown.

### Owner changes

Owners change configurations only on Tempo. A zone applies a change once its anchor reaches the Tempo block that contains it.

#### Pending transactions

When the anchor advances, the pool revalidates pending transactions whose signing accounts' commitments changed at the new anchor, finding the changed accounts from the configurable account precompile's events in the newly imported Tempo blocks or by comparing commitments between anchors. Either works. Three changes affect zone authority:

- A TIP-1107 owner update replaces the accepted configuration.
- A TIP-1113 migration retires the original key.
- An initial registration retires the colliding key. It emits `ConfigurableAccountConfigUpdated` at version zero.

Gas also differs between registered and unregistered accounts ([TIP-1107 gas](./tip-1107.md#gas)), so a cached commitment MUST be exact at the anchor.

#### Access keys

Access keys stay per-zone, exactly as on Tempo ([TIP-1111](./tip-1111.md)). A configurable account can grant and use keys on a zone, and an owner rotation does not revoke grants. Users who rotate after a compromise must revoke each zone's grants on that zone.

## Interfaces

Zones reuse TIP-1107's `getConfigCommitment` on the configurable account precompile and `verifyConfigurableAccount` on TIP-1020's `SignatureVerifier` precompile, which zones enable. The configurable account precompile adds one error, used only on zones:

```solidity
error UnsupportedOnZone();
```

## Rationale

Zones could instead keep their own copy of each commitment and read Tempo only for `0x05` verification. That makes plain EOA transactions cheaper to prove while most senders are EOAs, but the saving disappears as configurable accounts become the norm, because every configurable-account transaction still needs a Tempo proof. A copy also adds permanent zone state that grows with Tempo's accounts, a migration list on Tempo, and new `advanceTempo` rules, none of which can be removed later. Witnesses are ephemeral and can be compressed. Reading from Tempo can still move to a copy later, but a copy couldn't move back.

A zone reads Tempo only on a cold load, so pricing the read through the cold access charges exactly that event with one gas parameter, which every load path already applies. That covers the interpreter's opcodes, the JIT builtins, the out-of-gas guard that skips a cold load the caller can't pay for, precompile account loads and validation loads. The cost is the overcharge described in [Gas](#gas). Exempting precompiles and other ineligible accounts would need an eligibility check in each of those paths, priced before the account is loaded. Exempting only some paths would price the same access differently depending on how it is made. A TIP-20 token reached by `CALL` would then cost differently from the same token loaded by a precompile through `EvmPrecompileStorageProvider`. The overcharge is at most `L1_COMMITMENT_READ_GAS` per distinct account per transaction, and the first call target, the common case of a single token transfer, is exempt. So this TIP accepts it in exchange for one pricing rule.

# Compatibility

| Integration | What changes |
|---|---|
| Wallets and SDKs | Build `0x05` witnesses for zones as for Tempo, using the configuration valid at the zone's anchor. After a rotation, wait for the zone to import it before using the new configuration there. |
| Zone-only users | Companies whose customers operate only on a private zone still register and rotate those customers' configurable accounts on Tempo, since zones never write commitments. These Tempo transactions are public. A company that sponsors them with its own fee payer links every customer account to the company on Tempo. It should sponsor them with Tempo Labs' fee payer through the Tempo API instead. |
| Migrated accounts | The original key loses authority on a zone once it imports the migration. Funds stay at the same address under the account's owners. |
| Derived accounts | Can receive and move funds on zones from first use, with the same address as on Tempo. Until the account registers on Tempo and the zone imports that block, its colliding key also controls the address on the zone. |
| Zone operators | The Tempo state reader must serve account proofs at a block in addition to storage reads. |
| Zone RPC | Authorization tokens accept `0x05` signatures, checked against Tempo's commitment at the zone's current anchor. Tokens signed by a retired original key are rejected. Keychain tokens apply the [TIP-1113](./tip-1113.md#retirement-check) check to the signing key ID too, so an ordinary signature from a key ID with a nonzero commitment is rejected. Open sessions are rechecked when the anchor advances, and dropped when the commitment no longer authorizes them, as revoked keychain keys are today. Zone RPC reads commitments at the anchor of the zone block it executes against, so a simulation of an older zone block uses that block's anchor. Since authorization tokens cost nothing to mint, its commitment reads are a denial-of-service vector that nodes should mitigate. Zone RPC returns the code the EVM sees. The operator RPC's `eth_getCode` returns the `0xef` marker for an account whose Tempo commitment at the anchor is nonzero, so off-chain verifiers that check code before `ecrecover` reject its retired key. The redacted RPC serves neither `eth_getCode` nor `eth_getAccount`. Wallets read the commitment from `getConfigCommitment` on the zone, or from Tempo at the zone's anchor. |
| Forced exits | Not enabled on zones. When they are, their authorization MUST accept `0x05` signatures and reject a retired original key under the rules above, reading Tempo's commitment at the zone's anchor, not Tempo's latest state. |
| Transactions on zones | Every transaction pays 12,600 more intrinsic gas for its sender's commitment read, and `L1_COMMITMENT_READ_GAS` more for its first call target unless that is the sender or a precompile. Every later call to a new cold target, every other cold account access and every access-list address costs `L1_COMMITMENT_READ_GAS` more, including accounts that read nothing from Tempo, such as TIP-20 tokens. |
| Prover | Tempo witnesses grow by about 2.6 KB per distinct eligible account read, plus about 0.45 KB for each further anchor it is read at, bounded per block by `L1_COMMITMENT_READ_GAS` (see [Batch verification](#batch-verification)). |

# Observability

No new events. Every commitment change on Tempo is observed through the configurable account precompile's events. `ConfigurableAccountConfigUpdated` covers initial registration (at version zero, persisting when the transaction's calls revert) and owner updates, and `AccountUpgraded` covers migrations. The Tempo account proof at the anchor confirms each read. Zones add no new state transitions.

# Threat Model

The most consequential risk is a stale anchor. A removed owner, or a retired original key, keeps authority on a zone until the zone imports the rotation. Every full zone block imports exactly one child of the previous Tempo block and can't skip ancestry, so the anchor can fall behind only while the sequencer stalls the zone. Proving doesn't force freshness, since reads are checked against the anchor's state root, not Tempo's latest. After a stall, the sequencer can keep the lag instead of catching up.

| Actor | Trust boundary |
|---|---|
| Sequencer | Cannot fake a commitment, because the prover checks every read against the anchor's state root. It can delay rotations only by stalling the zone, then keeping the lag. |
| Removed owner / retired original key | Keeps zone authority until the zone's anchor includes the rotation. |
| Colliding key of a derived account | Controls the address on a zone until the account registers on Tempo and the zone's anchor includes it. |
| Access keys | Not revoked by an owner rotation on any chain. They must be revoked on each zone. |
| Depositors | Can still send funds to any address. Those funds are now usable by the account's current owners. |
| Transaction senders | Pay `L1_COMMITMENT_READ_GAS` for every cold account access their transaction makes, whether or not it reads Tempo. The coinbase's read is unpaid. |
| RPC callers | Zone RPC authorization, `eth_call`, `eth_estimateGas` and pool admission read commitments that no transaction pays for, a denial-of-service vector that nodes should mitigate, for example with rate limits or by bounding these reads. |

As a residual risk, a stall can leave a zone's anchor arbitrarily stale. A later change could cap how far a zone's anchor may lag before it rejects owner- or root-signed transactions.

# Invariants

The TIP-1107, TIP-1111 and TIP-1113 invariants hold on zones, with every commitment read served from Tempo at the anchor. The ones that require a registration to happen hold only on Tempo, since zones never register accounts. These are TIP-1107's nonzero commitment after signing, its single version-0 event per registration and its single new-account charge, and TIP-1111's nonzero commitment for a signing parent or delegate. Owner-update and migration invariants hold on zones trivially, since `updateConfig` and `upgradeAccount` revert there.

- An account unregistered on Tempo at the anchor that signs a zone transaction still has a zero commitment afterwards.
- For any zone transaction, every commitment read equals Tempo's configuration commitment for that address at the transaction's anchor.
- Zone state never stores a configuration commitment or the account marker, and no zone transaction changes one.
- A primitive signature from an address whose Tempo commitment at the anchor is nonzero never authorizes a zone action, except where TIP-1113 allows it on Tempo.
- An eligible account whose Tempo commitment at the anchor is nonzero has the account marker as its code on the zone. This relies on zones rejecting authorization lists and contract creation: an account with local code is not eligible, so its Tempo commitment would never be read.
- An unregistered derived account on a zone accepts only its version-zero configuration.
- A batch whose execution read a commitment without a valid Tempo account proof is not provable.
