From 8f0a9b2d46f57b8ed4478a2ec39840ba61367684 Mon Sep 17 00:00:00 2001 From: blaine Date: Fri, 15 Nov 2024 16:08:36 -0500 Subject: [PATCH] opcm-redesign: opcm targets a single release (#12851) * fix: semver locking. * fix: semver locking. * feat: opcm impl contracts now type safe. * feat: fixing test. * fix: removing unused imports. * fix: address didn't need to be payable. * fix: moving all smart contract changes to first pr. * fix: pr comments addressed. * fix: removed InputContracts struct. * fix: ran pre-pr * fix: deploy implementations renaming version. * fix: adding solidity changes to this pr. * fix: adding v160 initializer back in. * fix: removed branching logic from opcm. * fix: removed SystemConfigV160. * opcm-redesign: op-deployer changes * fix: linting fix. * fix: semver lock --------- Co-authored-by: Matthew Slipper --- op-chain-ops/interopgen/configs.go | 2 +- op-chain-ops/interopgen/deploy.go | 5 +- op-chain-ops/interopgen/deployments.go | 3 +- op-chain-ops/interopgen/recipe.go | 2 +- op-deployer/pkg/deployer/bootstrap/opcm.go | 15 +- op-deployer/pkg/deployer/inspect/l1.go | 4 +- .../deployer/integration_test/apply_test.go | 26 +- op-deployer/pkg/deployer/opcm/contract.go | 51 -- .../pkg/deployer/opcm/implementations.go | 6 +- op-deployer/pkg/deployer/opcm/opchain.go | 6 +- op-deployer/pkg/deployer/pipeline/alt_da.go | 2 +- .../pkg/deployer/pipeline/implementations.go | 5 +- op-deployer/pkg/deployer/pipeline/init.go | 4 +- op-deployer/pkg/deployer/pipeline/opchain.go | 8 +- op-deployer/pkg/deployer/standard/standard.go | 9 +- op-deployer/pkg/deployer/state/state.go | 2 +- .../scripts/deploy/Deploy.s.sol | 10 +- .../deploy/DeployImplementations.s.sol | 439 +++++------------- .../scripts/deploy/DeployOPChain.s.sol | 35 +- .../deploy/ReadImplementationAddresses.s.sol | 26 +- .../snapshots/abi/OPContractsManager.json | 271 ++++++----- .../abi/OPContractsManagerInterop.json | 271 ++++++----- .../snapshots/semver-lock.json | 4 +- .../storageLayout/OPContractsManager.json | 37 +- .../OPContractsManagerInterop.json | 37 +- .../src/L1/OPContractsManager.sol | 288 +++++------- .../src/L1/OPContractsManagerInterop.sol | 15 +- .../src/L1/interfaces/ISystemConfigV160.sol | 85 ---- .../test/L1/OPContractsManager.t.sol | 16 +- .../test/opcm/DeployImplementations.t.sol | 114 +---- .../test/opcm/DeployOPChain.t.sol | 19 +- .../test/universal/Specs.t.sol | 34 +- 32 files changed, 666 insertions(+), 1185 deletions(-) delete mode 100644 packages/contracts-bedrock/src/L1/interfaces/ISystemConfigV160.sol diff --git a/op-chain-ops/interopgen/configs.go b/op-chain-ops/interopgen/configs.go index 942588a9929c..948d9daa3053 100644 --- a/op-chain-ops/interopgen/configs.go +++ b/op-chain-ops/interopgen/configs.go @@ -35,7 +35,7 @@ type SuperFaultProofConfig struct { } type OPCMImplementationsConfig struct { - Release string + L1ContractsRelease string FaultProof SuperFaultProofConfig diff --git a/op-chain-ops/interopgen/deploy.go b/op-chain-ops/interopgen/deploy.go index 476406821ea5..e915b724e10b 100644 --- a/op-chain-ops/interopgen/deploy.go +++ b/op-chain-ops/interopgen/deploy.go @@ -170,10 +170,9 @@ func DeploySuperchainToL1(l1Host *script.Host, superCfg *SuperchainConfig) (*Sup ProofMaturityDelaySeconds: superCfg.Implementations.FaultProof.ProofMaturityDelaySeconds, DisputeGameFinalityDelaySeconds: superCfg.Implementations.FaultProof.DisputeGameFinalityDelaySeconds, MipsVersion: superCfg.Implementations.FaultProof.MipsVersion, - Release: superCfg.Implementations.Release, + L1ContractsRelease: superCfg.Implementations.L1ContractsRelease, SuperchainConfigProxy: superDeployment.SuperchainConfigProxy, ProtocolVersionsProxy: superDeployment.ProtocolVersionsProxy, - OpcmProxyOwner: superDeployment.SuperchainProxyAdmin, UseInterop: superCfg.Implementations.UseInterop, StandardVersionsToml: standard.VersionsMainnetData, }) @@ -210,7 +209,7 @@ func DeployL2ToL1(l1Host *script.Host, superCfg *SuperchainConfig, superDeployme BasefeeScalar: cfg.GasPriceOracleBaseFeeScalar, BlobBaseFeeScalar: cfg.GasPriceOracleBlobBaseFeeScalar, L2ChainId: new(big.Int).SetUint64(cfg.L2ChainID), - OpcmProxy: superDeployment.OpcmProxy, + Opcm: superDeployment.Opcm, SaltMixer: cfg.SaltMixer, GasLimit: cfg.GasLimit, DisputeGameType: cfg.DisputeGameType, diff --git a/op-chain-ops/interopgen/deployments.go b/op-chain-ops/interopgen/deployments.go index ba18fbfdf9bd..f98a0554d870 100644 --- a/op-chain-ops/interopgen/deployments.go +++ b/op-chain-ops/interopgen/deployments.go @@ -9,8 +9,7 @@ type L1Deployment struct { } type Implementations struct { - OpcmProxy common.Address `json:"OPCMProxy"` - OpcmImpl common.Address `json:"OPCMImpl"` + Opcm common.Address `json:"OPCM"` DelayedWETHImpl common.Address `json:"DelayedWETHImpl"` OptimismPortalImpl common.Address `json:"OptimismPortalImpl"` PreimageOracleSingleton common.Address `json:"PreimageOracleSingleton"` diff --git a/op-chain-ops/interopgen/recipe.go b/op-chain-ops/interopgen/recipe.go index 8983ee72da8e..e70c69e9f481 100644 --- a/op-chain-ops/interopgen/recipe.go +++ b/op-chain-ops/interopgen/recipe.go @@ -69,7 +69,7 @@ func (r *InteropDevRecipe) Build(addrs devkeys.Addresses) (*WorldConfig, error) ProtocolVersionsOwner: superchainProtocolVersionsOwner, Deployer: superchainDeployer, Implementations: OPCMImplementationsConfig{ - Release: "dev", + L1ContractsRelease: "dev", FaultProof: SuperFaultProofConfig{ WithdrawalDelaySeconds: big.NewInt(604800), MinProposalSizeBytes: big.NewInt(10000), diff --git a/op-deployer/pkg/deployer/bootstrap/opcm.go b/op-deployer/pkg/deployer/bootstrap/opcm.go index 2f5976f304ad..89a8c3df5123 100644 --- a/op-deployer/pkg/deployer/bootstrap/opcm.go +++ b/op-deployer/pkg/deployer/bootstrap/opcm.go @@ -164,10 +164,6 @@ func OPCM(ctx context.Context, cfg OPCMConfig) error { if err != nil { return fmt.Errorf("error getting standard versions TOML: %w", err) } - opcmProxyOwnerAddr, err := standard.ManagerOwnerAddrFor(chainIDU64) - if err != nil { - return fmt.Errorf("error getting superchain proxy admin: %w", err) - } signer := opcrypto.SignerFnFromBind(opcrypto.PrivateKeySignerFn(cfg.privateKeyECDSA, chainID)) chainDeployer := crypto.PubkeyToAddress(cfg.privateKeyECDSA.PublicKey) @@ -199,14 +195,14 @@ func OPCM(ctx context.Context, cfg OPCMConfig) error { } host.SetNonce(chainDeployer, nonce) - var release string + var l1ContractsRelease string if cfg.ArtifactsLocator.IsTag() { - release = cfg.ArtifactsLocator.Tag + l1ContractsRelease = cfg.ArtifactsLocator.Tag } else { - release = "dev" + l1ContractsRelease = "dev" } - lgr.Info("deploying OPCM", "release", release) + lgr.Info("deploying OPCM", "l1ContractsRelease", l1ContractsRelease) // We need to etch the Superchain addresses so that they have nonzero code // and the checks in the OPCM constructor pass. @@ -238,10 +234,9 @@ func OPCM(ctx context.Context, cfg OPCMConfig) error { ProofMaturityDelaySeconds: new(big.Int).SetUint64(cfg.ProofMaturityDelaySeconds), DisputeGameFinalityDelaySeconds: new(big.Int).SetUint64(cfg.DisputeGameFinalityDelaySeconds), MipsVersion: new(big.Int).SetUint64(cfg.MIPSVersion), - Release: release, + L1ContractsRelease: l1ContractsRelease, SuperchainConfigProxy: superchainConfigAddr, ProtocolVersionsProxy: protocolVersionsAddr, - OpcmProxyOwner: opcmProxyOwnerAddr, StandardVersionsToml: standardVersionsTOML, UseInterop: false, }, diff --git a/op-deployer/pkg/deployer/inspect/l1.go b/op-deployer/pkg/deployer/inspect/l1.go index d0a4f88172d1..4883e83486c3 100644 --- a/op-deployer/pkg/deployer/inspect/l1.go +++ b/op-deployer/pkg/deployer/inspect/l1.go @@ -45,7 +45,7 @@ type OpChainDeployment struct { } type ImplementationsDeployment struct { - OpcmProxyAddress common.Address `json:"opcmProxyAddress"` + OpcmAddress common.Address `json:"opcmAddress"` DelayedWETHImplAddress common.Address `json:"delayedWETHImplAddress"` OptimismPortalImplAddress common.Address `json:"optimismPortalImplAddress"` PreimageOracleSingletonAddress common.Address `json:"preimageOracleSingletonAddress"` @@ -113,7 +113,7 @@ func L1(globalState *state.State, chainID common.Hash) (*L1Contracts, error) { // DelayedWETHPermissionlessGameProxyAddress: chainState.DelayedWETHPermissionlessGameProxyAddress, }, ImplementationsDeployment: ImplementationsDeployment{ - OpcmProxyAddress: globalState.ImplementationsDeployment.OpcmProxyAddress, + OpcmAddress: globalState.ImplementationsDeployment.OpcmAddress, DelayedWETHImplAddress: globalState.ImplementationsDeployment.DelayedWETHImplAddress, OptimismPortalImplAddress: globalState.ImplementationsDeployment.OptimismPortalImplAddress, PreimageOracleSingletonAddress: globalState.ImplementationsDeployment.PreimageOracleSingletonAddress, diff --git a/op-deployer/pkg/deployer/integration_test/apply_test.go b/op-deployer/pkg/deployer/integration_test/apply_test.go index 215687c5cfc0..bcbc14eb7f19 100644 --- a/op-deployer/pkg/deployer/integration_test/apply_test.go +++ b/op-deployer/pkg/deployer/integration_test/apply_test.go @@ -207,6 +207,30 @@ func TestApplyExistingOPCM(t *testing.T) { )) validateOPChainDeployment(t, ethClientCodeGetter(ctx, l1Client), st, intent) + + releases := standard.L1VersionsSepolia.Releases["op-contracts/v1.6.0"] + + implTests := []struct { + name string + expAddr common.Address + actAddr common.Address + }{ + {"OptimismPortal", releases.OptimismPortal.ImplementationAddress, st.ImplementationsDeployment.OptimismPortalImplAddress}, + {"SystemConfig,", releases.SystemConfig.ImplementationAddress, st.ImplementationsDeployment.SystemConfigImplAddress}, + {"L1CrossDomainMessenger", releases.L1CrossDomainMessenger.ImplementationAddress, st.ImplementationsDeployment.L1CrossDomainMessengerImplAddress}, + {"L1ERC721Bridge", releases.L1ERC721Bridge.ImplementationAddress, st.ImplementationsDeployment.L1ERC721BridgeImplAddress}, + {"L1StandardBridge", releases.L1StandardBridge.ImplementationAddress, st.ImplementationsDeployment.L1StandardBridgeImplAddress}, + {"OptimismMintableERC20Factory", releases.OptimismMintableERC20Factory.ImplementationAddress, st.ImplementationsDeployment.OptimismMintableERC20FactoryImplAddress}, + {"DisputeGameFactory", releases.DisputeGameFactory.ImplementationAddress, st.ImplementationsDeployment.DisputeGameFactoryImplAddress}, + {"MIPS", releases.MIPS.Address, st.ImplementationsDeployment.MipsSingletonAddress}, + {"PreimageOracle", releases.PreimageOracle.Address, st.ImplementationsDeployment.PreimageOracleSingletonAddress}, + {"DelayedWETH", releases.DelayedWETH.ImplementationAddress, st.ImplementationsDeployment.DelayedWETHImplAddress}, + } + for _, tt := range implTests { + t.Run(tt.name, func(t *testing.T) { + require.Equal(t, tt.expAddr, tt.actAddr) + }) + } } func TestL2BlockTimeOverride(t *testing.T) { @@ -571,7 +595,7 @@ func validateSuperchainDeployment(t *testing.T, st *state.State, cg codeGetter) {"SuperchainConfigImpl", st.SuperchainDeployment.SuperchainConfigImplAddress}, {"ProtocolVersionsProxy", st.SuperchainDeployment.ProtocolVersionsProxyAddress}, {"ProtocolVersionsImpl", st.SuperchainDeployment.ProtocolVersionsImplAddress}, - {"OpcmProxy", st.ImplementationsDeployment.OpcmProxyAddress}, + {"Opcm", st.ImplementationsDeployment.OpcmAddress}, {"PreimageOracleSingleton", st.ImplementationsDeployment.PreimageOracleSingletonAddress}, {"MipsSingleton", st.ImplementationsDeployment.MipsSingletonAddress}, } diff --git a/op-deployer/pkg/deployer/opcm/contract.go b/op-deployer/pkg/deployer/opcm/contract.go index b90db5814192..8d02f77e8e0a 100644 --- a/op-deployer/pkg/deployer/opcm/contract.go +++ b/op-deployer/pkg/deployer/opcm/contract.go @@ -48,57 +48,6 @@ func (c *Contract) GenericAddressGetter(ctx context.Context, functionName string return c.callContractMethod(ctx, functionName, abi.Arguments{}) } -// GetImplementation retrieves the Implementation struct for a given release and contract name. -func (c *Contract) GetOPCMImplementationAddress(ctx context.Context, release, contractName string) (common.Address, error) { - methodName := "implementations" - method := abi.NewMethod( - methodName, - methodName, - abi.Function, - "view", - true, - false, - abi.Arguments{ - {Name: "release", Type: mustType("string")}, - {Name: "contractName", Type: mustType("string")}, - }, - abi.Arguments{ - {Name: "logic", Type: mustType("address")}, - {Name: "initializer", Type: mustType("bytes4")}, - }, - ) - - calldata, err := method.Inputs.Pack(release, contractName) - if err != nil { - return common.Address{}, fmt.Errorf("failed to pack inputs: %w", err) - } - - msg := ethereum.CallMsg{ - To: &c.addr, - Data: append(bytes.Clone(method.ID), calldata...), - } - - result, err := c.client.CallContract(ctx, msg, nil) - if err != nil { - return common.Address{}, fmt.Errorf("failed to call contract: %w", err) - } - - out, err := method.Outputs.Unpack(result) - if err != nil { - return common.Address{}, fmt.Errorf("failed to unpack result: %w", err) - } - if len(out) != 2 { - return common.Address{}, fmt.Errorf("unexpected output length: %d", len(out)) - } - - logic, ok := out[0].(common.Address) - if !ok { - return common.Address{}, fmt.Errorf("unexpected type for logic: %T", out[0]) - } - - return logic, nil -} - func (c *Contract) callContractMethod(ctx context.Context, methodName string, inputs abi.Arguments, args ...interface{}) (common.Address, error) { method := abi.NewMethod( methodName, diff --git a/op-deployer/pkg/deployer/opcm/implementations.go b/op-deployer/pkg/deployer/opcm/implementations.go index 8dd072eef246..413452b1d348 100644 --- a/op-deployer/pkg/deployer/opcm/implementations.go +++ b/op-deployer/pkg/deployer/opcm/implementations.go @@ -18,12 +18,11 @@ type DeployImplementationsInput struct { DisputeGameFinalityDelaySeconds *big.Int MipsVersion *big.Int // Release version to set OPCM implementations for, of the format `op-contracts/vX.Y.Z`. - Release string + L1ContractsRelease string SuperchainConfigProxy common.Address ProtocolVersionsProxy common.Address UseInterop bool // if true, deploy Interop implementations - OpcmProxyOwner common.Address StandardVersionsToml string // contents of 'standard-versions-mainnet.toml' or 'standard-versions-sepolia.toml' file } @@ -32,8 +31,7 @@ func (input *DeployImplementationsInput) InputSet() bool { } type DeployImplementationsOutput struct { - OpcmProxy common.Address - OpcmImpl common.Address + Opcm common.Address DelayedWETHImpl common.Address OptimismPortalImpl common.Address PreimageOracleSingleton common.Address diff --git a/op-deployer/pkg/deployer/opcm/opchain.go b/op-deployer/pkg/deployer/opcm/opchain.go index 1e1b468a417f..8c7e60fec4d2 100644 --- a/op-deployer/pkg/deployer/opcm/opchain.go +++ b/op-deployer/pkg/deployer/opcm/opchain.go @@ -26,7 +26,7 @@ type DeployOPChainInputV160 struct { BasefeeScalar uint32 BlobBaseFeeScalar uint32 L2ChainId *big.Int - OpcmProxy common.Address + Opcm common.Address SaltMixer string GasLimit uint64 @@ -122,8 +122,8 @@ func deployOPChain[T any](host *script.Host, input T) (DeployOPChainOutput, erro type ReadImplementationAddressesInput struct { DeployOPChainOutput - OpcmProxy common.Address - Release string + Opcm common.Address + Release string } type ReadImplementationAddressesOutput struct { diff --git a/op-deployer/pkg/deployer/pipeline/alt_da.go b/op-deployer/pkg/deployer/pipeline/alt_da.go index 62796832c93c..b36412620945 100644 --- a/op-deployer/pkg/deployer/pipeline/alt_da.go +++ b/op-deployer/pkg/deployer/pipeline/alt_da.go @@ -31,7 +31,7 @@ func DeployAltDA(env *Env, intent *state.Intent, st *state.State, chainID common lgr.Info("deploying alt-da contracts") dao, err = opcm.DeployAltDA(env.L1ScriptHost, opcm.DeployAltDAInput{ Salt: st.Create2Salt, - ProxyAdmin: st.ImplementationsDeployment.OpcmProxyAddress, + ProxyAdmin: chainState.ProxyAdminAddress, ChallengeContractOwner: chainIntent.Roles.L1ProxyAdminOwner, ChallengeWindow: new(big.Int).SetUint64(chainIntent.DangerousAltDAConfig.DAChallengeWindow), ResolveWindow: new(big.Int).SetUint64(chainIntent.DangerousAltDAConfig.DAResolveWindow), diff --git a/op-deployer/pkg/deployer/pipeline/implementations.go b/op-deployer/pkg/deployer/pipeline/implementations.go index 47ea91fbe963..9e65fd4f54a3 100644 --- a/op-deployer/pkg/deployer/pipeline/implementations.go +++ b/op-deployer/pkg/deployer/pipeline/implementations.go @@ -68,10 +68,9 @@ func DeployImplementations(env *Env, intent *state.Intent, st *state.State) erro ProofMaturityDelaySeconds: new(big.Int).SetUint64(proofParams.ProofMaturityDelaySeconds), DisputeGameFinalityDelaySeconds: new(big.Int).SetUint64(proofParams.DisputeGameFinalityDelaySeconds), MipsVersion: new(big.Int).SetUint64(proofParams.MIPSVersion), - Release: contractsRelease, + L1ContractsRelease: contractsRelease, SuperchainConfigProxy: st.SuperchainDeployment.SuperchainConfigProxyAddress, ProtocolVersionsProxy: st.SuperchainDeployment.ProtocolVersionsProxyAddress, - OpcmProxyOwner: st.SuperchainDeployment.ProxyAdminAddress, StandardVersionsToml: standardVersionsTOML, UseInterop: intent.UseInterop, }, @@ -81,7 +80,7 @@ func DeployImplementations(env *Env, intent *state.Intent, st *state.State) erro } st.ImplementationsDeployment = &state.ImplementationsDeployment{ - OpcmProxyAddress: dio.OpcmProxy, + OpcmAddress: dio.Opcm, DelayedWETHImplAddress: dio.DelayedWETHImpl, OptimismPortalImplAddress: dio.OptimismPortalImpl, PreimageOracleSingletonAddress: dio.PreimageOracleSingleton, diff --git a/op-deployer/pkg/deployer/pipeline/init.go b/op-deployer/pkg/deployer/pipeline/init.go index f8b12e36a431..b5c37c246f29 100644 --- a/op-deployer/pkg/deployer/pipeline/init.go +++ b/op-deployer/pkg/deployer/pipeline/init.go @@ -45,12 +45,12 @@ func InitLiveStrategy(ctx context.Context, env *Env, intent *state.Intent, st *s SuperchainConfigProxyAddress: common.Address(*superCfg.Config.SuperchainConfigAddr), } - opcmProxy, err := standard.ManagerImplementationAddrFor(intent.L1ChainID) + opcmAddress, err := standard.ManagerImplementationAddrFor(intent.L1ChainID) if err != nil { return fmt.Errorf("error getting OPCM proxy address: %w", err) } st.ImplementationsDeployment = &state.ImplementationsDeployment{ - OpcmProxyAddress: opcmProxy, + OpcmAddress: opcmAddress, } } diff --git a/op-deployer/pkg/deployer/pipeline/opchain.go b/op-deployer/pkg/deployer/pipeline/opchain.go index a49848883cea..90cc665e077d 100644 --- a/op-deployer/pkg/deployer/pipeline/opchain.go +++ b/op-deployer/pkg/deployer/pipeline/opchain.go @@ -34,7 +34,7 @@ func DeployOPChain(env *Env, intent *state.Intent, st *state.State, chainID comm return opcm.DeployOPChainOutput{}, fmt.Errorf("error making deploy OP chain input: %w", err) } - opcmAddr = input.OpcmProxy + opcmAddr = input.Opcm return opcm.DeployOPChainV160(env.L1ScriptHost, input) } default: @@ -44,7 +44,7 @@ func DeployOPChain(env *Env, intent *state.Intent, st *state.State, chainID comm return opcm.DeployOPChainOutput{}, fmt.Errorf("error making deploy OP chain input: %w", err) } - opcmAddr = input.OpcmProxy + opcmAddr = input.Opcm return opcm.DeployOPChainIsthmus(env.L1ScriptHost, input) } } @@ -67,7 +67,7 @@ func DeployOPChain(env *Env, intent *state.Intent, st *state.State, chainID comm readInput := opcm.ReadImplementationAddressesInput{ DeployOPChainOutput: dco, - OpcmProxy: opcmAddr, + Opcm: opcmAddr, Release: release, } impls, err := opcm.ReadImplementationAddresses(env.L1ScriptHost, readInput) @@ -126,7 +126,7 @@ func makeDCIV160(intent *state.Intent, thisIntent *state.ChainIntent, chainID co BasefeeScalar: standard.BasefeeScalar, BlobBaseFeeScalar: standard.BlobBaseFeeScalar, L2ChainId: chainID.Big(), - OpcmProxy: st.ImplementationsDeployment.OpcmProxyAddress, + Opcm: st.ImplementationsDeployment.OpcmAddress, SaltMixer: st.Create2Salt.String(), // passing through salt generated at state initialization GasLimit: standard.GasLimit, DisputeGameType: proofParams.DisputeGameType, diff --git a/op-deployer/pkg/deployer/standard/standard.go b/op-deployer/pkg/deployer/standard/standard.go index 2fb6de8c5bf7..8c4ade1dcfb3 100644 --- a/op-deployer/pkg/deployer/standard/standard.go +++ b/op-deployer/pkg/deployer/standard/standard.go @@ -134,10 +134,11 @@ func ManagerImplementationAddrFor(chainID uint64) (common.Address, error) { switch chainID { case 1: // Generated using the bootstrap command on 10/18/2024. - return common.HexToAddress("0x18cec91779995ad14c880e4095456b9147160790"), nil + // TODO: @blmalone this needs re-bootstrapped because it's still proxied + return common.HexToAddress(""), nil case 11155111: - // Generated using the bootstrap command on 10/18/2024. - return common.HexToAddress("0xf564eea7960ea244bfebcbbb17858748606147bf"), nil + // Generated using the bootstrap command on 11/15/2024. + return common.HexToAddress("0xde9eacb994a6eb12997445f8a63a22772c5c4313"), nil default: return common.Address{}, fmt.Errorf("unsupported chain ID: %d", chainID) } @@ -172,7 +173,7 @@ func SystemOwnerAddrFor(chainID uint64) (common.Address, error) { func ArtifactsURLForTag(tag string) (*url.URL, error) { switch tag { case "op-contracts/v1.6.0": - return url.Parse(standardArtifactsURL("3a27c6dc0cb61b36feaac26def98c64b4a48ec8f5c5ba6965e8ae3157606043c")) + return url.Parse(standardArtifactsURL("e1f0c4020618c4a98972e7124c39686cab2e31d5d7846f9ce5e0d5eed0f5ff32")) case "op-contracts/v1.7.0-beta.1+l2-contracts": return url.Parse(standardArtifactsURL("b0fb1f6f674519d637cff39a22187a5993d7f81a6d7b7be6507a0b50a5e38597")) default: diff --git a/op-deployer/pkg/deployer/state/state.go b/op-deployer/pkg/deployer/state/state.go index e3974fa2a78c..e17ed6184c5d 100644 --- a/op-deployer/pkg/deployer/state/state.go +++ b/op-deployer/pkg/deployer/state/state.go @@ -64,7 +64,7 @@ type SuperchainDeployment struct { } type ImplementationsDeployment struct { - OpcmProxyAddress common.Address `json:"opcmProxyAddress"` + OpcmAddress common.Address `json:"opcmAddress"` DelayedWETHImplAddress common.Address `json:"delayedWETHImplAddress"` OptimismPortalImplAddress common.Address `json:"optimismPortalImplAddress"` PreimageOracleSingletonAddress common.Address `json:"preimageOracleSingletonAddress"` diff --git a/packages/contracts-bedrock/scripts/deploy/Deploy.s.sol b/packages/contracts-bedrock/scripts/deploy/Deploy.s.sol index 54cc1a23e172..0253e20a1956 100644 --- a/packages/contracts-bedrock/scripts/deploy/Deploy.s.sol +++ b/packages/contracts-bedrock/scripts/deploy/Deploy.s.sol @@ -162,7 +162,7 @@ contract Deploy is Deployer { L1ERC721Bridge: getAddress("L1ERC721BridgeProxy"), ProtocolVersions: getAddress("ProtocolVersionsProxy"), SuperchainConfig: getAddress("SuperchainConfigProxy"), - OPContractsManager: getAddress("OPContractsManagerProxy") + OPContractsManager: getAddress("OPContractsManager") }); } @@ -378,13 +378,12 @@ contract Deploy is Deployer { dii.set(dii.disputeGameFinalityDelaySeconds.selector, cfg.disputeGameFinalityDelaySeconds()); dii.set(dii.mipsVersion.selector, Config.useMultithreadedCannon() ? 2 : 1); string memory release = "dev"; - dii.set(dii.release.selector, release); + dii.set(dii.l1ContractsRelease.selector, release); dii.set( dii.standardVersionsToml.selector, string.concat(vm.projectRoot(), "/test/fixtures/standard-versions.toml") ); dii.set(dii.superchainConfigProxy.selector, mustGetAddress("SuperchainConfigProxy")); dii.set(dii.protocolVersionsProxy.selector, mustGetAddress("ProtocolVersionsProxy")); - dii.set(dii.opcmProxyOwner.selector, cfg.finalSystemOwner()); if (_isInterop) { di = DeployImplementations(new DeployImplementationsInterop()); @@ -409,8 +408,7 @@ contract Deploy is Deployer { save("DelayedWETH", address(dio.delayedWETHImpl())); save("PreimageOracle", address(dio.preimageOracleSingleton())); save("Mips", address(dio.mipsSingleton())); - save("OPContractsManagerProxy", address(dio.opcmProxy())); - save("OPContractsManager", address(dio.opcmImpl())); + save("OPContractsManager", address(dio.opcm())); Types.ContractSet memory contracts = _impls(); ChainAssertions.checkL1CrossDomainMessenger({ _contracts: contracts, _vm: vm, _isProxy: false }); @@ -446,7 +444,7 @@ contract Deploy is Deployer { // Ensure that the requisite contracts are deployed address superchainConfigProxy = mustGetAddress("SuperchainConfigProxy"); - OPContractsManager opcm = OPContractsManager(mustGetAddress("OPContractsManagerProxy")); + OPContractsManager opcm = OPContractsManager(mustGetAddress("OPContractsManager")); OPContractsManager.DeployInput memory deployInput = getDeployInput(); OPContractsManager.DeployOutput memory deployOutput = opcm.deploy(deployInput); diff --git a/packages/contracts-bedrock/scripts/deploy/DeployImplementations.s.sol b/packages/contracts-bedrock/scripts/deploy/DeployImplementations.s.sol index c9048a07dfa3..9abff9149181 100644 --- a/packages/contracts-bedrock/scripts/deploy/DeployImplementations.s.sol +++ b/packages/contracts-bedrock/scripts/deploy/DeployImplementations.s.sol @@ -8,16 +8,11 @@ import { LibString } from "@solady/utils/LibString.sol"; import { IResourceMetering } from "src/L1/interfaces/IResourceMetering.sol"; import { ISuperchainConfig } from "src/L1/interfaces/ISuperchainConfig.sol"; import { IProtocolVersions } from "src/L1/interfaces/IProtocolVersions.sol"; -import { ISystemConfigV160 } from "src/L1/interfaces/ISystemConfigV160.sol"; -import { IL1CrossDomainMessengerV160 } from "src/L1/interfaces/IL1CrossDomainMessengerV160.sol"; -import { IL1StandardBridgeV160 } from "src/L1/interfaces/IL1StandardBridgeV160.sol"; import { Constants } from "src/libraries/Constants.sol"; import { Predeploys } from "src/libraries/Predeploys.sol"; import { Bytes } from "src/libraries/Bytes.sol"; -import { IProxy } from "src/universal/interfaces/IProxy.sol"; - import { IDelayedWETH } from "src/dispute/interfaces/IDelayedWETH.sol"; import { IPreimageOracle } from "src/cannon/interfaces/IPreimageOracle.sol"; import { IMIPS } from "src/cannon/interfaces/IMIPS.sol"; @@ -51,8 +46,9 @@ contract DeployImplementationsInput is BaseDeployIO { uint256 internal _disputeGameFinalityDelaySeconds; uint256 internal _mipsVersion; - // The release version to set OPCM implementations for, of the format `op-contracts/vX.Y.Z`. - string internal _release; + // This is used in opcm to signal which version of the L1 smart contracts is deployed. + // It takes the format of `op-contracts/v*.*.*`. + string internal _l1ContractsRelease; // Outputs from DeploySuperchain.s.sol. ISuperchainConfig internal _superchainConfigProxy; @@ -60,8 +56,6 @@ contract DeployImplementationsInput is BaseDeployIO { string internal _standardVersionsToml; - address internal _opcmProxyOwner; - function set(bytes4 _sel, uint256 _value) public { require(_value != 0, "DeployImplementationsInput: cannot set zero value"); @@ -85,7 +79,7 @@ contract DeployImplementationsInput is BaseDeployIO { function set(bytes4 _sel, string memory _value) public { require(!LibString.eq(_value, ""), "DeployImplementationsInput: cannot set empty string"); - if (_sel == this.release.selector) _release = _value; + if (_sel == this.l1ContractsRelease.selector) _l1ContractsRelease = _value; else if (_sel == this.standardVersionsToml.selector) _standardVersionsToml = _value; else revert("DeployImplementationsInput: unknown selector"); } @@ -94,7 +88,6 @@ contract DeployImplementationsInput is BaseDeployIO { require(_addr != address(0), "DeployImplementationsInput: cannot set zero address"); if (_sel == this.superchainConfigProxy.selector) _superchainConfigProxy = ISuperchainConfig(_addr); else if (_sel == this.protocolVersionsProxy.selector) _protocolVersionsProxy = IProtocolVersions(_addr); - else if (_sel == this.opcmProxyOwner.selector) _opcmProxyOwner = _addr; else revert("DeployImplementationsInput: unknown selector"); } @@ -141,9 +134,9 @@ contract DeployImplementationsInput is BaseDeployIO { return _mipsVersion; } - function release() public view returns (string memory) { - require(!LibString.eq(_release, ""), "DeployImplementationsInput: not set"); - return _release; + function l1ContractsRelease() public view returns (string memory) { + require(!LibString.eq(_l1ContractsRelease, ""), "DeployImplementationsInput: not set"); + return _l1ContractsRelease; } function standardVersionsToml() public view returns (string memory) { @@ -160,16 +153,10 @@ contract DeployImplementationsInput is BaseDeployIO { require(address(_protocolVersionsProxy) != address(0), "DeployImplementationsInput: not set"); return _protocolVersionsProxy; } - - function opcmProxyOwner() public view returns (address) { - require(address(_opcmProxyOwner) != address(0), "DeployImplementationsInput: not set"); - return _opcmProxyOwner; - } } contract DeployImplementationsOutput is BaseDeployIO { - OPContractsManager internal _opcmProxy; - OPContractsManager internal _opcmImpl; + OPContractsManager internal _opcm; IDelayedWETH internal _delayedWETHImpl; IOptimismPortal2 internal _optimismPortalImpl; IPreimageOracle internal _preimageOracleSingleton; @@ -185,8 +172,7 @@ contract DeployImplementationsOutput is BaseDeployIO { require(_addr != address(0), "DeployImplementationsOutput: cannot set zero address"); // forgefmt: disable-start - if (_sel == this.opcmProxy.selector) _opcmProxy = OPContractsManager(payable(_addr)); - else if (_sel == this.opcmImpl.selector) _opcmImpl = OPContractsManager(payable(_addr)); + if (_sel == this.opcm.selector) _opcm = OPContractsManager(_addr); else if (_sel == this.optimismPortalImpl.selector) _optimismPortalImpl = IOptimismPortal2(payable(_addr)); else if (_sel == this.delayedWETHImpl.selector) _delayedWETHImpl = IDelayedWETH(payable(_addr)); else if (_sel == this.preimageOracleSingleton.selector) _preimageOracleSingleton = IPreimageOracle(_addr); @@ -201,12 +187,11 @@ contract DeployImplementationsOutput is BaseDeployIO { // forgefmt: disable-end } - function checkOutput(DeployImplementationsInput _dii) public { + function checkOutput(DeployImplementationsInput _dii) public view { // With 12 addresses, we'd get a stack too deep error if we tried to do this inline as a // single call to `Solarray.addresses`. So we split it into two calls. address[] memory addrs1 = Solarray.addresses( - address(this.opcmProxy()), - address(this.opcmImpl()), + address(this.opcm()), address(this.optimismPortalImpl()), address(this.delayedWETHImpl()), address(this.preimageOracleSingleton()), @@ -227,15 +212,9 @@ contract DeployImplementationsOutput is BaseDeployIO { assertValidDeploy(_dii); } - function opcmProxy() public returns (OPContractsManager) { - DeployUtils.assertValidContractAddress(address(_opcmProxy)); - DeployUtils.assertERC1967ImplementationSet(address(_opcmProxy)); - return _opcmProxy; - } - - function opcmImpl() public view returns (OPContractsManager) { - DeployUtils.assertValidContractAddress(address(_opcmImpl)); - return _opcmImpl; + function opcm() public view returns (OPContractsManager) { + DeployUtils.assertValidContractAddress(address(_opcm)); + return _opcm; } function optimismPortalImpl() public view returns (IOptimismPortal2) { @@ -289,40 +268,22 @@ contract DeployImplementationsOutput is BaseDeployIO { } // -------- Deployment Assertions -------- - function assertValidDeploy(DeployImplementationsInput _dii) public { + function assertValidDeploy(DeployImplementationsInput _dii) public view { assertValidDelayedWETHImpl(_dii); assertValidDisputeGameFactoryImpl(_dii); assertValidL1CrossDomainMessengerImpl(_dii); assertValidL1ERC721BridgeImpl(_dii); assertValidL1StandardBridgeImpl(_dii); assertValidMipsSingleton(_dii); - assertValidOpcmProxy(_dii); - assertValidOpcmImpl(_dii); + assertValidOpcm(_dii); assertValidOptimismMintableERC20FactoryImpl(_dii); assertValidOptimismPortalImpl(_dii); assertValidPreimageOracleSingleton(_dii); assertValidSystemConfigImpl(_dii); } - function assertValidOpcmProxy(DeployImplementationsInput _dii) internal { - // First we check the proxy as itself. - IProxy proxy = IProxy(payable(address(opcmProxy()))); - vm.prank(address(0)); - address admin = proxy.admin(); - require(admin == address(_dii.opcmProxyOwner()), "OPCMP-10"); - - // Then we check the proxy as OPCM. - DeployUtils.assertInitialized({ _contractAddress: address(opcmProxy()), _slot: 0, _offset: 0 }); - require(address(opcmProxy().superchainConfig()) == address(_dii.superchainConfigProxy()), "OPCMP-20"); - require(address(opcmProxy().protocolVersions()) == address(_dii.protocolVersionsProxy()), "OPCMP-30"); - require(LibString.eq(opcmProxy().latestRelease(), _dii.release()), "OPCMP-50"); // Initial release is latest. - } - - function assertValidOpcmImpl(DeployImplementationsInput _dii) internal { - IProxy proxy = IProxy(payable(address(opcmProxy()))); - vm.prank(address(0)); - OPContractsManager impl = OPContractsManager(proxy.implementation()); - DeployUtils.assertInitialized({ _contractAddress: address(impl), _slot: 0, _offset: 0 }); + function assertValidOpcm(DeployImplementationsInput _dii) internal view { + OPContractsManager impl = OPContractsManager(address(opcm())); require(address(impl.superchainConfig()) == address(_dii.superchainConfigProxy()), "OPCMI-10"); require(address(impl.protocolVersions()) == address(_dii.protocolVersionsProxy()), "OPCMI-20"); } @@ -361,7 +322,6 @@ contract DeployImplementationsOutput is BaseDeployIO { function assertValidMipsSingleton(DeployImplementationsInput) internal view { IMIPS mips = mipsSingleton(); - require(address(mips.oracle()) == address(preimageOracleSingleton()), "MIPS-10"); } @@ -480,102 +440,38 @@ contract DeployImplementations is Script { // --- OP Contracts Manager --- - function opcmSystemConfigSetter( - DeployImplementationsInput _dii, - DeployImplementationsOutput _dio - ) - internal - view - virtual - returns (OPContractsManager.ImplementationSetter memory) - { - // When configuring OPCM during Solidity tests, we are using the latest SystemConfig.sol - // version in this repo, which contains Custom Gas Token (CGT) features. This CGT version - // has a different `initialize` signature than the SystemConfig version that was released - // as part of `op-contracts/v1.6.0`, which is no longer in the repo. When running this - // script's bytecode for a production deploy of OPCM at `op-contracts/v1.6.0`, we need to - // use the ISystemConfigV160 interface instead of ISystemConfig. Therefore the selector used - // is a function of the `release` passed in by the caller. - bytes4 selector = LibString.eq(_dii.release(), "op-contracts/v1.6.0") - ? ISystemConfigV160.initialize.selector - : ISystemConfig.initialize.selector; - return OPContractsManager.ImplementationSetter({ - name: "SystemConfig", - info: OPContractsManager.Implementation(address(_dio.systemConfigImpl()), selector) - }); - } - - function l1CrossDomainMessengerConfigSetter( - DeployImplementationsInput _dii, - DeployImplementationsOutput _dio - ) - internal - view - virtual - returns (OPContractsManager.ImplementationSetter memory) - { - bytes4 selector = LibString.eq(_dii.release(), "op-contracts/v1.6.0") - ? IL1CrossDomainMessengerV160.initialize.selector - : IL1CrossDomainMessenger.initialize.selector; - return OPContractsManager.ImplementationSetter({ - name: "L1CrossDomainMessenger", - info: OPContractsManager.Implementation(address(_dio.l1CrossDomainMessengerImpl()), selector) - }); - } - - function l1StandardBridgeConfigSetter( - DeployImplementationsInput _dii, - DeployImplementationsOutput _dio - ) - internal - view - virtual - returns (OPContractsManager.ImplementationSetter memory) - { - bytes4 selector = LibString.eq(_dii.release(), "op-contracts/v1.6.0") - ? IL1StandardBridgeV160.initialize.selector - : IL1StandardBridge.initialize.selector; - return OPContractsManager.ImplementationSetter({ - name: "L1StandardBridge", - info: OPContractsManager.Implementation(address(_dio.l1StandardBridgeImpl()), selector) - }); - } - - // Deploy and initialize a proxied OPContractsManager. function createOPCMContract( DeployImplementationsInput _dii, DeployImplementationsOutput _dio, OPContractsManager.Blueprints memory _blueprints, - string memory _release, - OPContractsManager.ImplementationSetter[] memory _setters + string memory _l1ContractsRelease ) internal virtual - returns (OPContractsManager opcmProxy_) + returns (OPContractsManager opcm_) { - address opcmProxyOwner = _dii.opcmProxyOwner(); + ISuperchainConfig superchainConfigProxy = _dii.superchainConfigProxy(); + IProtocolVersions protocolVersionsProxy = _dii.protocolVersionsProxy(); + + OPContractsManager.Implementations memory implementations = OPContractsManager.Implementations({ + l1ERC721BridgeImpl: address(_dio.l1ERC721BridgeImpl()), + optimismPortalImpl: address(_dio.optimismPortalImpl()), + systemConfigImpl: address(_dio.systemConfigImpl()), + optimismMintableERC20FactoryImpl: address(_dio.optimismMintableERC20FactoryImpl()), + l1CrossDomainMessengerImpl: address(_dio.l1CrossDomainMessengerImpl()), + l1StandardBridgeImpl: address(_dio.l1StandardBridgeImpl()), + disputeGameFactoryImpl: address(_dio.disputeGameFactoryImpl()), + delayedWETHImpl: address(_dio.delayedWETHImpl()), + mipsImpl: address(_dio.mipsSingleton()) + }); vm.broadcast(msg.sender); - IProxy proxy = IProxy( - DeployUtils.create1({ - _name: "Proxy", - _args: DeployUtils.encodeConstructor(abi.encodeCall(IProxy.__constructor__, (msg.sender))) - }) + opcm_ = new OPContractsManager( + superchainConfigProxy, protocolVersionsProxy, _l1ContractsRelease, _blueprints, implementations ); - deployOPContractsManagerImpl(_dii, _dio); - OPContractsManager opcmImpl = _dio.opcmImpl(); - - OPContractsManager.InitializerInputs memory initializerInputs = - OPContractsManager.InitializerInputs(_blueprints, _setters, _release, true); - - vm.startBroadcast(msg.sender); - proxy.upgradeToAndCall(address(opcmImpl), abi.encodeCall(opcmImpl.initialize, (initializerInputs))); - - proxy.changeAdmin(address(opcmProxyOwner)); // transfer ownership of Proxy contract to the ProxyAdmin contract - vm.stopBroadcast(); - - opcmProxy_ = OPContractsManager(address(proxy)); + vm.label(address(opcm_), "OPContractsManager"); + _dio.set(_dio.opcm.selector, address(opcm_)); } function deployOPContractsManager( @@ -585,72 +481,42 @@ contract DeployImplementations is Script { public virtual { - string memory release = _dii.release(); - - // First we deploy the blueprints for the singletons deployed by OPCM. - // forgefmt: disable-start - bytes32 salt = _dii.salt(); - OPContractsManager.Blueprints memory blueprints; - - vm.startBroadcast(msg.sender); - blueprints.addressManager = deployBytecode(Blueprint.blueprintDeployerBytecode(vm.getCode("AddressManager")), salt); - blueprints.proxy = deployBytecode(Blueprint.blueprintDeployerBytecode(vm.getCode("Proxy")), salt); - blueprints.proxyAdmin = deployBytecode(Blueprint.blueprintDeployerBytecode(vm.getCode("ProxyAdmin")), salt); - blueprints.l1ChugSplashProxy = deployBytecode(Blueprint.blueprintDeployerBytecode(vm.getCode("L1ChugSplashProxy")), salt); - blueprints.resolvedDelegateProxy = deployBytecode(Blueprint.blueprintDeployerBytecode(vm.getCode("ResolvedDelegateProxy")), salt); - blueprints.anchorStateRegistry = deployBytecode(Blueprint.blueprintDeployerBytecode(vm.getCode("AnchorStateRegistry")), salt); - (blueprints.permissionedDisputeGame1, blueprints.permissionedDisputeGame2) = deployBigBytecode(vm.getCode("PermissionedDisputeGame"), salt); - vm.stopBroadcast(); - // forgefmt: disable-end - - OPContractsManager.ImplementationSetter[] memory setters = new OPContractsManager.ImplementationSetter[](9); - setters[0] = OPContractsManager.ImplementationSetter({ - name: "L1ERC721Bridge", - info: OPContractsManager.Implementation(address(_dio.l1ERC721BridgeImpl()), IL1ERC721Bridge.initialize.selector) - }); - setters[1] = OPContractsManager.ImplementationSetter({ - name: "OptimismPortal", - info: OPContractsManager.Implementation( - address(_dio.optimismPortalImpl()), IOptimismPortal2.initialize.selector - ) - }); - setters[2] = opcmSystemConfigSetter(_dii, _dio); - setters[3] = OPContractsManager.ImplementationSetter({ - name: "OptimismMintableERC20Factory", - info: OPContractsManager.Implementation( - address(_dio.optimismMintableERC20FactoryImpl()), IOptimismMintableERC20Factory.initialize.selector - ) - }); - setters[4] = l1CrossDomainMessengerConfigSetter(_dii, _dio); - setters[5] = l1StandardBridgeConfigSetter(_dii, _dio); - setters[6] = OPContractsManager.ImplementationSetter({ - name: "DisputeGameFactory", - info: OPContractsManager.Implementation( - address(_dio.disputeGameFactoryImpl()), IDisputeGameFactory.initialize.selector - ) - }); - setters[7] = OPContractsManager.ImplementationSetter({ - name: "DelayedWETH", - info: OPContractsManager.Implementation(address(_dio.delayedWETHImpl()), IDelayedWETH.initialize.selector) - }); - setters[8] = OPContractsManager.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: OPContractsManager.Implementation(address(_dio.mipsSingleton()), bytes4(0)) - }); + string memory l1ContractsRelease = _dii.l1ContractsRelease(); + string memory stdVerToml = _dii.standardVersionsToml(); + string memory contractName = "op_contracts_manager"; + OPContractsManager opcm; - // This call contains a broadcast to deploy OPCM which is proxied. - OPContractsManager opcmProxy = createOPCMContract(_dii, _dio, blueprints, release, setters); + address existingImplementation = getReleaseAddress(l1ContractsRelease, contractName, stdVerToml); + if (existingImplementation != address(0)) { + opcm = OPContractsManager(existingImplementation); + } else { + // First we deploy the blueprints for the singletons deployed by OPCM. + // forgefmt: disable-start + bytes32 salt = _dii.salt(); + OPContractsManager.Blueprints memory blueprints; + + vm.startBroadcast(msg.sender); + blueprints.addressManager = deployBytecode(Blueprint.blueprintDeployerBytecode(vm.getCode("AddressManager")), salt); + blueprints.proxy = deployBytecode(Blueprint.blueprintDeployerBytecode(vm.getCode("Proxy")), salt); + blueprints.proxyAdmin = deployBytecode(Blueprint.blueprintDeployerBytecode(vm.getCode("ProxyAdmin")), salt); + blueprints.l1ChugSplashProxy = deployBytecode(Blueprint.blueprintDeployerBytecode(vm.getCode("L1ChugSplashProxy")), salt); + blueprints.resolvedDelegateProxy = deployBytecode(Blueprint.blueprintDeployerBytecode(vm.getCode("ResolvedDelegateProxy")), salt); + blueprints.anchorStateRegistry = deployBytecode(Blueprint.blueprintDeployerBytecode(vm.getCode("AnchorStateRegistry")), salt); + (blueprints.permissionedDisputeGame1, blueprints.permissionedDisputeGame2) = deployBigBytecode(vm.getCode("PermissionedDisputeGame"), salt); + vm.stopBroadcast(); + // forgefmt: disable-end + + opcm = createOPCMContract(_dii, _dio, blueprints, l1ContractsRelease); + } - vm.label(address(opcmProxy), "OPContractsManager"); - _dio.set(_dio.opcmProxy.selector, address(opcmProxy)); + vm.label(address(opcm), "OPContractsManager"); + _dio.set(_dio.opcm.selector, address(opcm)); } // --- Core Contracts --- function deploySystemConfigImpl(DeployImplementationsInput _dii, DeployImplementationsOutput _dio) public virtual { - string memory release = _dii.release(); + string memory release = _dii.l1ContractsRelease(); string memory stdVerToml = _dii.standardVersionsToml(); // Using snake case for contract name to match the TOML file in superchain-registry. string memory contractName = "system_config"; @@ -659,7 +525,7 @@ contract DeployImplementations is Script { address existingImplementation = getReleaseAddress(release, contractName, stdVerToml); if (existingImplementation != address(0)) { impl = ISystemConfig(existingImplementation); - } else if (isDevelopRelease(release)) { + } else { // Deploy a new implementation for development builds. vm.broadcast(msg.sender); impl = ISystemConfig( @@ -668,8 +534,6 @@ contract DeployImplementations is Script { _args: DeployUtils.encodeConstructor(abi.encodeCall(ISystemConfig.__constructor__, ())) }) ); - } else { - revert(string.concat("DeployImplementations: failed to deploy release ", release)); } vm.label(address(impl), "SystemConfigImpl"); @@ -683,7 +547,7 @@ contract DeployImplementations is Script { public virtual { - string memory release = _dii.release(); + string memory release = _dii.l1ContractsRelease(); string memory stdVerToml = _dii.standardVersionsToml(); string memory contractName = "l1_cross_domain_messenger"; IL1CrossDomainMessenger impl; @@ -691,7 +555,7 @@ contract DeployImplementations is Script { address existingImplementation = getReleaseAddress(release, contractName, stdVerToml); if (existingImplementation != address(0)) { impl = IL1CrossDomainMessenger(existingImplementation); - } else if (isDevelopRelease(release)) { + } else { vm.broadcast(msg.sender); impl = IL1CrossDomainMessenger( DeployUtils.create1({ @@ -699,8 +563,6 @@ contract DeployImplementations is Script { _args: DeployUtils.encodeConstructor(abi.encodeCall(IL1CrossDomainMessenger.__constructor__, ())) }) ); - } else { - revert(string.concat("DeployImplementations: failed to deploy release ", release)); } vm.label(address(impl), "L1CrossDomainMessengerImpl"); @@ -714,7 +576,7 @@ contract DeployImplementations is Script { public virtual { - string memory release = _dii.release(); + string memory release = _dii.l1ContractsRelease(); string memory stdVerToml = _dii.standardVersionsToml(); string memory contractName = "l1_erc721_bridge"; IL1ERC721Bridge impl; @@ -722,7 +584,7 @@ contract DeployImplementations is Script { address existingImplementation = getReleaseAddress(release, contractName, stdVerToml); if (existingImplementation != address(0)) { impl = IL1ERC721Bridge(existingImplementation); - } else if (isDevelopRelease(release)) { + } else { vm.broadcast(msg.sender); impl = IL1ERC721Bridge( DeployUtils.create1({ @@ -730,8 +592,6 @@ contract DeployImplementations is Script { _args: DeployUtils.encodeConstructor(abi.encodeCall(IL1ERC721Bridge.__constructor__, ())) }) ); - } else { - revert(string.concat("DeployImplementations: failed to deploy release ", release)); } vm.label(address(impl), "L1ERC721BridgeImpl"); @@ -745,7 +605,7 @@ contract DeployImplementations is Script { public virtual { - string memory release = _dii.release(); + string memory release = _dii.l1ContractsRelease(); string memory stdVerToml = _dii.standardVersionsToml(); string memory contractName = "l1_standard_bridge"; IL1StandardBridge impl; @@ -753,7 +613,7 @@ contract DeployImplementations is Script { address existingImplementation = getReleaseAddress(release, contractName, stdVerToml); if (existingImplementation != address(0)) { impl = IL1StandardBridge(payable(existingImplementation)); - } else if (isDevelopRelease(release)) { + } else { vm.broadcast(msg.sender); impl = IL1StandardBridge( DeployUtils.create1({ @@ -761,8 +621,6 @@ contract DeployImplementations is Script { _args: DeployUtils.encodeConstructor(abi.encodeCall(IL1StandardBridge.__constructor__, ())) }) ); - } else { - revert(string.concat("DeployImplementations: failed to deploy release ", release)); } vm.label(address(impl), "L1StandardBridgeImpl"); @@ -776,7 +634,7 @@ contract DeployImplementations is Script { public virtual { - string memory release = _dii.release(); + string memory release = _dii.l1ContractsRelease(); string memory stdVerToml = _dii.standardVersionsToml(); string memory contractName = "optimism_mintable_erc20_factory"; IOptimismMintableERC20Factory impl; @@ -784,7 +642,7 @@ contract DeployImplementations is Script { address existingImplementation = getReleaseAddress(release, contractName, stdVerToml); if (existingImplementation != address(0)) { impl = IOptimismMintableERC20Factory(existingImplementation); - } else if (isDevelopRelease(release)) { + } else { vm.broadcast(msg.sender); impl = IOptimismMintableERC20Factory( DeployUtils.create1({ @@ -792,32 +650,12 @@ contract DeployImplementations is Script { _args: DeployUtils.encodeConstructor(abi.encodeCall(IOptimismMintableERC20Factory.__constructor__, ())) }) ); - } else { - revert(string.concat("DeployImplementations: failed to deploy release ", release)); } vm.label(address(impl), "OptimismMintableERC20FactoryImpl"); _dio.set(_dio.optimismMintableERC20FactoryImpl.selector, address(impl)); } - function deployOPContractsManagerImpl( - DeployImplementationsInput _dii, - DeployImplementationsOutput _dio - ) - public - virtual - { - ISuperchainConfig superchainConfigProxy = _dii.superchainConfigProxy(); - IProtocolVersions protocolVersionsProxy = _dii.protocolVersionsProxy(); - - vm.broadcast(msg.sender); - // TODO: Eventually we will want to select the correct implementation based on the release. - OPContractsManager impl = new OPContractsManager(superchainConfigProxy, protocolVersionsProxy); - - vm.label(address(impl), "OPContractsManagerImpl"); - _dio.set(_dio.opcmImpl.selector, address(impl)); - } - // --- Fault Proofs Contracts --- // The fault proofs contracts are configured as follows: @@ -862,7 +700,7 @@ contract DeployImplementations is Script { public virtual { - string memory release = _dii.release(); + string memory release = _dii.l1ContractsRelease(); string memory stdVerToml = _dii.standardVersionsToml(); string memory contractName = "optimism_portal"; IOptimismPortal2 impl; @@ -870,7 +708,7 @@ contract DeployImplementations is Script { address existingImplementation = getReleaseAddress(release, contractName, stdVerToml); if (existingImplementation != address(0)) { impl = IOptimismPortal2(payable(existingImplementation)); - } else if (isDevelopRelease(release)) { + } else { uint256 proofMaturityDelaySeconds = _dii.proofMaturityDelaySeconds(); uint256 disputeGameFinalityDelaySeconds = _dii.disputeGameFinalityDelaySeconds(); vm.broadcast(msg.sender); @@ -884,8 +722,6 @@ contract DeployImplementations is Script { ) }) ); - } else { - revert(string.concat("DeployImplementations: failed to deploy release ", release)); } vm.label(address(impl), "OptimismPortalImpl"); @@ -893,7 +729,7 @@ contract DeployImplementations is Script { } function deployDelayedWETHImpl(DeployImplementationsInput _dii, DeployImplementationsOutput _dio) public virtual { - string memory release = _dii.release(); + string memory release = _dii.l1ContractsRelease(); string memory stdVerToml = _dii.standardVersionsToml(); string memory contractName = "delayed_weth"; IDelayedWETH impl; @@ -901,7 +737,7 @@ contract DeployImplementations is Script { address existingImplementation = getReleaseAddress(release, contractName, stdVerToml); if (existingImplementation != address(0)) { impl = IDelayedWETH(payable(existingImplementation)); - } else if (isDevelopRelease(release)) { + } else { uint256 withdrawalDelaySeconds = _dii.withdrawalDelaySeconds(); vm.broadcast(msg.sender); impl = IDelayedWETH( @@ -912,8 +748,6 @@ contract DeployImplementations is Script { ) }) ); - } else { - revert(string.concat("DeployImplementations: failed to deploy release ", release)); } vm.label(address(impl), "DelayedWETHImpl"); @@ -927,7 +761,7 @@ contract DeployImplementations is Script { public virtual { - string memory release = _dii.release(); + string memory release = _dii.l1ContractsRelease(); string memory stdVerToml = _dii.standardVersionsToml(); string memory contractName = "preimage_oracle"; IPreimageOracle singleton; @@ -935,7 +769,7 @@ contract DeployImplementations is Script { address existingImplementation = getReleaseAddress(release, contractName, stdVerToml); if (existingImplementation != address(0)) { singleton = IPreimageOracle(payable(existingImplementation)); - } else if (isDevelopRelease(release)) { + } else { uint256 minProposalSizeBytes = _dii.minProposalSizeBytes(); uint256 challengePeriodSeconds = _dii.challengePeriodSeconds(); vm.broadcast(msg.sender); @@ -947,8 +781,6 @@ contract DeployImplementations is Script { ) }) ); - } else { - revert(string.concat("DeployImplementations: failed to deploy release ", release)); } vm.label(address(singleton), "PreimageOracleSingleton"); @@ -956,7 +788,7 @@ contract DeployImplementations is Script { } function deployMipsSingleton(DeployImplementationsInput _dii, DeployImplementationsOutput _dio) public virtual { - string memory release = _dii.release(); + string memory release = _dii.l1ContractsRelease(); string memory stdVerToml = _dii.standardVersionsToml(); string memory contractName = "mips"; IMIPS singleton; @@ -964,7 +796,7 @@ contract DeployImplementations is Script { address existingImplementation = getReleaseAddress(release, contractName, stdVerToml); if (existingImplementation != address(0)) { singleton = IMIPS(payable(existingImplementation)); - } else if (isDevelopRelease(release)) { + } else { uint256 mipsVersion = _dii.mipsVersion(); IPreimageOracle preimageOracle = IPreimageOracle(address(_dio.preimageOracleSingleton())); vm.broadcast(msg.sender); @@ -974,8 +806,6 @@ contract DeployImplementations is Script { _args: DeployUtils.encodeConstructor(abi.encodeCall(IMIPS.__constructor__, (preimageOracle))) }) ); - } else { - revert(string.concat("DeployImplementations: failed to deploy release ", release)); } vm.label(address(singleton), "MIPSSingleton"); @@ -989,7 +819,7 @@ contract DeployImplementations is Script { public virtual { - string memory release = _dii.release(); + string memory release = _dii.l1ContractsRelease(); string memory stdVerToml = _dii.standardVersionsToml(); string memory contractName = "dispute_game_factory"; IDisputeGameFactory impl; @@ -997,7 +827,7 @@ contract DeployImplementations is Script { address existingImplementation = getReleaseAddress(release, contractName, stdVerToml); if (existingImplementation != address(0)) { impl = IDisputeGameFactory(payable(existingImplementation)); - } else if (isDevelopRelease(release)) { + } else { vm.broadcast(msg.sender); impl = IDisputeGameFactory( DeployUtils.create1({ @@ -1005,8 +835,6 @@ contract DeployImplementations is Script { _args: DeployUtils.encodeConstructor(abi.encodeCall(IDisputeGameFactory.__constructor__, ())) }) ); - } else { - revert(string.concat("DeployImplementations: failed to deploy release ", release)); } vm.label(address(impl), "DisputeGameFactoryImpl"); @@ -1076,11 +904,6 @@ contract DeployImplementations is Script { } } } - - // A release is considered a 'develop' release if it does not start with 'op-contracts'. - function isDevelopRelease(string memory _release) internal pure returns (bool) { - return !LibString.startsWith(_release, "op-contracts"); - } } // Similar to how DeploySuperchain.s.sol contains a lot of comments to thoroughly document the script @@ -1120,36 +943,35 @@ contract DeployImplementationsInterop is DeployImplementations { DeployImplementationsInput _dii, DeployImplementationsOutput _dio, OPContractsManager.Blueprints memory _blueprints, - string memory _release, - OPContractsManager.ImplementationSetter[] memory _setters + string memory _l1ContractsRelease ) internal + virtual override - returns (OPContractsManager opcmProxy_) + returns (OPContractsManager opcm_) { - address opcmProxyOwner = _dii.opcmProxyOwner(); + ISuperchainConfig superchainConfigProxy = _dii.superchainConfigProxy(); + IProtocolVersions protocolVersionsProxy = _dii.protocolVersionsProxy(); + + OPContractsManager.Implementations memory implementations = OPContractsManager.Implementations({ + l1ERC721BridgeImpl: address(_dio.l1ERC721BridgeImpl()), + optimismPortalImpl: address(_dio.optimismPortalImpl()), + systemConfigImpl: address(_dio.systemConfigImpl()), + optimismMintableERC20FactoryImpl: address(_dio.optimismMintableERC20FactoryImpl()), + l1CrossDomainMessengerImpl: address(_dio.l1CrossDomainMessengerImpl()), + l1StandardBridgeImpl: address(_dio.l1StandardBridgeImpl()), + disputeGameFactoryImpl: address(_dio.disputeGameFactoryImpl()), + delayedWETHImpl: address(_dio.delayedWETHImpl()), + mipsImpl: address(_dio.mipsSingleton()) + }); vm.broadcast(msg.sender); - IProxy proxy = IProxy( - DeployUtils.create1({ - _name: "Proxy", - _args: DeployUtils.encodeConstructor(abi.encodeCall(IProxy.__constructor__, (msg.sender))) - }) + opcm_ = new OPContractsManagerInterop( + superchainConfigProxy, protocolVersionsProxy, _l1ContractsRelease, _blueprints, implementations ); - deployOPContractsManagerImpl(_dii, _dio); // overriding function - OPContractsManager opcmImpl = _dio.opcmImpl(); - - OPContractsManager.InitializerInputs memory initializerInputs = - OPContractsManager.InitializerInputs(_blueprints, _setters, _release, true); - - vm.startBroadcast(msg.sender); - proxy.upgradeToAndCall(address(opcmImpl), abi.encodeCall(opcmImpl.initialize, (initializerInputs))); - - proxy.changeAdmin(opcmProxyOwner); // transfer ownership of Proxy contract to the ProxyAdmin contract - vm.stopBroadcast(); - - opcmProxy_ = OPContractsManagerInterop(address(proxy)); + vm.label(address(opcm_), "OPContractsManager"); + _dio.set(_dio.opcm.selector, address(opcm_)); } function deployOptimismPortalImpl( @@ -1159,7 +981,7 @@ contract DeployImplementationsInterop is DeployImplementations { public override { - string memory release = _dii.release(); + string memory release = _dii.l1ContractsRelease(); string memory stdVerToml = _dii.standardVersionsToml(); string memory contractName = "optimism_portal"; IOptimismPortalInterop impl; @@ -1167,7 +989,7 @@ contract DeployImplementationsInterop is DeployImplementations { address existingImplementation = getReleaseAddress(release, contractName, stdVerToml); if (existingImplementation != address(0)) { impl = IOptimismPortalInterop(payable(existingImplementation)); - } else if (isDevelopRelease(release)) { + } else { uint256 proofMaturityDelaySeconds = _dii.proofMaturityDelaySeconds(); uint256 disputeGameFinalityDelaySeconds = _dii.disputeGameFinalityDelaySeconds(); vm.broadcast(msg.sender); @@ -1182,8 +1004,6 @@ contract DeployImplementationsInterop is DeployImplementations { ) }) ); - } else { - revert(string.concat("DeployImplementations: failed to deploy release ", release)); } vm.label(address(impl), "OptimismPortalImpl"); @@ -1197,7 +1017,7 @@ contract DeployImplementationsInterop is DeployImplementations { public override { - string memory release = _dii.release(); + string memory release = _dii.l1ContractsRelease(); string memory stdVerToml = _dii.standardVersionsToml(); string memory contractName = "system_config"; @@ -1206,7 +1026,7 @@ contract DeployImplementationsInterop is DeployImplementations { address existingImplementation = getReleaseAddress(release, contractName, stdVerToml); if (existingImplementation != address(0)) { impl = ISystemConfigInterop(existingImplementation); - } else if (isDevelopRelease(release)) { + } else { vm.broadcast(msg.sender); impl = ISystemConfigInterop( DeployUtils.create1({ @@ -1214,46 +1034,9 @@ contract DeployImplementationsInterop is DeployImplementations { _args: DeployUtils.encodeConstructor(abi.encodeCall(ISystemConfigInterop.__constructor__, ())) }) ); - } else { - revert(string.concat("DeployImplementations: failed to deploy release ", release)); } vm.label(address(impl), "SystemConfigImpl"); _dio.set(_dio.systemConfigImpl.selector, address(impl)); } - - function deployOPContractsManagerImpl( - DeployImplementationsInput _dii, - DeployImplementationsOutput _dio - ) - public - override - { - ISuperchainConfig superchainConfigProxy = _dii.superchainConfigProxy(); - IProtocolVersions protocolVersionsProxy = _dii.protocolVersionsProxy(); - - vm.broadcast(msg.sender); - // TODO: Eventually we will want to select the correct implementation based on the release. - OPContractsManager impl = new OPContractsManagerInterop(superchainConfigProxy, protocolVersionsProxy); - - vm.label(address(impl), "OPContractsManagerImpl"); - _dio.set(_dio.opcmImpl.selector, address(impl)); - } - - function opcmSystemConfigSetter( - DeployImplementationsInput, - DeployImplementationsOutput _dio - ) - internal - view - override - returns (OPContractsManager.ImplementationSetter memory) - { - return OPContractsManager.ImplementationSetter({ - name: "SystemConfig", - info: OPContractsManager.Implementation( - address(_dio.systemConfigImpl()), ISystemConfigInterop.initialize.selector - ) - }); - } } diff --git a/packages/contracts-bedrock/scripts/deploy/DeployOPChain.s.sol b/packages/contracts-bedrock/scripts/deploy/DeployOPChain.s.sol index eb3b346452e9..a83dfb110625 100644 --- a/packages/contracts-bedrock/scripts/deploy/DeployOPChain.s.sol +++ b/packages/contracts-bedrock/scripts/deploy/DeployOPChain.s.sol @@ -47,7 +47,7 @@ contract DeployOPChainInput is BaseDeployIO { uint32 internal _basefeeScalar; uint32 internal _blobBaseFeeScalar; uint256 internal _l2ChainId; - OPContractsManager internal _opcmProxy; + OPContractsManager internal _opcm; string internal _saltMixer; uint64 internal _gasLimit; @@ -68,7 +68,7 @@ contract DeployOPChainInput is BaseDeployIO { else if (_sel == this.unsafeBlockSigner.selector) _unsafeBlockSigner = _addr; else if (_sel == this.proposer.selector) _proposer = _addr; else if (_sel == this.challenger.selector) _challenger = _addr; - else if (_sel == this.opcmProxy.selector) _opcmProxy = OPContractsManager(_addr); + else if (_sel == this.opcm.selector) _opcm = OPContractsManager(_addr); else revert("DeployOPChainInput: unknown selector"); } @@ -174,11 +174,10 @@ contract DeployOPChainInput is BaseDeployIO { return abi.encode(ScriptConstants.DEFAULT_STARTING_ANCHOR_ROOTS()); } - function opcmProxy() public returns (OPContractsManager) { - require(address(_opcmProxy) != address(0), "DeployOPChainInput: not set"); - DeployUtils.assertValidContractAddress(address(_opcmProxy)); - DeployUtils.assertERC1967ImplementationSet(address(_opcmProxy)); - return _opcmProxy; + function opcm() public view returns (OPContractsManager) { + require(address(_opcm) != address(0), "DeployOPChainInput: not set"); + DeployUtils.assertValidContractAddress(address(_opcm)); + return _opcm; } function saltMixer() public view returns (string memory) { @@ -347,7 +346,7 @@ contract DeployOPChain is Script { // -------- Core Deployment Methods -------- function run(DeployOPChainInput _doi, DeployOPChainOutput _doo) public { - OPContractsManager opcmProxy = _doi.opcmProxy(); + OPContractsManager opcm = _doi.opcm(); OPContractsManager.Roles memory roles = OPContractsManager.Roles({ opChainProxyAdminOwner: _doi.opChainProxyAdminOwner(), @@ -374,7 +373,7 @@ contract DeployOPChain is Script { }); vm.broadcast(msg.sender); - OPContractsManager.DeployOutput memory deployOutput = opcmProxy.deploy(deployInput); + OPContractsManager.DeployOutput memory deployOutput = opcm.deploy(deployInput); vm.label(address(deployOutput.opChainProxyAdmin), "opChainProxyAdmin"); vm.label(address(deployOutput.addressManager), "addressManager"); @@ -480,9 +479,9 @@ contract DeployOPChain is Script { "DPG-20" ); - OPContractsManager opcm = _doi.opcmProxy(); - (address mips,) = opcm.implementations(opcm.latestRelease(), "MIPS"); - require(game.vm() == IBigStepper(mips), "DPG-30"); + OPContractsManager opcm = _doi.opcm(); + address mipsImpl = opcm.implementations().mipsImpl; + require(game.vm() == IBigStepper(mipsImpl), "DPG-30"); require(address(game.weth()) == address(_doo.delayedWETHPermissionedGameProxy()), "DPG-40"); require(address(game.anchorStateRegistry()) == address(_doo.anchorStateRegistryProxy()), "DPG-50"); @@ -552,9 +551,7 @@ contract DeployOPChain is Script { require(outputConfig.maximumBaseFee == rConfig.maximumBaseFee, "SYSCON-130"); require(systemConfig.startBlock() == block.number, "SYSCON-140"); - require( - systemConfig.batchInbox() == _doi.opcmProxy().chainIdToBatchInboxAddress(_doi.l2ChainId()), "SYSCON-150" - ); + require(systemConfig.batchInbox() == _doi.opcm().chainIdToBatchInboxAddress(_doi.l2ChainId()), "SYSCON-150"); require(systemConfig.l1CrossDomainMessenger() == address(_doo.l1CrossDomainMessengerProxy()), "SYSCON-160"); require(systemConfig.l1ERC721Bridge() == address(_doo.l1ERC721BridgeProxy()), "SYSCON-170"); @@ -579,7 +576,7 @@ contract DeployOPChain is Script { require(address(messenger.PORTAL()) == address(_doo.optimismPortalProxy()), "L1xDM-30"); require(address(messenger.portal()) == address(_doo.optimismPortalProxy()), "L1xDM-40"); - require(address(messenger.superchainConfig()) == address(_doi.opcmProxy().superchainConfig()), "L1xDM-50"); + require(address(messenger.superchainConfig()) == address(_doi.opcm().superchainConfig()), "L1xDM-50"); bytes32 xdmSenderSlot = vm.load(address(messenger), bytes32(uint256(204))); require(address(uint160(uint256(xdmSenderSlot))) == Constants.DEFAULT_L2_SENDER, "L1xDM-60"); @@ -595,7 +592,7 @@ contract DeployOPChain is Script { require(address(bridge.messenger()) == address(messenger), "L1SB-20"); require(address(bridge.OTHER_BRIDGE()) == Predeploys.L2_STANDARD_BRIDGE, "L1SB-30"); require(address(bridge.otherBridge()) == Predeploys.L2_STANDARD_BRIDGE, "L1SB-40"); - require(address(bridge.superchainConfig()) == address(_doi.opcmProxy().superchainConfig()), "L1SB-50"); + require(address(bridge.superchainConfig()) == address(_doi.opcm().superchainConfig()), "L1SB-50"); } function assertValidOptimismMintableERC20Factory(DeployOPChainInput, DeployOPChainOutput _doo) internal { @@ -617,12 +614,12 @@ contract DeployOPChain is Script { require(address(bridge.MESSENGER()) == address(_doo.l1CrossDomainMessengerProxy()), "L721B-30"); require(address(bridge.messenger()) == address(_doo.l1CrossDomainMessengerProxy()), "L721B-40"); - require(address(bridge.superchainConfig()) == address(_doi.opcmProxy().superchainConfig()), "L721B-50"); + require(address(bridge.superchainConfig()) == address(_doi.opcm().superchainConfig()), "L721B-50"); } function assertValidOptimismPortal(DeployOPChainInput _doi, DeployOPChainOutput _doo) internal { IOptimismPortal2 portal = _doo.optimismPortalProxy(); - ISuperchainConfig superchainConfig = ISuperchainConfig(address(_doi.opcmProxy().superchainConfig())); + ISuperchainConfig superchainConfig = ISuperchainConfig(address(_doi.opcm().superchainConfig())); require(address(portal.disputeGameFactory()) == address(_doo.disputeGameFactoryProxy()), "PORTAL-10"); require(address(portal.systemConfig()) == address(_doo.systemConfigProxy()), "PORTAL-20"); diff --git a/packages/contracts-bedrock/scripts/deploy/ReadImplementationAddresses.s.sol b/packages/contracts-bedrock/scripts/deploy/ReadImplementationAddresses.s.sol index 3992cf1cb657..35aefbed16d5 100644 --- a/packages/contracts-bedrock/scripts/deploy/ReadImplementationAddresses.s.sol +++ b/packages/contracts-bedrock/scripts/deploy/ReadImplementationAddresses.s.sol @@ -12,29 +12,18 @@ import { IAddressManager } from "src/legacy/interfaces/IAddressManager.sol"; import { IStaticL1ChugSplashProxy } from "src/legacy/interfaces/IL1ChugSplashProxy.sol"; contract ReadImplementationAddressesInput is DeployOPChainOutput { - OPContractsManager internal _opcmProxy; - string internal _release; + OPContractsManager internal _opcm; function set(bytes4 _sel, address _addr) public override { require(_addr != address(0), "ReadImplementationAddressesInput: cannot set zero address"); - if (_sel == this.opcmProxy.selector) _opcmProxy = OPContractsManager(_addr); + if (_sel == this.opcm.selector) _opcm = OPContractsManager(_addr); else if (_sel == this.addressManager.selector) _addressManager = IAddressManager(_addr); else super.set(_sel, _addr); } - function set(bytes4 _sel, string memory _val) public { - if (_sel == this.release.selector) _release = _val; - else revert("ReadImplementationAddressesInput: unknown selector"); - } - - function opcmProxy() public view returns (OPContractsManager) { - DeployUtils.assertValidContractAddress(address(_opcmProxy)); - return _opcmProxy; - } - - function release() public view returns (string memory) { - require(bytes(_release).length != 0, "ReadImplementationAddressesInput: release not set"); - return _release; + function opcm() public view returns (OPContractsManager) { + DeployUtils.assertValidContractAddress(address(_opcm)); + return _opcm; } } @@ -154,9 +143,12 @@ contract ReadImplementationAddresses is Script { vm.prank(address(0)); _rio.set(_rio.l1StandardBridge.selector, l1SBImpl); - (address mipsLogic,) = _rii.opcmProxy().implementations(_rii.release(), "MIPS"); + address mipsLogic = _rii.opcm().implementations().mipsImpl; _rio.set(_rio.mipsSingleton.selector, mipsLogic); + address delayedWETH = _rii.opcm().implementations().delayedWETHImpl; + _rio.set(_rio.delayedWETH.selector, delayedWETH); + IAddressManager am = _rii.addressManager(); _rio.set(_rio.l1CrossDomainMessenger.selector, am.getAddress("OVM_L1CrossDomainMessenger")); diff --git a/packages/contracts-bedrock/snapshots/abi/OPContractsManager.json b/packages/contracts-bedrock/snapshots/abi/OPContractsManager.json index 7c478feb235d..b5758eca610f 100644 --- a/packages/contracts-bedrock/snapshots/abi/OPContractsManager.json +++ b/packages/contracts-bedrock/snapshots/abi/OPContractsManager.json @@ -10,6 +10,110 @@ "internalType": "contract IProtocolVersions", "name": "_protocolVersions", "type": "address" + }, + { + "internalType": "string", + "name": "_l1ContractsRelease", + "type": "string" + }, + { + "components": [ + { + "internalType": "address", + "name": "addressManager", + "type": "address" + }, + { + "internalType": "address", + "name": "proxy", + "type": "address" + }, + { + "internalType": "address", + "name": "proxyAdmin", + "type": "address" + }, + { + "internalType": "address", + "name": "l1ChugSplashProxy", + "type": "address" + }, + { + "internalType": "address", + "name": "resolvedDelegateProxy", + "type": "address" + }, + { + "internalType": "address", + "name": "anchorStateRegistry", + "type": "address" + }, + { + "internalType": "address", + "name": "permissionedDisputeGame1", + "type": "address" + }, + { + "internalType": "address", + "name": "permissionedDisputeGame2", + "type": "address" + } + ], + "internalType": "struct OPContractsManager.Blueprints", + "name": "_blueprints", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "address", + "name": "l1ERC721BridgeImpl", + "type": "address" + }, + { + "internalType": "address", + "name": "optimismPortalImpl", + "type": "address" + }, + { + "internalType": "address", + "name": "systemConfigImpl", + "type": "address" + }, + { + "internalType": "address", + "name": "optimismMintableERC20FactoryImpl", + "type": "address" + }, + { + "internalType": "address", + "name": "l1CrossDomainMessengerImpl", + "type": "address" + }, + { + "internalType": "address", + "name": "l1StandardBridgeImpl", + "type": "address" + }, + { + "internalType": "address", + "name": "disputeGameFactoryImpl", + "type": "address" + }, + { + "internalType": "address", + "name": "delayedWETHImpl", + "type": "address" + }, + { + "internalType": "address", + "name": "mipsImpl", + "type": "address" + } + ], + "internalType": "struct OPContractsManager.Implementations", + "name": "_implementations", + "type": "tuple" } ], "stateMutability": "nonpayable", @@ -298,138 +402,68 @@ "type": "function" }, { - "inputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - }, - { - "internalType": "string", - "name": "", - "type": "string" - } - ], + "inputs": [], "name": "implementations", "outputs": [ - { - "internalType": "address", - "name": "logic", - "type": "address" - }, - { - "internalType": "bytes4", - "name": "initializer", - "type": "bytes4" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ { "components": [ { - "components": [ - { - "internalType": "address", - "name": "addressManager", - "type": "address" - }, - { - "internalType": "address", - "name": "proxy", - "type": "address" - }, - { - "internalType": "address", - "name": "proxyAdmin", - "type": "address" - }, - { - "internalType": "address", - "name": "l1ChugSplashProxy", - "type": "address" - }, - { - "internalType": "address", - "name": "resolvedDelegateProxy", - "type": "address" - }, - { - "internalType": "address", - "name": "anchorStateRegistry", - "type": "address" - }, - { - "internalType": "address", - "name": "permissionedDisputeGame1", - "type": "address" - }, - { - "internalType": "address", - "name": "permissionedDisputeGame2", - "type": "address" - } - ], - "internalType": "struct OPContractsManager.Blueprints", - "name": "blueprints", - "type": "tuple" + "internalType": "address", + "name": "l1ERC721BridgeImpl", + "type": "address" }, { - "components": [ - { - "internalType": "string", - "name": "name", - "type": "string" - }, - { - "components": [ - { - "internalType": "address", - "name": "logic", - "type": "address" - }, - { - "internalType": "bytes4", - "name": "initializer", - "type": "bytes4" - } - ], - "internalType": "struct OPContractsManager.Implementation", - "name": "info", - "type": "tuple" - } - ], - "internalType": "struct OPContractsManager.ImplementationSetter[]", - "name": "setters", - "type": "tuple[]" + "internalType": "address", + "name": "optimismPortalImpl", + "type": "address" }, { - "internalType": "string", - "name": "release", - "type": "string" + "internalType": "address", + "name": "systemConfigImpl", + "type": "address" + }, + { + "internalType": "address", + "name": "optimismMintableERC20FactoryImpl", + "type": "address" + }, + { + "internalType": "address", + "name": "l1CrossDomainMessengerImpl", + "type": "address" + }, + { + "internalType": "address", + "name": "l1StandardBridgeImpl", + "type": "address" }, { - "internalType": "bool", - "name": "isLatest", - "type": "bool" + "internalType": "address", + "name": "disputeGameFactoryImpl", + "type": "address" + }, + { + "internalType": "address", + "name": "delayedWETHImpl", + "type": "address" + }, + { + "internalType": "address", + "name": "mipsImpl", + "type": "address" } ], - "internalType": "struct OPContractsManager.InitializerInputs", - "name": "_initializerInputs", + "internalType": "struct OPContractsManager.Implementations", + "name": "", "type": "tuple" } ], - "name": "initialize", - "outputs": [], - "stateMutability": "nonpayable", + "stateMutability": "view", "type": "function" }, { "inputs": [], - "name": "latestRelease", + "name": "l1ContractsRelease", "outputs": [ { "internalType": "string", @@ -529,19 +563,6 @@ "name": "Deployed", "type": "event" }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint8", - "name": "version", - "type": "uint8" - } - ], - "name": "Initialized", - "type": "event" - }, { "inputs": [ { diff --git a/packages/contracts-bedrock/snapshots/abi/OPContractsManagerInterop.json b/packages/contracts-bedrock/snapshots/abi/OPContractsManagerInterop.json index 7c478feb235d..b5758eca610f 100644 --- a/packages/contracts-bedrock/snapshots/abi/OPContractsManagerInterop.json +++ b/packages/contracts-bedrock/snapshots/abi/OPContractsManagerInterop.json @@ -10,6 +10,110 @@ "internalType": "contract IProtocolVersions", "name": "_protocolVersions", "type": "address" + }, + { + "internalType": "string", + "name": "_l1ContractsRelease", + "type": "string" + }, + { + "components": [ + { + "internalType": "address", + "name": "addressManager", + "type": "address" + }, + { + "internalType": "address", + "name": "proxy", + "type": "address" + }, + { + "internalType": "address", + "name": "proxyAdmin", + "type": "address" + }, + { + "internalType": "address", + "name": "l1ChugSplashProxy", + "type": "address" + }, + { + "internalType": "address", + "name": "resolvedDelegateProxy", + "type": "address" + }, + { + "internalType": "address", + "name": "anchorStateRegistry", + "type": "address" + }, + { + "internalType": "address", + "name": "permissionedDisputeGame1", + "type": "address" + }, + { + "internalType": "address", + "name": "permissionedDisputeGame2", + "type": "address" + } + ], + "internalType": "struct OPContractsManager.Blueprints", + "name": "_blueprints", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "address", + "name": "l1ERC721BridgeImpl", + "type": "address" + }, + { + "internalType": "address", + "name": "optimismPortalImpl", + "type": "address" + }, + { + "internalType": "address", + "name": "systemConfigImpl", + "type": "address" + }, + { + "internalType": "address", + "name": "optimismMintableERC20FactoryImpl", + "type": "address" + }, + { + "internalType": "address", + "name": "l1CrossDomainMessengerImpl", + "type": "address" + }, + { + "internalType": "address", + "name": "l1StandardBridgeImpl", + "type": "address" + }, + { + "internalType": "address", + "name": "disputeGameFactoryImpl", + "type": "address" + }, + { + "internalType": "address", + "name": "delayedWETHImpl", + "type": "address" + }, + { + "internalType": "address", + "name": "mipsImpl", + "type": "address" + } + ], + "internalType": "struct OPContractsManager.Implementations", + "name": "_implementations", + "type": "tuple" } ], "stateMutability": "nonpayable", @@ -298,138 +402,68 @@ "type": "function" }, { - "inputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - }, - { - "internalType": "string", - "name": "", - "type": "string" - } - ], + "inputs": [], "name": "implementations", "outputs": [ - { - "internalType": "address", - "name": "logic", - "type": "address" - }, - { - "internalType": "bytes4", - "name": "initializer", - "type": "bytes4" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ { "components": [ { - "components": [ - { - "internalType": "address", - "name": "addressManager", - "type": "address" - }, - { - "internalType": "address", - "name": "proxy", - "type": "address" - }, - { - "internalType": "address", - "name": "proxyAdmin", - "type": "address" - }, - { - "internalType": "address", - "name": "l1ChugSplashProxy", - "type": "address" - }, - { - "internalType": "address", - "name": "resolvedDelegateProxy", - "type": "address" - }, - { - "internalType": "address", - "name": "anchorStateRegistry", - "type": "address" - }, - { - "internalType": "address", - "name": "permissionedDisputeGame1", - "type": "address" - }, - { - "internalType": "address", - "name": "permissionedDisputeGame2", - "type": "address" - } - ], - "internalType": "struct OPContractsManager.Blueprints", - "name": "blueprints", - "type": "tuple" + "internalType": "address", + "name": "l1ERC721BridgeImpl", + "type": "address" }, { - "components": [ - { - "internalType": "string", - "name": "name", - "type": "string" - }, - { - "components": [ - { - "internalType": "address", - "name": "logic", - "type": "address" - }, - { - "internalType": "bytes4", - "name": "initializer", - "type": "bytes4" - } - ], - "internalType": "struct OPContractsManager.Implementation", - "name": "info", - "type": "tuple" - } - ], - "internalType": "struct OPContractsManager.ImplementationSetter[]", - "name": "setters", - "type": "tuple[]" + "internalType": "address", + "name": "optimismPortalImpl", + "type": "address" }, { - "internalType": "string", - "name": "release", - "type": "string" + "internalType": "address", + "name": "systemConfigImpl", + "type": "address" + }, + { + "internalType": "address", + "name": "optimismMintableERC20FactoryImpl", + "type": "address" + }, + { + "internalType": "address", + "name": "l1CrossDomainMessengerImpl", + "type": "address" + }, + { + "internalType": "address", + "name": "l1StandardBridgeImpl", + "type": "address" }, { - "internalType": "bool", - "name": "isLatest", - "type": "bool" + "internalType": "address", + "name": "disputeGameFactoryImpl", + "type": "address" + }, + { + "internalType": "address", + "name": "delayedWETHImpl", + "type": "address" + }, + { + "internalType": "address", + "name": "mipsImpl", + "type": "address" } ], - "internalType": "struct OPContractsManager.InitializerInputs", - "name": "_initializerInputs", + "internalType": "struct OPContractsManager.Implementations", + "name": "", "type": "tuple" } ], - "name": "initialize", - "outputs": [], - "stateMutability": "nonpayable", + "stateMutability": "view", "type": "function" }, { "inputs": [], - "name": "latestRelease", + "name": "l1ContractsRelease", "outputs": [ { "internalType": "string", @@ -529,19 +563,6 @@ "name": "Deployed", "type": "event" }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint8", - "name": "version", - "type": "uint8" - } - ], - "name": "Initialized", - "type": "event" - }, { "inputs": [ { diff --git a/packages/contracts-bedrock/snapshots/semver-lock.json b/packages/contracts-bedrock/snapshots/semver-lock.json index e96fa687e9c6..8f40dca3ff43 100644 --- a/packages/contracts-bedrock/snapshots/semver-lock.json +++ b/packages/contracts-bedrock/snapshots/semver-lock.json @@ -20,8 +20,8 @@ "sourceCodeHash": "0x4132ff37d267cb12224b75ea806c0aa7d25407b0d66ce526d7fcda8f7d223882" }, "src/L1/OPContractsManager.sol": { - "initCodeHash": "0xd58cb3978affc5c1457cdd498ff8420c90aef804d4c3b62cf42ab2691986d6d2", - "sourceCodeHash": "0x7bfa6eff76176649fe600303cd60009a0f6e282cbaec55836b5ea1f8875cbeb5" + "initCodeHash": "0xd038cc35325d023499151264232d75fa4ecc81f04a8c8353e6b50c43af224d6e", + "sourceCodeHash": "0xa13f3ab2b8744015290dbabe5f20fdd44774607e6a7ad3e5e016303fc4aa8c12" }, "src/L1/OptimismPortal.sol": { "initCodeHash": "0x152167cfa18635ae4918a6eb3371a599cfa084418c0a652799cdb48bfc0ee0cc", diff --git a/packages/contracts-bedrock/snapshots/storageLayout/OPContractsManager.json b/packages/contracts-bedrock/snapshots/storageLayout/OPContractsManager.json index aeef539c5c20..aa8148b34cba 100644 --- a/packages/contracts-bedrock/snapshots/storageLayout/OPContractsManager.json +++ b/packages/contracts-bedrock/snapshots/storageLayout/OPContractsManager.json @@ -1,51 +1,30 @@ [ - { - "bytes": "1", - "label": "_initialized", - "offset": 0, - "slot": "0", - "type": "uint8" - }, - { - "bytes": "1", - "label": "_initializing", - "offset": 1, - "slot": "0", - "type": "bool" - }, { "bytes": "32", - "label": "latestRelease", + "label": "l1ContractsRelease", "offset": 0, - "slot": "1", + "slot": "0", "type": "string" }, - { - "bytes": "32", - "label": "implementations", - "offset": 0, - "slot": "2", - "type": "mapping(string => mapping(string => struct OPContractsManager.Implementation))" - }, { "bytes": "32", "label": "systemConfigs", "offset": 0, - "slot": "3", + "slot": "1", "type": "mapping(uint256 => contract ISystemConfig)" }, { "bytes": "256", "label": "blueprint", "offset": 0, - "slot": "4", + "slot": "2", "type": "struct OPContractsManager.Blueprints" }, { - "bytes": "1600", - "label": "__gap", + "bytes": "288", + "label": "implementation", "offset": 0, - "slot": "12", - "type": "uint256[50]" + "slot": "10", + "type": "struct OPContractsManager.Implementations" } ] \ No newline at end of file diff --git a/packages/contracts-bedrock/snapshots/storageLayout/OPContractsManagerInterop.json b/packages/contracts-bedrock/snapshots/storageLayout/OPContractsManagerInterop.json index aeef539c5c20..aa8148b34cba 100644 --- a/packages/contracts-bedrock/snapshots/storageLayout/OPContractsManagerInterop.json +++ b/packages/contracts-bedrock/snapshots/storageLayout/OPContractsManagerInterop.json @@ -1,51 +1,30 @@ [ - { - "bytes": "1", - "label": "_initialized", - "offset": 0, - "slot": "0", - "type": "uint8" - }, - { - "bytes": "1", - "label": "_initializing", - "offset": 1, - "slot": "0", - "type": "bool" - }, { "bytes": "32", - "label": "latestRelease", + "label": "l1ContractsRelease", "offset": 0, - "slot": "1", + "slot": "0", "type": "string" }, - { - "bytes": "32", - "label": "implementations", - "offset": 0, - "slot": "2", - "type": "mapping(string => mapping(string => struct OPContractsManager.Implementation))" - }, { "bytes": "32", "label": "systemConfigs", "offset": 0, - "slot": "3", + "slot": "1", "type": "mapping(uint256 => contract ISystemConfig)" }, { "bytes": "256", "label": "blueprint", "offset": 0, - "slot": "4", + "slot": "2", "type": "struct OPContractsManager.Blueprints" }, { - "bytes": "1600", - "label": "__gap", + "bytes": "288", + "label": "implementation", "offset": 0, - "slot": "12", - "type": "uint256[50]" + "slot": "10", + "type": "struct OPContractsManager.Implementations" } ] \ No newline at end of file diff --git a/packages/contracts-bedrock/src/L1/OPContractsManager.sol b/packages/contracts-bedrock/src/L1/OPContractsManager.sol index 4bf52ff228a1..a2a5a5f215b0 100644 --- a/packages/contracts-bedrock/src/L1/OPContractsManager.sol +++ b/packages/contracts-bedrock/src/L1/OPContractsManager.sol @@ -4,15 +4,12 @@ pragma solidity 0.8.15; import { Blueprint } from "src/libraries/Blueprint.sol"; import { Constants } from "src/libraries/Constants.sol"; -import { Initializable } from "@openzeppelin/contracts/proxy/utils/Initializable.sol"; - 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 { ISystemConfigV160 } from "src/L1/interfaces/ISystemConfigV160.sol"; import { IAddressManager } from "src/legacy/interfaces/IAddressManager.sol"; import { IProxyAdmin } from "src/universal/interfaces/IProxyAdmin.sol"; @@ -28,14 +25,12 @@ import { ISuperchainConfig } from "src/L1/interfaces/ISuperchainConfig.sol"; import { IProtocolVersions } from "src/L1/interfaces/IProtocolVersions.sol"; import { IOptimismPortal2 } from "src/L1/interfaces/IOptimismPortal2.sol"; import { ISystemConfig } from "src/L1/interfaces/ISystemConfig.sol"; -import { ISystemConfigV160 } from "src/L1/interfaces/ISystemConfigV160.sol"; import { IL1CrossDomainMessenger } from "src/L1/interfaces/IL1CrossDomainMessenger.sol"; import { IL1ERC721Bridge } from "src/L1/interfaces/IL1ERC721Bridge.sol"; import { IL1StandardBridge } from "src/L1/interfaces/IL1StandardBridge.sol"; import { IOptimismMintableERC20Factory } from "src/universal/interfaces/IOptimismMintableERC20Factory.sol"; -/// @custom:proxied true -contract OPContractsManager is ISemver, Initializable { +contract OPContractsManager is ISemver { // -------- Structs -------- /// @notice Represents the roles that can be set when deploying a standard OP Stack chain. @@ -89,19 +84,6 @@ contract OPContractsManager is ISemver, Initializable { IDelayedWETH delayedWETHPermissionlessGameProxy; } - /// @notice The logic address and initializer selector for an implementation contract. - struct Implementation { - address logic; // Address containing the deployed logic contract. - bytes4 initializer; // Function selector for the initializer. - } - - /// @notice Used to set the implementation for a contract by mapping a contract - /// name to the implementation data. - struct ImplementationSetter { - string name; // Contract name. - Implementation info; // Implementation to set. - } - /// @notice Addresses of ERC-5202 Blueprint contracts. There are used for deploying full size /// contracts, to reduce the code size of this factory contract. If it deployed full contracts /// using the `new Proxy()` syntax, the code size would get large fast, since this contract would @@ -118,19 +100,23 @@ contract OPContractsManager is ISemver, Initializable { address permissionedDisputeGame2; } - /// @notice Inputs required when initializing the OPContractsManager. To avoid 'StackTooDeep' errors, - /// all necessary inputs (excluding immutables) for initialization are bundled together in this struct. - struct InitializerInputs { - Blueprints blueprints; - ImplementationSetter[] setters; - string release; - bool isLatest; + /// @notice The latest implementation contracts for the OP Stack. + struct Implementations { + address l1ERC721BridgeImpl; + address optimismPortalImpl; + address systemConfigImpl; + address optimismMintableERC20FactoryImpl; + address l1CrossDomainMessengerImpl; + address l1StandardBridgeImpl; + address disputeGameFactoryImpl; + address delayedWETHImpl; + address mipsImpl; } // -------- Constants and Variables -------- - /// @custom:semver 1.0.0-beta.20 - string public constant version = "1.0.0-beta.20"; + /// @custom:semver 1.0.0-beta.21 + string public constant version = "1.0.0-beta.21"; /// @notice Represents the interface version so consumers know how to decode the DeployOutput struct /// that's emitted in the `Deployed` event. Whenever that struct changes, a new version should be used. @@ -142,24 +128,20 @@ contract OPContractsManager is ISemver, Initializable { /// @notice Address of the ProtocolVersions contract shared by all chains. IProtocolVersions public immutable protocolVersions; - /// @notice The latest release of the OP Contracts Manager, as a string of the format `op-contracts/vX.Y.Z`. - string public latestRelease; - - /// @notice Maps a release version to a contract name to it's implementation data. - mapping(string => mapping(string => Implementation)) public implementations; + // @notice L1 smart contracts release deployed by this version of OPCM. This is used in opcm to signal which version + // of the L1 smart contracts is deployed. It takes the format of `op-contracts/vX.Y.Z`. + string public l1ContractsRelease; /// @notice Maps an L2 Chain ID to the SystemConfig for that chain. mapping(uint256 => ISystemConfig) 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. + /// addresses, but we want it to return a struct. 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; + /// @notice Addresses of the latest implementation contracts. + Implementations internal implementation; // -------- Events -------- @@ -197,37 +179,26 @@ contract OPContractsManager is ISemver, Initializable { // -------- Methods -------- - /// @notice OPCM is proxied. Therefore the `initialize` function replaces most constructor logic for this contract. - - constructor(ISuperchainConfig _superchainConfig, IProtocolVersions _protocolVersions) { + constructor( + ISuperchainConfig _superchainConfig, + IProtocolVersions _protocolVersions, + string memory _l1ContractsRelease, + Blueprints memory _blueprints, + Implementations memory _implementations + ) { assertValidContractAddress(address(_superchainConfig)); assertValidContractAddress(address(_protocolVersions)); superchainConfig = _superchainConfig; protocolVersions = _protocolVersions; - _disableInitializers(); - } - - function initialize(InitializerInputs memory _initializerInputs) public initializer { - if (_initializerInputs.isLatest) latestRelease = _initializerInputs.release; - if (keccak256(bytes(latestRelease)) == keccak256("")) revert LatestReleaseNotSet(); + l1ContractsRelease = _l1ContractsRelease; - for (uint256 i = 0; i < _initializerInputs.setters.length; i++) { - ImplementationSetter memory setter = _initializerInputs.setters[i]; - Implementation storage impl = implementations[_initializerInputs.release][setter.name]; - if (impl.logic != address(0)) revert AlreadyReleased(); - - impl.initializer = setter.info.initializer; - impl.logic = setter.info.logic; - } - - blueprint = _initializerInputs.blueprints; + blueprint = _blueprints; + implementation = _implementations; } function deploy(DeployInput calldata _input) external returns (DeployOutput memory) { assertValidInputs(_input); - uint256 l2ChainId = _input.l2ChainId; - // The salt for a non-proxy contract is a function of the chain ID and the salt mixer. string memory saltMixer = _input.saltMixer; bytes32 salt = keccak256(abi.encode(l2ChainId, saltMixer)); @@ -266,7 +237,6 @@ contract OPContractsManager is ISemver, Initializable { payable(Blueprint.deployFrom(blueprint.l1ChugSplashProxy, salt, abi.encode(output.opChainProxyAdmin))) ); output.opChainProxyAdmin.setProxyType(address(output.l1StandardBridgeProxy), IProxyAdmin.ProxyType.CHUGSPLASH); - string memory contractName = "OVM_L1CrossDomainMessenger"; output.l1CrossDomainMessengerProxy = IL1CrossDomainMessenger( Blueprint.deployFrom(blueprint.resolvedDelegateProxy, salt, abi.encode(output.addressManager, contractName)) @@ -275,10 +245,8 @@ contract OPContractsManager is ISemver, Initializable { address(output.l1CrossDomainMessengerProxy), IProxyAdmin.ProxyType.RESOLVED ); output.opChainProxyAdmin.setImplementationName(address(output.l1CrossDomainMessengerProxy), contractName); - // Now that all proxies are deployed, we can transfer ownership of the AddressManager to the ProxyAdmin. output.addressManager.transferOwnership(address(output.opChainProxyAdmin)); - // The AnchorStateRegistry Implementation is not MCP Ready, and therefore requires an implementation per chain. // It must be deployed after the DisputeGameFactoryProxy so that it can be provided as a constructor argument. output.anchorStateRegistryImpl = IAnchorStateRegistry( @@ -301,54 +269,76 @@ contract OPContractsManager is ISemver, Initializable { ); // -------- Set and Initialize Proxy Implementations -------- - Implementation memory impl; bytes memory data; - impl = getLatestImplementation("L1ERC721Bridge"); - data = encodeL1ERC721BridgeInitializer(impl.initializer, output); - upgradeAndCall(output.opChainProxyAdmin, address(output.l1ERC721BridgeProxy), impl.logic, data); + data = encodeL1ERC721BridgeInitializer(IL1ERC721Bridge.initialize.selector, output); + upgradeAndCall( + output.opChainProxyAdmin, address(output.l1ERC721BridgeProxy), implementation.l1ERC721BridgeImpl, data + ); - impl = getLatestImplementation("OptimismPortal"); - data = encodeOptimismPortalInitializer(impl.initializer, output); - upgradeAndCall(output.opChainProxyAdmin, address(output.optimismPortalProxy), impl.logic, data); + data = encodeOptimismPortalInitializer(IOptimismPortal2.initialize.selector, output); + upgradeAndCall( + output.opChainProxyAdmin, address(output.optimismPortalProxy), implementation.optimismPortalImpl, data + ); // First we upgrade the implementation so it's version can be retrieved, then we initialize // it afterwards. See the comments in encodeSystemConfigInitializer to learn more. - impl = getLatestImplementation("SystemConfig"); - output.opChainProxyAdmin.upgrade(payable(address(output.systemConfigProxy)), impl.logic); - data = encodeSystemConfigInitializer(impl.initializer, _input, output); - upgradeAndCall(output.opChainProxyAdmin, address(output.systemConfigProxy), impl.logic, data); + output.opChainProxyAdmin.upgrade(payable(address(output.systemConfigProxy)), implementation.systemConfigImpl); + data = encodeSystemConfigInitializer(_input, output); + upgradeAndCall( + output.opChainProxyAdmin, address(output.systemConfigProxy), implementation.systemConfigImpl, data + ); - impl = getLatestImplementation("OptimismMintableERC20Factory"); - data = encodeOptimismMintableERC20FactoryInitializer(impl.initializer, output); - upgradeAndCall(output.opChainProxyAdmin, address(output.optimismMintableERC20FactoryProxy), impl.logic, data); + data = encodeOptimismMintableERC20FactoryInitializer(IOptimismMintableERC20Factory.initialize.selector, output); + upgradeAndCall( + output.opChainProxyAdmin, + address(output.optimismMintableERC20FactoryProxy), + implementation.optimismMintableERC20FactoryImpl, + data + ); - impl = getLatestImplementation("L1CrossDomainMessenger"); - data = encodeL1CrossDomainMessengerInitializer(impl.initializer, output); - upgradeAndCall(output.opChainProxyAdmin, address(output.l1CrossDomainMessengerProxy), impl.logic, data); + data = encodeL1CrossDomainMessengerInitializer(IL1CrossDomainMessenger.initialize.selector, output); + upgradeAndCall( + output.opChainProxyAdmin, + address(output.l1CrossDomainMessengerProxy), + implementation.l1CrossDomainMessengerImpl, + data + ); - impl = getLatestImplementation("L1StandardBridge"); - data = encodeL1StandardBridgeInitializer(impl.initializer, output); - upgradeAndCall(output.opChainProxyAdmin, address(output.l1StandardBridgeProxy), impl.logic, data); + data = encodeL1StandardBridgeInitializer(IL1StandardBridge.initialize.selector, output); + upgradeAndCall( + output.opChainProxyAdmin, address(output.l1StandardBridgeProxy), implementation.l1StandardBridgeImpl, data + ); - impl = getLatestImplementation("DelayedWETH"); - data = encodeDelayedWETHInitializer(impl.initializer, _input); + data = encodeDelayedWETHInitializer(IDelayedWETH.initialize.selector, _input); // Eventually we will switch from DelayedWETHPermissionedGameProxy to DelayedWETHPermissionlessGameProxy. - upgradeAndCall(output.opChainProxyAdmin, address(output.delayedWETHPermissionedGameProxy), impl.logic, data); + upgradeAndCall( + output.opChainProxyAdmin, + address(output.delayedWETHPermissionedGameProxy), + implementation.delayedWETHImpl, + 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); + data = encodeDisputeGameFactoryInitializer(IDisputeGameFactory.initialize.selector, _input); + upgradeAndCall( + output.opChainProxyAdmin, + address(output.disputeGameFactoryProxy), + implementation.disputeGameFactoryImpl, + data + ); output.disputeGameFactoryProxy.setImplementation( GameTypes.PERMISSIONED_CANNON, IDisputeGame(address(output.permissionedDisputeGame)) ); output.disputeGameFactoryProxy.transferOwnership(address(_input.roles.opChainProxyAdminOwner)); - impl.logic = address(output.anchorStateRegistryImpl); - impl.initializer = IAnchorStateRegistry.initialize.selector; - data = encodeAnchorStateRegistryInitializer(impl.initializer, _input); - upgradeAndCall(output.opChainProxyAdmin, address(output.anchorStateRegistryProxy), impl.logic, data); + data = encodeAnchorStateRegistryInitializer(IAnchorStateRegistry.initialize.selector, _input); + upgradeAndCall( + output.opChainProxyAdmin, + address(output.anchorStateRegistryProxy), + address(output.anchorStateRegistryImpl), + data + ); // -------- Finalize Deployment -------- // Transfer ownership of the ProxyAdmin from this contract to the specified owner. @@ -402,13 +392,6 @@ contract OPContractsManager is ISemver, Initializable { return Blueprint.deployFrom(blueprint.proxy, salt, abi.encode(_proxyAdmin)); } - /// @notice Returns the implementation data for a contract name. Makes a copy of the internal - // Implementation struct in storage to prevent accidental mutation of the internal data. - function getLatestImplementation(string memory _name) internal view returns (Implementation memory) { - Implementation storage impl = implementations[latestRelease][_name]; - return Implementation({ logic: impl.logic, initializer: impl.initializer }); - } - // -------- Initializer Encoding -------- /// @notice Helper method for encoding the L1ERC721Bridge initializer data. @@ -445,7 +428,6 @@ contract OPContractsManager is ISemver, Initializable { /// @notice Helper method for encoding the SystemConfig initializer data. function encodeSystemConfigInitializer( - bytes4 _selector, DeployInput memory _input, DeployOutput memory _output ) @@ -454,50 +436,22 @@ contract OPContractsManager is ISemver, Initializable { virtual returns (bytes memory) { - // We inspect the SystemConfig contract and determine it's signature here. This is required - // because this OPCM contract is being developed in a repository that no longer contains the - // SystemConfig contract that was released as part of `op-contracts/v1.6.0`, but in production - // it needs to support that version, in addition to the version currently on develop. - string memory semver = _output.systemConfigProxy.version(); - if (keccak256(abi.encode(semver)) == keccak256(abi.encode(string("2.2.0")))) { - // We are using the op-contracts/v1.6.0 SystemConfig contract. - ( - IResourceMetering.ResourceConfig memory referenceResourceConfig, - ISystemConfigV160.Addresses memory opChainAddrs - ) = defaultSystemConfigV160Params(_selector, _input, _output); - - return abi.encodeWithSelector( - _selector, - _input.roles.systemConfigOwner, - _input.basefeeScalar, - _input.blobBasefeeScalar, - bytes32(uint256(uint160(_input.roles.batcher))), // batcherHash - _input.gasLimit, - _input.roles.unsafeBlockSigner, - referenceResourceConfig, - chainIdToBatchInboxAddress(_input.l2ChainId), - opChainAddrs - ); - } else { - // We are using the latest SystemConfig contract from the repo. - ( - IResourceMetering.ResourceConfig memory referenceResourceConfig, - ISystemConfig.Addresses memory opChainAddrs - ) = defaultSystemConfigParams(_selector, _input, _output); - - return abi.encodeWithSelector( - _selector, - _input.roles.systemConfigOwner, - _input.basefeeScalar, - _input.blobBasefeeScalar, - bytes32(uint256(uint160(_input.roles.batcher))), // batcherHash - _input.gasLimit, - _input.roles.unsafeBlockSigner, - referenceResourceConfig, - chainIdToBatchInboxAddress(_input.l2ChainId), - opChainAddrs - ); - } + bytes4 selector = ISystemConfig.initialize.selector; + (IResourceMetering.ResourceConfig memory referenceResourceConfig, ISystemConfig.Addresses memory opChainAddrs) = + defaultSystemConfigParams(selector, _input, _output); + + return abi.encodeWithSelector( + selector, + _input.roles.systemConfigOwner, + _input.basefeeScalar, + _input.blobBasefeeScalar, + bytes32(uint256(uint160(_input.roles.batcher))), // batcherHash + _input.gasLimit, + _input.roles.unsafeBlockSigner, + referenceResourceConfig, + chainIdToBatchInboxAddress(_input.l2ChainId), + opChainAddrs + ); } /// @notice Helper method for encoding the OptimismMintableERC20Factory initializer data. @@ -599,7 +553,7 @@ contract OPContractsManager is ISemver, Initializable { _input.disputeSplitDepth, _input.disputeClockExtension, _input.disputeMaxClockDuration, - IBigStepper(getLatestImplementation("MIPS").logic), + IBigStepper(implementation.mipsImpl), IDelayedWETH(payable(address(_output.delayedWETHPermissionedGameProxy))), IAnchorStateRegistry(address(_output.anchorStateRegistryProxy)), _input.l2ChainId, @@ -645,45 +599,6 @@ contract OPContractsManager is ISemver, Initializable { assertValidContractAddress(opChainAddrs_.optimismMintableERC20Factory); } - /// @notice Returns default, standard config arguments for the SystemConfig initializer. - /// This is used by subclasses to reduce code duplication. - function defaultSystemConfigV160Params( - bytes4, /* selector */ - DeployInput memory, /* _input */ - DeployOutput memory _output - ) - internal - view - virtual - returns ( - IResourceMetering.ResourceConfig memory resourceConfig_, - ISystemConfigV160.Addresses memory opChainAddrs_ - ) - { - // We use assembly to easily convert from IResourceMetering.ResourceConfig to ResourceMetering.ResourceConfig. - // This is required because we have not yet fully migrated the codebase to be interface-based. - IResourceMetering.ResourceConfig memory resourceConfig = Constants.DEFAULT_RESOURCE_CONFIG(); - assembly ("memory-safe") { - resourceConfig_ := resourceConfig - } - - opChainAddrs_ = ISystemConfigV160.Addresses({ - l1CrossDomainMessenger: address(_output.l1CrossDomainMessengerProxy), - l1ERC721Bridge: address(_output.l1ERC721BridgeProxy), - l1StandardBridge: address(_output.l1StandardBridgeProxy), - disputeGameFactory: address(_output.disputeGameFactoryProxy), - optimismPortal: address(_output.optimismPortalProxy), - optimismMintableERC20Factory: address(_output.optimismMintableERC20FactoryProxy) - }); - - assertValidContractAddress(opChainAddrs_.l1CrossDomainMessenger); - assertValidContractAddress(opChainAddrs_.l1ERC721Bridge); - assertValidContractAddress(opChainAddrs_.l1StandardBridge); - assertValidContractAddress(opChainAddrs_.disputeGameFactory); - assertValidContractAddress(opChainAddrs_.optimismPortal); - assertValidContractAddress(opChainAddrs_.optimismMintableERC20Factory); - } - /// @notice Makes an external call to the target to initialize the proxy with the specified data. /// First performs safety checks to ensure the target, implementation, and proxy admin are valid. function upgradeAndCall( @@ -710,4 +625,9 @@ contract OPContractsManager is ISemver, Initializable { function blueprints() public view returns (Blueprints memory) { return blueprint; } + + /// @notice Returns the implementation contract addresses. + function implementations() public view returns (Implementations memory) { + return implementation; + } } diff --git a/packages/contracts-bedrock/src/L1/OPContractsManagerInterop.sol b/packages/contracts-bedrock/src/L1/OPContractsManagerInterop.sol index 19de5537b41c..79e0efda9735 100644 --- a/packages/contracts-bedrock/src/L1/OPContractsManagerInterop.sol +++ b/packages/contracts-bedrock/src/L1/OPContractsManagerInterop.sol @@ -6,20 +6,22 @@ import { ISuperchainConfig } from "src/L1/interfaces/ISuperchainConfig.sol"; import { IProtocolVersions } from "src/L1/interfaces/IProtocolVersions.sol"; import { IResourceMetering } from "src/L1/interfaces/IResourceMetering.sol"; import { ISystemConfig } from "src/L1/interfaces/ISystemConfig.sol"; +import { ISystemConfigInterop } from "src/L1/interfaces/ISystemConfigInterop.sol"; -/// @custom:proxied true contract OPContractsManagerInterop is OPContractsManager { constructor( ISuperchainConfig _superchainConfig, - IProtocolVersions _protocolVersions + IProtocolVersions _protocolVersions, + string memory _l1ContractsRelease, + Blueprints memory _blueprints, + Implementations memory _implementations ) - OPContractsManager(_superchainConfig, _protocolVersions) + OPContractsManager(_superchainConfig, _protocolVersions, _l1ContractsRelease, _blueprints, _implementations) { } // The `SystemConfigInterop` contract has an extra `address _dependencyManager` argument // that we must account for. function encodeSystemConfigInitializer( - bytes4 _selector, DeployInput memory _input, DeployOutput memory _output ) @@ -29,8 +31,9 @@ contract OPContractsManagerInterop is OPContractsManager { override returns (bytes memory) { + bytes4 selector = ISystemConfigInterop.initialize.selector; (IResourceMetering.ResourceConfig memory referenceResourceConfig, ISystemConfig.Addresses memory opChainAddrs) = - defaultSystemConfigParams(_selector, _input, _output); + defaultSystemConfigParams(selector, _input, _output); // TODO For now we assume that the dependency manager is the same as system config owner. // This is currently undefined since it's not part of the standard config, so we may need @@ -40,7 +43,7 @@ contract OPContractsManagerInterop is OPContractsManager { address dependencyManager = address(_input.roles.systemConfigOwner); return abi.encodeWithSelector( - _selector, + selector, _input.roles.systemConfigOwner, _input.basefeeScalar, _input.blobBasefeeScalar, diff --git a/packages/contracts-bedrock/src/L1/interfaces/ISystemConfigV160.sol b/packages/contracts-bedrock/src/L1/interfaces/ISystemConfigV160.sol deleted file mode 100644 index 210b0ddf8e5e..000000000000 --- a/packages/contracts-bedrock/src/L1/interfaces/ISystemConfigV160.sol +++ /dev/null @@ -1,85 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import { IResourceMetering } from "src/L1/interfaces/IResourceMetering.sol"; - -/// @notice This interface corresponds to the op-contracts/v1.6.0 release of the SystemConfig -/// contract, which has a semver of 2.2.0 as specified in -/// https://github.com/ethereum-optimism/optimism/releases/tag/op-contracts%2Fv1.6.0 -interface ISystemConfigV160 { - enum UpdateType { - BATCHER, - FEE_SCALARS, - GAS_LIMIT, - UNSAFE_BLOCK_SIGNER - } - - struct Addresses { - address l1CrossDomainMessenger; - address l1ERC721Bridge; - address l1StandardBridge; - address disputeGameFactory; - address optimismPortal; - address optimismMintableERC20Factory; - } - - event ConfigUpdate(uint256 indexed version, UpdateType indexed updateType, bytes data); - event Initialized(uint8 version); - event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); - - function BATCH_INBOX_SLOT() external view returns (bytes32); - function DISPUTE_GAME_FACTORY_SLOT() external view returns (bytes32); - function L1_CROSS_DOMAIN_MESSENGER_SLOT() external view returns (bytes32); - function L1_ERC_721_BRIDGE_SLOT() external view returns (bytes32); - function L1_STANDARD_BRIDGE_SLOT() external view returns (bytes32); - function OPTIMISM_MINTABLE_ERC20_FACTORY_SLOT() external view returns (bytes32); - function OPTIMISM_PORTAL_SLOT() external view returns (bytes32); - function START_BLOCK_SLOT() external view returns (bytes32); - function UNSAFE_BLOCK_SIGNER_SLOT() external view returns (bytes32); - function VERSION() external view returns (uint256); - function basefeeScalar() external view returns (uint32); - function batchInbox() external view returns (address addr_); - function batcherHash() external view returns (bytes32); - function blobbasefeeScalar() external view returns (uint32); - function disputeGameFactory() external view returns (address addr_); - function gasLimit() external view returns (uint64); - function gasPayingToken() external view returns (address addr_, uint8 decimals_); - function gasPayingTokenName() external view returns (string memory name_); - function gasPayingTokenSymbol() external view returns (string memory symbol_); - function initialize( - address _owner, - uint256 _basefeeScalar, - uint256 _blobbasefeeScalar, - bytes32 _batcherHash, - uint64 _gasLimit, - address _unsafeBlockSigner, - IResourceMetering.ResourceConfig memory _config, - address _batchInbox, - Addresses memory _addresses - ) - external; - function isCustomGasToken() external view returns (bool); - function l1CrossDomainMessenger() external view returns (address addr_); - function l1ERC721Bridge() external view returns (address addr_); - function l1StandardBridge() external view returns (address addr_); - function maximumGasLimit() external pure returns (uint64); - function minimumGasLimit() external view returns (uint64); - function optimismMintableERC20Factory() external view returns (address addr_); - function optimismPortal() external view returns (address addr_); - function overhead() external view returns (uint256); - function owner() external view returns (address); - function renounceOwnership() external; - function resourceConfig() external view returns (IResourceMetering.ResourceConfig memory); - function scalar() external view returns (uint256); - function setBatcherHash(bytes32 _batcherHash) external; - function setGasConfig(uint256 _overhead, uint256 _scalar) external; - function setGasConfigEcotone(uint32 _basefeeScalar, uint32 _blobbasefeeScalar) external; - function setGasLimit(uint64 _gasLimit) external; - function setUnsafeBlockSigner(address _unsafeBlockSigner) external; - function startBlock() external view returns (uint256 startBlock_); - function transferOwnership(address newOwner) external; // nosemgrep - function unsafeBlockSigner() external view returns (address addr_); - function version() external pure returns (string memory); - - function __constructor__() external; -} diff --git a/packages/contracts-bedrock/test/L1/OPContractsManager.t.sol b/packages/contracts-bedrock/test/L1/OPContractsManager.t.sol index 5b2260fce992..e828b415621e 100644 --- a/packages/contracts-bedrock/test/L1/OPContractsManager.t.sol +++ b/packages/contracts-bedrock/test/L1/OPContractsManager.t.sol @@ -14,9 +14,12 @@ import { IProtocolVersions } from "src/L1/interfaces/IProtocolVersions.sol"; contract OPContractsManager_Harness is OPContractsManager { constructor( ISuperchainConfig _superchainConfig, - IProtocolVersions _protocolVersions + IProtocolVersions _protocolVersions, + string memory _l1ContractsRelease, + Blueprints memory _blueprints, + Implementations memory _implementations ) - OPContractsManager(_superchainConfig, _protocolVersions) + OPContractsManager(_superchainConfig, _protocolVersions, _l1ContractsRelease, _blueprints, _implementations) { } function chainIdToBatchInboxAddress_exposed(uint256 l2ChainId) public pure returns (address) { @@ -49,7 +52,7 @@ contract OPContractsManager_Deploy_Test is DeployOPChain_TestBase { doi.set(doi.basefeeScalar.selector, basefeeScalar); doi.set(doi.blobBaseFeeScalar.selector, blobBaseFeeScalar); doi.set(doi.l2ChainId.selector, l2ChainId); - doi.set(doi.opcmProxy.selector, address(opcm)); + doi.set(doi.opcm.selector, address(opcm)); doi.set(doi.gasLimit.selector, gasLimit); doi.set(doi.disputeGameType.selector, disputeGameType); @@ -116,12 +119,17 @@ contract OPContractsManager_InternalMethods_Test is Test { function setUp() public { ISuperchainConfig superchainConfigProxy = ISuperchainConfig(makeAddr("superchainConfig")); IProtocolVersions protocolVersionsProxy = IProtocolVersions(makeAddr("protocolVersions")); + OPContractsManager.Blueprints memory emptyBlueprints; + OPContractsManager.Implementations memory emptyImpls; vm.etch(address(superchainConfigProxy), hex"01"); vm.etch(address(protocolVersionsProxy), hex"01"); opcmHarness = new OPContractsManager_Harness({ _superchainConfig: superchainConfigProxy, - _protocolVersions: protocolVersionsProxy + _protocolVersions: protocolVersionsProxy, + _l1ContractsRelease: "dev", + _blueprints: emptyBlueprints, + _implementations: emptyImpls }); } diff --git a/packages/contracts-bedrock/test/opcm/DeployImplementations.t.sol b/packages/contracts-bedrock/test/opcm/DeployImplementations.t.sol index 0282ea0b3d90..8d3feac2de0d 100644 --- a/packages/contracts-bedrock/test/opcm/DeployImplementations.t.sol +++ b/packages/contracts-bedrock/test/opcm/DeployImplementations.t.sol @@ -61,7 +61,7 @@ contract DeployImplementationsInput_Test is Test { dii.disputeGameFinalityDelaySeconds(); vm.expectRevert("DeployImplementationsInput: not set"); - dii.release(); + dii.l1ContractsRelease(); vm.expectRevert("DeployImplementationsInput: not set"); dii.superchainConfigProxy(); @@ -69,23 +69,9 @@ contract DeployImplementationsInput_Test is Test { vm.expectRevert("DeployImplementationsInput: not set"); dii.protocolVersionsProxy(); - vm.expectRevert("DeployImplementationsInput: not set"); - dii.opcmProxyOwner(); - vm.expectRevert("DeployImplementationsInput: not set"); dii.standardVersionsToml(); } - - function test_opcmProxyOwner_whenNotSet_reverts() public { - vm.expectRevert("DeployImplementationsInput: not set"); - dii.opcmProxyOwner(); - } - - function test_opcmProxyOwner_succeeds() public { - dii.set(dii.opcmProxyOwner.selector, address(msg.sender)); - address opcmProxyOwner = dii.opcmProxyOwner(); - assertEq(address(msg.sender), address(opcmProxyOwner), "100"); - } } contract DeployImplementationsOutput_Test is Test { @@ -96,17 +82,7 @@ contract DeployImplementationsOutput_Test is Test { } function test_set_succeeds() public { - IProxy proxy = IProxy( - DeployUtils.create1({ - _name: "Proxy", - _args: DeployUtils.encodeConstructor(abi.encodeCall(IProxy.__constructor__, (address(0)))) - }) - ); - address opcmImpl = address(makeAddr("opcmImpl")); - vm.prank(address(0)); - proxy.upgradeTo(opcmImpl); - - OPContractsManager opcmProxy = OPContractsManager(address(proxy)); + OPContractsManager opcm = OPContractsManager(address(makeAddr("opcm"))); IOptimismPortal2 optimismPortalImpl = IOptimismPortal2(payable(makeAddr("optimismPortalImpl"))); IDelayedWETH delayedWETHImpl = IDelayedWETH(payable(makeAddr("delayedWETHImpl"))); IPreimageOracle preimageOracleSingleton = IPreimageOracle(makeAddr("preimageOracleSingleton")); @@ -120,8 +96,7 @@ contract DeployImplementationsOutput_Test is Test { IOptimismMintableERC20Factory(makeAddr("optimismMintableERC20FactoryImpl")); IDisputeGameFactory disputeGameFactoryImpl = IDisputeGameFactory(makeAddr("disputeGameFactoryImpl")); - vm.etch(address(opcmProxy), address(opcmProxy).code); - vm.etch(address(opcmImpl), hex"01"); + vm.etch(address(opcm), hex"01"); vm.etch(address(optimismPortalImpl), hex"01"); vm.etch(address(delayedWETHImpl), hex"01"); vm.etch(address(preimageOracleSingleton), hex"01"); @@ -132,7 +107,7 @@ contract DeployImplementationsOutput_Test is Test { vm.etch(address(l1StandardBridgeImpl), hex"01"); vm.etch(address(optimismMintableERC20FactoryImpl), hex"01"); vm.etch(address(disputeGameFactoryImpl), hex"01"); - dio.set(dio.opcmProxy.selector, address(opcmProxy)); + dio.set(dio.opcm.selector, address(opcm)); dio.set(dio.optimismPortalImpl.selector, address(optimismPortalImpl)); dio.set(dio.delayedWETHImpl.selector, address(delayedWETHImpl)); dio.set(dio.preimageOracleSingleton.selector, address(preimageOracleSingleton)); @@ -144,7 +119,7 @@ contract DeployImplementationsOutput_Test is Test { dio.set(dio.optimismMintableERC20FactoryImpl.selector, address(optimismMintableERC20FactoryImpl)); dio.set(dio.disputeGameFactoryImpl.selector, address(disputeGameFactoryImpl)); - assertEq(address(opcmProxy), address(dio.opcmProxy()), "50"); + assertEq(address(opcm), address(dio.opcm()), "50"); assertEq(address(optimismPortalImpl), address(dio.optimismPortalImpl()), "100"); assertEq(address(delayedWETHImpl), address(dio.delayedWETHImpl()), "200"); assertEq(address(preimageOracleSingleton), address(dio.preimageOracleSingleton()), "300"); @@ -273,7 +248,7 @@ contract DeployImplementations_Test is Test { function test_deployImplementation_succeeds() public { string memory deployContractsRelease = "dev-release"; - dii.set(dii.release.selector, deployContractsRelease); + dii.set(dii.l1ContractsRelease.selector, deployContractsRelease); deployImplementations.deploySystemConfigImpl(dii, dio); assertTrue(address(0) != address(dio.systemConfigImpl())); } @@ -282,7 +257,7 @@ contract DeployImplementations_Test is Test { // All hardcoded addresses below are taken from the superchain-registry config: // https://github.com/ethereum-optimism/superchain-registry/blob/be65d22f8128cf0c4e5b4e1f677daf86843426bf/validation/standard/standard-versions.toml#L11 string memory testRelease = "op-contracts/v1.6.0"; - dii.set(dii.release.selector, testRelease); + dii.set(dii.l1ContractsRelease.selector, testRelease); deployImplementations.deploySystemConfigImpl(dii, dio); address srSystemConfigImpl = address(0xF56D96B2535B932656d3c04Ebf51baBff241D886); @@ -335,71 +310,6 @@ contract DeployImplementations_Test is Test { assertEq(srDisputeGameFactoryImpl, address(dio.disputeGameFactoryImpl())); } - function test_deploy_atNonExistentRelease_reverts() public { - string memory unknownRelease = "op-contracts/v0.0.0"; - dii.set(dii.release.selector, unknownRelease); - - bytes memory expectedErr = - bytes(string.concat("DeployImplementations: failed to deploy release ", unknownRelease)); - - vm.expectRevert(expectedErr); - deployImplementations.deploySystemConfigImpl(dii, dio); - - vm.expectRevert(expectedErr); - deployImplementations.deployL1CrossDomainMessengerImpl(dii, dio); - - vm.expectRevert(expectedErr); - deployImplementations.deployL1ERC721BridgeImpl(dii, dio); - - vm.expectRevert(expectedErr); - deployImplementations.deployL1StandardBridgeImpl(dii, dio); - - vm.expectRevert(expectedErr); - deployImplementations.deployOptimismMintableERC20FactoryImpl(dii, dio); - - // TODO: Uncomment the code below when OPContractsManager is deployed based on release. Superchain-registry - // doesn't contain OPContractsManager yet. - // dii.set(dii.superchainConfigProxy.selector, address(superchainConfigProxy)); - // dii.set(dii.protocolVersionsProxy.selector, address(protocolVersionsProxy)); - // vm.etch(address(superchainConfigProxy), hex"01"); - // vm.etch(address(protocolVersionsProxy), hex"01"); - // vm.expectRevert(expectedErr); - // deployImplementations.deployOPContractsManagerImpl(dii, dio); - - dii.set(dii.proofMaturityDelaySeconds.selector, 1); - dii.set(dii.disputeGameFinalityDelaySeconds.selector, 2); - vm.expectRevert(expectedErr); - deployImplementations.deployOptimismPortalImpl(dii, dio); - - dii.set(dii.withdrawalDelaySeconds.selector, 1); - vm.expectRevert(expectedErr); - deployImplementations.deployDelayedWETHImpl(dii, dio); - - dii.set(dii.minProposalSizeBytes.selector, 1); - dii.set(dii.challengePeriodSeconds.selector, 2); - vm.expectRevert(expectedErr); - deployImplementations.deployPreimageOracleSingleton(dii, dio); - - address preImageOracleSingleton = makeAddr("preImageOracleSingleton"); - vm.etch(address(preImageOracleSingleton), hex"01"); - dio.set(dio.preimageOracleSingleton.selector, preImageOracleSingleton); - vm.expectRevert(expectedErr); - deployImplementations.deployMipsSingleton(dii, dio); - - vm.expectRevert(expectedErr); // fault proof contracts don't exist at this release - deployImplementations.deployDisputeGameFactoryImpl(dii, dio); - } - - function test_deploy_noContractExistsAtRelease_reverts() public { - string memory unknownRelease = "op-contracts/v1.3.0"; - dii.set(dii.release.selector, unknownRelease); - bytes memory expectedErr = - bytes(string.concat("DeployImplementations: failed to deploy release ", unknownRelease)); - - vm.expectRevert(expectedErr); // fault proof contracts don't exist at this release - deployImplementations.deployDisputeGameFactoryImpl(dii, dio); - } - function testFuzz_run_memory_succeeds(bytes32 _seed) public { withdrawalDelaySeconds = uint256(hash(_seed, 0)); minProposalSizeBytes = uint256(hash(_seed, 1)); @@ -409,7 +319,7 @@ contract DeployImplementations_Test is Test { string memory release = string(bytes.concat(hash(_seed, 5))); protocolVersionsProxy = IProtocolVersions(address(uint160(uint256(hash(_seed, 7))))); - // Must configure the ProxyAdmin contract which is used to upgrade the OPCM's proxy contract. + // Must configure the ProxyAdmin contract. IProxyAdmin superchainProxyAdmin = IProxyAdmin( DeployUtils.create1({ _name: "ProxyAdmin", @@ -439,10 +349,9 @@ contract DeployImplementations_Test is Test { dii.set(dii.proofMaturityDelaySeconds.selector, proofMaturityDelaySeconds); dii.set(dii.disputeGameFinalityDelaySeconds.selector, disputeGameFinalityDelaySeconds); dii.set(dii.mipsVersion.selector, 1); - dii.set(dii.release.selector, release); + dii.set(dii.l1ContractsRelease.selector, release); dii.set(dii.superchainConfigProxy.selector, address(superchainConfigProxy)); dii.set(dii.protocolVersionsProxy.selector, address(protocolVersionsProxy)); - dii.set(dii.opcmProxyOwner.selector, msg.sender); deployImplementations.run(dii, dio); @@ -453,10 +362,9 @@ contract DeployImplementations_Test is Test { assertEq(proofMaturityDelaySeconds, dii.proofMaturityDelaySeconds(), "400"); assertEq(disputeGameFinalityDelaySeconds, dii.disputeGameFinalityDelaySeconds(), "500"); assertEq(1, dii.mipsVersion(), "512"); - assertEq(release, dii.release(), "525"); + assertEq(release, dii.l1ContractsRelease(), "525"); assertEq(address(superchainConfigProxy), address(dii.superchainConfigProxy()), "550"); assertEq(address(protocolVersionsProxy), address(dii.protocolVersionsProxy()), "575"); - assertEq(msg.sender, dii.opcmProxyOwner(), "580"); // Architecture assertions. assertEq(address(dio.mipsSingleton().oracle()), address(dio.preimageOracleSingleton()), "600"); @@ -475,7 +383,7 @@ contract DeployImplementations_Test is Test { dii.set(dii.disputeGameFinalityDelaySeconds.selector, disputeGameFinalityDelaySeconds); dii.set(dii.mipsVersion.selector, 1); string memory release = "dev-release"; - dii.set(dii.release.selector, release); + dii.set(dii.l1ContractsRelease.selector, release); dii.set(dii.superchainConfigProxy.selector, address(superchainConfigProxy)); dii.set(dii.protocolVersionsProxy.selector, address(protocolVersionsProxy)); diff --git a/packages/contracts-bedrock/test/opcm/DeployOPChain.t.sol b/packages/contracts-bedrock/test/opcm/DeployOPChain.t.sol index 5249ded41cc9..5280328168b9 100644 --- a/packages/contracts-bedrock/test/opcm/DeployOPChain.t.sol +++ b/packages/contracts-bedrock/test/opcm/DeployOPChain.t.sol @@ -39,10 +39,10 @@ contract DeployOPChainInput_Test is Test { address unsafeBlockSigner = makeAddr("unsafeBlockSigner"); address proposer = makeAddr("proposer"); address challenger = makeAddr("challenger"); + address opcm = makeAddr("opcm"); uint32 basefeeScalar = 100; uint32 blobBaseFeeScalar = 200; uint256 l2ChainId = 300; - OPContractsManager opcm = OPContractsManager(makeAddr("opcm")); string saltMixer = "saltMixer"; function setUp() public { @@ -60,9 +60,8 @@ contract DeployOPChainInput_Test is Test { doi.set(doi.blobBaseFeeScalar.selector, blobBaseFeeScalar); doi.set(doi.l2ChainId.selector, l2ChainId); doi.set(doi.allowCustomDisputeParameters.selector, true); - - (IProxy opcmProxy) = DeployUtils.buildERC1967ProxyWithImpl("opcmProxy"); - doi.set(doi.opcmProxy.selector, address(opcmProxy)); + doi.set(doi.opcm.selector, opcm); + vm.etch(opcm, hex"01"); // Compare the default inputs to the getter methods. assertEq(opChainProxyAdminOwner, doi.opChainProxyAdminOwner(), "200"); @@ -74,7 +73,7 @@ contract DeployOPChainInput_Test is Test { assertEq(basefeeScalar, doi.basefeeScalar(), "800"); assertEq(blobBaseFeeScalar, doi.blobBaseFeeScalar(), "900"); assertEq(l2ChainId, doi.l2ChainId(), "1000"); - assertEq(address(opcmProxy), address(doi.opcmProxy()), "1100"); + assertEq(opcm, address(doi.opcm()), "1100"); assertEq(true, doi.allowCustomDisputeParameters(), "1200"); } @@ -396,7 +395,7 @@ contract DeployOPChain_TestBase is Test { dii.set(dii.proofMaturityDelaySeconds.selector, proofMaturityDelaySeconds); dii.set(dii.disputeGameFinalityDelaySeconds.selector, disputeGameFinalityDelaySeconds); dii.set(dii.mipsVersion.selector, 1); - dii.set(dii.release.selector, release); + dii.set(dii.l1ContractsRelease.selector, release); dii.set(dii.superchainConfigProxy.selector, address(superchainConfigProxy)); dii.set(dii.protocolVersionsProxy.selector, address(protocolVersionsProxy)); // End users of the DeployImplementations contract will need to set the `standardVersionsToml`. @@ -404,7 +403,7 @@ contract DeployOPChain_TestBase is Test { string.concat(vm.projectRoot(), "/test/fixtures/standard-versions.toml"); string memory standardVersionsToml = vm.readFile(standardVersionsTomlPath); dii.set(dii.standardVersionsToml.selector, standardVersionsToml); - dii.set(dii.opcmProxyOwner.selector, address(1)); + deployImplementations.run(dii, dio); // Deploy DeployOpChain, but defer populating the input values to the test suites inheriting this contract. @@ -412,7 +411,7 @@ contract DeployOPChain_TestBase is Test { (doi, doo) = deployOPChain.etchIOContracts(); // Set the OPContractsManager input for DeployOPChain. - opcm = dio.opcmProxy(); + opcm = dio.opcm(); } // See the function of the same name in the `DeployImplementations_Test` contract of @@ -466,7 +465,7 @@ contract DeployOPChain_Test is DeployOPChain_TestBase { doi.set(doi.basefeeScalar.selector, basefeeScalar); doi.set(doi.blobBaseFeeScalar.selector, blobBaseFeeScalar); doi.set(doi.l2ChainId.selector, l2ChainId); - doi.set(doi.opcmProxy.selector, address(opcm)); // Not fuzzed since it must be an actual instance. + doi.set(doi.opcm.selector, address(opcm)); doi.set(doi.saltMixer.selector, saltMixer); doi.set(doi.gasLimit.selector, gasLimit); doi.set(doi.disputeGameType.selector, disputeGameType); @@ -559,7 +558,7 @@ contract DeployOPChain_Test is DeployOPChain_TestBase { doi.set(doi.basefeeScalar.selector, basefeeScalar); doi.set(doi.blobBaseFeeScalar.selector, blobBaseFeeScalar); doi.set(doi.l2ChainId.selector, l2ChainId); - doi.set(doi.opcmProxy.selector, address(opcm)); + doi.set(doi.opcm.selector, address(opcm)); doi.set(doi.saltMixer.selector, saltMixer); doi.set(doi.gasLimit.selector, gasLimit); doi.set(doi.disputeGameType.selector, disputeGameType); diff --git a/packages/contracts-bedrock/test/universal/Specs.t.sol b/packages/contracts-bedrock/test/universal/Specs.t.sol index 3e5648fdfde0..49e35e835f36 100644 --- a/packages/contracts-bedrock/test/universal/Specs.t.sol +++ b/packages/contracts-bedrock/test/universal/Specs.t.sol @@ -16,6 +16,7 @@ import { IOptimismPortal } from "src/L1/interfaces/IOptimismPortal.sol"; import { IOptimismPortal2 } from "src/L1/interfaces/IOptimismPortal2.sol"; import { IOptimismPortalInterop } from "src/L1/interfaces/IOptimismPortalInterop.sol"; import { ISystemConfig } from "src/L1/interfaces/ISystemConfig.sol"; +import { ISystemConfigInterop } from "src/L1/interfaces/ISystemConfigInterop.sol"; import { IDataAvailabilityChallenge } from "src/L1/interfaces/IDataAvailabilityChallenge.sol"; import { IProtocolVersions } from "src/L1/interfaces/IProtocolVersions.sol"; @@ -479,36 +480,37 @@ contract Specification_Test is CommonTest { _addSpec({ _name: "SystemConfigInterop", _sel: _getSel("gasLimit()") }); _addSpec({ _name: "SystemConfigInterop", _sel: _getSel("eip1559Denominator()") }); _addSpec({ _name: "SystemConfigInterop", _sel: _getSel("eip1559Elasticity()") }); + _addSpec({ _name: "SystemConfigInterop", _sel: ISystemConfigInterop.initialize.selector }); _addSpec({ _name: "SystemConfigInterop", _sel: ISystemConfig.initialize.selector }); - _addSpec({ _name: "SystemConfigInterop", _sel: ISystemConfig.minimumGasLimit.selector }); + _addSpec({ _name: "SystemConfigInterop", _sel: ISystemConfigInterop.minimumGasLimit.selector }); _addSpec({ _name: "SystemConfigInterop", _sel: _getSel("overhead()") }); _addSpec({ _name: "SystemConfigInterop", _sel: _getSel("owner()") }); _addSpec({ _name: "SystemConfigInterop", _sel: _getSel("renounceOwnership()"), _auth: Role.SYSTEMCONFIGOWNER }); - _addSpec({ _name: "SystemConfigInterop", _sel: ISystemConfig.resourceConfig.selector }); + _addSpec({ _name: "SystemConfigInterop", _sel: ISystemConfigInterop.resourceConfig.selector }); _addSpec({ _name: "SystemConfigInterop", _sel: _getSel("scalar()") }); _addSpec({ _name: "SystemConfigInterop", - _sel: ISystemConfig.setBatcherHash.selector, + _sel: ISystemConfigInterop.setBatcherHash.selector, _auth: Role.SYSTEMCONFIGOWNER }); _addSpec({ _name: "SystemConfigInterop", - _sel: ISystemConfig.setGasConfig.selector, + _sel: ISystemConfigInterop.setGasConfig.selector, _auth: Role.SYSTEMCONFIGOWNER }); _addSpec({ _name: "SystemConfigInterop", - _sel: ISystemConfig.setGasLimit.selector, + _sel: ISystemConfigInterop.setGasLimit.selector, _auth: Role.SYSTEMCONFIGOWNER }); _addSpec({ _name: "SystemConfigInterop", - _sel: ISystemConfig.setEIP1559Params.selector, + _sel: ISystemConfigInterop.setEIP1559Params.selector, _auth: Role.SYSTEMCONFIGOWNER }); _addSpec({ _name: "SystemConfigInterop", - _sel: ISystemConfig.setUnsafeBlockSigner.selector, + _sel: ISystemConfigInterop.setUnsafeBlockSigner.selector, _auth: Role.SYSTEMCONFIGOWNER }); _addSpec({ @@ -516,7 +518,7 @@ contract Specification_Test is CommonTest { _sel: _getSel("transferOwnership(address)"), _auth: Role.SYSTEMCONFIGOWNER }); - _addSpec({ _name: "SystemConfigInterop", _sel: ISystemConfig.unsafeBlockSigner.selector }); + _addSpec({ _name: "SystemConfigInterop", _sel: ISystemConfigInterop.unsafeBlockSigner.selector }); _addSpec({ _name: "SystemConfigInterop", _sel: _getSel("version()") }); _addSpec({ _name: "SystemConfigInterop", _sel: _getSel("l1CrossDomainMessenger()") }); _addSpec({ _name: "SystemConfigInterop", _sel: _getSel("l1ERC721Bridge()") }); @@ -552,12 +554,6 @@ contract Specification_Test is CommonTest { _auth: Role.DEPENDENCYMANAGER }); _addSpec({ _name: "SystemConfigInterop", _sel: _getSel("dependencyManager()") }); - _addSpec({ - _name: "SystemConfigInterop", - _sel: _getSel( - "initialize(address,uint32,uint32,bytes32,uint64,address,(uint32,uint8,uint8,uint32,uint32,uint128),address,(address,address,address,address,address,address,address),address)" - ) - }); // ProxyAdmin _addSpec({ _name: "ProxyAdmin", _sel: _getSel("addressManager()") }); @@ -841,27 +837,25 @@ contract Specification_Test is CommonTest { _addSpec({ _name: "OPContractsManager", _sel: _getSel("version()") }); _addSpec({ _name: "OPContractsManager", _sel: _getSel("superchainConfig()") }); _addSpec({ _name: "OPContractsManager", _sel: _getSel("protocolVersions()") }); - _addSpec({ _name: "OPContractsManager", _sel: _getSel("latestRelease()") }); - _addSpec({ _name: "OPContractsManager", _sel: _getSel("implementations(string,string)") }); + _addSpec({ _name: "OPContractsManager", _sel: _getSel("l1ContractsRelease()") }); _addSpec({ _name: "OPContractsManager", _sel: _getSel("systemConfigs(uint256)") }); _addSpec({ _name: "OPContractsManager", _sel: _getSel("OUTPUT_VERSION()") }); - _addSpec({ _name: "OPContractsManager", _sel: OPContractsManager.initialize.selector }); _addSpec({ _name: "OPContractsManager", _sel: OPContractsManager.deploy.selector }); _addSpec({ _name: "OPContractsManager", _sel: OPContractsManager.blueprints.selector }); _addSpec({ _name: "OPContractsManager", _sel: OPContractsManager.chainIdToBatchInboxAddress.selector }); + _addSpec({ _name: "OPContractsManager", _sel: OPContractsManager.implementations.selector }); // OPContractsManagerInterop _addSpec({ _name: "OPContractsManagerInterop", _sel: _getSel("version()") }); _addSpec({ _name: "OPContractsManagerInterop", _sel: _getSel("superchainConfig()") }); _addSpec({ _name: "OPContractsManagerInterop", _sel: _getSel("protocolVersions()") }); - _addSpec({ _name: "OPContractsManagerInterop", _sel: _getSel("latestRelease()") }); - _addSpec({ _name: "OPContractsManagerInterop", _sel: _getSel("implementations(string,string)") }); + _addSpec({ _name: "OPContractsManagerInterop", _sel: _getSel("l1ContractsRelease()") }); _addSpec({ _name: "OPContractsManagerInterop", _sel: _getSel("systemConfigs(uint256)") }); _addSpec({ _name: "OPContractsManagerInterop", _sel: _getSel("OUTPUT_VERSION()") }); - _addSpec({ _name: "OPContractsManagerInterop", _sel: OPContractsManager.initialize.selector }); _addSpec({ _name: "OPContractsManagerInterop", _sel: OPContractsManager.deploy.selector }); _addSpec({ _name: "OPContractsManagerInterop", _sel: OPContractsManager.blueprints.selector }); _addSpec({ _name: "OPContractsManagerInterop", _sel: OPContractsManager.chainIdToBatchInboxAddress.selector }); + _addSpec({ _name: "OPContractsManagerInterop", _sel: OPContractsManager.implementations.selector }); // DeputyGuardianModule _addSpec({