SuperchainETHBridge
Table of Contents
- Overview
- Constants
- Definitions
- Assumptions
- Invariants
- Function Specification
- Events
Overview
The SuperchainETHBridge is a predeploy contract that facilitates cross-chain ETH bridging within
the Superchain interop set. It serves as an abstraction layer on top of the
L2toL2CrossDomainMessenger specifically designed for native ETH transfers between chains. The
contract integrates with the ETHLiquidity contract to manage native ETH liquidity across chains,
ensuring seamless cross-chain transfers of native ETH.
The SuperchainETHBridge only handles native ETH cross-chain transfers. For interoperable ETH
withdrawals, see the ETHLockbox specification.
Constants
| Name | Value |
|---|---|
SuperchainETHBridge Address | 0x4200000000000000000000000000000000000024 |
Definitions
ETH Bridging
ETH Bridging refers to the process of transferring native ETH from one chain to another within the Superchain interop set. This process involves burning ETH on the source chain and minting an equivalent amount on the destination chain.
ETH Liquidity
ETH Liquidity refers to the availability of native ETH on a particular chain. The ETHLiquidity
contract manages this liquidity by providing a mechanism to burn and mint ETH as needed for
cross-chain transfers.
Cross-Chain Message
A Cross-Chain Message is a message sent from one chain to another using the
L2ToL2CrossDomainMessenger. In the context of the SuperchainETHBridge, these messages contain
instructions to relay ETH to a recipient on the destination chain.
Source Chain
The Source Chain is the chain from which a user initiates an ETH transfer. On this chain, ETH is burned from the user's account and a cross-chain message is sent to the destination chain.
Destination Chain
The Destination Chain is the chain to which ETH is being transferred. On this chain, ETH is sent to the recipient's account based on the cross-chain message received from the source chain.
Assumptions
aSEB-001: L2ToL2CrossDomainMessenger properly delivers messages
We assume that the L2ToL2CrossDomainMessenger contract properly and faithfully delivers messages
between chains, maintaining the integrity and authenticity of the message contents.
Mitigations
- Extensive testing of the
L2ToL2CrossDomainMessengercontract - Audits of the messaging protocol
- Monitoring of cross-chain message delivery
aSEB-002: ETHLiquidity contract maintains sufficient liquidity
We assume that the ETHLiquidity contract maintains sufficient liquidity to fulfill all valid ETH
minting requests. This is ensured by initializing the contract with type(uint128).max wei.
Mitigations
- Total ETH supply is much less than the initial balance of the
ETHLiquiditycontract - Contract is initially initialized with
type(uint128).maxwei and can hold up totype(uint256).maxwei to prevent balance overflow
aSEB-003: SafeSend correctly transfers ETH to recipients
We assume that the SafeSend mechanism correctly transfers ETH to recipients without reverting
for valid addresses.
Mitigations
- Extensive testing of the
SafeSendmechanism - Audits of the ETH transfer logic
aSEB-004: ETH sent to an unauthorized chain is lost
We assume that users send ETH only to chains whose portals this chain's ETHLockbox authorizes. ETH sent to any
other chain ID cannot be relayed or refunded until this chain's ETHLockbox authorizes that chain's portal.
sendMessage checks only that the destination is not this chain, and relayUndeliveredMessage reverts for a portal
that the ETHLockbox does not authorize.
Mitigations
- Applications and wallets should check that the destination chain is in this chain's dependency set before sending
Invariants
iSEB-001: ETH sent equals ETH received
The amount of ETH sent from the source chain must equal the amount of ETH received on the destination chain, or refunded on the source chain, for any given cross-chain transfer.
Impact
Severity: Critical
If this invariant is broken, users could receive more or less ETH than they sent, leading to inflation or loss of funds.
Dependencies
iSEB-002: Only authorized contracts can call relayETH
The relayETH function must only be callable by the L2ToL2CrossDomainMessenger contract, and the
cross-domain sender must be the SuperchainETHBridge contract on the source chain.
Impact
Severity: Critical
If this invariant is broken, unauthorized parties could mint ETH on the destination chain without burning an equivalent amount on the source chain, leading to inflation.
Dependencies
iSEB-003: ETH cannot be sent to the zero address
The sendETH function must revert if the recipient address is the zero address.
Impact
Severity: High
If this invariant is broken, ETH could be sent to the zero address, effectively burning it without the possibility of recovery.
Dependencies
None
iSEB-004: ETH is refunded only for expired sends, at most once
refundETH must pay out only for a send whose message is marked expired, at most once per message, only the
amount that the send's message committed to, and only to the address that called sendETH, when that address
calls refundETH.
Impact
Severity: Critical
If this invariant is broken, ETH could be both delivered on the destination chain and refunded on the source chain, leading to inflation.
Dependencies
iSEB-005: Each send pays out at most once
Across all chains, each sendETH must pay out at most once, through relayETH on the destination chain or refundETH on
the source chain. The payout must equal the amount burned.
Impact
Severity: Critical
If this invariant is broken, the same ETH could be paid out on both chains, or twice on one, leading to inflation.
Dependencies
Function Specification
sendETH
Deposits the msg.value of ETH into the ETHLiquidity contract and sends a cross-chain message
to the specified _chainId to call relayETH with the _to address as the recipient and the
msg.value as the amount.
function sendETH(address _to, uint256 _chainId) external payable returns (bytes32 msgHash_);
- MUST accept ETH via
msg.value. - MUST revert if the
_toaddress is the zero address. - MUST revert with
SuperchainETHBridge_SenderIsMessengerifmsg.senderis theL2ToL2CrossDomainMessenger. A relayed message that calledsendETHwould make the messenger the sender, and it could never claim a refund. TheL2CrossDomainMessengerstays allowed: a message from L1 that reverted here would keep its ETH there. Its sends cannot be refunded to their sender on L1; seerefundETH. - MUST transfer
msg.valueof ETH from themsg.senderto theETHLiquiditycontract by callingETHLiquidity.burn{value: msg.value}(). - MUST create a cross-chain message to the
SuperchainETHBridgecontract on the destination chain with the following parameters:_chainId: The destination chain ID.message: An encoded call torelayETH(msg.sender, _to, msg.value).
- MUST return the message hash
msgHash_generated by theL2ToL2CrossDomainMessenger. - MUST emit a
SendETHevent with themsg.sender,_to,msg.value, and_chainId.
relayETH
Withdraws ETH from the ETHLiquidity contract equal to the _amount and sends it to the _to address.
function relayETH(address _from, address _to, uint256 _amount) external;
- MUST revert if called by any address other than the
L2ToL2CrossDomainMessenger. - MUST revert if the cross-domain sender is not the
SuperchainETHBridgecontract on the source chain. - MUST withdraw
_amountof ETH from theETHLiquiditycontract by callingETHLiquidity.mint(_amount). - MUST transfer the
_amountof ETH to the_toaddress usingnew SafeSend{value: _amount}(_to). - MUST emit a
RelayETHevent with the_fromaddress,_toaddress,_amount, and source chain ID.
refundETH
Returns the ETH of a send whose message expired: its destination chain never relayed it, and never can.
function refundETH(uint256 _destination, uint256 _nonce, address _to, uint256 _amount) external;
mapping(bytes32 => bool) public refunded;
- MUST compute the message hash of the send from its arguments, with this chain as
the source and the
SuperchainETHBridgeas both sender and target of arelayETH(msg.sender, _to, _amount)call. - MUST revert with
SuperchainETHBridge_MessageNotExpiredifL2ToL2CrossDomainMessenger.expiredMessages(messageHash)isfalse. This covers a caller that did not send it. - MUST revert with
SuperchainETHBridge_AlreadyRefundedifrefunded[messageHash]istrue. - MUST set
refunded[messageHash]totruebefore transferring ETH. - MUST withdraw
_amountof ETH from theETHLiquiditycontract by callingETHLiquidity.mint(_amount). - MUST transfer the
_amountof ETH tomsg.senderusingnew SafeSend{value: _amount}(msg.sender). - MUST emit a
RefundETHevent withmsg.sender,_amount, and the message hash.
Only the msg.sender of sendETH can claim its refund, and the ETH goes back to it. A contract that called
sendETH on behalf of someone else calls refundETH itself and passes the ETH on. Two kinds of sender cannot get
their ETH back:
- A send made from L1 through the
L2CrossDomainMessenger. ArefundETHcall made the same way matches the send's hash, but pays theL2CrossDomainMessenger, and the ETH stays there. A sender on L1 should deposit through theOptimismPortaland callsendETHfrom its own address, or send through a contract on L2. - A contract that has no way to call
refundETH.
While ETHLiquidity is paused, sendETH, relayETH and refundETH revert, because
burn and mint do. Relays and refunds can be retried after the unpause. A send whose message expires during the
pause can be refunded after the unpause.
Events
SendETH event
MUST be triggered when sendETH is called.
event SendETH(address indexed from, address indexed to, uint256 amount, uint256 destination);
RelayETH event
MUST be triggered when relayETH is called.
event RelayETH(address indexed from, address indexed to, uint256 amount, uint256 source);
RefundETH event
MUST be triggered when refundETH is called.
event RefundETH(address indexed from, uint256 amount, bytes32 indexed messageHash);