Last Resort Liveness: Pricing Aztec's Escape Hatch

Introduction to the Escape Hatch

The Escape Hatch (EH) is a permissionless, last-resort mechanism that guarantees liveness and safety for L2→L1 messages (e.g. withdrawals), even in the presence of censorship, sequencer or committee faults. Its primary purpose is to satisfy decentralization requirements by ensuring there is no way to indefinitely block a valid L2→L1 message.

At a high level:

  • The protocol periodically opens short windows called Hatches.
  • Anyone may post collateral to register into the candidate set for a chance to be selected as the EH proposer.
  • During a Hatch, a single, randomly selected EH proposer is allowed to post L2 blocks directly, bypassing the sequencer committee.
  • The proposer must later produce a valid proof for all blocks posted during the Hatch.
  • If they fail to do so, they are slashed.

The Escape Hatch is not meant to replace the normal sequencing path. It is intentionally expensive, rate-limited, and operationally demanding, so it is only exercised when the happy path is unavailable.

Suggested Economic Parameters:

Parameter Value Rationale
BOND_SIZE 332M AZTEC Priced against committee capture cost
BOND_TOKEN AZTEC Ensures attacker bears protocol risk
FAILED_HATCH_PUNISHMENT 9.6M AZTEC Matches committee liveness guarantees

This forum post aims to introduce the EH and shed light on how the EH economics can work - Aztec stakeholders are invited to share feedback on the economics. Refer to the design document for a more thorough review of design tradeoffs.

Hatches and Timing

Hatches are periodic windows during which the escape hatch is open.

Example parameters:

  • FREQUENCY=10 epochs (a hatch every 10 epochs)
  • ACTIVE_DURATION=2 epochs (each hatch is open for 2 epochs)
Epochs:    0  1  2  3  4  5  6  7  8  9  10 11 12 13 14 15 16 17 18 19  20 21 22 ...
           |--------- Hatch 0 ---------||--------- Hatch 1 ----------| |-- Hatch 2 --
           [===]                         [===]                          [===]
           open                          open                           open
  • Hatch 0: epochs 0–1 (open), 2–9 (closed)
  • Hatch 1: epochs 10–11 (open), 12–19 (closed)
  • Hatch 2: epochs 20–21 (open), etc.

Selecting an Escape Hatch Proposer

For each Hatch, the protocol must determine:

  1. Who is eligible to be selected (the candidate set)
  2. How one proposer is chosen (randomness via RANDAO)

The danger: If an attacker knows one before the other is locked, they can manipulate the outcome.

Example parameters:

  • LAG_IN_EPOCHS_FOR_SET_SIZE=2 epochs (set frozen 2 epochs before sampling hatch starts)
  • LAG_IN_EPOCHS_FOR_RANDAO=1 epoch (seed taken 1 epoch before sampling hatch starts)
  • LAG_IN_HATCHES=1 epoch (during Hatch N, we select the proposer for Hatch N+1)
                      SELECTING FOR HATCH 2
                      =====================

  Epochs:  0    5    10   11   12   15   18   19   20   21   22   23   29
           |    |    |    |    |    |    |    |    |    |    |    |    |
           ▼    ▼    ▼    ▼    ▼    ▼    ▼    ▼    ▼    ▼    ▼    ▼    ▼
  ─────────────────────────────────────────────────────────────────────────►

           [H0 open]  [====== HATCH 1 OPEN ======] [==== HATCH 2 OPEN ====]
                      ▲                             ▲
                      │                             │
                      │                             └─ Hatch 2 STARTS (epoch 20)
                      │                                Proposer must be ready!
                      │
                      └─ SAMPLING HATCH (Hatch 1)
                         Selection can HAPPEN anytime between epochs (10-19)
                         (currentHatch=1, targetHatch=1+1=2)
           ┌─────────────────────────────────────────────────────────────┐
           │  KEY TIMESTAMPS FOR HATCH 2 SELECTION:                      │
           │                                                             │
           │  • Sampling hatch = Hatch 1 (starts epoch 10)               │
           │  • freezeTs = epoch 10 - 2 = epoch 8                        │
           │  • seedTs = epoch 10 - 1 = epoch 9                          │
           └─────────────────────────────────────────────────────────────┘


  Epoch:   7         8         9         10        11   ...   20
           │         │         │         │         │          │
           ▼         ▼         ▼         ▼         ▼          ▼
  ─────────●─────────●─────────●─────────●─────────●──────────●─────────►
                     │         │         │                    │
                     │         │         │                    │
                ┌────┴────┐    │    ┌────┴────────────┐       │
                │ SET     │    │    │ SELECTION       │       │
                │ FROZEN  │    │    │ HAPPENS         │       │
                │         │    │    │ (in Hatch 1)    │       │
                │ Cannot  │    │    │                 │       │
                │ join or │    │    │ selectCandidates()      │
                │ leave   │    │    │ can be called   │       │
                │ anymore │    │    └─────────────────┘       │
                └─────────┘    │                              │
                               │                         ┌────┴────┐
                          ┌────┴────┐                    │ HATCH 2 │
                          │ RANDAO  │                    │ OPENS   │
                          │ SAMPLED │                    │         │
                          │         │                    │ Selected│
                          │ Random  │                    │ proposer│
                          │ seed    │                    │ can now │
                          │ locked  │                    │ propose │
                          └─────────┘                    └─────────┘

Exit Semantics

Escape Hatch candidates may exit, but exit timing is constrained to preserve selection integrity. When a candidate calls initiateExit(), the protocol checks whether they are already included in a forzen snapshot for a future Hatch.

  • If exit occurs before the freeze timestamp for the next relevant Hatch, the exit is immediate.
  • If exit occurs after the freeze timestamp, the candidate must remain until that Hatch is resolved.

This guarantees that proposer selection cannot be disrupted once the candidate set is locked.

Example

Assume an EH candidate calls initiateExit() during epoch 15 (middle of Hatch 1):

  • currentHatch = 1
  • The proposer for Hatch 2 has already been determined (candidate set + seed frozen). This happened 1 epoch before Hatch 1 started.
  • The next candidate set to be frozen is to elect a proposer for Hatch 3 and this happens in epochs 18-19.

Therefore, during epoch 15 an EH candidate is free to exit immediately.

However, say the EH candidate calls initiateExit() during epoch 21 (this is in Hatch 2) then they are in the snapshot of Hatch 3 ( which is the frozen set of possible proposers for Hatch 4 ). Remember that if LAG_IN_HATCHES=1 then during Hatch 3 anyone can call selectCandidates() to sample a proposer for Hatch 4.

So in this case, the candidate who calls initiateExit() in epoch 21 must wait until the beginning of Hatch 3. At that point, it will be known whether they were selected or not to propose for Hatch 4 and if they were not, they are free to exit immediately.

Relevant parameters:
PROPOSING_EXIT_DELAY=525

Once an EH candidate initiates an exit, they are subject to an exit delay which will be similar to the exit delay of sequencers.

Pricing the Escape Hatch

To register as a candidate, an entity must deposit BOND_SIZE of BOND_TOKEN into the EscapeHatch.sol contract, and their address will be added to a candidate set.

The escape hatch is a last-resort, unhappy-path mechanism that guarantees liveness when the normal block production pipeline fails.

  • Happy path: Blocks are proposed and finalized by a decentralized, permissionless sequencer committee.
  • Unhappy path: The escape hatch forces progress when the committee fails.

The escape hatch must be:

  • Credibly usable by anyone
  • Economically safe against abuse
  • Strictly worse than the happy path
  • Aligned with the same economic guarantees as the committee

Escape Hatch Outcomes

When an Escape Hatch is used, there are three possible outcomes:

Outcome Description Severity
Success Proposer submits valid blocks and valid proofs Neutral ✓
Soundness exploit Proposer submits invalid blocks with fraudulent proofs (exploiting an AVM bug) Catastrophic ✗
Liveness failure Proposer submits blocks but fails to deliver proofs Damaging ✗

Success is the intended outcome—nothing bad happens.

Soundness exploit is catastrophic. In the happy path, the committee (48 elected sequencers) attests to correct execution, providing “training wheels” against such attacks. During the EH, these training wheels are absent. We price BOND_SIZE to match the cost of achieving this outcome via committee capture.

Liveness failure causes temporary ambiguity—unproven blocks create uncertainty until they expire. We price FAILED_HATCH_PUNISHMENT to match the committee’s liveness guarantees.

Threat Model

A key design assumption is that just-in-time bribery of the sequencer committee is impractical:

  • Committees are sampled only one epoch before duties begin
  • Coordinating a 33/48 committee capture requires custom software, proofs, and transaction data
  • This is not realistic to execute on a short notice

Therefore, the realistic attack vector is stake acquisition, not bribery.

Pricing Philosophy

Rather than pricing the escape hatch against the cost of bribing a committee, we price it against:

The cost of acquiring enough stake to control a committee supermajority with high probability within the same liveness window.

Pricing BOND_SIZE (Against Soundness Attacks)

Protocol Parameters:

Parameter Value
Total sequencers 4,000
Committee size 48
Supermajority threshold 33/48
Epoch duration ~38.4 minutes
Escape hatch frequency 112 epochs (~3 days)
Sequencer stake 200,000 AZTEC

Attack Cost Calculation:

To obtain a 99% probability of controlling at least one 33/48 committee within a 3-day window, an attacker must control:

  • ~55.3% of total stake
  • ~2,212 sequencers
  • ~442M AZTEC total stake

Assuming a 70–80% token price drawdown following a catastrophic exploit, the attacker’s expected economic loss is:

~332M AZTEC

This represents the true cost of exploiting a soundness bug via committee capture. An EH proposer gains equivalent power (posting unattested blocks), so their bond must impose equivalent risk.

Why AZTEC, not ETH?

Allowing ETH deposits would let an attacker exploit soundness bugs without bearing protocol risk i.e. they could profit from the exploit while their collateral remains unaffected. Requiring AZTEC ensures the attacker’s collateral is directly impacted by the damage they cause.

Parameter Suggested Value
BOND_SIZE 332M AZTEC
BOND_TOKEN AZTEC

Pricing FAILED_HATCH_PUNISHMENT

FAILED_HATCH_PUNISHMENT is the penalty for an elected EH proposer who fails to extend the proven chain (posts no blocks, or posts blocks without proofs).

Two scenarios cause liveness failure outside the EH:

  1. Malicious committee capture: An attacker controls enough stake to obtain a committee within 112 epochs and deliberately stalls.

  2. Honest failure: No attack, but no available provers—the committee fails to procure proving resources in time.

Scenario 1: Malicious Liveness Attack

An attacker could post invalid state transitions i.e. falsely showing a large exchange selling a massive AZTEC position, causing market panic. Since the state is unproven, it won’t finalize (assuming no soundness bugs), but during the ~77 minute proving window, ambiguity exists and markets may react.
A 10–20% token dump is plausible. Pricing at ~15% of the committee capture cost yields:

~66M AZTEC

Scenario 2: Honest Committee Failure

An honest committee that fails to deliver proofs loses up-to their entire stake:

48 × 200,000 = 9.6M AZTEC

Recommendation:

We suggest pricing FAILED_HATCH_PUNISHMENT at 9.6M AZTEC to match the economic guarantees of the happy path. This ensures the EH proposer bears equivalent risk to an honest committee that fails to deliver proofs.

Parameter Suggested Value
FAILED_HATCH_PUNISHMENT 9.6M AZTEC

Pricing WITHDRAWAL_TAX

WITHDRAWAL_TAX is a fee deducted from every candidate’s bond upon exit, regardless of whether they successfully proposed or not.

Purpose:

The withdrawal tax serves the following functions - mainly the first one:

  1. Discourages zero-cost or frivolous participation: Prevents entities from cheaply joining and exiting the candidate set without genuine intent to serve as proposers.

  2. Increases manipulation cost: An attacker attempting to influence selection by cycling candidates in/out must pay the tax on each exit, making such strategies expensive.

Pricing Considerations:

The tax must balance two concerns:

Concern Implication
Too high Limits usage of EH to L2 → L1 msgs that exit at least WT of value
Too low Frequent disruption of the happy path block production

Recommendation:

We suggest pricing WITHDRAWAL_TAX as a small percentage of BOND_SIZE , high enough to discourage frivolous participation, but low enough that legitimate candidates aren’t deterred from joining.

A tax of 0.1–1% of BOND_SIZE seems reasonable:

Tax Rate Value
0.1% 332K AZTEC
0.5% 1.66M AZTEC
1.0% 3.32M AZTEC
Parameter Suggested Value
WITHDRAWAL_TAX 1.66M AZTEC (0.5% of bond)

Conclusion

The Escape Hatch provides a credible, permissionless fallback for L2→L1 message liveness. By pricing BOND_SIZE against the cost of committee capture and FAILED_HATCH_PUNISHMENT against committee liveness guarantees, we ensure the EH offers equivalent economic security to the happy path—without creating a cheaper attack surface.

We invite the Aztec community to review these parameters and provide feedback. The goal is to make the Escape Hatch expensive enough to deter abuse, yet accessible enough to remain a credible last resort.

3 Likes

The FAILED_HATCH_PUNISHMENT parameter should be dynamic, defined in terms of committee size/stake.

Edit: Remove BOND, because an attacker will just borrow the required tokens.
Your pricing strategy fails to account for short positions where the attacker profits from a token crash.

Doesn’t seem impractical. Deploying a smart contract that reads the L2 state and pays out colluders is trivial enough that an LLM could write it today.

Replace WITHDRAWAL_TAX with a simple time lock.

Use the L1 aution instead of registering+lottery (just-in-time bond).

At the proposed hatch-rate, how many users can exit within 30 days?

2 Likes

Writing a collusion contract is easy, achieving collusion is hard. The scenario we’re most worried about here is blind outsourcing of block-building AND blind attestations from validators to a single attacker. In the current mainnet design, it is entirely viable that block-building could be outsourced, but for validators to attest to blocks without checking their validity is another. Have you thought about what the specifics of such a bribing contract? It could be an interesting exercise to discuss what it could look like and the types of bribes that validators would need to accept the bribe.

Borrowing still exposes the borrower to capital loss – more than just owning the tokens in the case of DeFi over-collateralization. However, it does also expose the lender, as most/all(?) lending protocols will incentivize liquidators to re-buy Aztec tokens on behalf of the lender. Lending could be a dangerous game in the early days given this – especially if there is a liquid long/short futures market.

Which auction?

There needs to be some WITHDRAWAL_TAX – the EH proposer will have monopoly sequencing rights for a full epoch. Given the permissionless nature of becoming the EH, the protocol and its underlying applications would prefer this didn’t happen – monopoly sequencing without a strong incentive to do good for the protocol (as is the case in centralized sequencer rollups) is bad for business. The tax charges for this.

We can only make educated guesses here. There are some high-level scenarios to consider:

  • Normal proposing good, EH proposers bad: (1- (1/112)) blocks are used for exiting
  • Normal proposing broken, EH proposers good: <(1/112) blocks are used for exiting
  • Normal proposing broken, EH proposers bad: nothing we can do here.

We need to assume that in the unlikely scenario that normal proposing breaks, honest EH proposers will step up to exit their own funds, as well as including other users’ transactions to help subsidize the reasonably high cost of exiting (token ownership, tax, onboarding as a EH proposer, L1 fees, etc). In this scenario, we have approx (30 x 24 x 60 x 60) *1/122 seconds available for exiting. At 1 TPS, this is 21,000 transactions available for exiting – in the reality of complete failure of normal proposing, 21,000 is an upperbound. However, with the active research path of state migration ongoing, certain apps may have back-up plans for enabling migration to new rollup instances that doesn’t require a per-user exit transaction on the previous rollup instance. That being said, at 1/112 EH frequency, users must be conscious of this – whether their funds/credentials need an exit transaction or not. Interested to see more designs on the migration side :grinning_face:

1 Like

Checking validity requires running a full node, which has nontrivial hardware costs. Therefore most staking/validating will be outsourced to a few non-asset-holding entities.

Disagree, a sophisticated borrower will have no trouble hedging the risk. Maybe if the bond was extreme it would deter attackers, but only because it would be difficult for anyone to gather enough tokens, making the escape hatch less useful.

For the escape-hatch block, let any L1 transaction call bond_and_propose_l2_block().

The fee should be at most the cost to bribe an epochs proposer set, ~block_reward_per_epoch + estimated_fees_per_epoch.
I propose replacing WITHDRAWAL_TAX with ONE_SHOT_EPOCH_FEE = previous_epoch_user_fees * 1.15, with EH proposers earning block rewards. The escape-hatch epoch therefore must be worth at least 15% more to users than a consensus-provided epoch.
Calculating previous user fees must resist consensus manipulation and therefore should adjust slowly (long moving window median, limited maximum rate of change, maybe a fixed upper limit). Similar to Ethereum burn.

I propose extending the escape hatch window conditional on paying an exponentially increasing ONE_SHOT_EPOCH_FEE (a limited number of times).

3 days seems long. L2 DeFi will need lockups of at least this length of time to ensure security against censorship attacks.

This depends on less sophisticated actors providing the hedger with liquidity. What you’re saying makes sense, give it enough time and people will start selling downside protection without the correct downside premium for “someone who finds a bug in the circuits could brick this rollup instance” priced in. But there the problem is with an inefficient market. You’re assuming that we will get downside protection markets that make it “easy” for someone to bet on themselves to cause a critical issue. In the early days where this matters most, it’s not clear to me such liquid markets will exist.

No, the lending rate includes the risk of exploitation. I’ll reiterate that a short position (attacker selling borrowed tokens) allows an attacker to profit from a crash.

Some ideas for addressing soundness risk directly:

  • Postpone the escape hatch until after Prediction-marketed non-governance prices the risk of exploit below a threshold
  • Create an on-chain soundness bounty that disables the escape hatch for a while
  • Pay third-party contractors for security audits