Commit 5b0b8cf5 authored by Maurelian's avatar Maurelian Committed by GitHub

Merge pull request #8237 from ethereum-optimism/add-superchain-config

Add minimal SuperchainConfig contract
parents d8bdedb3 e13439b0
......@@ -41,5 +41,6 @@
"SafeProxyFactory",
"DelayedVetoable",
"ISemver",
"StorageSetter"
"StorageSetter",
"SuperchainConfig"
]
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
// Code generated - DO NOT EDIT.
// This file is a generated binding and any manual changes will be lost.
package bindings
import (
"encoding/json"
"github.com/ethereum-optimism/optimism/op-bindings/solc"
)
const SuperchainConfigStorageLayoutJSON = "{\"storage\":[{\"astId\":1000,\"contract\":\"src/L1/SuperchainConfig.sol:SuperchainConfig\",\"label\":\"_initialized\",\"offset\":0,\"slot\":\"0\",\"type\":\"t_uint8\"},{\"astId\":1001,\"contract\":\"src/L1/SuperchainConfig.sol:SuperchainConfig\",\"label\":\"_initializing\",\"offset\":1,\"slot\":\"0\",\"type\":\"t_bool\"}],\"types\":{\"t_bool\":{\"encoding\":\"inplace\",\"label\":\"bool\",\"numberOfBytes\":\"1\"},\"t_uint8\":{\"encoding\":\"inplace\",\"label\":\"uint8\",\"numberOfBytes\":\"1\"}}}"
var SuperchainConfigStorageLayout = new(solc.StorageLayout)
var SuperchainConfigDeployedBin = "0x608060405234801561001057600080fd5b50600436106100885760003560e01c80636da663551161005b5780636da663551461012a5780637fbf7b6a1461013d578063c23a451a14610153578063c4d66de81461015b57600080fd5b80633f4ba83a1461008d578063452a93201461009757806354fd4d50146100c95780635c975abb14610112575b600080fd5b61009561016e565b005b61009f610294565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b6101056040518060400160405280600581526020017f312e302e3000000000000000000000000000000000000000000000000000000081525081565b6040516100c09190610768565b61011a6102cd565b60405190151581526020016100c0565b6100956101383660046107b1565b610305565b610145610435565b6040519081526020016100c0565b610145610463565b610095610169366004610880565b61048e565b610176610294565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610235576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f5375706572636861696e436f6e6669673a206f6e6c7920677561726469616e2060448201527f63616e20756e706175736500000000000000000000000000000000000000000060648201526084015b60405180910390fd5b61026961026360017f54176ff9944c4784e5857ec4e5ef560a462c483bf534eda43f91bb01a470b1b76108b6565b60009055565b6040517fa45f47fdea8a1efdd9029a5691c7f759c32b7c698632b563573e155625d1693390600090a1565b60006102c86102c460017fd30e835d3f35624761057ff5b27d558f97bd5be034621e62240e5c0b784abe696108b6565b5490565b905090565b60006102fd6102c460017f54176ff9944c4784e5857ec4e5ef560a462c483bf534eda43f91bb01a470b1b76108b6565b600114905090565b61030d610294565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146103c7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f5375706572636861696e436f6e6669673a206f6e6c7920677561726469616e2060448201527f63616e2070617573650000000000000000000000000000000000000000000000606482015260840161022c565b6103fb6103f560017f54176ff9944c4784e5857ec4e5ef560a462c483bf534eda43f91bb01a470b1b76108b6565b60019055565b7fc32e6d5d6d1de257f64eac19ddb1f700ba13527983849c9486b1ab007ea283818160405161042a9190610768565b60405180910390a150565b61046060017f54176ff9944c4784e5857ec4e5ef560a462c483bf534eda43f91bb01a470b1b76108b6565b81565b61046060017fd30e835d3f35624761057ff5b27d558f97bd5be034621e62240e5c0b784abe696108b6565b600054610100900460ff16158080156104ae5750600054600160ff909116105b806104c85750303b1580156104c8575060005460ff166001145b610554576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a6564000000000000000000000000000000000000606482015260840161022c565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905580156105b257600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b6105bb82610642565b801561061e57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b9055565b61067561067060017fd30e835d3f35624761057ff5b27d558f97bd5be034621e62240e5c0b784abe696108b6565b829055565b60006040805173ffffffffffffffffffffffffffffffffffffffff841660208201527f7b743789cff01dafdeae47739925425aab5dfd02d0c8229e4a508bcd2b9f42bb9101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152908290526106f291610768565b60405180910390a250565b6000815180845260005b8181101561072357602081850181015186830182015201610707565b81811115610735576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061077b60208301846106fd565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000602082840312156107c357600080fd5b813567ffffffffffffffff808211156107db57600080fd5b818401915084601f8301126107ef57600080fd5b81358181111561080157610801610782565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190838211818310171561084757610847610782565b8160405282815287602084870101111561086057600080fd5b826020860160208301376000928101602001929092525095945050505050565b60006020828403121561089257600080fd5b813573ffffffffffffffffffffffffffffffffffffffff8116811461077b57600080fd5b6000828210156108ef577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b50039056fea164736f6c634300080f000a"
func init() {
if err := json.Unmarshal([]byte(SuperchainConfigStorageLayoutJSON), SuperchainConfigStorageLayout); err != nil {
panic(err)
}
layouts["SuperchainConfig"] = SuperchainConfigStorageLayout
deployedBytecodes["SuperchainConfig"] = SuperchainConfigDeployedBin
}
......@@ -8,4 +8,4 @@ GasBenchMark_L1StandardBridge_Finalize:test_finalizeETHWithdrawal_benchmark() (g
GasBenchMark_L2OutputOracle:test_proposeL2Output_benchmark() (gas: 86629)
GasBenchMark_OptimismPortal:test_depositTransaction_benchmark() (gas: 68474)
GasBenchMark_OptimismPortal:test_depositTransaction_benchmark_1() (gas: 68911)
GasBenchMark_OptimismPortal:test_proveWithdrawalTransaction_benchmark() (gas: 143106)
\ No newline at end of file
GasBenchMark_OptimismPortal:test_proveWithdrawalTransaction_benchmark() (gas: 143100)
\ No newline at end of file
......@@ -9,6 +9,7 @@ import { Constants } from "src/libraries/Constants.sol";
import { L1StandardBridge } from "src/L1/L1StandardBridge.sol";
import { L2OutputOracle } from "src/L1/L2OutputOracle.sol";
import { ProtocolVersion, ProtocolVersions } from "src/L1/ProtocolVersions.sol";
import { SuperchainConfig } from "src/L1/SuperchainConfig.sol";
import { OptimismPortal } from "src/L1/OptimismPortal.sol";
import { L1CrossDomainMessenger } from "src/L1/L1CrossDomainMessenger.sol";
import { OptimismMintableERC20Factory } from "src/universal/OptimismMintableERC20Factory.sol";
......@@ -178,4 +179,11 @@ library ChainAssertions {
require(ProtocolVersion.unwrap(versions.recommended()) == 0);
}
}
/// @notice Asserts that the SuperchainConfig is setup correctly
function checkSuperchainConfig(Types.ContractSet memory _contracts, DeployConfig _cfg) internal view {
SuperchainConfig superchainConfig = SuperchainConfig(_contracts.SuperchainConfig);
require(superchainConfig.guardian() == _cfg.portalGuardian());
require(superchainConfig.paused() == false);
}
}
......@@ -26,6 +26,7 @@ import { ResolvedDelegateProxy } from "src/legacy/ResolvedDelegateProxy.sol";
import { L1CrossDomainMessenger } from "src/L1/L1CrossDomainMessenger.sol";
import { L2OutputOracle } from "src/L1/L2OutputOracle.sol";
import { OptimismMintableERC20Factory } from "src/universal/OptimismMintableERC20Factory.sol";
import { SuperchainConfig } from "src/L1/SuperchainConfig.sol";
import { SystemConfig } from "src/L1/SystemConfig.sol";
import { ResourceMetering } from "src/L1/ResourceMetering.sol";
import { Constants } from "src/libraries/Constants.sol";
......@@ -102,7 +103,7 @@ contract Deploy is Deployer {
return keccak256(bytes(vm.envOr("IMPL_SALT", string("ethers phoenix"))));
}
/// @notice Returns the proxy addresses
/// @notice Returns the proxy addresses. If a proxy is not found, it will have address(0).
function _proxies() private view returns (Types.ContractSet memory proxies_) {
proxies_ = Types.ContractSet({
L1CrossDomainMessenger: mustGetAddress("L1CrossDomainMessengerProxy"),
......@@ -112,7 +113,8 @@ contract Deploy is Deployer {
OptimismPortal: mustGetAddress("OptimismPortalProxy"),
SystemConfig: mustGetAddress("SystemConfigProxy"),
L1ERC721Bridge: mustGetAddress("L1ERC721BridgeProxy"),
ProtocolVersions: mustGetAddress("ProtocolVersionsProxy")
ProtocolVersions: mustGetAddress("ProtocolVersionsProxy"),
SuperchainConfig: mustGetAddress("SuperchainConfigProxy")
});
}
......@@ -126,7 +128,8 @@ contract Deploy is Deployer {
OptimismPortal: getAddress("OptimismPortalProxy"),
SystemConfig: getAddress("SystemConfigProxy"),
L1ERC721Bridge: getAddress("L1ERC721BridgeProxy"),
ProtocolVersions: getAddress("ProtocolVersionsProxy")
ProtocolVersions: getAddress("ProtocolVersionsProxy"),
SuperchainConfig: getAddress("SuperchainConfigProxy")
});
}
......@@ -207,25 +210,57 @@ contract Deploy is Deployer {
console.log("Deployment context: %s", deploymentContext);
}
/// @notice Deploy all of the L1 contracts
/// @notice Deploy all of the L1 contracts necessary for a full Superchain with a single Op Chain.
function run() public {
console.log("Deploying L1 system");
deployProxies();
deployImplementations();
console.log("Deploying a fresh OP Stack including SuperchainConfig");
deploySafe();
transferProxyAdminOwnership(); // to the Safe
setupSuperchain();
setupOpChain();
}
initializeDisputeGameFactory();
initializeSystemConfig();
initializeL1StandardBridge();
initializeL1ERC721Bridge();
initializeOptimismMintableERC20Factory();
initializeL1CrossDomainMessenger();
initializeL2OutputOracle();
initializeOptimismPortal();
////////////////////////////////////////////////////////////////
// High Level Deployment Functions //
////////////////////////////////////////////////////////////////
/// @notice Deploy a full system with a new SuperchainConfig
/// The Superchain system has 2 singleton contracts which lie outside of an OP Chain:
/// 1. The SuperchainConfig contract
/// 2. The ProtocolVersions contract
function setupSuperchain() public {
console.log("Setting up Superchain");
// Deploy a new ProxyAdmin and AddressManager
// This proxy will be used on the SuperchainConfig and ProtocolVersions contracts, as well as the contracts
// in the OP Chain system.
deployAddressManager();
deployProxyAdmin();
transferProxyAdminOwnership();
// Deploy the SuperchainConfigProxy
deployERC1967Proxy("SuperchainConfigProxy");
deploySuperchainConfig();
initializeSuperchainConfig();
// Deploy the ProtocolVersionsProxy
deployERC1967Proxy("ProtocolVersionsProxy");
deployProtocolVersions();
initializeProtocolVersions();
}
/// @notice Deploy a new OP Chain, with an existing SuperchainConfig provided
function setupOpChain() public {
console.log("Deploying OP Chain");
// Ensure that the requisite contracts are deployed
mustGetAddress("SuperchainConfigProxy");
mustGetAddress("SystemOwnerSafe");
mustGetAddress("AddressManager");
mustGetAddress("ProxyAdmin");
deployProxies();
deployImplementations();
initializeImplementations();
setAlphabetFaultGameImplementation();
setCannonFaultGameImplementation();
......@@ -233,14 +268,9 @@ contract Deploy is Deployer {
transferDisputeGameFactoryOwnership();
}
////////////////////////////////////////////////////////////////
// High Level Deployment Functions //
////////////////////////////////////////////////////////////////
/// @notice Deploy all of the proxies
function deployProxies() public {
deployAddressManager();
deployProxyAdmin();
console.log("Deploying proxies");
deployERC1967Proxy("OptimismPortalProxy");
deployERC1967Proxy("L2OutputOracleProxy");
......@@ -250,13 +280,13 @@ contract Deploy is Deployer {
deployERC1967Proxy("OptimismMintableERC20FactoryProxy");
deployERC1967Proxy("L1ERC721BridgeProxy");
deployERC1967Proxy("DisputeGameFactoryProxy");
deployERC1967Proxy("ProtocolVersionsProxy");
transferAddressManagerOwnership(); // to the ProxyAdmin
}
/// @notice Deploy all of the implementations
function deployImplementations() public {
console.log("Deploying implementations");
deployOptimismPortal();
deployL1CrossDomainMessenger();
deployL2OutputOracle();
......@@ -268,7 +298,19 @@ contract Deploy is Deployer {
deployBlockOracle();
deployPreimageOracle();
deployMips();
deployProtocolVersions();
}
/// @notice Initialize all of the implementations
function initializeImplementations() public {
console.log("Initializing implementations");
initializeDisputeGameFactory();
initializeSystemConfig();
initializeL1StandardBridge();
initializeL1ERC721Bridge();
initializeOptimismMintableERC20Factory();
initializeL1CrossDomainMessenger();
initializeL2OutputOracle();
initializeOptimismPortal();
}
////////////////////////////////////////////////////////////////
......@@ -391,6 +433,18 @@ contract Deploy is Deployer {
// Implementation Deployment Functions //
////////////////////////////////////////////////////////////////
/// @notice Deploy the SuperchainConfig contract
function deploySuperchainConfig() public broadcast {
SuperchainConfig superchainConfig = new SuperchainConfig{ salt: _implSalt() }();
require(superchainConfig.guardian() == address(0));
bytes32 initialized = vm.load(address(superchainConfig), bytes32(0));
require(initialized != 0);
save("SuperchainConfig", address(superchainConfig));
console.log("SuperchainConfig deployed at %s", address(superchainConfig));
}
/// @notice Deploy the L1CrossDomainMessenger
function deployL1CrossDomainMessenger() public broadcast returns (address addr_) {
console.log("Deploying L1CrossDomainMessenger implementation");
......@@ -646,6 +700,19 @@ contract Deploy is Deployer {
// Initialize Functions //
////////////////////////////////////////////////////////////////
/// @notice Initialize the SuperchainConfig
function initializeSuperchainConfig() public broadcast {
address payable superchainConfigProxy = mustGetAddress("SuperchainConfigProxy");
address payable superchainConfig = mustGetAddress("SuperchainConfig");
_upgradeAndCallViaSafe({
_proxy: superchainConfigProxy,
_implementation: superchainConfig,
_innerCallData: abi.encodeCall(SuperchainConfig.initialize, (cfg.portalGuardian()))
});
ChainAssertions.checkSuperchainConfig(_proxiesUnstrict(), cfg);
}
/// @notice Initialize the DisputeGameFactory
function initializeDisputeGameFactory() public onlyDevnet broadcast {
console.log("Upgrading and initializing DisputeGameFactory proxy");
......@@ -884,7 +951,7 @@ contract Deploy is Deployer {
string memory version = versions.version();
console.log("ProtocolVersions version: %s", version);
ChainAssertions.checkProtocolVersions({ _contracts: _proxies(), _cfg: cfg, _isProxy: true });
ChainAssertions.checkProtocolVersions({ _contracts: _proxiesUnstrict(), _cfg: cfg, _isProxy: true });
require(loadInitializedSlot("ProtocolVersions", true) == 1, "ProtocolVersionsProxy is not initialized");
}
......
......@@ -12,5 +12,6 @@ library Types {
address SystemConfig;
address L1ERC721Bridge;
address ProtocolVersions;
address SuperchainConfig;
}
}
......@@ -8,6 +8,7 @@
"src/L1/L2OutputOracle.sol": "0xbc8acf3cdf2ea6107e2f9fad37e68a8f039f289d88b2ce002920c9ae00310450",
"src/L1/OptimismPortal.sol": "0x1f2ee207a5802d7c33a70aacd81e19c3880e593fa71c82adf02414d71066b934",
"src/L1/ProtocolVersions.sol": "0x6401853c57ca29e8e9bb38173b5ac9f0856395a325324a08eeb965cc831f0419",
"src/L1/SuperchainConfig.sol": "0x316e49c6d1d34d3172916015a049039d04364aabe0f0ddfa29472354a1fe6ea9",
"src/L1/SystemConfig.sol": "0xc24454da676297e0cd718ebf017933c5b1084e389e78ebe2a69d31053ea2f051",
"src/L2/BaseFeeVault.sol": "0xe36f9be65c910694e60a14f266f9b6569f01b4ddd74fa0557305eb83e7e9d112",
"src/L2/GasPriceOracle.sol": "0x88efffbd40f8d012d700a5d7fde0d92266f65e9d7006cd8f034bacaa036d0eb2",
......
......@@ -235,9 +235,9 @@
"type": "uint256"
},
{
"internalType": "uint256",
"name": "_l2BlockNumber",
"type": "uint256"
"internalType": "bytes32",
"name": "_localContext",
"type": "bytes32"
},
{
"internalType": "uint256",
......
......@@ -49,9 +49,9 @@
"type": "bytes"
},
{
"internalType": "uint256",
"internalType": "bytes32",
"name": "_localContext",
"type": "uint256"
"type": "bytes32"
}
],
"name": "step",
......
......@@ -30,9 +30,9 @@
"type": "uint256"
},
{
"internalType": "uint256",
"internalType": "bytes32",
"name": "_localContext",
"type": "uint256"
"type": "bytes32"
},
{
"internalType": "bytes32",
......
[
{
"inputs": [],
"stateMutability": "nonpayable",
"type": "constructor"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "enum SuperchainConfig.UpdateType",
"name": "updateType",
"type": "uint8"
},
{
"indexed": false,
"internalType": "bytes",
"name": "data",
"type": "bytes"
}
],
"name": "ConfigUpdate",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "uint8",
"name": "version",
"type": "uint8"
}
],
"name": "Initialized",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "string",
"name": "identifier",
"type": "string"
}
],
"name": "Paused",
"type": "event"
},
{
"anonymous": false,
"inputs": [],
"name": "Unpaused",
"type": "event"
},
{
"inputs": [],
"name": "GUARDIAN_SLOT",
"outputs": [
{
"internalType": "bytes32",
"name": "",
"type": "bytes32"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "PAUSED_SLOT",
"outputs": [
{
"internalType": "bytes32",
"name": "",
"type": "bytes32"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "guardian",
"outputs": [
{
"internalType": "address",
"name": "guardian_",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "_guardian",
"type": "address"
}
],
"name": "initialize",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "string",
"name": "_identifier",
"type": "string"
}
],
"name": "pause",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "paused",
"outputs": [
{
"internalType": "bool",
"name": "paused_",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "unpause",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "version",
"outputs": [
{
"internalType": "string",
"name": "",
"type": "string"
}
],
"stateMutability": "view",
"type": "function"
}
]
\ No newline at end of file
......@@ -4,6 +4,6 @@
"label": "mapping(uint256 => struct BlockOracle.BlockInfo)",
"offset": 0,
"slot": "0",
"type": "t_mapping(t_uint256,t_struct(BlockInfo)81992_storage)"
"type": "t_mapping(t_uint256,t_struct(BlockInfo)71413_storage)"
}
]
\ No newline at end of file
......@@ -39,20 +39,20 @@
"label": "mapping(GameType => contract IDisputeGame)",
"offset": 0,
"slot": "101",
"type": "t_mapping(t_userDefinedValueType(GameType)86039,t_contract(IDisputeGame)83713)"
"type": "t_mapping(t_userDefinedValueType(GameType)75267,t_contract(IDisputeGame)73134)"
},
{
"bytes": "32",
"label": "mapping(Hash => GameId)",
"offset": 0,
"slot": "102",
"type": "t_mapping(t_userDefinedValueType(Hash)86021,t_userDefinedValueType(GameId)86033)"
"type": "t_mapping(t_userDefinedValueType(Hash)75249,t_userDefinedValueType(GameId)75261)"
},
{
"bytes": "32",
"label": "GameId[]",
"offset": 0,
"slot": "103",
"type": "t_array(t_userDefinedValueType(GameId)86033)dyn_storage"
"type": "t_array(t_userDefinedValueType(GameId)75261)dyn_storage"
}
]
\ No newline at end of file
......@@ -11,6 +11,6 @@
"label": "mapping(string => struct Drippie.DripState)",
"offset": 0,
"slot": "1",
"type": "t_mapping(t_string_memory_ptr,t_struct(DripState)89080_storage)"
"type": "t_mapping(t_string_memory_ptr,t_struct(DripState)89118_storage)"
}
]
\ No newline at end of file
......@@ -18,7 +18,7 @@
"label": "mapping(bytes32 => struct Attestation)",
"offset": 0,
"slot": "50",
"type": "t_mapping(t_bytes32,t_struct(Attestation)55167_storage)"
"type": "t_mapping(t_bytes32,t_struct(Attestation)55326_storage)"
},
{
"bytes": "32",
......
......@@ -4,14 +4,14 @@
"label": "mapping(contract IFaucetAuthModule => struct Faucet.ModuleConfig)",
"offset": 0,
"slot": "0",
"type": "t_mapping(t_contract(IFaucetAuthModule)90001,t_struct(ModuleConfig)89678_storage)"
"type": "t_mapping(t_contract(IFaucetAuthModule)90039,t_struct(ModuleConfig)89716_storage)"
},
{
"bytes": "32",
"label": "mapping(contract IFaucetAuthModule => mapping(bytes32 => uint256))",
"offset": 0,
"slot": "1",
"type": "t_mapping(t_contract(IFaucetAuthModule)90001,t_mapping(t_bytes32,t_uint256))"
"type": "t_mapping(t_contract(IFaucetAuthModule)90039,t_mapping(t_bytes32,t_uint256))"
},
{
"bytes": "32",
......
......@@ -4,49 +4,49 @@
"label": "Timestamp",
"offset": 0,
"slot": "0",
"type": "t_userDefinedValueType(Timestamp)86029"
"type": "t_userDefinedValueType(Timestamp)75257"
},
{
"bytes": "1",
"label": "enum GameStatus",
"offset": 8,
"slot": "0",
"type": "t_enum(GameStatus)86045"
"type": "t_enum(GameStatus)75273"
},
{
"bytes": "20",
"label": "contract IBondManager",
"offset": 9,
"slot": "0",
"type": "t_contract(IBondManager)83636"
"type": "t_contract(IBondManager)73057"
},
{
"bytes": "32",
"label": "Hash",
"offset": 0,
"slot": "1",
"type": "t_userDefinedValueType(Hash)86021"
"type": "t_userDefinedValueType(Hash)75249"
},
{
"bytes": "32",
"label": "struct IFaultDisputeGame.ClaimData[]",
"offset": 0,
"slot": "2",
"type": "t_array(t_struct(ClaimData)83850_storage)dyn_storage"
"type": "t_array(t_struct(ClaimData)73271_storage)dyn_storage"
},
{
"bytes": "128",
"label": "struct IFaultDisputeGame.OutputProposals",
"offset": 0,
"slot": "3",
"type": "t_struct(OutputProposals)83865_storage"
"type": "t_struct(OutputProposals)73286_storage"
},
{
"bytes": "32",
"label": "mapping(ClaimHash => bool)",
"offset": 0,
"slot": "7",
"type": "t_mapping(t_userDefinedValueType(ClaimHash)86025,t_bool)"
"type": "t_mapping(t_userDefinedValueType(ClaimHash)75253,t_bool)"
},
{
"bytes": "32",
......
......@@ -39,7 +39,7 @@
"label": "mapping(address => struct Counters.Counter)",
"offset": 0,
"slot": "5",
"type": "t_mapping(t_address,t_struct(Counter)51095_storage)"
"type": "t_mapping(t_address,t_struct(Counter)49118_storage)"
},
{
"bytes": "32",
......@@ -60,14 +60,14 @@
"label": "mapping(address => struct ERC20Votes.Checkpoint[])",
"offset": 0,
"slot": "8",
"type": "t_mapping(t_address,t_array(t_struct(Checkpoint)48241_storage)dyn_storage)"
"type": "t_mapping(t_address,t_array(t_struct(Checkpoint)46264_storage)dyn_storage)"
},
{
"bytes": "32",
"label": "struct ERC20Votes.Checkpoint[]",
"offset": 0,
"slot": "9",
"type": "t_array(t_struct(Checkpoint)48241_storage)dyn_storage"
"type": "t_array(t_struct(Checkpoint)46264_storage)dyn_storage"
},
{
"bytes": "20",
......
......@@ -32,6 +32,6 @@
"label": "struct Types.OutputProposal[]",
"offset": 0,
"slot": "3",
"type": "t_array(t_struct(OutputProposal)86894_storage)dyn_storage"
"type": "t_array(t_struct(OutputProposal)76122_storage)dyn_storage"
}
]
\ No newline at end of file
......@@ -18,7 +18,7 @@
"label": "struct ResourceMetering.ResourceParams",
"offset": 0,
"slot": "1",
"type": "t_struct(ResourceParams)75993_storage"
"type": "t_struct(ResourceParams)66223_storage"
},
{
"bytes": "1536",
......@@ -46,7 +46,7 @@
"label": "mapping(bytes32 => struct OptimismPortal.ProvenWithdrawal)",
"offset": 0,
"slot": "52",
"type": "t_mapping(t_bytes32,t_struct(ProvenWithdrawal)75053_storage)"
"type": "t_mapping(t_bytes32,t_struct(ProvenWithdrawal)65283_storage)"
},
{
"bytes": "1",
......
......@@ -11,7 +11,7 @@
"label": "mapping(address => enum ProxyAdmin.ProxyType)",
"offset": 0,
"slot": "1",
"type": "t_mapping(t_address,t_enum(ProxyType)92990)"
"type": "t_mapping(t_address,t_enum(ProxyType)79943)"
},
{
"bytes": "32",
......@@ -25,7 +25,7 @@
"label": "contract AddressManager",
"offset": 0,
"slot": "3",
"type": "t_contract(AddressManager)84528"
"type": "t_contract(AddressManager)73949"
},
{
"bytes": "1",
......
......@@ -11,6 +11,6 @@
"label": "mapping(address => contract AddressManager)",
"offset": 0,
"slot": "1",
"type": "t_mapping(t_address,t_contract(AddressManager)84528)"
"type": "t_mapping(t_address,t_contract(AddressManager)73949)"
}
]
\ No newline at end of file
......@@ -4,7 +4,7 @@
"label": "mapping(bytes32 => struct SchemaRecord)",
"offset": 0,
"slot": "0",
"type": "t_mapping(t_bytes32,t_struct(SchemaRecord)57547_storage)"
"type": "t_mapping(t_bytes32,t_struct(SchemaRecord)57706_storage)"
},
{
"bytes": "1568",
......
[
{
"bytes": "1",
"label": "uint8",
"offset": 0,
"slot": "0",
"type": "t_uint8"
},
{
"bytes": "1",
"label": "bool",
"offset": 1,
"slot": "0",
"type": "t_bool"
}
]
\ No newline at end of file
......@@ -67,6 +67,6 @@
"label": "struct ResourceMetering.ResourceConfig",
"offset": 0,
"slot": "105",
"type": "t_struct(ResourceConfig)76006_storage"
"type": "t_struct(ResourceConfig)66236_storage"
}
]
\ No newline at end of file
// SPDX-License-Identifier: MIT
pragma solidity 0.8.15;
import { Initializable } from "@openzeppelin/contracts/proxy/utils/Initializable.sol";
import { ISemver } from "src/universal/ISemver.sol";
import { Storage } from "src/libraries/Storage.sol";
/// @custom:audit none This contracts is not yet audited.
/// @title SuperchainConfig
/// @notice The SuperchainConfig contract is used to manage configuration of global superchain values.
contract SuperchainConfig is Initializable, ISemver {
/// @notice Enum representing different types of updates.
/// @custom:value GUARDIAN Represents an update to the guardian.
enum UpdateType { GUARDIAN }
/// @notice Whether or not the Superchain is paused.
bytes32 public constant PAUSED_SLOT = bytes32(uint256(keccak256("superchainConfig.paused")) - 1);
/// @notice The address of the guardian, which can pause withdrawals from the System.
/// It can only be modified by an upgrade.
bytes32 public constant GUARDIAN_SLOT = bytes32(uint256(keccak256("superchainConfig.guardian")) - 1);
/// @notice Emitted when the pause is triggered.
/// @param identifier A string helping to identify provenance of the pause transaction.
event Paused(string identifier);
/// @notice Emitted when the pause is lifted.
event Unpaused();
/// @notice Emitted when configuration is updated.
/// @param updateType Type of update.
/// @param data Encoded update data.
event ConfigUpdate(UpdateType indexed updateType, bytes data);
/// @notice Semantic version.
/// @custom:semver 1.0.0
string public constant version = "1.0.0";
/// @notice Constructs the SuperchainConfig contract.
constructor() {
initialize({ _guardian: address(0) });
}
/// @notice Initializer.
/// @param _guardian Address of the guardian, can pause the OptimismPortal.
function initialize(address _guardian) public initializer {
_setGuardian(_guardian);
}
/// @notice Getter for the guardian address.
function guardian() public view returns (address guardian_) {
guardian_ = Storage.getAddress(GUARDIAN_SLOT);
}
/// @notice Getter for the current paused status.
function paused() public view returns (bool paused_) {
paused_ = (Storage.getUint(PAUSED_SLOT) == 1);
}
/// @notice Pauses withdrawals.
/// @param _identifier (Optional) A string to identify provenance of the pause transaction.
function pause(string memory _identifier) external {
require(msg.sender == guardian(), "SuperchainConfig: only guardian can pause");
Storage.setUint(PAUSED_SLOT, 1);
emit Paused(_identifier);
}
/// @notice Unpauses withdrawals.
function unpause() external {
require(msg.sender == guardian(), "SuperchainConfig: only guardian can unpause");
Storage.setUint(PAUSED_SLOT, 0);
emit Unpaused();
}
/// @notice Sets the guardian address. This is only callable during initialization, so an upgrade
/// will be required to change the guardian.
/// @param _guardian The new guardian address.
function _setGuardian(address _guardian) internal {
Storage.setAddress(GUARDIAN_SLOT, _guardian);
emit ConfigUpdate(UpdateType.GUARDIAN, abi.encode(_guardian));
}
}
......@@ -35,6 +35,14 @@ contract Initializer_Test is Bridge_Initializer {
// Initialize the `contracts` array with the addresses of the contracts to test, the
// calldata used to initialize them, and the storage slot of their `_initialized` flag.
// SuperchainConfig
contracts.push(
InitializeableContract({
target: address(superchainConfig),
initCalldata: abi.encodeCall(superchainConfig.initialize, (address(0))),
initializedSlotVal: deploy.loadInitializedSlot("SuperchainConfig", true)
})
);
// L1CrossDomainMessenger
contracts.push(
InitializeableContract({
......
// SPDX-License-Identifier: MIT
pragma solidity 0.8.15;
import { CommonTest } from "test/setup/CommonTest.sol";
// Libraries
import { Types } from "src/libraries/Types.sol";
import { Hashing } from "src/libraries/Hashing.sol";
// Target contract dependencies
import { Proxy } from "src/universal/Proxy.sol";
// Target contract
import { SuperchainConfig } from "src/L1/SuperchainConfig.sol";
contract SuperchainConfig_Init_Test is CommonTest {
/// @dev Tests that initialization sets the correct values. These are defined in CommonTest.sol.
function test_initialize_values_succeeds() external {
assertFalse(superchainConfig.paused());
assertEq(superchainConfig.guardian(), deploy.cfg().portalGuardian());
}
}
contract SuperchainConfig_Pause_TestFail is CommonTest {
/// @dev Tests that `pause` reverts when called by a non-guardian.
function test_pause_notGuardian_reverts() external {
assertFalse(superchainConfig.paused());
assertTrue(superchainConfig.guardian() != alice);
vm.expectRevert("SuperchainConfig: only guardian can pause");
vm.prank(alice);
superchainConfig.pause("identifier");
assertFalse(superchainConfig.paused());
}
}
contract SuperchainConfig_Pause_Test is CommonTest {
/// @dev Tests that `pause` successfully pauses
/// when called by the guardian.
function test_pause_succeeds() external {
assertFalse(superchainConfig.paused());
vm.expectEmit(address(superchainConfig));
emit Paused("identifier");
vm.prank(superchainConfig.guardian());
superchainConfig.pause("identifier");
assertTrue(superchainConfig.paused());
}
}
contract SuperchainConfig_Unpause_TestFail is CommonTest {
/// @dev Tests that `unpause` reverts when called by a non-guardian.
function test_unpause_notGuardian_reverts() external {
vm.prank(deploy.cfg().portalGuardian());
superchainConfig.pause("identifier");
assertEq(superchainConfig.paused(), true);
assertTrue(superchainConfig.guardian() != alice);
vm.expectRevert("SuperchainConfig: only guardian can unpause");
vm.prank(alice);
superchainConfig.unpause();
assertTrue(superchainConfig.paused());
}
}
contract SuperchainConfig_Unpause_Test is CommonTest {
/// @dev Tests that `unpause` successfully unpauses
/// when called by the guardian.
function test_unpause_succeeds() external {
vm.prank(deploy.cfg().portalGuardian());
superchainConfig.pause("identifier");
assertEq(superchainConfig.paused(), true);
vm.expectEmit(address(superchainConfig));
emit Unpaused();
vm.prank(deploy.cfg().portalGuardian());
superchainConfig.unpause();
assertFalse(superchainConfig.paused());
}
}
......@@ -94,4 +94,8 @@ contract Events {
uint256 amount,
bytes data
);
event Paused(string identifier);
event Unpaused();
}
......@@ -30,6 +30,7 @@ import { L1ERC721Bridge } from "src/L1/L1ERC721Bridge.sol";
import { AddressAliasHelper } from "src/vendor/AddressAliasHelper.sol";
import { Executables } from "scripts/Executables.sol";
import { Vm } from "forge-std/Vm.sol";
import { SuperchainConfig } from "src/L1/SuperchainConfig.sol";
/// @title Setup
/// @dev This contact is responsible for setting up the contracts in state. It currently
......@@ -50,6 +51,7 @@ contract Setup {
L1ERC721Bridge l1ERC721Bridge;
OptimismMintableERC20Factory l1OptimismMintableERC20Factory;
ProtocolVersions protocolVersions;
SuperchainConfig superchainConfig;
L2CrossDomainMessenger l2CrossDomainMessenger =
L2CrossDomainMessenger(payable(Predeploys.L2_CROSS_DOMAIN_MESSENGER));
......@@ -106,6 +108,7 @@ contract Setup {
l1OptimismMintableERC20Factory =
OptimismMintableERC20Factory(deploy.mustGetAddress("OptimismMintableERC20FactoryProxy"));
protocolVersions = ProtocolVersions(deploy.mustGetAddress("ProtocolVersionsProxy"));
superchainConfig = SuperchainConfig(deploy.mustGetAddress("SuperchainConfigProxy"));
vm.label(address(l2OutputOracle), "L2OutputOracle");
vm.label(deploy.mustGetAddress("L2OutputOracleProxy"), "L2OutputOracleProxy");
......@@ -124,6 +127,8 @@ contract Setup {
vm.label(deploy.mustGetAddress("OptimismMintableERC20FactoryProxy"), "OptimismMintableERC20FactoryProxy");
vm.label(address(protocolVersions), "ProtocolVersions");
vm.label(deploy.mustGetAddress("ProtocolVersionsProxy"), "ProtocolVersionsProxy");
vm.label(address(superchainConfig), "SuperchainConfig");
vm.label(deploy.mustGetAddress("SuperchainConfigProxy"), "SuperchainConfigProxy");
vm.label(AddressAliasHelper.applyL1ToL2Alias(address(l1CrossDomainMessenger)), "L1CrossDomainMessenger_aliased");
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment