From 6dbb2cf21ddd53b60ab855468028deaeadbfa74f Mon Sep 17 00:00:00 2001 From: Matt Solomon Date: Fri, 20 Sep 2024 09:53:33 -0700 Subject: [PATCH 01/15] chore: fix semver lock --- packages/contracts-bedrock/semver-lock.json | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/contracts-bedrock/semver-lock.json b/packages/contracts-bedrock/semver-lock.json index db35c5b37429..38814ce6673e 100644 --- a/packages/contracts-bedrock/semver-lock.json +++ b/packages/contracts-bedrock/semver-lock.json @@ -32,8 +32,8 @@ "sourceCodeHash": "0xde4df0f9633dc0cdb1c9f634003ea5b0f7c5c1aebc407bc1b2f44c0ecf938649" }, "src/L1/OPStackManager.sol": { - "initCodeHash": "0x4bffecbd95e63f9bd04ab8e3c6a804cc25e0cd151ebeb7f8d6b9330332e6eb20", - "sourceCodeHash": "0x850f1eacc77f1a5c680625196618bc4b4332cb68924d9eddd57c749bedcd7c94" + "initCodeHash": "0x01b766827738191bb13f15e077c107c61f0f4b3cf614e959bfb6828b6d41be20", + "sourceCodeHash": "0x9cb5418c650984d2a3e5d4a680f95aaf17b6f33a1c7a9a89effac360a65fa4a1" }, "src/L1/OptimismPortal.sol": { "initCodeHash": "0xbe2c0c81b3459014f287d8c89cdc0d27dde5d1f44e5d024fa1e4773ddc47c190", @@ -227,4 +227,3 @@ "initCodeHash": "0x00b8b883597e67e5c3548e7ba4139ed720893c0acb217dd170bec520cefdfab5", "sourceCodeHash": "0xf63aff9c38f4c5e9cdbd1f910bc002e16008a592d26c0dcc67929e0024638edd" } -} \ No newline at end of file From e3741ff193afce789b71b4ce42afeaf785a64a04 Mon Sep 17 00:00:00 2001 From: Matt Solomon Date: Fri, 20 Sep 2024 09:54:13 -0700 Subject: [PATCH 02/15] fix: no permissionless root, remove hash from 0xdead --- op-chain-ops/deployer/pipeline/opchain.go | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/op-chain-ops/deployer/pipeline/opchain.go b/op-chain-ops/deployer/pipeline/opchain.go index 90d03b028142..88a18b6333af 100644 --- a/op-chain-ops/deployer/pipeline/opchain.go +++ b/op-chain-ops/deployer/pipeline/opchain.go @@ -7,12 +7,17 @@ import ( "github.com/ethereum-optimism/optimism/op-chain-ops/deployer/opsm" "github.com/ethereum-optimism/optimism/op-chain-ops/deployer/state" - "github.com/ethereum-optimism/optimism/op-chain-ops/foundry" "github.com/ethereum-optimism/optimism/op-chain-ops/script" "github.com/ethereum/go-ethereum/common" ) -func DeployOPChain(ctx context.Context, env *Env, artifactsFS foundry.StatDirFs, intent *state.Intent, st *state.State, chainID common.Hash) error { +// PermissionedGameStartingAnchorRoots is a root of `0xdead` for the permissioned game at block 0, +// and no root for the permissionless game. It was generated with a console.log in DeployOpChain.s.sol +var PermissionedGameStartingAnchorRoots = []byte{ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x56, 0xd3, 0x26, 0xa8, 0xef, 0x15, 0x96, 0xf3, 0xd8, 0x73, 0x97, 0xc6, 0xc7, 0xb7, 0xb9, 0xda, 0xca, 0xf8, 0x68, 0x5e, 0xd9, 0x7d, 0xdd, 0x31, 0xf0, 0xaa, 0x04, 0x29, 0x4e, 0xaf, 0x9f, 0xca, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +} + +func DeployOPChain(ctx context.Context, env *Env, intent *state.Intent, st *state.State, chainID common.Hash) error { lgr := env.Logger.New("stage", "deploy-opchain") if !shouldDeployOPChain(intent, st, chainID) { From b69db30591482754c9a8ba37fab5fc270a28f4db Mon Sep 17 00:00:00 2001 From: Matt Solomon Date: Fri, 20 Sep 2024 10:31:51 -0700 Subject: [PATCH 03/15] fix: use 0xdead root properly --- op-chain-ops/deployer/pipeline/opchain.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/op-chain-ops/deployer/pipeline/opchain.go b/op-chain-ops/deployer/pipeline/opchain.go index 88a18b6333af..a70aeb15055a 100644 --- a/op-chain-ops/deployer/pipeline/opchain.go +++ b/op-chain-ops/deployer/pipeline/opchain.go @@ -11,10 +11,10 @@ import ( "github.com/ethereum/go-ethereum/common" ) -// PermissionedGameStartingAnchorRoots is a root of `0xdead` for the permissioned game at block 0, +// PermissionedGameStartingAnchorRoots is a root of bytes32(hex"dead") for the permissioned game at block 0, // and no root for the permissionless game. It was generated with a console.log in DeployOpChain.s.sol var PermissionedGameStartingAnchorRoots = []byte{ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x56, 0xd3, 0x26, 0xa8, 0xef, 0x15, 0x96, 0xf3, 0xd8, 0x73, 0x97, 0xc6, 0xc7, 0xb7, 0xb9, 0xda, 0xca, 0xf8, 0x68, 0x5e, 0xd9, 0x7d, 0xdd, 0x31, 0xf0, 0xaa, 0x04, 0x29, 0x4e, 0xaf, 0x9f, 0xca, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xde, 0xad, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, } func DeployOPChain(ctx context.Context, env *Env, intent *state.Intent, st *state.State, chainID common.Hash) error { From cb7982c938e783fb7b7e64c57f75f3ebe086dc97 Mon Sep 17 00:00:00 2001 From: Matt Solomon Date: Fri, 20 Sep 2024 13:55:12 -0600 Subject: [PATCH 04/15] feat: add remaining fault proof support --- .../scripts/DeployImplementations.s.sol | 31 +++-- .../scripts/DeployOPChain.s.sol | 38 ++++-- packages/contracts-bedrock/semver-lock.json | 4 +- .../snapshots/abi/OPStackManager.json | 10 ++ .../snapshots/abi/OPStackManagerInterop.json | 10 ++ .../storageLayout/OPStackManager.json | 27 +++-- .../storageLayout/OPStackManagerInterop.json | 27 +++-- .../src/L1/OPStackManager.sol | 111 ++++++++++++++---- 8 files changed, 195 insertions(+), 63 deletions(-) diff --git a/packages/contracts-bedrock/scripts/DeployImplementations.s.sol b/packages/contracts-bedrock/scripts/DeployImplementations.s.sol index 433b1573efe4..20b33ba8ca74 100644 --- a/packages/contracts-bedrock/scripts/DeployImplementations.s.sol +++ b/packages/contracts-bedrock/scripts/DeployImplementations.s.sol @@ -23,6 +23,7 @@ import { IPreimageOracle } from "src/cannon/interfaces/IPreimageOracle.sol"; import { MIPS } from "src/cannon/MIPS.sol"; import { DisputeGameFactory } from "src/dispute/DisputeGameFactory.sol"; import { AnchorStateRegistry } from "src/dispute/AnchorStateRegistry.sol"; +import { PermissionedDisputeGame } from "src/dispute/PermissionedDisputeGame.sol"; import { SuperchainConfig } from "src/L1/SuperchainConfig.sol"; import { ProtocolVersions } from "src/L1/ProtocolVersions.sol"; @@ -514,10 +515,11 @@ contract DeployImplementations is Script { blueprints.l1ChugSplashProxy = deployBytecode(Blueprint.blueprintDeployerBytecode(type(L1ChugSplashProxy).creationCode), salt); blueprints.resolvedDelegateProxy = deployBytecode(Blueprint.blueprintDeployerBytecode(type(ResolvedDelegateProxy).creationCode), salt); blueprints.anchorStateRegistry = deployBytecode(Blueprint.blueprintDeployerBytecode(type(AnchorStateRegistry).creationCode), salt); + blueprints.permissionedDisputeGame = deployBytecode(Blueprint.blueprintDeployerBytecode(type(PermissionedDisputeGame).creationCode), salt); vm.stopBroadcast(); // forgefmt: disable-end - OPStackManager.ImplementationSetter[] memory setters = new OPStackManager.ImplementationSetter[](7); + OPStackManager.ImplementationSetter[] memory setters = new OPStackManager.ImplementationSetter[](9); setters[0] = OPStackManager.ImplementationSetter({ name: "L1ERC721Bridge", info: OPStackManager.Implementation(address(_dio.l1ERC721BridgeImpl()), L1ERC721Bridge.initialize.selector) @@ -543,13 +545,22 @@ contract DeployImplementations is Script { name: "L1StandardBridge", info: OPStackManager.Implementation(address(_dio.l1StandardBridgeImpl()), L1StandardBridge.initialize.selector) }); - setters[6] = OPStackManager.ImplementationSetter({ name: "DisputeGameFactory", info: OPStackManager.Implementation( address(_dio.disputeGameFactoryImpl()), DisputeGameFactory.initialize.selector ) }); + setters[7] = OPStackManager.ImplementationSetter({ + name: "DelayedWETH", + info: OPStackManager.Implementation(address(_dio.delayedWETHImpl()), DelayedWETH.initialize.selector) + }); + setters[8] = OPStackManager.ImplementationSetter({ + name: "MIPS", + // MIPS is a singleton for all chains, so it doesn't need to be initialized, so the + // selector is just `bytes4(0)`. + info: OPStackManager.Implementation(address(_dio.mipsSingleton()), bytes4(0)) + }); // This call contains a broadcast to deploy OPSM which is proxied. OPStackManager opsmProxy = createOPSMContract(_dii, _dio, blueprints, release, setters); @@ -617,14 +628,14 @@ contract DeployImplementations is Script { // The fault proofs contracts are configured as follows: // | Contract | Proxied | Deployment | MCP Ready | // |-------------------------|---------|-----------------------------------|------------| - // | DisputeGameFactory | Yes | Bespoke | Yes | X - // | AnchorStateRegistry | Yes | Bespoke | No | X - // | FaultDisputeGame | No | Bespoke | No | Todo - // | PermissionedDisputeGame | No | Bespoke | No | Todo - // | DelayedWETH | Yes | Two bespoke (one per DisputeGame) | No | Todo: Proxies. - // | PreimageOracle | No | Shared | N/A | X - // | MIPS | No | Shared | N/A | X - // | OptimismPortal2 | Yes | Shared | No | X + // | DisputeGameFactory | Yes | Bespoke | Yes | + // | AnchorStateRegistry | Yes | Bespoke | No | + // | FaultDisputeGame | No | Bespoke | No | Not yet supported by OPCM + // | PermissionedDisputeGame | No | Bespoke | No | + // | DelayedWETH | Yes | Two bespoke (one per DisputeGame) | No | + // | PreimageOracle | No | Shared | N/A | + // | MIPS | No | Shared | N/A | + // | OptimismPortal2 | Yes | Shared | No | // // This script only deploys the shared contracts. The bespoke contracts are deployed by // `DeployOPChain.s.sol`. When the shared contracts are proxied, the contracts deployed here are diff --git a/packages/contracts-bedrock/scripts/DeployOPChain.s.sol b/packages/contracts-bedrock/scripts/DeployOPChain.s.sol index 50fd9060ae91..e0df48cc6029 100644 --- a/packages/contracts-bedrock/scripts/DeployOPChain.s.sol +++ b/packages/contracts-bedrock/scripts/DeployOPChain.s.sol @@ -11,6 +11,7 @@ import { BaseDeployIO } from "scripts/utils/BaseDeployIO.sol"; import { IResourceMetering } from "src/L1/interfaces/IResourceMetering.sol"; import { ISuperchainConfig } from "src/L1/interfaces/ISuperchainConfig.sol"; +import { IBigStepper } from "src/dispute/interfaces/IBigStepper.sol"; import { Constants } from "src/libraries/Constants.sol"; import { Predeploys } from "src/libraries/Predeploys.sol"; @@ -23,7 +24,7 @@ import { DisputeGameFactory } from "src/dispute/DisputeGameFactory.sol"; import { AnchorStateRegistry } from "src/dispute/AnchorStateRegistry.sol"; import { FaultDisputeGame } from "src/dispute/FaultDisputeGame.sol"; import { PermissionedDisputeGame } from "src/dispute/PermissionedDisputeGame.sol"; -import { GameType, GameTypes, Hash, OutputRoot } from "src/dispute/lib/Types.sol"; +import { Claim, GameType, GameTypes, Hash, OutputRoot } from "src/dispute/lib/Types.sol"; import { OPStackManager } from "src/L1/OPStackManager.sol"; import { OptimismPortal2 } from "src/L1/OptimismPortal2.sol"; @@ -201,7 +202,7 @@ contract DeployOPChainOutput is BaseDeployIO { address(_disputeGameFactoryProxy), address(_anchorStateRegistryProxy), address(_anchorStateRegistryImpl), - address(_faultDisputeGame), + // address(_faultDisputeGame), address(_permissionedDisputeGame), address(_delayedWETHPermissionedGameProxy), address(_delayedWETHPermissionlessGameProxy) @@ -289,8 +290,8 @@ contract DeployOPChainOutput is BaseDeployIO { // -------- Deployment Assertions -------- function assertValidDeploy(DeployOPChainInput _doi) internal { - assertValidAnchorStateRegistryProxy(_doi); assertValidAnchorStateRegistryImpl(_doi); + assertValidAnchorStateRegistryProxy(_doi); assertValidDelayedWETHs(_doi); assertValidDisputeGameFactory(_doi); assertValidL1CrossDomainMessenger(_doi); @@ -298,9 +299,23 @@ contract DeployOPChainOutput is BaseDeployIO { assertValidL1StandardBridge(_doi); assertValidOptimismMintableERC20Factory(_doi); assertValidOptimismPortal(_doi); + assertValidPermissionedDisputeGame(_doi); assertValidSystemConfig(_doi); - // TODO Other FP assertions like the dispute games, anchor state registry, etc. - // TODO add initialization assertions + } + + function assertValidPermissionedDisputeGame(DeployOPChainInput _doi) internal view { + PermissionedDisputeGame game = permissionedDisputeGame(); + + require(GameType.unwrap(game.gameType()) == GameType.unwrap(GameTypes.PERMISSIONED_CANNON), "DPG-10"); + require(Claim.unwrap(game.absolutePrestate()) == bytes32(hex"dead"), "DPG-20"); + + OPStackManager opsm = _doi.opsmProxy(); + (address mips,) = opsm.implementations(opsm.latestRelease(), "MIPS"); + require(game.vm() == IBigStepper(mips), "DPG-30"); + + require(address(game.weth()) == address(delayedWETHPermissionedGameProxy()), "DPG-40"); + require(address(game.anchorStateRegistry()) == address(anchorStateRegistryProxy()), "DPG-50"); + require(game.l2ChainId() == _doi.l2ChainId(), "DPG-60"); } function assertValidAnchorStateRegistryProxy(DeployOPChainInput) internal { @@ -436,7 +451,14 @@ contract DeployOPChainOutput is BaseDeployIO { } function assertValidDisputeGameFactory(DeployOPChainInput) internal view { - // TODO add in once FP support is added. + DisputeGameFactory factory = disputeGameFactoryProxy(); + + DeployUtils.assertInitialized({ _contractAddress: address(factory), _slot: 0, _offset: 0 }); + + require( + address(factory.gameImpls(GameTypes.PERMISSIONED_CANNON)) == address(permissionedDisputeGame()), "DF-10" + ); + require(factory.owner() == address(opChainProxyAdmin()), "DF-20"); } function assertValidDelayedWETHs(DeployOPChainInput) internal view { @@ -480,7 +502,7 @@ contract DeployOPChain is Script { vm.label(address(deployOutput.disputeGameFactoryProxy), "disputeGameFactoryProxy"); vm.label(address(deployOutput.anchorStateRegistryProxy), "anchorStateRegistryProxy"); vm.label(address(deployOutput.anchorStateRegistryImpl), "anchorStateRegistryImpl"); - vm.label(address(deployOutput.faultDisputeGame), "faultDisputeGame"); + // vm.label(address(deployOutput.faultDisputeGame), "faultDisputeGame"); vm.label(address(deployOutput.permissionedDisputeGame), "permissionedDisputeGame"); vm.label(address(deployOutput.delayedWETHPermissionedGameProxy), "delayedWETHPermissionedGameProxy"); vm.label(address(deployOutput.delayedWETHPermissionlessGameProxy), "delayedWETHPermissionlessGameProxy"); @@ -498,7 +520,7 @@ contract DeployOPChain is Script { _doo.set(_doo.disputeGameFactoryProxy.selector, address(deployOutput.disputeGameFactoryProxy)); _doo.set(_doo.anchorStateRegistryProxy.selector, address(deployOutput.anchorStateRegistryProxy)); _doo.set(_doo.anchorStateRegistryImpl.selector, address(deployOutput.anchorStateRegistryImpl)); - _doo.set(_doo.faultDisputeGame.selector, address(deployOutput.faultDisputeGame)); + // _doo.set(_doo.faultDisputeGame.selector, address(deployOutput.faultDisputeGame)); _doo.set(_doo.permissionedDisputeGame.selector, address(deployOutput.permissionedDisputeGame)); _doo.set(_doo.delayedWETHPermissionedGameProxy.selector, address(deployOutput.delayedWETHPermissionedGameProxy)); _doo.set( diff --git a/packages/contracts-bedrock/semver-lock.json b/packages/contracts-bedrock/semver-lock.json index 38814ce6673e..b59a9f557e9e 100644 --- a/packages/contracts-bedrock/semver-lock.json +++ b/packages/contracts-bedrock/semver-lock.json @@ -32,8 +32,8 @@ "sourceCodeHash": "0xde4df0f9633dc0cdb1c9f634003ea5b0f7c5c1aebc407bc1b2f44c0ecf938649" }, "src/L1/OPStackManager.sol": { - "initCodeHash": "0x01b766827738191bb13f15e077c107c61f0f4b3cf614e959bfb6828b6d41be20", - "sourceCodeHash": "0x9cb5418c650984d2a3e5d4a680f95aaf17b6f33a1c7a9a89effac360a65fa4a1" + "initCodeHash": "0xf228c25742dc07b3fafcc30d57a543e3b0015d0502caeaaac7987f3209db2285", + "sourceCodeHash": "0x894b1042de7ad7a8b26e67a8f94966fd132cb29918f8fcf7aad1bf36f4eeb606" }, "src/L1/OptimismPortal.sol": { "initCodeHash": "0xbe2c0c81b3459014f287d8c89cdc0d27dde5d1f44e5d024fa1e4773ddc47c190", diff --git a/packages/contracts-bedrock/snapshots/abi/OPStackManager.json b/packages/contracts-bedrock/snapshots/abi/OPStackManager.json index 2ad0a4d1dc2c..be671a408879 100644 --- a/packages/contracts-bedrock/snapshots/abi/OPStackManager.json +++ b/packages/contracts-bedrock/snapshots/abi/OPStackManager.json @@ -50,6 +50,11 @@ "internalType": "address", "name": "anchorStateRegistry", "type": "address" + }, + { + "internalType": "address", + "name": "permissionedDisputeGame", + "type": "address" } ], "internalType": "struct OPStackManager.Blueprints", @@ -298,6 +303,11 @@ "internalType": "address", "name": "anchorStateRegistry", "type": "address" + }, + { + "internalType": "address", + "name": "permissionedDisputeGame", + "type": "address" } ], "internalType": "struct OPStackManager.Blueprints", diff --git a/packages/contracts-bedrock/snapshots/abi/OPStackManagerInterop.json b/packages/contracts-bedrock/snapshots/abi/OPStackManagerInterop.json index 2ad0a4d1dc2c..be671a408879 100644 --- a/packages/contracts-bedrock/snapshots/abi/OPStackManagerInterop.json +++ b/packages/contracts-bedrock/snapshots/abi/OPStackManagerInterop.json @@ -50,6 +50,11 @@ "internalType": "address", "name": "anchorStateRegistry", "type": "address" + }, + { + "internalType": "address", + "name": "permissionedDisputeGame", + "type": "address" } ], "internalType": "struct OPStackManager.Blueprints", @@ -298,6 +303,11 @@ "internalType": "address", "name": "anchorStateRegistry", "type": "address" + }, + { + "internalType": "address", + "name": "permissionedDisputeGame", + "type": "address" } ], "internalType": "struct OPStackManager.Blueprints", diff --git a/packages/contracts-bedrock/snapshots/storageLayout/OPStackManager.json b/packages/contracts-bedrock/snapshots/storageLayout/OPStackManager.json index 881871a50dd1..53fc706587fe 100644 --- a/packages/contracts-bedrock/snapshots/storageLayout/OPStackManager.json +++ b/packages/contracts-bedrock/snapshots/storageLayout/OPStackManager.json @@ -13,32 +13,39 @@ "slot": "0", "type": "bool" }, - { - "bytes": "192", - "label": "blueprint", - "offset": 0, - "slot": "1", - "type": "struct OPStackManager.Blueprints" - }, { "bytes": "32", "label": "latestRelease", "offset": 0, - "slot": "7", + "slot": "1", "type": "string" }, { "bytes": "32", "label": "implementations", "offset": 0, - "slot": "8", + "slot": "2", "type": "mapping(string => mapping(string => struct OPStackManager.Implementation))" }, { "bytes": "32", "label": "systemConfigs", "offset": 0, - "slot": "9", + "slot": "3", "type": "mapping(uint256 => contract SystemConfig)" + }, + { + "bytes": "224", + "label": "blueprint", + "offset": 0, + "slot": "4", + "type": "struct OPStackManager.Blueprints" + }, + { + "bytes": "1600", + "label": "__gap", + "offset": 0, + "slot": "11", + "type": "uint256[50]" } ] \ No newline at end of file diff --git a/packages/contracts-bedrock/snapshots/storageLayout/OPStackManagerInterop.json b/packages/contracts-bedrock/snapshots/storageLayout/OPStackManagerInterop.json index 881871a50dd1..53fc706587fe 100644 --- a/packages/contracts-bedrock/snapshots/storageLayout/OPStackManagerInterop.json +++ b/packages/contracts-bedrock/snapshots/storageLayout/OPStackManagerInterop.json @@ -13,32 +13,39 @@ "slot": "0", "type": "bool" }, - { - "bytes": "192", - "label": "blueprint", - "offset": 0, - "slot": "1", - "type": "struct OPStackManager.Blueprints" - }, { "bytes": "32", "label": "latestRelease", "offset": 0, - "slot": "7", + "slot": "1", "type": "string" }, { "bytes": "32", "label": "implementations", "offset": 0, - "slot": "8", + "slot": "2", "type": "mapping(string => mapping(string => struct OPStackManager.Implementation))" }, { "bytes": "32", "label": "systemConfigs", "offset": 0, - "slot": "9", + "slot": "3", "type": "mapping(uint256 => contract SystemConfig)" + }, + { + "bytes": "224", + "label": "blueprint", + "offset": 0, + "slot": "4", + "type": "struct OPStackManager.Blueprints" + }, + { + "bytes": "1600", + "label": "__gap", + "offset": 0, + "slot": "11", + "type": "uint256[50]" } ] \ No newline at end of file diff --git a/packages/contracts-bedrock/src/L1/OPStackManager.sol b/packages/contracts-bedrock/src/L1/OPStackManager.sol index f7d71233005e..1b6d2b6d9f9f 100644 --- a/packages/contracts-bedrock/src/L1/OPStackManager.sol +++ b/packages/contracts-bedrock/src/L1/OPStackManager.sol @@ -8,6 +8,10 @@ import { Initializable } from "@openzeppelin/contracts/proxy/utils/Initializable import { ISemver } from "src/universal/interfaces/ISemver.sol"; import { IResourceMetering } from "src/L1/interfaces/IResourceMetering.sol"; +import { IBigStepper } from "src/dispute/interfaces/IBigStepper.sol"; +import { IDelayedWETH } from "src/dispute/interfaces/IDelayedWETH.sol"; +import { IAnchorStateRegistry } from "src/dispute/interfaces/IAnchorStateRegistry.sol"; +import { IDisputeGame } from "src/dispute/interfaces/IDisputeGame.sol"; import { Proxy } from "src/universal/Proxy.sol"; import { ProxyAdmin } from "src/universal/ProxyAdmin.sol"; @@ -23,7 +27,7 @@ import { DisputeGameFactory } from "src/dispute/DisputeGameFactory.sol"; import { AnchorStateRegistry } from "src/dispute/AnchorStateRegistry.sol"; import { FaultDisputeGame } from "src/dispute/FaultDisputeGame.sol"; import { PermissionedDisputeGame } from "src/dispute/PermissionedDisputeGame.sol"; -import { GameTypes } from "src/dispute/lib/Types.sol"; +import { Claim, Duration, GameType, GameTypes } from "src/dispute/lib/Types.sol"; import { SuperchainConfig } from "src/L1/SuperchainConfig.sol"; import { ProtocolVersions } from "src/L1/ProtocolVersions.sol"; @@ -105,6 +109,7 @@ contract OPStackManager is ISemver, Initializable { address l1ChugSplashProxy; address resolvedDelegateProxy; address anchorStateRegistry; + address permissionedDisputeGame; } /// @notice Inputs required when initializing the OPStackManager. To avoid 'StackTooDeep' errors, @@ -118,8 +123,8 @@ contract OPStackManager is ISemver, Initializable { // -------- Constants and Variables -------- - /// @custom:semver 1.0.0-beta.4 - string public constant version = "1.0.0-beta.4"; + /// @custom:semver 1.0.0-beta.5 + string public constant version = "1.0.0-beta.5"; /// @notice Address of the SuperchainConfig contract shared by all chains. SuperchainConfig public immutable superchainConfig; @@ -127,12 +132,6 @@ contract OPStackManager is ISemver, Initializable { /// @notice Address of the ProtocolVersions contract shared by all chains. ProtocolVersions public immutable protocolVersions; - /// @notice Addresses of the Blueprint contracts. - /// This is internal because if public the autogenerated getter method would return a tuple of - /// addresses, but we want it to return a struct. This is also set via `initialize` because - /// we can't make this an immutable variable as it is a non-value type. - Blueprints internal blueprint; - /// @notice The latest release of the OP Stack Manager, as a string of the format `op-contracts/vX.Y.Z`. string public latestRelease; @@ -142,6 +141,16 @@ contract OPStackManager is ISemver, Initializable { /// @notice Maps an L2 Chain ID to the SystemConfig for that chain. mapping(uint256 => SystemConfig) public systemConfigs; + /// @notice Addresses of the Blueprint contracts. + /// This is internal because if public the autogenerated getter method would return a tuple of + /// addresses, but we want it to return a struct. This is also set via `initialize` because + /// we can't make this an immutable variable as it is a non-value type. + Blueprints internal blueprint; + + /// @notice Storage gap for future modifications, so we can expand the number of blueprints + /// without affecting other storage variables. + uint256[50] private __gap; + // -------- Events -------- /// @notice Emitted when a new OP Stack chain is deployed. @@ -206,16 +215,6 @@ contract OPStackManager is ISemver, Initializable { bytes32 salt = bytes32(_input.l2ChainId); DeployOutput memory output; - // -------- TODO: Placeholders -------- - // For contracts we don't yet deploy, we set the outputs to dummy proxies so they have code to pass assertions. - // We do these first, that way the disputeGameFactoryProxy is set when passed to the SystemConfig input. - output.faultDisputeGame = FaultDisputeGame(deployProxy(l2ChainId, output.opChainProxyAdmin, "5")); - output.permissionedDisputeGame = PermissionedDisputeGame(deployProxy(l2ChainId, output.opChainProxyAdmin, "6")); - output.delayedWETHPermissionedGameProxy = - DelayedWETH(payable(deployProxy(l2ChainId, output.opChainProxyAdmin, "7"))); - output.delayedWETHPermissionlessGameProxy = - DelayedWETH(payable(deployProxy(l2ChainId, output.opChainProxyAdmin, "8"))); - // -------- Deploy Chain Singletons -------- // The ProxyAdmin is the owner of all proxies for the chain. We temporarily set the owner to @@ -266,6 +265,19 @@ contract OPStackManager is ISemver, Initializable { Blueprint.deployFrom(blueprint.anchorStateRegistry, salt, abi.encode(output.disputeGameFactoryProxy)) ); + // We have two delayed WETH contracts per chain, one for each of the permissioned and permissionless games. + output.delayedWETHPermissionlessGameProxy = + DelayedWETH(payable(deployProxy(l2ChainId, output.opChainProxyAdmin, "DelayedWETHPermissionlessGame"))); + output.delayedWETHPermissionedGameProxy = + DelayedWETH(payable(deployProxy(l2ChainId, output.opChainProxyAdmin, "DelayedWETHPermissionedGame"))); + + // While not a proxy, we deploy the PermissionedDisputeGame here as well because it's bespoke per chain. + output.permissionedDisputeGame = PermissionedDisputeGame( + Blueprint.deployFrom( + blueprint.permissionedDisputeGame, salt, encodePermissionedDisputeGameConstructor(_input, output) + ) + ); + // -------- Set and Initialize Proxy Implementations -------- Implementation memory impl; bytes memory data; @@ -294,10 +306,20 @@ contract OPStackManager is ISemver, Initializable { data = encodeL1StandardBridgeInitializer(impl.initializer, output); upgradeAndCall(output.opChainProxyAdmin, address(output.l1StandardBridgeProxy), impl.logic, data); - // TODO: also call setImplementation() once the dispute games are deployed. + impl = getLatestImplementation("DelayedWETH"); + data = encodeDelayedWETHInitializer(impl.initializer, _input); + upgradeAndCall(output.opChainProxyAdmin, address(output.delayedWETHPermissionedGameProxy), impl.logic, data); + upgradeAndCall(output.opChainProxyAdmin, address(output.delayedWETHPermissionlessGameProxy), impl.logic, data); + + // We set the initial owner to this contract, set game implementations, then transfer ownership. impl = getLatestImplementation("DisputeGameFactory"); data = encodeDisputeGameFactoryInitializer(impl.initializer, _input); upgradeAndCall(output.opChainProxyAdmin, address(output.disputeGameFactoryProxy), impl.logic, data); + output.disputeGameFactoryProxy.setImplementation( + GameTypes.PERMISSIONED_CANNON, IDisputeGame(address(output.permissionedDisputeGame)) + ); + output.disputeGameFactoryProxy.setInitBond(GameTypes.PERMISSIONED_CANNON, 0.08 ether); + output.disputeGameFactoryProxy.transferOwnership(address(output.opChainProxyAdmin)); impl.logic = address(output.anchorStateRegistryImpl); impl.initializer = AnchorStateRegistry.initialize.selector; @@ -387,7 +409,11 @@ contract OPStackManager is ISemver, Initializable { _output; // TODO make GameTypes.CANNON an input once FPs are supported return abi.encodeWithSelector( - _selector, _output.disputeGameFactoryProxy, _output.systemConfigProxy, superchainConfig, GameTypes.CANNON + _selector, + _output.disputeGameFactoryProxy, + _output.systemConfigProxy, + superchainConfig, + GameTypes.PERMISSIONED_CANNON ); } @@ -463,14 +489,16 @@ contract OPStackManager is ISemver, Initializable { function encodeDisputeGameFactoryInitializer( bytes4 _selector, - DeployInput memory _input + DeployInput memory ) internal view virtual returns (bytes memory) { - return abi.encodeWithSelector(_selector, _input.roles.opChainProxyAdminOwner); + // This contract must be the initial owner so we can set game implementations, then + // ownership is transferred after. + return abi.encodeWithSelector(_selector, address(this)); } function encodeAnchorStateRegistryInitializer( @@ -488,6 +516,43 @@ contract OPStackManager is ISemver, Initializable { return abi.encodeWithSelector(_selector, startingAnchorRoots, superchainConfig); } + function encodeDelayedWETHInitializer( + bytes4 _selector, + DeployInput memory _input + ) + internal + view + virtual + returns (bytes memory) + { + return abi.encodeWithSelector(_selector, _input.roles.opChainProxyAdminOwner, superchainConfig); + } + + function encodePermissionedDisputeGameConstructor( + DeployInput memory _input, + DeployOutput memory _output + ) + internal + view + virtual + returns (bytes memory) + { + return abi.encode( + GameType.wrap(1), + Claim.wrap(bytes32(hex"dead")), // absolutePrestate + 73, // maxGameDepth + 30, // splitDepth + Duration.wrap(3 hours), // clockExtension + Duration.wrap(3.5 days), // maxClockDuration + IBigStepper(getLatestImplementation("MIPS").logic), + IDelayedWETH(payable(address(_output.delayedWETHPermissionedGameProxy))), + IAnchorStateRegistry(address(_output.anchorStateRegistryProxy)), + _input.l2ChainId, + _input.roles.proposer, + _input.roles.challenger + ); + } + /// @notice Returns default, standard config arguments for the SystemConfig initializer. /// This is used by subclasses to reduce code duplication. function defaultSystemConfigParams( From ff3cb575ed107c5b12d2d3c5e63c017c7087e576 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Mon, 23 Sep 2024 12:49:15 -0400 Subject: [PATCH 05/15] chore: Update semver-lock --- packages/contracts-bedrock/semver-lock.json | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/contracts-bedrock/semver-lock.json b/packages/contracts-bedrock/semver-lock.json index b59a9f557e9e..3618b94b86f0 100644 --- a/packages/contracts-bedrock/semver-lock.json +++ b/packages/contracts-bedrock/semver-lock.json @@ -32,8 +32,8 @@ "sourceCodeHash": "0xde4df0f9633dc0cdb1c9f634003ea5b0f7c5c1aebc407bc1b2f44c0ecf938649" }, "src/L1/OPStackManager.sol": { - "initCodeHash": "0xf228c25742dc07b3fafcc30d57a543e3b0015d0502caeaaac7987f3209db2285", - "sourceCodeHash": "0x894b1042de7ad7a8b26e67a8f94966fd132cb29918f8fcf7aad1bf36f4eeb606" + "initCodeHash": "0x3e13faf04ca25b6c76c79072c2048af38305c360ec3ff1ad9ad71f16180b5518", + "sourceCodeHash": "0xb1b01aae0dfcb1cff037a73ab1a043303e36b4577d5d6a98858b560be6a9488c" }, "src/L1/OptimismPortal.sol": { "initCodeHash": "0xbe2c0c81b3459014f287d8c89cdc0d27dde5d1f44e5d024fa1e4773ddc47c190", @@ -227,3 +227,4 @@ "initCodeHash": "0x00b8b883597e67e5c3548e7ba4139ed720893c0acb217dd170bec520cefdfab5", "sourceCodeHash": "0xf63aff9c38f4c5e9cdbd1f910bc002e16008a592d26c0dcc67929e0024638edd" } +} \ No newline at end of file From 4aba7ec5de42198c9c05c7f9814ecf9916333f85 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Mon, 23 Sep 2024 13:09:36 -0400 Subject: [PATCH 06/15] fix: Remove extra anchor root definition and restore aritfactsFs argument --- op-chain-ops/deployer/pipeline/opchain.go | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/op-chain-ops/deployer/pipeline/opchain.go b/op-chain-ops/deployer/pipeline/opchain.go index a70aeb15055a..90d03b028142 100644 --- a/op-chain-ops/deployer/pipeline/opchain.go +++ b/op-chain-ops/deployer/pipeline/opchain.go @@ -7,17 +7,12 @@ import ( "github.com/ethereum-optimism/optimism/op-chain-ops/deployer/opsm" "github.com/ethereum-optimism/optimism/op-chain-ops/deployer/state" + "github.com/ethereum-optimism/optimism/op-chain-ops/foundry" "github.com/ethereum-optimism/optimism/op-chain-ops/script" "github.com/ethereum/go-ethereum/common" ) -// PermissionedGameStartingAnchorRoots is a root of bytes32(hex"dead") for the permissioned game at block 0, -// and no root for the permissionless game. It was generated with a console.log in DeployOpChain.s.sol -var PermissionedGameStartingAnchorRoots = []byte{ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xde, 0xad, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -} - -func DeployOPChain(ctx context.Context, env *Env, intent *state.Intent, st *state.State, chainID common.Hash) error { +func DeployOPChain(ctx context.Context, env *Env, artifactsFS foundry.StatDirFs, intent *state.Intent, st *state.State, chainID common.Hash) error { lgr := env.Logger.New("stage", "deploy-opchain") if !shouldDeployOPChain(intent, st, chainID) { From 288602ddbe6e99b678bb0bb820905a55a5affdb5 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Mon, 23 Sep 2024 16:29:30 -0400 Subject: [PATCH 07/15] feat: Add wip big blueprint code --- .../scripts/DeployImplementations.s.sol | 19 +++++++++++++- .../src/L1/OPStackManager.sol | 8 ++++-- .../src/libraries/Blueprint.sol | 26 +++++++++++++++++++ 3 files changed, 50 insertions(+), 3 deletions(-) diff --git a/packages/contracts-bedrock/scripts/DeployImplementations.s.sol b/packages/contracts-bedrock/scripts/DeployImplementations.s.sol index 20b33ba8ca74..3d15943f60d1 100644 --- a/packages/contracts-bedrock/scripts/DeployImplementations.s.sol +++ b/packages/contracts-bedrock/scripts/DeployImplementations.s.sol @@ -515,7 +515,7 @@ contract DeployImplementations is Script { blueprints.l1ChugSplashProxy = deployBytecode(Blueprint.blueprintDeployerBytecode(type(L1ChugSplashProxy).creationCode), salt); blueprints.resolvedDelegateProxy = deployBytecode(Blueprint.blueprintDeployerBytecode(type(ResolvedDelegateProxy).creationCode), salt); blueprints.anchorStateRegistry = deployBytecode(Blueprint.blueprintDeployerBytecode(type(AnchorStateRegistry).creationCode), salt); - blueprints.permissionedDisputeGame = deployBytecode(Blueprint.blueprintDeployerBytecode(type(PermissionedDisputeGame).creationCode), salt); + (blueprints.permissionedDisputeGame1, blueprints.permissionedDisputeGame2) = this.deployBigBytecode(Blueprint.blueprintDeployerBytecode(type(PermissionedDisputeGame).creationCode), salt); vm.stopBroadcast(); // forgefmt: disable-end @@ -742,6 +742,23 @@ contract DeployImplementations is Script { } require(newContract_ != address(0), "DeployImplementations: create2 failed"); } + + function deployBigBytecode( + bytes calldata _bytecode, + bytes32 _salt + ) + external + returns (address newContract1_, address newContract2_) + { + // Preamble needs 3 bytes. + uint256 maxInitCodeSize = 24576 - 3; + require(_bytecode.length > maxInitCodeSize, "DeployImplementations: Use deployBytecode instead"); + + bytes memory part1 = _bytecode[0:maxInitCodeSize - 1]; + bytes memory part2 = _bytecode[maxInitCodeSize:_bytecode.length - 1]; + newContract1_ = deployBytecode(Blueprint.blueprintDeployerBytecode(part1), _salt); + newContract2_ = deployBytecode(Blueprint.blueprintDeployerBytecode(part2), _salt); + } } // Similar to how DeploySuperchain.s.sol contains a lot of comments to thoroughly document the script diff --git a/packages/contracts-bedrock/src/L1/OPStackManager.sol b/packages/contracts-bedrock/src/L1/OPStackManager.sol index 1b6d2b6d9f9f..e6f7f758fbc0 100644 --- a/packages/contracts-bedrock/src/L1/OPStackManager.sol +++ b/packages/contracts-bedrock/src/L1/OPStackManager.sol @@ -109,7 +109,8 @@ contract OPStackManager is ISemver, Initializable { address l1ChugSplashProxy; address resolvedDelegateProxy; address anchorStateRegistry; - address permissionedDisputeGame; + address permissionedDisputeGame1; + address permissionedDisputeGame2; } /// @notice Inputs required when initializing the OPStackManager. To avoid 'StackTooDeep' errors, @@ -274,7 +275,10 @@ contract OPStackManager is ISemver, Initializable { // While not a proxy, we deploy the PermissionedDisputeGame here as well because it's bespoke per chain. output.permissionedDisputeGame = PermissionedDisputeGame( Blueprint.deployFrom( - blueprint.permissionedDisputeGame, salt, encodePermissionedDisputeGameConstructor(_input, output) + blueprint.permissionedDisputeGame1, + blueprint.permissionedDisputeGame2, + salt, + encodePermissionedDisputeGameConstructor(_input, output) ) ); diff --git a/packages/contracts-bedrock/src/libraries/Blueprint.sol b/packages/contracts-bedrock/src/libraries/Blueprint.sol index 2e0979e1c6bf..725f7a97d332 100644 --- a/packages/contracts-bedrock/src/libraries/Blueprint.sol +++ b/packages/contracts-bedrock/src/libraries/Blueprint.sol @@ -112,6 +112,32 @@ library Blueprint { if (newContract_ == address(0)) revert DeploymentFailed(); } + /// @notice Parses the code at two target addresses as individual blueprints, concatentates them and then deploys + /// the resulting initcode with the given `_data` appended, i.e. `_data` is the ABI-encoded constructor arguments. + function deployFrom( + address _target1, + address _target2, + bytes32 _salt, + bytes memory _data + ) + internal + returns (address newContract_) + { + Preamble memory preamble1 = parseBlueprintPreamble(address(_target1).code); + if (preamble1.ercVersion != 0) revert UnsupportedERCVersion(preamble1.ercVersion); + if (preamble1.preambleData.length != 0) revert UnexpectedPreambleData(preamble1.preambleData); + + Preamble memory preamble2 = parseBlueprintPreamble(address(_target2).code); + if (preamble2.ercVersion != 0) revert UnsupportedERCVersion(preamble2.ercVersion); + if (preamble2.preambleData.length != 0) revert UnexpectedPreambleData(preamble2.preambleData); + + bytes memory initcode = bytes.concat(preamble1.initcode, preamble2.initcode, _data); + assembly ("memory-safe") { + newContract_ := create2(0, add(initcode, 0x20), mload(initcode), _salt) + } + if (newContract_ == address(0)) revert DeploymentFailed(); + } + /// @notice Convert a bytes array to a uint256. function bytesToUint(bytes memory _b) internal pure returns (uint256) { if (_b.length > 32) revert BytesArrayTooLong(); From 8dc07c17b302e0e25fe5d2b8d4a5774e0d41de5d Mon Sep 17 00:00:00 2001 From: Maurelian Date: Mon, 23 Sep 2024 16:35:18 -0400 Subject: [PATCH 08/15] Don't wrap input to deployBigBytecode with preamble --- packages/contracts-bedrock/scripts/DeployImplementations.s.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/contracts-bedrock/scripts/DeployImplementations.s.sol b/packages/contracts-bedrock/scripts/DeployImplementations.s.sol index 3d15943f60d1..590cecdf5e04 100644 --- a/packages/contracts-bedrock/scripts/DeployImplementations.s.sol +++ b/packages/contracts-bedrock/scripts/DeployImplementations.s.sol @@ -515,7 +515,7 @@ contract DeployImplementations is Script { blueprints.l1ChugSplashProxy = deployBytecode(Blueprint.blueprintDeployerBytecode(type(L1ChugSplashProxy).creationCode), salt); blueprints.resolvedDelegateProxy = deployBytecode(Blueprint.blueprintDeployerBytecode(type(ResolvedDelegateProxy).creationCode), salt); blueprints.anchorStateRegistry = deployBytecode(Blueprint.blueprintDeployerBytecode(type(AnchorStateRegistry).creationCode), salt); - (blueprints.permissionedDisputeGame1, blueprints.permissionedDisputeGame2) = this.deployBigBytecode(Blueprint.blueprintDeployerBytecode(type(PermissionedDisputeGame).creationCode), salt); + (blueprints.permissionedDisputeGame1, blueprints.permissionedDisputeGame2) = this.deployBigBytecode(type(PermissionedDisputeGame).creationCode, salt); vm.stopBroadcast(); // forgefmt: disable-end From d7b4f11eca50d910aad687d92ac38edbd4a5ccb9 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Mon, 23 Sep 2024 16:55:17 -0400 Subject: [PATCH 09/15] fix: off by one in deployBigBytecode --- .../contracts-bedrock/scripts/DeployImplementations.s.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/contracts-bedrock/scripts/DeployImplementations.s.sol b/packages/contracts-bedrock/scripts/DeployImplementations.s.sol index 590cecdf5e04..59d199c884a1 100644 --- a/packages/contracts-bedrock/scripts/DeployImplementations.s.sol +++ b/packages/contracts-bedrock/scripts/DeployImplementations.s.sol @@ -754,8 +754,8 @@ contract DeployImplementations is Script { uint256 maxInitCodeSize = 24576 - 3; require(_bytecode.length > maxInitCodeSize, "DeployImplementations: Use deployBytecode instead"); - bytes memory part1 = _bytecode[0:maxInitCodeSize - 1]; - bytes memory part2 = _bytecode[maxInitCodeSize:_bytecode.length - 1]; + bytes memory part1 = _bytecode[0:maxInitCodeSize]; + bytes memory part2 = _bytecode[maxInitCodeSize:_bytecode.length]; newContract1_ = deployBytecode(Blueprint.blueprintDeployerBytecode(part1), _salt); newContract2_ = deployBytecode(Blueprint.blueprintDeployerBytecode(part2), _salt); } From 02ff983e350dae14f705f381b16f702ff919c27e Mon Sep 17 00:00:00 2001 From: Maurelian Date: Mon, 23 Sep 2024 17:08:54 -0400 Subject: [PATCH 10/15] feat: more gas efficient blueprint deployment for permissioned game --- .../scripts/DeployImplementations.s.sol | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/packages/contracts-bedrock/scripts/DeployImplementations.s.sol b/packages/contracts-bedrock/scripts/DeployImplementations.s.sol index 59d199c884a1..69af4b1a377e 100644 --- a/packages/contracts-bedrock/scripts/DeployImplementations.s.sol +++ b/packages/contracts-bedrock/scripts/DeployImplementations.s.sol @@ -754,10 +754,11 @@ contract DeployImplementations is Script { uint256 maxInitCodeSize = 24576 - 3; require(_bytecode.length > maxInitCodeSize, "DeployImplementations: Use deployBytecode instead"); - bytes memory part1 = _bytecode[0:maxInitCodeSize]; - bytes memory part2 = _bytecode[maxInitCodeSize:_bytecode.length]; - newContract1_ = deployBytecode(Blueprint.blueprintDeployerBytecode(part1), _salt); - newContract2_ = deployBytecode(Blueprint.blueprintDeployerBytecode(part2), _salt); + bytes memory part1 = Blueprint.blueprintDeployerBytecode(_bytecode[0:maxInitCodeSize]); + bytes memory part2 = Blueprint.blueprintDeployerBytecode(_bytecode[maxInitCodeSize:_bytecode.length]); + + newContract1_ = deployBytecode(part1, _salt); + newContract2_ = deployBytecode(part2, _salt); } } From 4497f8ec721ad9822ee4f342a9e2e3269974aec5 Mon Sep 17 00:00:00 2001 From: Matthew Slipper Date: Mon, 23 Sep 2024 16:52:38 -0600 Subject: [PATCH 11/15] Get the big deployments working --- .../deployer/integration_test/apply_test.go | 5 ++++- .../scripts/DeployImplementations.s.sol | 13 ++++++++----- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/op-chain-ops/deployer/integration_test/apply_test.go b/op-chain-ops/deployer/integration_test/apply_test.go index 6d673ed03791..58b55801e9ce 100644 --- a/op-chain-ops/deployer/integration_test/apply_test.go +++ b/op-chain-ops/deployer/integration_test/apply_test.go @@ -27,6 +27,8 @@ import ( const TestParams = ` participants: - el_type: geth + el_extra_params: + - "--gcmode=archive" cl_type: lighthouse network_params: prefunded_accounts: '{ "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266": { "balance": "1000000ETH" } }' @@ -41,6 +43,7 @@ network_params: }' network_id: "77799777" seconds_per_slot: 3 + genesis_delay: 0 ` type deployerKey struct{} @@ -56,7 +59,7 @@ func (d *deployerKey) String() string { func TestEndToEndApply(t *testing.T) { kurtosisutil.Test(t) - lgr := testlog.Logger(t, slog.LevelInfo) + lgr := testlog.Logger(t, slog.LevelDebug) ctx, cancel := context.WithCancel(context.Background()) defer cancel() diff --git a/packages/contracts-bedrock/scripts/DeployImplementations.s.sol b/packages/contracts-bedrock/scripts/DeployImplementations.s.sol index 69af4b1a377e..81cafa89c272 100644 --- a/packages/contracts-bedrock/scripts/DeployImplementations.s.sol +++ b/packages/contracts-bedrock/scripts/DeployImplementations.s.sol @@ -10,6 +10,7 @@ import { ISuperchainConfig } from "src/L1/interfaces/ISuperchainConfig.sol"; import { Constants } from "src/libraries/Constants.sol"; import { Predeploys } from "src/libraries/Predeploys.sol"; +import { Bytes } from "src/libraries/Bytes.sol"; import { ProxyAdmin } from "src/universal/ProxyAdmin.sol"; import { Proxy } from "src/universal/Proxy.sol"; @@ -515,7 +516,7 @@ contract DeployImplementations is Script { blueprints.l1ChugSplashProxy = deployBytecode(Blueprint.blueprintDeployerBytecode(type(L1ChugSplashProxy).creationCode), salt); blueprints.resolvedDelegateProxy = deployBytecode(Blueprint.blueprintDeployerBytecode(type(ResolvedDelegateProxy).creationCode), salt); blueprints.anchorStateRegistry = deployBytecode(Blueprint.blueprintDeployerBytecode(type(AnchorStateRegistry).creationCode), salt); - (blueprints.permissionedDisputeGame1, blueprints.permissionedDisputeGame2) = this.deployBigBytecode(type(PermissionedDisputeGame).creationCode, salt); + (blueprints.permissionedDisputeGame1, blueprints.permissionedDisputeGame2) = deployBigBytecode(type(PermissionedDisputeGame).creationCode, salt); vm.stopBroadcast(); // forgefmt: disable-end @@ -744,18 +745,20 @@ contract DeployImplementations is Script { } function deployBigBytecode( - bytes calldata _bytecode, + bytes memory _bytecode, bytes32 _salt ) - external + public returns (address newContract1_, address newContract2_) { // Preamble needs 3 bytes. uint256 maxInitCodeSize = 24576 - 3; require(_bytecode.length > maxInitCodeSize, "DeployImplementations: Use deployBytecode instead"); - bytes memory part1 = Blueprint.blueprintDeployerBytecode(_bytecode[0:maxInitCodeSize]); - bytes memory part2 = Blueprint.blueprintDeployerBytecode(_bytecode[maxInitCodeSize:_bytecode.length]); + bytes memory part1Slice = Bytes.slice(_bytecode, 0, maxInitCodeSize); + bytes memory part1 = Blueprint.blueprintDeployerBytecode(part1Slice); + bytes memory part2Slice = Bytes.slice(_bytecode, maxInitCodeSize, _bytecode.length - maxInitCodeSize); + bytes memory part2 = Blueprint.blueprintDeployerBytecode(part2Slice); newContract1_ = deployBytecode(part1, _salt); newContract2_ = deployBytecode(part2, _salt); From a13223688ee875e51dfbd490051af3a1c8eb88b4 Mon Sep 17 00:00:00 2001 From: Matt Solomon Date: Mon, 23 Sep 2024 17:02:35 -0700 Subject: [PATCH 12/15] perf: more efficient preamble parsing --- packages/contracts-bedrock/semver-lock.json | 4 +-- .../snapshots/abi/OPStackManager.json | 14 ++++++++-- .../snapshots/abi/OPStackManagerInterop.json | 14 ++++++++-- .../storageLayout/OPStackManager.json | 4 +-- .../storageLayout/OPStackManagerInterop.json | 4 +-- .../src/libraries/Blueprint.sol | 27 +++++++++++++++---- .../test/libraries/Blueprint.t.sol | 2 +- 7 files changed, 53 insertions(+), 16 deletions(-) diff --git a/packages/contracts-bedrock/semver-lock.json b/packages/contracts-bedrock/semver-lock.json index 3618b94b86f0..fdba023b82ab 100644 --- a/packages/contracts-bedrock/semver-lock.json +++ b/packages/contracts-bedrock/semver-lock.json @@ -32,8 +32,8 @@ "sourceCodeHash": "0xde4df0f9633dc0cdb1c9f634003ea5b0f7c5c1aebc407bc1b2f44c0ecf938649" }, "src/L1/OPStackManager.sol": { - "initCodeHash": "0x3e13faf04ca25b6c76c79072c2048af38305c360ec3ff1ad9ad71f16180b5518", - "sourceCodeHash": "0xb1b01aae0dfcb1cff037a73ab1a043303e36b4577d5d6a98858b560be6a9488c" + "initCodeHash": "0xc7f2c86b47f1a74532979fd229a4bb0864b9b0026f29a198d15db71cab739093", + "sourceCodeHash": "0x76dc02823148d0c104828bb3355a3bd8d2e60357643b592e6a789e090b08f954" }, "src/L1/OptimismPortal.sol": { "initCodeHash": "0xbe2c0c81b3459014f287d8c89cdc0d27dde5d1f44e5d024fa1e4773ddc47c190", diff --git a/packages/contracts-bedrock/snapshots/abi/OPStackManager.json b/packages/contracts-bedrock/snapshots/abi/OPStackManager.json index be671a408879..97aec32ac51d 100644 --- a/packages/contracts-bedrock/snapshots/abi/OPStackManager.json +++ b/packages/contracts-bedrock/snapshots/abi/OPStackManager.json @@ -53,7 +53,12 @@ }, { "internalType": "address", - "name": "permissionedDisputeGame", + "name": "permissionedDisputeGame1", + "type": "address" + }, + { + "internalType": "address", + "name": "permissionedDisputeGame2", "type": "address" } ], @@ -306,7 +311,12 @@ }, { "internalType": "address", - "name": "permissionedDisputeGame", + "name": "permissionedDisputeGame1", + "type": "address" + }, + { + "internalType": "address", + "name": "permissionedDisputeGame2", "type": "address" } ], diff --git a/packages/contracts-bedrock/snapshots/abi/OPStackManagerInterop.json b/packages/contracts-bedrock/snapshots/abi/OPStackManagerInterop.json index be671a408879..97aec32ac51d 100644 --- a/packages/contracts-bedrock/snapshots/abi/OPStackManagerInterop.json +++ b/packages/contracts-bedrock/snapshots/abi/OPStackManagerInterop.json @@ -53,7 +53,12 @@ }, { "internalType": "address", - "name": "permissionedDisputeGame", + "name": "permissionedDisputeGame1", + "type": "address" + }, + { + "internalType": "address", + "name": "permissionedDisputeGame2", "type": "address" } ], @@ -306,7 +311,12 @@ }, { "internalType": "address", - "name": "permissionedDisputeGame", + "name": "permissionedDisputeGame1", + "type": "address" + }, + { + "internalType": "address", + "name": "permissionedDisputeGame2", "type": "address" } ], diff --git a/packages/contracts-bedrock/snapshots/storageLayout/OPStackManager.json b/packages/contracts-bedrock/snapshots/storageLayout/OPStackManager.json index 53fc706587fe..c22ed7c2c8da 100644 --- a/packages/contracts-bedrock/snapshots/storageLayout/OPStackManager.json +++ b/packages/contracts-bedrock/snapshots/storageLayout/OPStackManager.json @@ -35,7 +35,7 @@ "type": "mapping(uint256 => contract SystemConfig)" }, { - "bytes": "224", + "bytes": "256", "label": "blueprint", "offset": 0, "slot": "4", @@ -45,7 +45,7 @@ "bytes": "1600", "label": "__gap", "offset": 0, - "slot": "11", + "slot": "12", "type": "uint256[50]" } ] \ No newline at end of file diff --git a/packages/contracts-bedrock/snapshots/storageLayout/OPStackManagerInterop.json b/packages/contracts-bedrock/snapshots/storageLayout/OPStackManagerInterop.json index 53fc706587fe..c22ed7c2c8da 100644 --- a/packages/contracts-bedrock/snapshots/storageLayout/OPStackManagerInterop.json +++ b/packages/contracts-bedrock/snapshots/storageLayout/OPStackManagerInterop.json @@ -35,7 +35,7 @@ "type": "mapping(uint256 => contract SystemConfig)" }, { - "bytes": "224", + "bytes": "256", "label": "blueprint", "offset": 0, "slot": "4", @@ -45,7 +45,7 @@ "bytes": "1600", "label": "__gap", "offset": 0, - "slot": "11", + "slot": "12", "type": "uint256[50]" } ] \ No newline at end of file diff --git a/packages/contracts-bedrock/src/libraries/Blueprint.sol b/packages/contracts-bedrock/src/libraries/Blueprint.sol index 725f7a97d332..6fdde0ef30ff 100644 --- a/packages/contracts-bedrock/src/libraries/Blueprint.sol +++ b/packages/contracts-bedrock/src/libraries/Blueprint.sol @@ -56,7 +56,7 @@ library Blueprint { /// @notice Given bytecode as a sequence of bytes, parse the blueprint preamble and deconstruct /// the bytecode into the ERC version, preamble data and initcode. Reverts if the bytecode is /// not a valid blueprint contract according to ERC-5202. - function parseBlueprintPreamble(bytes memory _bytecode) internal pure returns (Preamble memory) { + function parseBlueprintPreamble(bytes memory _bytecode) internal view returns (Preamble memory) { if (_bytecode.length < 2 || _bytecode[0] != 0xFE || _bytecode[1] != 0x71) { revert NotABlueprint(); } @@ -77,18 +77,35 @@ library Blueprint { bytes memory preambleData = new bytes(dataLength); if (nLengthBytes != 0) { uint256 dataStart = 3 + nLengthBytes; + // We don't currently use the preamble data, so unlike the initcode loop below, we avoid + // using assembly here and stick with Solidity for readability. for (uint256 i = 0; i < dataLength; i++) { preambleData[i] = _bytecode[dataStart + i]; } } + // Parsing the initcode byte-by-byte is too costly for long initcode, perform a staticcall + // to the identity precompile at address(0x04) to copy the initcode. uint256 initcodeStart = 3 + nLengthBytes + dataLength; - bytes memory initcode = new bytes(_bytecode.length - initcodeStart); - for (uint256 i = 0; i < initcode.length; i++) { - initcode[i] = _bytecode[initcodeStart + i]; + uint256 initcodeLength = _bytecode.length - initcodeStart; + if (initcodeLength == 0) revert EmptyInitcode(); + + bytes memory initcode = new bytes(initcodeLength); + bool success; + assembly ("memory-safe") { + // Calculate the memory address of the input data (initcode) within _bytecode. + // - add(_bytecode, 32): Moves past the length field to the start of _bytecode's data. + // - add(..., initcodeStart): Adds the offset to reach the initcode within _bytecode. + let inputData := add(add(_bytecode, 32), initcodeStart) + + // Calculate the memory address for the output data in initcode. + let outputData := add(initcode, 32) + + // Perform the staticcall to the identity precompile. + success := staticcall(gas(), 0x04, inputData, initcodeLength, outputData, initcodeLength) } - if (initcode.length == 0) revert EmptyInitcode(); + if (!success) revert DeploymentFailed(); return Preamble(ercVersion, preambleData, initcode); } diff --git a/packages/contracts-bedrock/test/libraries/Blueprint.t.sol b/packages/contracts-bedrock/test/libraries/Blueprint.t.sol index 94a30ab99fb0..c94616a88e4f 100644 --- a/packages/contracts-bedrock/test/libraries/Blueprint.t.sol +++ b/packages/contracts-bedrock/test/libraries/Blueprint.t.sol @@ -22,7 +22,7 @@ contract BlueprintHarness { return Blueprint.blueprintDeployerBytecode(_initcode); } - function parseBlueprintPreamble(bytes memory _bytecode) public pure returns (Blueprint.Preamble memory) { + function parseBlueprintPreamble(bytes memory _bytecode) public view returns (Blueprint.Preamble memory) { return Blueprint.parseBlueprintPreamble(_bytecode); } From c5341dc17f7e4d2242a8751d00d2b66b540a277b Mon Sep 17 00:00:00 2001 From: Matt Solomon Date: Mon, 23 Sep 2024 17:56:08 -0700 Subject: [PATCH 13/15] chore: snapshots + fix revert --- packages/contracts-bedrock/semver-lock.json | 2 +- packages/contracts-bedrock/snapshots/abi/OPStackManager.json | 5 +++++ .../snapshots/abi/OPStackManagerInterop.json | 5 +++++ packages/contracts-bedrock/src/libraries/Blueprint.sol | 5 ++++- 4 files changed, 15 insertions(+), 2 deletions(-) diff --git a/packages/contracts-bedrock/semver-lock.json b/packages/contracts-bedrock/semver-lock.json index fdba023b82ab..d520f172bb42 100644 --- a/packages/contracts-bedrock/semver-lock.json +++ b/packages/contracts-bedrock/semver-lock.json @@ -32,7 +32,7 @@ "sourceCodeHash": "0xde4df0f9633dc0cdb1c9f634003ea5b0f7c5c1aebc407bc1b2f44c0ecf938649" }, "src/L1/OPStackManager.sol": { - "initCodeHash": "0xc7f2c86b47f1a74532979fd229a4bb0864b9b0026f29a198d15db71cab739093", + "initCodeHash": "0x5b451782192b8429f6822c88270c4f0dbd10342518c5695ecf4dff7b5ebfb4e4", "sourceCodeHash": "0x76dc02823148d0c104828bb3355a3bd8d2e60357643b592e6a789e090b08f954" }, "src/L1/OptimismPortal.sol": { diff --git a/packages/contracts-bedrock/snapshots/abi/OPStackManager.json b/packages/contracts-bedrock/snapshots/abi/OPStackManager.json index 97aec32ac51d..9654f8f084ab 100644 --- a/packages/contracts-bedrock/snapshots/abi/OPStackManager.json +++ b/packages/contracts-bedrock/snapshots/abi/OPStackManager.json @@ -519,6 +519,11 @@ "name": "EmptyInitcode", "type": "error" }, + { + "inputs": [], + "name": "IdentityPrecompileCallFailed", + "type": "error" + }, { "inputs": [], "name": "InvalidChainId", diff --git a/packages/contracts-bedrock/snapshots/abi/OPStackManagerInterop.json b/packages/contracts-bedrock/snapshots/abi/OPStackManagerInterop.json index 97aec32ac51d..9654f8f084ab 100644 --- a/packages/contracts-bedrock/snapshots/abi/OPStackManagerInterop.json +++ b/packages/contracts-bedrock/snapshots/abi/OPStackManagerInterop.json @@ -519,6 +519,11 @@ "name": "EmptyInitcode", "type": "error" }, + { + "inputs": [], + "name": "IdentityPrecompileCallFailed", + "type": "error" + }, { "inputs": [], "name": "InvalidChainId", diff --git a/packages/contracts-bedrock/src/libraries/Blueprint.sol b/packages/contracts-bedrock/src/libraries/Blueprint.sol index 6fdde0ef30ff..c5d221010ec7 100644 --- a/packages/contracts-bedrock/src/libraries/Blueprint.sol +++ b/packages/contracts-bedrock/src/libraries/Blueprint.sol @@ -20,6 +20,9 @@ library Blueprint { /// @notice Thrown when parsing a blueprint preamble and the resulting initcode is empty. error EmptyInitcode(); + /// @notice Thrown when call to the identity precompile fails. + error IdentityPrecompileCallFailed(); + /// @notice Thrown when parsing a blueprint preamble and the bytecode does not contain the expected prefix bytes. error NotABlueprint(); @@ -105,7 +108,7 @@ library Blueprint { success := staticcall(gas(), 0x04, inputData, initcodeLength, outputData, initcodeLength) } - if (!success) revert DeploymentFailed(); + if (!success) revert IdentityPrecompileCallFailed(); return Preamble(ercVersion, preambleData, initcode); } From 646a47984c13111f3693b0fa064ed66fda312469 Mon Sep 17 00:00:00 2001 From: Matt Solomon Date: Mon, 23 Sep 2024 18:21:49 -0700 Subject: [PATCH 14/15] test: skip FaultDisputeGameAddress since we don't deploy it yet --- op-chain-ops/deployer/integration_test/apply_test.go | 6 +++++- packages/contracts-bedrock/scripts/DeployOPChain.s.sol | 7 +++++++ packages/contracts-bedrock/test/DeployOPChain.t.sol | 2 +- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/op-chain-ops/deployer/integration_test/apply_test.go b/op-chain-ops/deployer/integration_test/apply_test.go index 58b55801e9ce..b69595b67761 100644 --- a/op-chain-ops/deployer/integration_test/apply_test.go +++ b/op-chain-ops/deployer/integration_test/apply_test.go @@ -27,7 +27,7 @@ import ( const TestParams = ` participants: - el_type: geth - el_extra_params: + el_extra_params: - "--gcmode=archive" cl_type: lighthouse network_params: @@ -192,6 +192,10 @@ func TestEndToEndApply(t *testing.T) { {"DelayedWETHPermissionlessGameProxyAddress", chainState.DelayedWETHPermissionlessGameProxyAddress}, } for _, addr := range chainAddrs { + // TODO Delete this `if`` block once FaultDisputeGameAddress is deployed. + if addr.name == "FaultDisputeGameAddress" { + continue + } t.Run(fmt.Sprintf("chain %s - %s", chainState.ID, addr.name), func(t *testing.T) { code, err := l1Client.CodeAt(ctx, addr.addr, nil) require.NoError(t, err) diff --git a/packages/contracts-bedrock/scripts/DeployOPChain.s.sol b/packages/contracts-bedrock/scripts/DeployOPChain.s.sol index e0df48cc6029..b83f1d81b63d 100644 --- a/packages/contracts-bedrock/scripts/DeployOPChain.s.sol +++ b/packages/contracts-bedrock/scripts/DeployOPChain.s.sol @@ -2,6 +2,8 @@ pragma solidity 0.8.15; import { Script } from "forge-std/Script.sol"; +import { VmSafe } from "forge-std/Vm.sol"; +import { console } from "forge-std/console.sol"; import { SafeCast } from "@openzeppelin/contracts/utils/math/SafeCast.sol"; @@ -490,6 +492,11 @@ contract DeployOPChain is Script { vm.broadcast(msg.sender); OPStackManager.DeployOutput memory deployOutput = opsmProxy.deploy(deployInput); + VmSafe.Gas memory gas = vm.lastCallGas(); + console.log("gasLimit", gas.gasLimit); + console.log("gasTotalUsed", gas.gasTotalUsed); + console.log("gasMemoryUsed", gas.gasMemoryUsed); + console.log("gasRemaining", gas.gasRemaining); vm.label(address(deployOutput.opChainProxyAdmin), "opChainProxyAdmin"); vm.label(address(deployOutput.addressManager), "addressManager"); diff --git a/packages/contracts-bedrock/test/DeployOPChain.t.sol b/packages/contracts-bedrock/test/DeployOPChain.t.sol index ef8fc06cc626..d53e6e8017c5 100644 --- a/packages/contracts-bedrock/test/DeployOPChain.t.sol +++ b/packages/contracts-bedrock/test/DeployOPChain.t.sol @@ -411,7 +411,7 @@ contract DeployOPChain_Test is DeployOPChain_TestBase { return keccak256(abi.encode(_seed, _i)); } - function testFuzz_run_memory_succeed(bytes32 _seed) public { + function testFuzz_run_memory_succeedX(bytes32 _seed) public { opChainProxyAdminOwner = address(uint160(uint256(hash(_seed, 0)))); systemConfigOwner = address(uint160(uint256(hash(_seed, 1)))); batcher = address(uint160(uint256(hash(_seed, 2)))); From c65f8565cee426a26e4c97ebe6ef231428608fca Mon Sep 17 00:00:00 2001 From: Matt Solomon Date: Mon, 23 Sep 2024 18:32:56 -0700 Subject: [PATCH 15/15] chore: cleanup --- packages/contracts-bedrock/scripts/DeployOPChain.s.sol | 7 ------- packages/contracts-bedrock/semver-lock.json | 2 +- packages/contracts-bedrock/src/L1/OPStackManager.sol | 2 +- packages/contracts-bedrock/src/libraries/Blueprint.sol | 5 ++--- packages/contracts-bedrock/test/DeployOPChain.t.sol | 2 +- 5 files changed, 5 insertions(+), 13 deletions(-) diff --git a/packages/contracts-bedrock/scripts/DeployOPChain.s.sol b/packages/contracts-bedrock/scripts/DeployOPChain.s.sol index b83f1d81b63d..e0df48cc6029 100644 --- a/packages/contracts-bedrock/scripts/DeployOPChain.s.sol +++ b/packages/contracts-bedrock/scripts/DeployOPChain.s.sol @@ -2,8 +2,6 @@ pragma solidity 0.8.15; import { Script } from "forge-std/Script.sol"; -import { VmSafe } from "forge-std/Vm.sol"; -import { console } from "forge-std/console.sol"; import { SafeCast } from "@openzeppelin/contracts/utils/math/SafeCast.sol"; @@ -492,11 +490,6 @@ contract DeployOPChain is Script { vm.broadcast(msg.sender); OPStackManager.DeployOutput memory deployOutput = opsmProxy.deploy(deployInput); - VmSafe.Gas memory gas = vm.lastCallGas(); - console.log("gasLimit", gas.gasLimit); - console.log("gasTotalUsed", gas.gasTotalUsed); - console.log("gasMemoryUsed", gas.gasMemoryUsed); - console.log("gasRemaining", gas.gasRemaining); vm.label(address(deployOutput.opChainProxyAdmin), "opChainProxyAdmin"); vm.label(address(deployOutput.addressManager), "addressManager"); diff --git a/packages/contracts-bedrock/semver-lock.json b/packages/contracts-bedrock/semver-lock.json index d520f172bb42..7312208bee3e 100644 --- a/packages/contracts-bedrock/semver-lock.json +++ b/packages/contracts-bedrock/semver-lock.json @@ -33,7 +33,7 @@ }, "src/L1/OPStackManager.sol": { "initCodeHash": "0x5b451782192b8429f6822c88270c4f0dbd10342518c5695ecf4dff7b5ebfb4e4", - "sourceCodeHash": "0x76dc02823148d0c104828bb3355a3bd8d2e60357643b592e6a789e090b08f954" + "sourceCodeHash": "0x4a9c242ce96471437ec97662d2365a7bda376db765c630a41cbe238811f1df51" }, "src/L1/OptimismPortal.sol": { "initCodeHash": "0xbe2c0c81b3459014f287d8c89cdc0d27dde5d1f44e5d024fa1e4773ddc47c190", diff --git a/packages/contracts-bedrock/src/L1/OPStackManager.sol b/packages/contracts-bedrock/src/L1/OPStackManager.sol index e6f7f758fbc0..1a81430ff1e6 100644 --- a/packages/contracts-bedrock/src/L1/OPStackManager.sol +++ b/packages/contracts-bedrock/src/L1/OPStackManager.sol @@ -542,7 +542,7 @@ contract OPStackManager is ISemver, Initializable { returns (bytes memory) { return abi.encode( - GameType.wrap(1), + GameType.wrap(1), // Permissioned Cannon Claim.wrap(bytes32(hex"dead")), // absolutePrestate 73, // maxGameDepth 30, // splitDepth diff --git a/packages/contracts-bedrock/src/libraries/Blueprint.sol b/packages/contracts-bedrock/src/libraries/Blueprint.sol index c5d221010ec7..a7ddf1f9009b 100644 --- a/packages/contracts-bedrock/src/libraries/Blueprint.sol +++ b/packages/contracts-bedrock/src/libraries/Blueprint.sol @@ -80,14 +80,13 @@ library Blueprint { bytes memory preambleData = new bytes(dataLength); if (nLengthBytes != 0) { uint256 dataStart = 3 + nLengthBytes; - // We don't currently use the preamble data, so unlike the initcode loop below, we avoid - // using assembly here and stick with Solidity for readability. + // This loop is very small, so not worth using the identity precompile like we do with initcode below. for (uint256 i = 0; i < dataLength; i++) { preambleData[i] = _bytecode[dataStart + i]; } } - // Parsing the initcode byte-by-byte is too costly for long initcode, perform a staticcall + // Parsing the initcode byte-by-byte is too costly for long initcode, so we perform a staticcall // to the identity precompile at address(0x04) to copy the initcode. uint256 initcodeStart = 3 + nLengthBytes + dataLength; uint256 initcodeLength = _bytecode.length - initcodeStart; diff --git a/packages/contracts-bedrock/test/DeployOPChain.t.sol b/packages/contracts-bedrock/test/DeployOPChain.t.sol index d53e6e8017c5..ef8fc06cc626 100644 --- a/packages/contracts-bedrock/test/DeployOPChain.t.sol +++ b/packages/contracts-bedrock/test/DeployOPChain.t.sol @@ -411,7 +411,7 @@ contract DeployOPChain_Test is DeployOPChain_TestBase { return keccak256(abi.encode(_seed, _i)); } - function testFuzz_run_memory_succeedX(bytes32 _seed) public { + function testFuzz_run_memory_succeed(bytes32 _seed) public { opChainProxyAdminOwner = address(uint160(uint256(hash(_seed, 0)))); systemConfigOwner = address(uint160(uint256(hash(_seed, 1)))); batcher = address(uint160(uint256(hash(_seed, 2))));