Overview

Table of Contents

This upgrade enables a deterministic L2 genesis state by moving all network specific configuration out of the initial L2 genesis state. All network specific configuration is sourced from deposit transactions during the initialization of the SystemConfig.

Constants

NameValueDefinition
ConfigTypeuint8An enum representing the type of config being set
WithdrawalNetworkuint8(0) or uint8(1)0 means withdraw to L1, 1 means withdraw to L2
RECIPIENTaddressThe account that will receive funds sent out of the FeeVault
MIN_WITHDRAWAL_AMOUNTuint256The minimum amount of native asset held in the FeeVault before withdrawal is authorized
Fee Vault Configbytes32bytes32((WithdrawalNetwork << 248) || uint256(uint88(MIN_WITHDRAWAL_AMOUNT)) || uint256(uint160(RECIPIENT)))
BASE_FEE_VAULT_CONFIGbytes32(uint256(keccak256("opstack.basefeevaultconfig")) - 1)The Fee Vault Config for the BaseFeeVault
L1_FEE_VAULT_CONFIGbytes32(uint256(keccak256("opstack.l1feevaultconfig")) - 1)The Fee Vault Config for the L1FeeVault
SEQUENCER_FEE_VAULT_CONFIGbytes32(uint256(keccak256("opstack.sequencerfeevaultconfig")) - 1)The Fee Vault Config for the SequencerFeeVault
L1_CROSS_DOMAIN_MESSENGER_ADDRESSbytes32(uint256(keccak256("opstack.l1crossdomainmessengeraddress")) - 1)abi.encode(address(L1CrossDomainMessengerProxy))
L1_ERC_721_BRIDGE_ADDRESSbytes32(uint256(keccak256("opstack.l1erc721bridgeaddress")) - 1)abi.encode(address(L1ERC721BridgeProxy))
L1_STANDARD_BRIDGE_ADDRESSbytes32(uint256(keccak256("opstack.l1standardbridgeaddress")) - 1)abi.encode(address(L1StandardBridgeProxy))
REMOTE_CHAIN_IDbytes32(uint256(keccak256("opstack.remotechainid")) - 1)Chain ID of the remote chain

Predeploys

All network specific configuration is moved to a single contract, the L1Block predeploy. All predeploys make calls to the L1Block contract to fetch network specific configuration rather than reading it from local state.

graph LR
  subgraph L1
  SystemConfig -- "setConfig(uint8,bytes)" --> OptimismPortal
  end
  subgraph L2
  L1Block
  BaseFeeVault -- "baseFeeVaultConfig()(address,uint256,uint8)" --> L1Block
  SequencerFeeVault -- "sequencerFeeVaultConfig()(address,uint256,uint8)" --> L1Block
  L1FeeVault -- "l1FeeVaultConfig()(address,uint256,uint8)" --> L1Block
  L2CrossDomainMessenger -- "l1CrossDomainMessenger()(address)" --> L1Block
  L2StandardBridge -- "l1StandardBridge()(address)" --> L1Block
  L2ERC721Bridge -- "l1ERC721Bridge()(address)" --> L1Block
  OptimismMintableERC721Factory -- "remoteChainId()(uint256)" --> L1Block
  end
  OptimismPortal -- "setConfig(uint8,bytes)" --> L1Block

L1Block

Storage

The following storage slots are defined:

  • BASE_FEE_VAULT_CONFIG
  • L1_FEE_VAULT_CONFIG
  • SEQUENCER_FEE_VAULT_CONFIG
  • L1_CROSS_DOMAIN_MESSENGER_ADDRESS
  • L1_ERC_721_BRIDGE_ADDRESS
  • L1_STANDARD_BRIDGE_ADDRESS
  • REMOTE_CHAIN_ID

Each slot MUST have a defined ConfigType that authorizes the setting of the storage slot via a deposit transaction from the DEPOSITOR_ACCOUNT.

Interface

setL1BlockValuesHolocene

This function MUST only be callable by the DEPOSITOR_ACCOUNT. It is a replacement for setL1BlockValuesEcotone and its calldata is defined in L1 Attributes.

function setL1BlockValuesHolocene()
setHolocene

This function is meant to be called once on the activation block of the holocene network upgrade. It MUST only be callable by the DEPOSITOR_ACCOUNT once. When it is called, it MUST call call each getter for the network specific config and set the returndata into storage.

eip1559Elasticity

This function returns the currently configured EIP-1559 elasticity.

function eip1559Elasticity()(uint64)
eip1559Denominator

This function returns the currently configured EIP-1559 denominator.

function eip1559Denominator()(uint64)
setConfig

This function MUST only be callable by the DEPOSITOR_ACCOUNT. It modifies the storage directly of the L1Block contract. It MUST handle all defined ConfigTypes. To ensure a simple ABI, the bytes value MUST be abi decoded based on the ConfigType.

function setConfig(ConfigType,bytes)

Note that ConfigType is an enum which is an alias for a uint8.

baseFeeVaultConfig

This function MUST be called by the BaseFeeVault to fetch network specific configuration.

function baseFeeVaultConfig()(address,uint256,WithdrawalNetwork)
sequencerFeeVaultConfig

This function MUST be called by the SequencerFeeVault to fetch network specific configuration.

function sequencerFeeVaultConfig()(address,uint256,WithdrawalNetwork)
l1FeeVaultConfig

This function MUST be called by the L1FeeVault to fetch network specific configuration.

function l1FeeVaultConfig()(address,uint256,WithdrawalNetwork)
l1CrossDomainMessenger

This function MUST be called by the L2CrossDomainMessenger to fetch the address of the L1CrossDomainMessenger.

function l1CrossDomainMessenger()(address)
l1StandardBridge

This function MUST be called by the L2StandardBridge to fetch the address of the L2CrossDomainMessenger.

function l1StandardBridge()(address)
l1ERC721Bridge

This function MUST be called by the L2ERC721Bridge to fetch the address of the L1ERC721Bridge.

function l1ERC721Bridge()(address)
remoteChainId

This function MUST be called by the OptimismMintableERC721Factory to fetch the chain id of the remote chain. For an L2, this is the L1 chain id.

function remoteChainId()(uint256)

FeeVault

The following changes apply to each of the BaseFeeVault, the L1FeeVault and the SequencerFeeVault.

Interface

The following functions are updated to read from the L1Block contract:

  • recipient()(address)
  • withdrawalNetwork()(WithdrawalNetwork)
  • minWithdrawalAmount()(uint256)
  • withdraw()
NameCall
BaseFeeVaultL1Block.baseFeeVaultConfig()
SequencerFeeVaultL1Block.sequencerFeeVaultConfig()
L1FeeVaultL1Block.l1FeeVaultConfig()
config

A new function is added to fetch the full Fee Vault Config.

function config()(address,uint256,WithdrawalNetwork)

L2CrossDomainMessenger

Interface

The following functions are updated to read from the L1Block contract by calling L1Block.l1CrossDomainMessenger():

  • otherMessenger()(address)
  • OTHER_MESSENGER()(address)

L2ERC721Bridge

Interface

The following functions are updated to read from the L1Block contract by calling L1Block.l1ERC721Bridge()

  • otherBridge()(address)
  • OTHER_BRIDGE()(address)

L2StandardBridge

Interface

The following functions are updated to read from the L1Block contract by calling L1Block.l1StandardBridge()

  • otherBridge()(address)
  • OTHER_BRIDGE()(address)

OptimismMintableERC721Factory

The chain id is no longer read from storage but instead is read from the L1Block contract by calling L1Block.remoteChainId()

Security Considerations

GovernanceToken

The predeploy defined by GovernanceToken should be an empty account until it is defined by a future hardfork.