From d4f9828fe6ea24e97638978e09d814f518e00c99 Mon Sep 17 00:00:00 2001 From: Michael de Hoog Date: Sat, 28 Sep 2024 20:11:08 -1000 Subject: [PATCH] Genesis configuration --- enclave/config.go | 8 ++- script/DeploySystem.s.sol | 2 +- src/DeployChain.sol | 127 ++++++++++++++++++++++---------------- src/OutputOracle.sol | 10 ++- 4 files changed, 89 insertions(+), 58 deletions(-) diff --git a/enclave/config.go b/enclave/config.go index 86149aa..6559e65 100644 --- a/enclave/config.go +++ b/enclave/config.go @@ -101,9 +101,7 @@ func (p *PerChainConfig) ToRollupConfig() *rollup.Config { func (p *PerChainConfig) ForceDefaults() { p.BlockTime = 1 p.Genesis.L2.Number = 0 - p.Genesis.SystemConfig.GasLimit = uint64(deployConfig.L2GenesisBlockGasLimit) p.Genesis.SystemConfig.Overhead = eth.Bytes32{} - p.Genesis.SystemConfig.Scalar = deployConfig.FeeScalar() } func (p *PerChainConfig) Hash() (common.Hash, error) { @@ -122,6 +120,9 @@ func (p *PerChainConfig) MarshalBinary() (data []byte, err error) { {Name: "genesisL1Number", Type: uint64Type}, {Name: "genesisL2Hash", Type: bytes32Type}, {Name: "genesisL2Time", Type: uint64Type}, + {Name: "genesisBatcherAddress", Type: addressType}, + {Name: "genesisScalar", Type: bytes32Type}, + {Name: "genesisGasLimit", Type: uint64Type}, {Name: "depositContractAddress", Type: addressType}, {Name: "l1SystemConfigAddress", Type: addressType}, } @@ -132,6 +133,9 @@ func (p *PerChainConfig) MarshalBinary() (data []byte, err error) { p.Genesis.L1.Number, p.Genesis.L2.Hash, p.Genesis.L2Time, + p.Genesis.SystemConfig.BatcherAddr, + p.Genesis.SystemConfig.Scalar, + p.Genesis.SystemConfig.GasLimit, p.DepositContractAddress, p.L1SystemConfigAddress, ) diff --git a/script/DeploySystem.s.sol b/script/DeploySystem.s.sol index 03bd7e0..14951b9 100644 --- a/script/DeploySystem.s.sol +++ b/script/DeploySystem.s.sol @@ -295,7 +295,7 @@ contract DeploySystem is Deploy { _proxy: payable(l2OutputOracleProxy), _implementation: l2OutputOracle, _innerCallData: abi.encodeCall( - OutputOracle.initialize, (0) + OutputOracle.initialize, (0, 0) ) }); diff --git a/src/DeployChain.sol b/src/DeployChain.sol index 68c45ad..ad62150 100644 --- a/src/DeployChain.sol +++ b/src/DeployChain.sol @@ -13,19 +13,15 @@ import { L1CrossDomainMessenger } from "@eth-optimism-bedrock/src/L1/L1CrossDoma import { L1ERC721Bridge } from "@eth-optimism-bedrock/src/L1/L1ERC721Bridge.sol"; import { OptimismMintableERC20Factory } from "@eth-optimism-bedrock/src/universal/OptimismMintableERC20Factory.sol"; import { ResourceMetering } from "@eth-optimism-bedrock/src/L1/ResourceMetering.sol"; +import { Hashing } from "@eth-optimism-bedrock/src/libraries/Hashing.sol"; +import { Types } from "@eth-optimism-bedrock/src/libraries/Types.sol"; +import { Constants } from "@eth-optimism-bedrock/src/libraries/Constants.sol"; contract DeployChain { - struct PerChainConfig { - uint256 chainID; - bytes32 genesisL1Hash; - uint64 genesisL1Number; - bytes32 genesisL2Hash; - uint64 genesisL2Time; - address depositContractAddress; - address l1SystemConfigAddress; - } - struct Deploy { + uint64 l1Number; + bytes32 l1Hash; + uint64 l2Time; address l2OutputOracle; address systemConfig; address optimismPortal; @@ -35,6 +31,8 @@ contract DeployChain { address optimismMintableERC20Factory; } + bytes32 public constant MESSAGE_PASSER_STORAGE_HASH = 0x8ed4baae3a927be3dea54996b4d5899f8c01e7594bf50b17dc1e741388ce3d12; + address public immutable proxyAdmin; address public immutable portal; address public immutable systemConfig; @@ -67,23 +65,17 @@ contract DeployChain { superchainConfig = _superchainConfig; } - function setupProxy(address proxy, bytes32 salt) internal returns (address instance) { - address _proxyAdmin = proxyAdmin; - /// @solidity memory-safe-assembly - assembly { - let ptr := mload(0x40) - mstore(ptr, 0x60678060095f395ff363204e1c7a60e01b5f5273000000000000000000000000) - mstore(add(ptr, 0x14), shl(0x60, proxy)) - mstore(add(ptr, 0x28), 0x6004525f5f60245f730000000000000000000000000000000000000000000000) - mstore(add(ptr, 0x31), shl(0x60, _proxyAdmin)) - mstore(add(ptr, 0x45), 0x5afa3d5f5f3e3d60201416604d573d5ffd5b5f5f365f5f51365f5f375af43d5f) - mstore(add(ptr, 0x65), 0x5f3e5f3d91606557fd5bf3000000000000000000000000000000000000000000) - instance := create2(0, ptr, 0x70, salt) - } - require(instance != address(0), "Proxy: create2 failed"); - } - - function deploy(bytes32 salt, uint256 chainID, bytes32 genesisHash) external returns (Deploy memory) { + function deploy( + bytes32 salt, + uint256 chainID, + bytes32 genesisL2Hash, + bytes32 genesisL2StateRoot, + address batcherAddress, + uint32 basefeeScalar, + uint32 blobbasefeeScalar, + uint64 gasLimit, + address unsafeBlockSigner + ) external returns (Deploy memory) { address _outputOracle = setupProxy(outputOracle, salt); address _systemConfig = setupProxy(systemConfig, salt); address _portal = setupProxy(portal, salt); @@ -92,37 +84,41 @@ contract DeployChain { address _l1ERC721Bridge = setupProxy(l1ERC721Bridge, salt); address _optimismMintableERC20Factory = setupProxy(optimismMintableERC20Factory, salt); - PerChainConfig memory config = PerChainConfig({ - chainID: chainID, - genesisL1Hash: blockhash(block.number-1), - genesisL1Number: uint64(block.number-1), - genesisL2Hash: genesisHash, - genesisL2Time: uint64(block.timestamp-2), - depositContractAddress: _portal, - l1SystemConfigAddress: _systemConfig - }); + bytes32 scalar = bytes32((uint256(0x01) << 248) | (uint256(blobbasefeeScalar) << 32) | basefeeScalar); + uint64 genesisL1Number = uint64(block.number - 1); + bytes32 genesisL1Hash = blockhash(uint256(genesisL1Number)); + uint64 genesisL2Time = uint64(block.timestamp - 2); bytes32 configHash = keccak256(abi.encodePacked( uint64(0), // version - config.chainID, - config.genesisL1Hash, - config.genesisL1Number, - config.genesisL2Hash, - config.genesisL2Time, - config.depositContractAddress, - config.l1SystemConfigAddress + chainID, + genesisL1Hash, + genesisL1Number, + genesisL2Hash, + genesisL2Time, + batcherAddress, + scalar, + gasLimit, + _portal, + _systemConfig )); - OutputOracle(_outputOracle).initialize(configHash); + bytes32 genesisOutputRoot = Hashing.hashOutputRootProof(Types.OutputRootProof({ + version: 0, + stateRoot: genesisL2StateRoot, + messagePasserStorageRoot: MESSAGE_PASSER_STORAGE_HASH, + latestBlockhash: genesisL2Hash + })); + + OutputOracle(_outputOracle).initialize(configHash, genesisOutputRoot); - SystemConfigOwnable _configTemplate = SystemConfigOwnable(systemConfig); SystemConfigOwnable(_systemConfig).initialize({ - _basefeeScalar: _configTemplate.basefeeScalar(), - _blobbasefeeScalar: _configTemplate.blobbasefeeScalar(), - _batcherHash: _configTemplate.batcherHash(), - _gasLimit: _configTemplate.gasLimit(), - _unsafeBlockSigner: _configTemplate.unsafeBlockSigner(), - _config: _configTemplate.resourceConfig(), - _batchInbox: _configTemplate.batchInbox(), + _basefeeScalar: basefeeScalar, + _blobbasefeeScalar: blobbasefeeScalar, + _batcherHash: bytes32(uint256(uint160(batcherAddress))), + _gasLimit: gasLimit, + _unsafeBlockSigner: unsafeBlockSigner, + _config: Constants.DEFAULT_RESOURCE_CONFIG(), + _batchInbox: calculateBatchInbox(chainID), _addresses: SystemConfig.Addresses({ l1CrossDomainMessenger: _l1CrossDomainMessenger, l1ERC721Bridge: _l1ERC721Bridge, @@ -162,6 +158,9 @@ contract DeployChain { ); return Deploy({ + l1Number: genesisL1Number, + l1Hash: genesisL1Hash, + l2Time: genesisL2Time, l2OutputOracle: _outputOracle, systemConfig: _systemConfig, optimismPortal: _portal, @@ -171,4 +170,28 @@ contract DeployChain { optimismMintableERC20Factory: _optimismMintableERC20Factory }); } + + function setupProxy(address proxy, bytes32 salt) internal returns (address instance) { + address _proxyAdmin = proxyAdmin; + /// @solidity memory-safe-assembly + assembly { + let ptr := mload(0x40) + mstore(ptr, 0x60678060095f395ff363204e1c7a60e01b5f5273000000000000000000000000) + mstore(add(ptr, 0x14), shl(0x60, proxy)) + mstore(add(ptr, 0x28), 0x6004525f5f60245f730000000000000000000000000000000000000000000000) + mstore(add(ptr, 0x31), shl(0x60, _proxyAdmin)) + mstore(add(ptr, 0x45), 0x5afa3d5f5f3e3d60201416604d573d5ffd5b5f5f365f5f51365f5f375af43d5f) + mstore(add(ptr, 0x65), 0x5f3e5f3d91606557fd5bf3000000000000000000000000000000000000000000) + instance := create2(0, ptr, 0x70, salt) + } + require(instance != address(0), "Proxy: create2 failed"); + } + + function calculateBatchInbox(uint256 chainID) internal returns (address) { + uint256 inbox = 0; + for (; chainID > 0; chainID /= 10) { + inbox = (inbox << 4) | (chainID % 10); + } + return address(uint160(inbox | (0xff << 152))); + } } diff --git a/src/OutputOracle.sol b/src/OutputOracle.sol index 5440d99..1442f8f 100644 --- a/src/OutputOracle.sol +++ b/src/OutputOracle.sol @@ -59,13 +59,17 @@ contract OutputOracle is Initializable, ISemver { ) { systemConfigGlobal = _systemConfigGlobal; maxOutputCount = _maxOutputCount; - initialize(0); + initialize(0, 0); } /// @notice Initializer. - function initialize(bytes32 _configHash) public initializer { + function initialize(bytes32 _configHash, bytes32 _genesisOutputRoot) public initializer { configHash = _configHash; - latestOutputIndex = maxOutputCount-1; + l2Outputs.push(Types.OutputProposal({ + outputRoot: _genesisOutputRoot, + timestamp: uint128(block.timestamp), + l2BlockNumber: uint128(0) + })); } function proposer() public view returns (address) {