L2ERC721Bridge
Table of Contents
Overview
The L2ERC721Bridge enables ERC721 token transfers between Ethereum L1 and an OP Stack L2 chain. It mints tokens on L2 when deposits are finalized from L1 and burns tokens on L2 when withdrawals are initiated to L1.
Definitions
N/A
Assumptions
a01-001: L1ERC721Bridge is trusted
The L1ERC721Bridge contract on L1 is trusted to only send valid finalization messages for legitimate deposits.
Mitigations
- The L1ERC721Bridge address is set during initialization and cannot be changed
- Cross-chain messages are authenticated through the L2CrossDomainMessenger
a01-002: L2CrossDomainMessenger is trusted
The L2CrossDomainMessenger accurately validates cross-chain messages and correctly identifies the sender.
Mitigations
- The messenger is a system predeploy contract maintained by the protocol
- Message authentication uses the xDomainMessageSender mechanism
Invariants
i01-001: Users who deposit NFTs on L1 receive them on L2
Users who successfully deposit an NFT through the L1 bridge always receive the corresponding NFT on L2 when the deposit is finalized.
Impact
Severity: Critical
If violated, users lose their NFTs permanently as the L1 token is escrowed but the L2 token is never minted.
i01-002: Users who withdraw NFTs on L2 can claim them on L1
Users who successfully initiate a withdrawal on L2 can always claim the corresponding NFT on L1 after the challenge period, provided the withdrawal is properly finalized on L1.
Impact
Severity: Critical
If violated, users lose their NFTs permanently as the L2 token is burned but the L1 token cannot be claimed.
i01-003: One-to-one custody across chains via paired lock/mint and burn/unlock
For each bridged tokenId, exactly one of the following holds at any time: it is held on L1 by the bridge (locked) or it is represented on L2 by exactly one OptimismMintableERC721. Transitions between these states occur only through the canonical flows: a valid deposit locks the token on L1 and is paired with a mint on L2; a valid withdrawal burns the token on L2 and is paired with an unlock on L1. No other mechanism may create or release representations.
Impact
Severity: Critical
If violated, attackers could mint arbitrary NFTs on L2 without depositing the corresponding L1 tokens, breaking the 1:1 correspondence between L1 and L2 tokens.
Function Specification
initialize
Initializes the L2ERC721Bridge contract with the L1 bridge address.
Parameters:
_l1ERC721Bridge: Address of the L1ERC721Bridge contract
Behavior:
- MUST set the messenger to the L2CrossDomainMessenger predeploy at 0x4200000000000000000000000000000000000007
- MUST set the otherBridge to the provided L1ERC721Bridge address
- MUST revert if called more than once (initializer modifier)
finalizeBridgeERC721
Completes an ERC721 bridge from L1 and mints the token to the recipient on L2.
Parameters:
_localToken: Address of the OptimismMintableERC721 token on L2_remoteToken: Address of the ERC721 token on L1_from: Address that initiated the bridge on L1_to: Address to receive the token on L2_tokenId: ID of the token being deposited_extraData: Optional data forwarded from L1 (not used for execution, only emitted)
Behavior:
- MUST revert if caller is not the L2CrossDomainMessenger
- MUST revert if xDomainMessageSender is not the L1ERC721Bridge
- MUST revert if
_localTokenis the bridge contract itself - MUST revert if
_localTokendoes not implement IOptimismMintableERC721 - MUST revert if
_remoteTokendoes not match the remoteToken() value of_localToken - MUST call safeMint on
_localTokento mint_tokenIdto_to - MUST emit ERC721BridgeFinalized event with all parameters
bridgeERC721
Initiates a bridge of an NFT to the caller's account on L1.
Parameters:
_localToken: Address of the OptimismMintableERC721 token on L2_remoteToken: Address of the ERC721 token on L1_tokenId: Token ID to bridge_minGasLimit: Minimum gas limit for the bridge message on L1_extraData: Optional data forwarded to L1 (not used for execution, only emitted)
Behavior:
- MUST revert if caller is not an externally owned account (EOA)
- MUST call _initiateBridgeERC721 with msg.sender as both
_fromand_to
bridgeERC721To
Initiates a bridge of an NFT to a specified recipient's account on L1.
Parameters:
_localToken: Address of the OptimismMintableERC721 token on L2_remoteToken: Address of the ERC721 token on L1_to: Address to receive the token on L1_tokenId: Token ID to bridge_minGasLimit: Minimum gas limit for the bridge message on L1_extraData: Optional data forwarded to L1 (not used for execution, only emitted)
Behavior:
- MUST revert if
_tois address(0) - MUST call _initiateBridgeERC721 with msg.sender as
_fromand provided_to
_initiateBridgeERC721
Internal function that initiates a token bridge to L1.
Parameters:
_localToken: Address of the OptimismMintableERC721 token on L2_remoteToken: Address of the ERC721 token on L1_from: Address of the sender on L2_to: Address to receive the token on L1_tokenId: Token ID to bridge_minGasLimit: Minimum gas limit for the bridge message on L1_extraData: Optional data forwarded to L1 (not used for execution, only emitted)
Behavior:
- MUST revert if
_remoteTokenis address(0) - MUST revert if
_fromis not the owner of_tokenIdin_localToken - MUST retrieve remoteToken from
_localTokenand verify it matches_remoteToken - MUST call burn on
_localTokento burn_tokenIdfrom_from - MUST send a cross-chain message to L1ERC721Bridge calling finalizeBridgeERC721 with the parameters
- MUST emit ERC721BridgeInitiated event with all parameters
paused
Returns whether the bridge is paused.
Behavior:
- MUST always return false (L2 bridge cannot be paused)
MESSENGER
Legacy getter for the messenger contract.
Behavior:
- MUST return the messenger contract address
OTHER_BRIDGE
Legacy getter for the other bridge contract.
Behavior:
- MUST return the L1ERC721Bridge contract address