Predeploys

Table of Contents

Overview

Predeployed smart contracts exist on Optimism at predetermined addresses in the genesis state. They are similar to precompiles but instead run directly in the EVM instead of running native code outside of the EVM.

Predeploys are used instead of precompiles to make it easier for multiclient implementations as well as allowing for more integration with hardhat/foundry network forking.

Predeploy addresses exist in a prefixed namespace 0x4200000000000000000000000000000000000xxx. Proxies are set at the first 2048 addresses in the namespace, except for the addresses reserved for the GovernanceToken and WETH predeploys.

The LegacyERC20ETH predeploy lives at a special address 0xDeadDeAddeAddEAddeadDEaDDEAdDeaDDeAD0000 and there is no proxy deployed at that account.

The following table includes each of the predeploys. The system version indicates when the predeploy was introduced. The possible values are Legacy or Bedrock or Canyon. Deprecated contracts should not be used.

NameAddressIntroducedDeprecatedProxied
LegacyMessagePasser0x4200000000000000000000000000000000000000LegacyYesYes
DeployerWhitelist0x4200000000000000000000000000000000000002LegacyYesYes
LegacyERC20ETH0xDeadDeAddeAddEAddeadDEaDDEAdDeaDDeAD0000LegacyYesNo
WETH90x4200000000000000000000000000000000000006LegacyNoNo
L2CrossDomainMessenger0x4200000000000000000000000000000000000007LegacyNoYes
L2StandardBridge0x4200000000000000000000000000000000000010LegacyNoYes
SequencerFeeVault0x4200000000000000000000000000000000000011LegacyNoYes
OptimismMintableERC20Factory0x4200000000000000000000000000000000000012LegacyNoYes
L1BlockNumber0x4200000000000000000000000000000000000013LegacyYesYes
GasPriceOracle0x420000000000000000000000000000000000000FLegacyNoYes
GovernanceToken0x4200000000000000000000000000000000000042LegacyNoNo
L1Block0x4200000000000000000000000000000000000015BedrockNoYes
L2ToL1MessagePasser0x4200000000000000000000000000000000000016BedrockNoYes
L2ERC721Bridge0x4200000000000000000000000000000000000014LegacyNoYes
OptimismMintableERC721Factory0x4200000000000000000000000000000000000017BedrockNoYes
ProxyAdmin0x4200000000000000000000000000000000000018BedrockNoYes
BaseFeeVault0x4200000000000000000000000000000000000019BedrockNoYes
L1FeeVault0x420000000000000000000000000000000000001aBedrockNoYes
SchemaRegistry0x4200000000000000000000000000000000000020BedrockNoYes
EAS0x4200000000000000000000000000000000000021BedrockNoYes
BeaconBlockRoot0x000F3df6D732807Ef1319fB7B8bB8522d0Beac02EcotoneNoNo

LegacyMessagePasser

Implementation

Address: 0x4200000000000000000000000000000000000000

The LegacyMessagePasser contract stores commitments to withdrawal transactions before the Bedrock upgrade. A merkle proof to a particular storage slot that commits to the withdrawal transaction is used as part of the withdrawing transaction on L1. The expected account that includes the storage slot is hardcoded into the L1 logic. After the bedrock upgrade, the L2ToL1MessagePasser is used instead. Finalizing withdrawals from this contract will no longer be supported after the Bedrock and is only left to allow for alternative bridges that may depend on it. This contract does not forward calls to the L2ToL1MessagePasser and calling it is considered a no-op in context of doing withdrawals through the CrossDomainMessenger system.

Any pending withdrawals that have not been finalized are migrated to the L2ToL1MessagePasser as part of the upgrade so that they can still be finalized.

L2ToL1MessagePasser

Implementation

Address: 0x4200000000000000000000000000000000000016

The L2ToL1MessagePasser stores commitments to withdrawal transactions. When a user is submitting the withdrawing transaction on L1, they provide a proof that the transaction that they withdrew on L2 is in the sentMessages mapping of this contract.

Any withdrawn ETH accumulates into this contract on L2 and can be permissionlessly removed from the L2 supply by calling the burn() function.

DeployerWhitelist

Implementation

Address: 0x4200000000000000000000000000000000000002

The DeployerWhitelist is a predeploy that was used to provide additional safety during the initial phases of Optimism. It previously defined the accounts that are allowed to deploy contracts to the network.

Arbitrary contract deployment was subsequently enabled and it is not possible to turn off. In the legacy system, this contract was hooked into CREATE and CREATE2 to ensure that the deployer was allowlisted.

In the Bedrock system, this contract will no longer be used as part of the CREATE codepath.

This contract is deprecated and its usage should be avoided.

LegacyERC20ETH

Implementation

Address: 0xDeadDeAddeAddEAddeadDEaDDEAdDeaDDeAD0000

The LegacyERC20ETH predeploy represents all ether in the system before the Bedrock upgrade. All ETH was represented as an ERC20 token and users could opt into the ERC20 interface or the native ETH interface.

The upgrade to Bedrock migrates all ether out of this contract and moves it to its native representation. All of the stateful methods in this contract will revert after the Bedrock upgrade.

This contract is deprecated and its usage should be avoided.

WETH9

Implementation

Address: 0x4200000000000000000000000000000000000006

WETH9 is the standard implementation of Wrapped Ether on Optimism. It is a commonly used contract and is placed as a predeploy so that it is at a deterministic address across Optimism based networks.

L2CrossDomainMessenger

Implementation

Address: 0x4200000000000000000000000000000000000007

The L2CrossDomainMessenger gives a higher level API for sending cross domain messages compared to directly calling the L2ToL1MessagePasser. It maintains a mapping of L1 messages that have been relayed to L2 to prevent replay attacks and also allows for replayability if the L1 to L2 transaction reverts on L2.

Any calls to the L1CrossDomainMessenger on L1 are serialized such that they go through the L2CrossDomainMessenger on L2.

The relayMessage function executes a transaction from the remote domain while the sendMessage function sends a transaction to be executed on the remote domain through the remote domain's relayMessage function.

L2StandardBridge

Implementation

Address: 0x4200000000000000000000000000000000000010

The L2StandardBridge is a higher level API built on top of the L2CrossDomainMessenger that gives a standard interface for sending ETH or ERC20 tokens across domains.

To deposit a token from L1 to L2, the L1StandardBridge locks the token and sends a cross domain message to the L2StandardBridge which then mints the token to the specified account.

To withdraw a token from L2 to L1, the user will burn the token on L2 and the L2StandardBridge will send a message to the L1StandardBridge which will unlock the underlying token and transfer it to the specified account.

The OptimismMintableERC20Factory can be used to create an ERC20 token contract on a remote domain that maps to an ERC20 token contract on the local domain where tokens can be deposited to the remote domain. It deploys an OptimismMintableERC20 which has the interface that works with the StandardBridge.

This contract can also be deployed on L1 to allow for L2 native tokens to be withdrawn to L1.

L1BlockNumber

Implementation

Address: 0x4200000000000000000000000000000000000013

The L1BlockNumber returns the last known L1 block number. This contract was introduced in the legacy system and should be backwards compatible by calling out to the L1Block contract under the hood.

It is recommended to use the L1Block contract for getting information about L1 on L2.

GasPriceOracle

Implementation

Address: 0x420000000000000000000000000000000000000F

In the legacy system, the GasPriceOracle was a permissioned contract that was pushed the L1 base fee and the L2 gas price by an offchain actor. The offchain actor observes the L1 blockheaders to get the L1 base fee as well as the gas usage on L2 to compute what the L2 gas price should be based on a congestion control algorithm.

After Bedrock, the GasPriceOracle is no longer a permissioned contract and only exists to preserve the API for offchain gas estimation. The function getL1Fee(bytes) accepts an unsigned RLP transaction and will return the L1 portion of the fee. This fee pays for using L1 as a data availability layer and should be added to the L2 portion of the fee, which pays for execution, to compute the total transaction fee.

The values used to compute the L1 portion of the fee prior to the Ecotone upgrade are:

  • scalar
  • overhead
  • decimals

After the Bedrock upgrade, these values are instead managed by the SystemConfig contract on L1. The scalar and overhead values are sent to the L1Block contract each block and the decimals value has been hardcoded to 6.

Following the Ecotone upgrade, the values used for L1 fee computation are:

  • baseFeeScalar
  • blobBaseFeeScalar
  • decimals

These new scalar values are managed by the SystemConfig contract on the L1 by introducing a backwards compatible versioned encoding scheme of its scalars storage slot. The decimals remains hardcoded to 6, and the overhead value is ignored.

L1Block

Implementation

Address: 0x4200000000000000000000000000000000000015

The L1Block was introduced in Bedrock and is responsible for maintaining L1 context in L2. This allows for L1 state to be accessed in L2.

ProxyAdmin

ProxyAdmin Address: 0x4200000000000000000000000000000000000018

The ProxyAdmin is the owner of all of the proxy contracts set at the predeploys. It is itself behind a proxy. The owner of the ProxyAdmin will have the ability to upgrade any of the other predeploy contracts.

SequencerFeeVault

Implementation

Address: 0x4200000000000000000000000000000000000011

The SequencerFeeVault accumulates any transaction priority fee and is the value of block.coinbase. When enough fees accumulate in this account, they can be withdrawn to an immutable L1 address.

To change the L1 address that fees are withdrawn to, the contract must be upgraded by changing its proxy's implementation key.

OptimismMintableERC20Factory

Implementation

Address: 0x4200000000000000000000000000000000000012

The OptimismMintableERC20Factory is responsible for creating ERC20 contracts on L2 that can be used for depositing native L1 tokens into. These ERC20 contracts can be created permissionlessly and implement the interface required by the StandardBridge to just work with deposits and withdrawals.

Each ERC20 contract that is created by the OptimismMintableERC20Factory allows for the L2StandardBridge to mint and burn tokens, depending on if the user is depositing from L1 to L2 or withdrawing from L2 to L1.

OptimismMintableERC721Factory

Implementation

Address: 0x4200000000000000000000000000000000000017

The OptimismMintableERC721Factory is responsible for creating ERC721 contracts on L2 that can be used for depositing native L1 NFTs into.

BaseFeeVault

Implementation

Address: 0x4200000000000000000000000000000000000019

The BaseFeeVault predeploy receives the base fees on L2. The base fee is not burnt on L2 like it is on L1. Once the contract has received a certain amount of fees, the ETH can be withdrawn to an immutable address on L1.

L1FeeVault

Implementation

Address: 0x420000000000000000000000000000000000001a

The L1FeeVault predeploy receives the L1 portion of the transaction fees. Once the contract has received a certain amount of fees, the ETH can be withdrawn to an immutable address on L1.

SchemaRegistry

Implementation

Address: 0x4200000000000000000000000000000000000020

The SchemaRegistry predeploy implements the global attestation schemas for the Ethereum Attestation Service protocol.

EAS

Implementation

Address: 0x4200000000000000000000000000000000000021

The EAS predeploy implements the Ethereum Attestation Service protocol.

Beacon Block Root

Address: 0x000F3df6D732807Ef1319fB7B8bB8522d0Beac02

The BeaconBlockRoot predeploy provides access to the L1 beacon block roots. This was added during the Ecotone network upgrade and is specified in EIP-4788.