During times of high congestion, Ethereum can price out even its most enthusiastic users. We’ve seen this happen many times – quite recently with the Yuga Labs NFT drop, where some users paid thousands of dollars for a single transaction.
There is an immediate need for scaling solutions for Ethereum that don’t compromise on its security guarantees. Optimism is one such solution. It makes transacting with Ethereum assets more affordable by constructing a separate “layer 2” blockchain where transactions are cheaper, with exit guarantees back to Ethereum’s Layer 1. To get onto this L2 though, existing Ethereum users need to bridge their assets to Optimism.
Optimism's execution environment is general purpose and practically the same as Ethereum; Optimism runs only a slight modification of the Ethereum Virtual Machine. This means that the same contract can be deployed to both networks, and we can expect them to work the same way.
Optimism contracts can communicate with Ethereum smart contracts (and vice versa), via a cross-domain messaging protocol. We can use this protocol to build a “bridging contract” that facilitates asset transfers across the two networks – sending balance updates upon each deposit or withdrawal.
For example, the Uniswap $UNI token could be deployed to both Ethereum and Optimism, and users would be able to bridge these tokens back and forth. When a deposit to the bridge is made on Ethereum, the balance on the Optimism contract increases and grants more $UNI tokens to the user on that network.
Note: What’s extraordinary is that bridging in this way has the same security guarantees as an Ethereum transfer – as do all subsequent transfers on Optimism.
Messages that are sent across the two networks arrive asynchronously – unlike the instant calls we are familiar with from the EVM. Depending on whether we’re sending messages to Optimism (e.g. depositing), or from Optimism (e.g. withdrawing), the delay time will be very different. Messages sent to Optimism typically arrive in a few minutes, whereas messages that are sent from Optimism take at least a week. This seven-day delay is called a “challenge period” because during this time the transaction can be contested and overturned, given a valid fault-proof.
Despite the inherent delay in communication from Optimism to Ethereum, a few advanced bridging protocols have already solved withdrawal delays for common ERC20 tokens. Anyone who wants to use those protocols can get instant withdrawals for a small fee. This fee appears to be similar to what we experience in traditional withdrawals in the US – e.g. when withdrawing from Coinbase to a Chase account.
Note: The protocols that solve the withdrawal delay problem typically do so by composing with other stable financial protocols on Ethereum. They are an excellent example of the benefits of permissionless blockchain composability!
The Standard Optimism Bridge is a simple bridging protocol created by the Optimism team. While it doesn’t solve the withdrawal delay problem, it does give users a safe and standard way to bridge ETH and ERC20s between Optimism and Ethereum.
The protocol consists of two pertinent contracts:
The two contracts know about each other; the
L1StandardBridge on Ethereum stores an address for the
L2StandardBridge deployment on Optimism, and the
L2StandardBridge stores an address for the
L1StandardBridge. The contracts use these addresses to transmit messages and validate received messages (since they only receive cross-domain messages from each other).
L1StandardBridge stores a balance of deposits for each ERC20 that has been deposited. It does this by mapping the L1 token address to the L2 token’s address, and mapping that to an integer that represents the deposit balance. The deposit amount is incremented when funds are sent to the bridge and subtracted when they are withdrawn.
The simplest way to bridge ETH to Optimism is just to send ETH directly to the standard bridge contract. In this case, the bridge’s
receive method (which allows it to accept ETH directly), communicates with the L2 bridge contract through the cross-domain messaging protocol, instructing it to mint an ERC20 token that represents ETH on Optimism.
Along the way, the protocol will need to produce a new block on Optimism, by queuing a transaction up on Optimism’s Canonical Transaction Chain. Here’s a technical breakdown of the process; the call-stack looks like this:
receive()- first, the contract handles the directly deposited ETH
_initiateETHDeposit()- it calls an internal function to initiate the deposit, specifying the transaction sender’s address as the beneficiary of the L2 funds.
sendCrossDomainMessage()- it uses a cross-domain messaging protocol to communicate with the L2 bridge contract. The method we want to call on the L2 contract is
getAddress()- within the messaging protocol, an address is retrieved for the messenger’s implementation address, named
sendMessage()once the implementation is found, the call is delegated.
enqueue()– finally, the transaction is enqueued onto the
relayMessage()– Still within the cross-domain messaging protocol, but now running on the L2, a contract called
OVM_L2CrossDomainMessengerrelays the transaction to the relevant L2 contract: the
L2StandardBridge. The message will be marked as successfully relayed after the L2 bridge’s method is called.
finalizeDeposit()– This method will check that the token is valid, and then attempt to mint the same amount that was deposited on the L1, to the transaction’s sender.
Besides sending ETH directly to the bridge contract, there are two other methods for depositing ERC20s to the bridge. The difference between them is just the ability to specify the recipient of the L2 token once the bridge transaction is complete. This difference is made clear by the function names:
depositETH- accepts deposits from an EOA (a non-contract account)
depositETHTo- accepts deposits from an EOA or a contract, with the recipient specified
depositERC20- transfers an ERC20 token from an EOA into the bridge contract
depositERC20To- transfers an ERC20 token from an EOA or another contract into the bridge contract
withdraw()- the user calls on the
L2StandardBridgecontract, specifying the amount and the token (e.g.
0xdeaddeaddeaddeaddeaddeaddeaddeaddead0000for Optimism’s Ether token)
_burn()- the L2 contract then attempts to burn the number of tokens specified. This will remove it from the sender’s balance, and decrease the total supply of those tokens on Optimism.
WithdrawalInitiatedevent is emitted from the bridge contract. Also, the tokens are burned on Optimism, but nothing has happened yet on Ethereum.
sendMessage()- The bridge now attempts to send a message to the L1 bridge, via the cross-domain messaging protocol.
finalizeERC20Withdrawalshould be called (depending on whether ETH or an ERC20 is being withdrawn), given arguments that include the equivalent amount of the token that was burned, and the address that should receive those tokens on Ethereum.
L2CrossDomainMessengercontract to communicate this, invoking the method called
At this point, the 7-day delay is invoked. The withdrawal transaction is received by the L1 bridging contract after one week. This window is called a “challenge period”, and it gives actors on the network time to challenge transactions with a fault-proof. Funds cannot exit from the Optimism network without this time delay.
Note: The length of this challenging period could technically actually be updated! Advocates for changing the challenge duration can argue their case via Github issues.
Transactions on Optimism are cheap but not free. Like on Ethereum, Optimism users have to pay gas for the amount of computation and storage they use.
A transaction that bridges Ethereum and Optimism will trigger a contract execution on both networks. The major cost of an Ethereum to Optimism deposit transaction comes from sending the transaction on Ethereum.
Optimism makes a particular concession on deposits – it gives away the first 1.92 million gas on L2 for free. Since the execution typically uses less gas than this, the L2 charge ends up being free. Users only pay for the L1 charge when bridging to Optimism.
Note: Optimism charges for gas limits higher than 1.92 million, to prevent denial of service attacks on the network. The amount is paid on Ethereum, at a rate of 1/32 of the Optimism computation beyond the free amount.
Both the 1.92 million gas concession and the 1/32 rate are updatable parameters – so they may change in the future.
A withdrawal from Optimism to Ethereum combines the L2 initialization transaction and the L1 finalization transaction. The L1 finalization transaction is usually more expensive than the L2 initialization transaction.
Since gas prices on Ethereum may be volatile and bridging transactions are asynchronous, it becomes Optimism’s responsibility to pay whatever the L1 gas price is after the sequencer has processed the transaction. If the L1 gas price spikes during the withdrawal, Optimism will need to pay a higher cost.
Note: Optimism currently does not have a mempool, which means there is no gas price auction when submitting transactions on Optimism. Instead, the network will reject low-fee transactions.
We hope this has provided a thorough “walk across the Optimism bridge”, and that it provides some insight into how bridging in general works on Optimism. We are considering diving more deeply into other bridges that are more advanced, and comparing those to the standard bridge.
We expect a significant amount of ETH to move into the Optimism network, and that will need to happen across secure bridges such as these. Protocol Review is here to review!
Protocol Review is excited to continue publishing accessible reviews for decentralized protocols. We believe in using our deep technical knowledge to distill protocols and increase their mainstream understanding. To stay up to date with the latest reviews or if you’re interested in writing for the publication follow us on Twitter.
Thank you to everyone that made this post possible. @avichalp and @zachobront for your research and notes. @julianjhutton for your brand and design work.