From 035a35e3a3c51f2e534c6e731a1039a6333a907e Mon Sep 17 00:00:00 2001 From: agusduha Date: Fri, 3 Jan 2025 16:16:06 -0300 Subject: [PATCH] feat: update L2 genesis specs --- specs/protocol/isthmus/configurability.md | 76 ++++++++++++++--------- specs/protocol/isthmus/overview.md | 4 ++ specs/protocol/isthmus/predeploys.md | 76 ++++++++++++++--------- 3 files changed, 95 insertions(+), 61 deletions(-) diff --git a/specs/protocol/isthmus/configurability.md b/specs/protocol/isthmus/configurability.md index ed16365e9..58a840634 100644 --- a/specs/protocol/isthmus/configurability.md +++ b/specs/protocol/isthmus/configurability.md @@ -12,13 +12,15 @@ - [Initialization](#initialization) - [Interface](#interface) - [Fee Vault Config](#fee-vault-config) - - [`setBaseFeeVaultConfig`](#setbasefeevaultconfig) - - [`setL1FeeVaultConfig`](#setl1feevaultconfig) - - [`setSequencerFeeVaultConfig`](#setsequencerfeevaultconfig) + - [`setFeeVaultConfig`](#setfeevaultconfig) + - [Fee Admin](#fee-admin) + - [`feeAdmin`](#feeadmin) + - [Invariants](#invariants) - [`OptimismPortal`](#optimismportal) - [Interface](#interface-1) - [`setConfig`](#setconfig) - [`upgrade`](#upgrade) + - [Invariants](#invariants-1) @@ -33,16 +35,16 @@ configurability. The `ConfigType` enum represents configuration that can be modified. -| Name | Value | Description | -| ---- | ----- | --- | -| `GAS_PAYING_TOKEN` | `uint8(0)` | Modifies the gas paying token for the chain | -| `BASE_FEE_VAULT_CONFIG` | `uint8(1)` | Sets the Fee Vault Config for the `BaseFeeVault` | -| `L1_FEE_VAULT_CONFIG` | `uint8(2)` | Sets the Fee Vault Config for the `L1FeeVault` | -| `SEQUENCER_FEE_VAULT_CONFIG` | `uint8(3)` | Sets the Fee Vault Config for the `SequencerFeeVault` | -| `L1_CROSS_DOMAIN_MESSENGER_ADDRESS` | `uint8(4)` | Sets the `L1CrossDomainMessenger` address | -| `L1_ERC_721_BRIDGE_ADDRESS` | `uint8(5)` | Sets the `L1ERC721Bridge` address | -| `L1_STANDARD_BRIDGE_ADDRESS` | `uint8(6)` | Sets the `L1StandardBridge` address | -| `REMOTE_CHAIN_ID` | `uint8(7)` | Sets the chain id of the base chain | +| Name | Value | Description | +| ----------------------------------- | ---------- | ----------------------------------------------------- | +| `GAS_PAYING_TOKEN` | `uint8(0)` | Modifies the gas paying token for the chain | +| `BASE_FEE_VAULT_CONFIG` | `uint8(1)` | Sets the Fee Vault Config for the `BaseFeeVault` | +| `L1_FEE_VAULT_CONFIG` | `uint8(2)` | Sets the Fee Vault Config for the `L1FeeVault` | +| `SEQUENCER_FEE_VAULT_CONFIG` | `uint8(3)` | Sets the Fee Vault Config for the `SequencerFeeVault` | +| `L1_CROSS_DOMAIN_MESSENGER_ADDRESS` | `uint8(4)` | Sets the `L1CrossDomainMessenger` address | +| `L1_ERC_721_BRIDGE_ADDRESS` | `uint8(5)` | Sets the `L1ERC721Bridge` address | +| `L1_STANDARD_BRIDGE_ADDRESS` | `uint8(6)` | Sets the `L1StandardBridge` address | +| `REMOTE_CHAIN_ID` | `uint8(7)` | Sets the chain id of the base chain | ## `SystemConfig` @@ -50,13 +52,13 @@ The `ConfigType` enum represents configuration that can be modified. The following `ConfigUpdate` event is defined where the `CONFIG_VERSION` is `uint256(0)`: -| Name | Value | Definition | Usage | -| ---- | ----- | --- | -- | -| `BATCHER` | `uint8(0)` | `abi.encode(address)` | Modifies the account that is authorized to progress the safe chain | -| `FEE_SCALARS` | `uint8(1)` | `(uint256(0x01) << 248) \| (uint256(_blobbasefeeScalar) << 32) \| _basefeeScalar` | Modifies the fee scalars | -| `GAS_LIMIT` | `uint8(2)` | `abi.encode(uint64 _gasLimit)` | Modifies the L2 gas limit | -| `UNSAFE_BLOCK_SIGNER` | `uint8(3)` | `abi.encode(address)` | Modifies the account that is authorized to progress the unsafe chain | -| `EIP_1559_PARAMS` | `uint8(4)` | `uint256(uint64(uint32(_denominator))) << 32 \| uint64(uint32(_elasticity))` | Modifies the EIP-1559 denominator and elasticity | +| Name | Value | Definition | Usage | +| --------------------- | ---------- | --------------------------------------------------------------------------------- | -------------------------------------------------------------------- | +| `BATCHER` | `uint8(0)` | `abi.encode(address)` | Modifies the account that is authorized to progress the safe chain | +| `FEE_SCALARS` | `uint8(1)` | `(uint256(0x01) << 248) \| (uint256(_blobbasefeeScalar) << 32) \| _basefeeScalar` | Modifies the fee scalars | +| `GAS_LIMIT` | `uint8(2)` | `abi.encode(uint64 _gasLimit)` | Modifies the L2 gas limit | +| `UNSAFE_BLOCK_SIGNER` | `uint8(3)` | `abi.encode(address)` | Modifies the account that is authorized to progress the unsafe chain | +| `EIP_1559_PARAMS` | `uint8(4)` | `uint256(uint64(uint32(_denominator))) << 32 \| uint64(uint32(_elasticity))` | Modifies the EIP-1559 denominator and elasticity | ### Initialization @@ -84,28 +86,32 @@ These actions MAY only be triggered if there is a diff to the value. For each `FeeVault`, there is a setter for its config. The arguments to the setter include the `RECIPIENT`, the `MIN_WITHDRAWAL_AMOUNT` and the `WithdrawalNetwork`. -Each of these functions should be `public` and only callable by the chain governor. +This function should be `public` and only callable by the fee admin. Each function calls `OptimismPortal.setConfig(ConfigType,bytes)` with its corresponding `ConfigType`. -##### `setBaseFeeVaultConfig` +##### `setFeeVaultConfig` ```solidity -function setBaseFeeVaultConfig(address,uint256,WithdrawalNetwork) +function setFeeVaultConfig(ConfigType,address,uint256,WithdrawalNetwork) ``` -##### `setL1FeeVaultConfig` +#### Fee Admin -```solidity -function setL1FeeVaultConfig(address,uint256,WithdrawalNetwork) -``` +A new role is introduced to call the vault config setters. This role is updated at the `initialize` function. -##### `setSequencerFeeVaultConfig` +##### `feeAdmin` ```solidity -function setSequencerFeeVaultConfig(address,uint256,WithdrawalNetwork) +function feeAdmin() returns (address) ``` +### Invariants + +- Only the fee admin MUST be able to update a fee vault config + +- Updating a fee vault config MUST emit a system deposit tx through the `OptimismPortal` + ## `OptimismPortal` The `OptimismPortal` is updated to emit a special system `TransactionDeposited` event. @@ -133,7 +139,7 @@ The following fields are included: - `to` is `Predeploys.L1Block` - `version` is `uint256(0)` - `opaqueData` is the tightly packed transaction data where `mint` is `0`, `value` is `0`, the `gasLimit` - is `200_000`, `isCreation` is `false` and the `data` is `abi.encodeCall(L1Block.setConfig, (_type, _value))` + is `200_000`, `isCreation` is `false` and the `data` is `abi.encodeCall(L1Block.setConfig, (_type, _value))` #### `upgrade` @@ -156,4 +162,12 @@ The following fields are included: - `to` is `Predeploys.ProxyAdmin` - `version` is `uint256(0)` - `opaqueData` is the tightly packed transaction data where `mint` is `0`, `value` is `0`, the `gasLimit` - is `200_000`, `isCreation` is `false` and the `data` is the data passed into `upgrade`. + is `200_000`, `isCreation` is `false` and the `data` is the data passed into `upgrade`. + +### Invariants + +- Only the `SystemConfig` MUST be able to call `setConfig` + +- Only the `UPGRADER` role MUST be able to call `upgrade` + +- `setConfig` and `upgrade` MUST emit a system deposit tx through `TransactionDeposited` event diff --git a/specs/protocol/isthmus/overview.md b/specs/protocol/isthmus/overview.md index 90c286eb2..60c008766 100644 --- a/specs/protocol/isthmus/overview.md +++ b/specs/protocol/isthmus/overview.md @@ -21,3 +21,7 @@ This document is not finalized and should be considered experimental. ## Smart Contracts - [SuperchainConfig](./superchain-config.md) + +- [SystemConfig and OptimismPortal](./configurability.md) + +- [Predeploys](./predeploys.md) diff --git a/specs/protocol/isthmus/predeploys.md b/specs/protocol/isthmus/predeploys.md index 51cd6ed58..591635a8d 100644 --- a/specs/protocol/isthmus/predeploys.md +++ b/specs/protocol/isthmus/predeploys.md @@ -18,12 +18,10 @@ - [Interface](#interface-1) - [`config`](#config) - [L2CrossDomainMessenger](#l2crossdomainmessenger) - - [Interface](#interface-2) - [L2ERC721Bridge](#l2erc721bridge) - - [Interface](#interface-3) - [L2StandardBridge](#l2standardbridge) - - [Interface](#interface-4) - [OptimismMintableERC721Factory](#optimismmintableerc721factory) + - [OptimismMintableERC20Factory](#optimismmintableerc20factory) - [Security Considerations](#security-considerations) - [GovernanceToken](#governancetoken) @@ -36,20 +34,20 @@ of the `SystemConfig`. ## Constants -| Name | Value | Definition | -| --------- | ------------------------- | -- | -| `ConfigType` | `uint8` | An enum representing the type of config being set | -| `WithdrawalNetwork` | `uint8(0)` or `uint8(1)` | `0` means withdraw to L1, `1` means withdraw to L2 | -| `RECIPIENT` | `address` | The account that will receive funds sent out of the `FeeVault` | -| `MIN_WITHDRAWAL_AMOUNT` | `uint256` | The minimum amount of native asset held in the `FeeVault` before withdrawal is authorized | -| Fee Vault Config | `bytes32` | `bytes32((WithdrawalNetwork << 248) \|\| uint256(uint88(MIN_WITHDRAWAL_AMOUNT)) \|\| uint256(uint160(RECIPIENT)))` | -| `BASE_FEE_VAULT_CONFIG` | `bytes32(uint256(keccak256("opstack.basefeevaultconfig")) - 1)` | The Fee Vault Config for the `BaseFeeVault` | -| `L1_FEE_VAULT_CONFIG` | `bytes32(uint256(keccak256("opstack.l1feevaultconfig")) - 1)` | The Fee Vault Config for the `L1FeeVault` | -| `SEQUENCER_FEE_VAULT_CONFIG` | `bytes32(uint256(keccak256("opstack.sequencerfeevaultconfig")) - 1)` | The Fee Vault Config for the `SequencerFeeVault` | -| `L1_CROSS_DOMAIN_MESSENGER_ADDRESS` | `bytes32(uint256(keccak256("opstack.l1crossdomainmessengeraddress")) - 1)` | `abi.encode(address(L1CrossDomainMessengerProxy))` | -| `L1_ERC_721_BRIDGE_ADDRESS` | `bytes32(uint256(keccak256("opstack.l1erc721bridgeaddress")) - 1)` | `abi.encode(address(L1ERC721BridgeProxy))` | -| `L1_STANDARD_BRIDGE_ADDRESS` | `bytes32(uint256(keccak256("opstack.l1standardbridgeaddress")) - 1)` | `abi.encode(address(L1StandardBridgeProxy))` | -| `REMOTE_CHAIN_ID` | `bytes32(uint256(keccak256("opstack.remotechainid")) - 1)` | Chain ID of the remote chain | +| Name | Value | Definition | +| ----------------------------------- | -------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ | +| `ConfigType` | `uint8` | An enum representing the type of config being set | +| `WithdrawalNetwork` | `uint8(0)` or `uint8(1)` | `0` means withdraw to L1, `1` means withdraw to L2 | +| `RECIPIENT` | `address` | The account that will receive funds sent out of the `FeeVault` | +| `MIN_WITHDRAWAL_AMOUNT` | `uint256` | The minimum amount of native asset held in the `FeeVault` before withdrawal is authorized | +| Fee Vault Config | `bytes32` | `bytes32((WithdrawalNetwork << 248) \|\| uint256(uint88(MIN_WITHDRAWAL_AMOUNT)) \|\| uint256(uint160(RECIPIENT)))` | +| `BASE_FEE_VAULT_CONFIG` | `bytes32(uint256(keccak256("opstack.basefeevaultconfig")) - 1)` | The Fee Vault Config for the `BaseFeeVault` | +| `L1_FEE_VAULT_CONFIG` | `bytes32(uint256(keccak256("opstack.l1feevaultconfig")) - 1)` | The Fee Vault Config for the `L1FeeVault` | +| `SEQUENCER_FEE_VAULT_CONFIG` | `bytes32(uint256(keccak256("opstack.sequencerfeevaultconfig")) - 1)` | The Fee Vault Config for the `SequencerFeeVault` | +| `L1_CROSS_DOMAIN_MESSENGER_ADDRESS` | `bytes32(uint256(keccak256("opstack.l1crossdomainmessengeraddress")) - 1)` | `abi.encode(address(L1CrossDomainMessengerProxy))` | +| `L1_ERC_721_BRIDGE_ADDRESS` | `bytes32(uint256(keccak256("opstack.l1erc721bridgeaddress")) - 1)` | `abi.encode(address(L1ERC721BridgeProxy))` | +| `L1_STANDARD_BRIDGE_ADDRESS` | `bytes32(uint256(keccak256("opstack.l1standardbridgeaddress")) - 1)` | `abi.encode(address(L1StandardBridgeProxy))` | +| `REMOTE_CHAIN_ID` | `bytes32(uint256(keccak256("opstack.remotechainid")) - 1)` | Chain ID of the remote chain | ## Predeploys @@ -110,9 +108,9 @@ via a deposit transaction from the `DEPOSITOR_ACCOUNT`. ##### `setIsthmus` -This function is meant to be called once on the activation block of the holocene network upgrade. +This function is meant to be called once on the activation block of the Isthmus 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. +each getter for the network specific config and set the returndata into storage. ##### `setConfig` @@ -151,11 +149,11 @@ The following functions are updated to read from the `L1Block` contract: - `minWithdrawalAmount()(uint256)` - `withdraw()` -| Name | Call | -| ---- | -------- | -| `BaseFeeVault` | `L1Block.getConfig(ConfigType.BASE_FEE_VAULT_CONFIG)` | +| Name | Call | +| ------------------- | ---------------------------------------------------------- | +| `BaseFeeVault` | `L1Block.getConfig(ConfigType.BASE_FEE_VAULT_CONFIG)` | | `SequencerFeeVault` | `L1Block.getConfig(ConfigType.SEQUENCER_FEE_VAULT_CONFIG)` | -| `L1FeeVault` | `L1Block.getConfig(ConfigType.L1_FEE_VAULT_CONFIG)` | +| `L1FeeVault` | `L1Block.getConfig(ConfigType.L1_FEE_VAULT_CONFIG)` | ##### `config` @@ -167,16 +165,18 @@ function config()(address,uint256,WithdrawalNetwork) ### L2CrossDomainMessenger -#### Interface - -The following functions are updated to read from the `L1Block` contract by calling `L1Block.getConfig(ConfigType.L1_CROSS_DOMAIN_MESSENGER_ADDRESS)`: +To make this contract not initializable, the universal `CrossDomainMessenger` contract is updated to no longer be initializable. +However, the L1 version continues to be. -- `otherMessenger()(address)` -- `OTHER_MESSENGER()(address)` +The `otherMessenger()(address)` function is updated to read from the `L1Block` contract +by calling `L1Block.getConfig(ConfigType.L1_CROSS_DOMAIN_MESSENGER_ADDRESS)`. ### L2ERC721Bridge -#### Interface +To make this contract not initializable, the universal `ERC721Bridge` contract is updated to no longer be initializable. +However, the L1 version continues to be. + +The `messenger()` function is updated to return `Predeploys.L2_CROSS_DOMAIN_MESSENGER`. The following functions are updated to read from the `L1Block` contract by calling `L1Block.getConfig(ConfigType.L1_ERC721_BRIDGE_ADDRESS)`: @@ -185,7 +185,10 @@ The following functions are updated to read from the `L1Block` contract by calli ### L2StandardBridge -#### Interface +To make this contract not initializable, the universal `StandardBridge` contract is updated to no longer be initializable. +However, the L1 version continues to be. + +The `messenger()` function is updated to return `Predeploys.L2_CROSS_DOMAIN_MESSENGER`. The following functions are updated to read from the `L1Block` contract by calling `L1Block.getConfig(ConfigType.L1_STANDARD_BRIDGE_ADDRESS)`: @@ -194,9 +197,22 @@ The following functions are updated to read from the `L1Block` contract by calli ### OptimismMintableERC721Factory +This contract is updated to remove its constructor. + The chain id is no longer read from storage but instead is read from the `L1Block` contract by calling `L1Block.getConfig(ConfigType.REMOTE_CHAIN_ID)` +The bridge is no longer set in the constructor but instead it uses the `Predeploys.L2_ERC721_BRIDGE` + +### OptimismMintableERC20Factory + +The universal contract is updated to be abstract and no longer initializable. +Two new contracts are derived from it: `L1OptimismMintableERC20Factory` and `L2OptimismMintableERC20Factory` + +In L2, the bridge is no longer set in the constructor but instead it uses the `Predeploys.L2_STANDARD_BRIDGE` + +The L1 version continues to be initializable. + ## Security Considerations ### GovernanceToken