Legacy Testnet Escape Hatch
Overview
This page describes the necessary steps to withdraw funds from the Zircuit network in the event blocks cease to be produced for a long period of time. These steps bypass the conventional withdrawal mechanisms of Zircuit and allow for a forced withdrawal of assets.
These steps utilise functionally called an escape hatch, which allows users to remove Ether and tokens from a Zircuit network in case a state update has not occurred in the past 30 days. Assets that are withdrawn this way are said to be escaped. For the purpose of this page, the L2 (layer 2) network is the Zircuit Legacy Testnet and the L1 (layer 1) is Sepolia.
Eligible Assets for Escape
The Zircuit Legacy Testnet escape hatch allows the withdrawal of Legacy Testnet ETH and WETH from OptimismPortal, and any ERC20 tokens that were bridged using Zircuit L1StandardBridge on Sepolia. These funds account for the majority of assets present on the Legacy Testnet.
Throughout this page, several assumptions are made in order to simplify the instructions to withdraw the assets described above. Future versions of this functionality will support additional assets; be sure to use the instructions for the right escape hatch.
Escape Hatch Tooling
Scripts that implement the functionality necessary to escape ETH and ERC20 tokens can be found here, which implement the functionality described below. Users who are not interested in understanding how the escape hatch works can simply use the scripts.
Escaping with EOAs
These instructions can be used once the escape hatch functionality is enabled, due to a lack of state root update.
Escaping ETH
Users can initiate ETH withdrawals via the escapeETH() function on the OptimismPortalProxy contract. This process requires generating and verifying inclusion proofs to reconstruct the user's balance on L2 at the last known valid state.
Here is a TypeScript/ethers.js example showing how to prepare and submit an escapeETH() transaction.
Escaping ERC20s
Unlike ETH, which is tracked via account balances, ERC20 token balances are stored in smart contract storage slots. Escaping ERC20s therefore requires not only proving the state of the ERC20 contract itself, but also providing a Merkle proof of the user’s token balance stored in the contract's storage trie.
The escape mechanism for ERC20s is available via the escapeERC20() function on the L1StandardBridgeProxy contract on Ethereum.
Here’s a TypeScript/ethers.js script that shows how to gather the necessary proofs and invoke the escapeERC20() function.
In this example, it is assumed that ERC20 balances are stored in a mapping at slot 0 as this is the slot of the default mintable ERC20 used by the StandardBridge.
Escaping Assets Held in Smart Contracts
When users deposit assets into smart contracts on L2 (e.g., staking pools or token vaults), those assets are often pooled. This makes escape more complex than with EOAs, since:
The contract may hold tokens on behalf of many users.
Each user's entitlement must be calculated from contract state, not just simple balances.
To solve this, Zircuit introduces resolver contracts on L1, which encapsulate the logic needed to read the L2 contract’s storage and compute how much a user can rightfully claim. Resolver contracts are explained in this paper.
Further Reading
Additional details can be found in the paper describing the escape hatch mechanism.
Last updated
Was this helpful?