ETH Lockbox
Table of Contents
Overview
With interoperable ETH, withdrawals will fail if the referenced OptimismPortal lacks sufficient ETH.
This is due to having the possibility to move ETH liquidity across the different chains and it could happen
that a chain ends up with more liquidity than its OptimismPortal.
The ETHLockbox improves the Superchain's interoperable ETH withdrawal user experience and avoids this issue.
To do so, it unifies ETH L1 liquidity in a single contract (ETHLockbox), enabling seamless withdrawals of ETH
from any OP chain in the Superchain, regardless of where the ETH was initially deposited.
Design
The ETHLockbox contract is designed to manage the unified ETH liquidity for the Superchain.
It implements two main functions: lockETH for depositing ETH into the lockbox,
and unlockETH for withdrawing ETH from the lockbox.
These functions are called by the OptimismPortal contracts to manage the shared ETH liquidity
when making deposits or finalizing withdrawals.
Authorization of OptimismPortals is managed by the ProxyAdmin owner.
The ETHLockbox contract is proxied and managed by the L1 ProxyAdmin.
Interface and properties
initialize
Initializes the ETHLockbox contract.
- MUST only be callable by the ProxyAdmin or its owner.
- MUST set the SystemConfig contract.
- MUST authorize all portals provided in the initialization array.
- MUST check that all portals have the same SuperchainConfig as the ETHLockbox.
lockETH
Deposits and locks ETH into the lockbox's liquidity pool.
- The function MUST accept ETH.
- Only authorized
OptimismPortaladdresses MUST be allowed to interact. - The function MUST NOT revert when called by an authorized
OptimismPortal - The function MUST emit the
ETHLockedevent with theportalthat called it and theamount. - The function CAN be called by an OptimismPortal while it is executing a withdrawal transaction.
function lockETH() external payable;
unlockETH
Withdraws a specified amount of ETH from the lockbox's liquidity pool to the OptimismPortal calling it.
- Only authorized
OptimismPortaladdresses MUST be allowed to interact. - The function MUST NOT revert when called by an authorized
OptimismPortalunless paused. - The function MUST check if the ETHLockbox has sufficient balance to fulfill the withdrawal.
- The function MUST emit the
ETHUnlockedevent with theportalthat called it and theamount. - The function MUST use
donateETHwhen sending ETH to avoid triggering deposits. - The function MUST NOT allow to be called as part of a withdrawal transaction (
OptimismPortal.l2Sender()MUST be theDEFAULT_L2_SENDER). - The function MUST revert if an OptimismPortal attempts to call it while executing a withdrawal transaction.
function unlockETH(uint256 _value) external;
authorizePortal
Authorizes an OptimismPortal to interact with the ETHLockbox.
- Only the
ProxyAdminowner can call the function. - The
ProxyAdminowner of theOptimismPortalmust be the same as theProxyAdminowner of theETHLockbox. - The
OptimismPortalandETHLockboxMUST share the sameSuperchainConfigaddress - The function MUST emit the
PortalAuthorizedevent with theportal.
function authorizePortal(address _portal) external;
authorizeLockbox
Authorizes another ETHLockbox to migrate its ETH liquidity to the current ETHLockbox.
- Only the
ProxyAdminowner can call the function. - The
ProxyAdminowner of the source lockbox must be the same as theProxyAdminowner of the destination lockbox. - Once a lockbox is authorized, it cannot be removed from the authorized list.
- The function MUST emit the
LockboxAuthorizedevent with thelockboxthat is being authorized.
function authorizeLockbox(address _lockbox) external;
migrateLiquidity
Migrates the ETH liquidity from the current ETHLockbox to another ETHLockbox.
- Only the
ProxyAdminowner can call the function. - The
ProxyAdminowner of the source lockbox must be the same as theProxyAdminowner of the destination lockbox. - The function MUST call
receiveLiquidityfrom the destinationETHLockboxwith the entire ETH balance. - SHOULD be called atomically with
OptimismPortal.migrateToSuperRoots()in the same transaction batch, or otherwise theOptimismPortalmay not be able to unlock ETH from the ETHLockbox on finalized withdrawals. - The function MUST emit the
LiquidityMigratedevent with thelockboxthat is being migrated to and the amount of ETH migrated.
function migrateLiquidity(address _lockbox) external;
receiveLiquidity
Receives the ETH liquidity from another ETHLockbox.
- Only an authorized
ETHLockboxcan call the function. - The function MUST emit the
LiquidityReceivedevent with thelockboxthat is being received from and the amount of ETH received.
function receiveLiquidity() external payable;
paused
Returns whether the contract is paused, delegating to the SystemConfig.
superchainConfig
Returns the SuperchainConfig contract from the SystemConfig.
proxyAdminOwner
Returns the ProxyAdmin owner that manages the ETHLockbox.
Events
ETHLocked
MUST be triggered when lockETH is called
event ETHLocked(OptimismPortal indexed portal, uint256 amount);
ETHUnlocked
MUST be triggered when unlockETH is called
event ETHUnlocked(OptimismPortal indexed portal, uint256 amount);
PortalAuthorized
MUST be triggered when authorizePortal is called
event PortalAuthorized(OptimismPortal indexed portal);
LockboxAuthorized
MUST be triggered when authorizeLockbox is called
event LockboxAuthorized(ETHLockbox indexed lockbox);
LiquidityMigrated
MUST be triggered when migrateLiquidity is called
event LiquidityMigrated(ETHLockbox indexed lockbox, uint256 amount);
LiquidityReceived
MUST be triggered when receiveLiquidity is called
event LiquidityReceived(ETHLockbox indexed lockbox, uint256 amount);
Invariants
System level invariants
-
The ETH held in the
ETHLockboxMUST never be less than the amount deposited but not yet withdrawn by theOptimismPortals -
All chains joining the same
ETHLockboxMUST have the sameProxyAdminowner -
The total withdrawable ETH amount present on all the dependency set's chains MUST NEVER be more than the amount held by the
ETHLockboxof the clusterWith "withdrawable amount", the ETH balance held on
ETHLiquidityis excluded
Contract level invariants
-
It MUST allow only authorized portals to lock ETH
-
It MUST allow only authorized portals to unlock ETH
-
It MUST be in paused state if the
SuperchainConfigis paused -
No Ether MUST flow out of the contract when in a paused state
-
It MUST NOT trigger a new deposit when ETH amount is being unlocked from the
ETHLockboxby theOptimismPortal -
It MUST allow only the
ProxyAdminowner to call theauthorizePortal,authorizeLockboxandmigrateLiquidityfunctions -
It MUST allow only authorized lockboxes to call the
receiveLiquidityfunction -
It MUST migrate the whole ETH liquidity from the source
ETHLockboxto the destinationETHLockboxwhen callingmigrateLiquidity -
It MUST emit:
-
An
ETHLockedevent when locking ETH -
An
ETHUnlockedevent when unlocking ETH -
A
PortalAuthorizedevent when authorizing a portal -
A
LockboxAuthorizedevent when authorizing a lockbox -
A
LiquidityMigratedevent when migrating liquidity -
A
LiquidityReceivedevent when receiving liquidity
-
Architecture
ETH Management
-
ETH is locked in the
ETHLockboxwhen:-
A portal migrates its ETH liquidity when updating
-
A deposit is made with ETH value on an authorized portal
-
-
ETH is unlocked from the
ETHLockboxwhen:- An authorized portal finalizes a withdrawal that requires ETH
Merge process
The merge process is the process of merging two ETHLockboxes into a single one,
transferring the ETH liquidity from the both source ETHLockbox to the destination ETHLockbox.
For each source ETHLockbox, the following steps MUST be followed:
-
The destination
ETHLockboxMUST callauthorizeLockboxwith the sourceETHLockboxas argument. -
The source
ETHLockboxMUST callmigrateLiquiditywith the destinationETHLockboxas argument. -
migrateLiquidityMUST callreceiveLiquidityfrom the destinationETHLockbox.
This process ensures that the ETH liquidity is migrated from the source ETHLockbox to the correct destination ETHLockbox.
These transactions SHOULD be executed atomically. A possible way is through the OPCM contract.