diff --git a/op-chain-ops/interopgen/deployments.go b/op-chain-ops/interopgen/deployments.go index a4ead545ac2bb..6b9e34b7a871e 100644 --- a/op-chain-ops/interopgen/deployments.go +++ b/op-chain-ops/interopgen/deployments.go @@ -10,6 +10,10 @@ type L1Deployment struct { type Implementations struct { Opcm common.Address `json:"OPCM"` + OpcmContractsContainer common.Address `json:"OPCMContractsContainer"` + OpcmGameTypeAdder common.Address `json:"OPCMGameTypeAdder"` + OpcmDeployer common.Address `json:"OPCMDeployer"` + OpcmUpgrader common.Address `json:"OPCMUpgrader"` DelayedWETHImpl common.Address `json:"DelayedWETHImpl"` OptimismPortalImpl common.Address `json:"OptimismPortalImpl"` PreimageOracleSingleton common.Address `json:"PreimageOracleSingleton"` diff --git a/op-deployer/pkg/deployer/opcm/implementations.go b/op-deployer/pkg/deployer/opcm/implementations.go index 7e8d70bf53525..163e899fc9d22 100644 --- a/op-deployer/pkg/deployer/opcm/implementations.go +++ b/op-deployer/pkg/deployer/opcm/implementations.go @@ -31,6 +31,10 @@ func (input *DeployImplementationsInput) InputSet() bool { type DeployImplementationsOutput struct { Opcm common.Address + OpcmContractsContainer common.Address + OpcmGameTypeAdder common.Address + OpcmDeployer common.Address + OpcmUpgrader common.Address DelayedWETHImpl common.Address OptimismPortalImpl common.Address PreimageOracleSingleton common.Address @@ -86,10 +90,7 @@ func DeployImplementations( defer cleanupDeploy() opcmContract := "OPContractsManager" - if input.UseInterop { - opcmContract = "OPContractsManagerInterop" - } - if err := host.RememberOnLabel("OPContractsManager", opcmContract+".sol", opcmContract); err != nil { + if err := host.RememberOnLabel("OPContractsManager", "OPContractsManager.sol", opcmContract); err != nil { return output, fmt.Errorf("failed to link OPContractsManager label: %w", err) } diff --git a/op-deployer/pkg/deployer/pipeline/implementations.go b/op-deployer/pkg/deployer/pipeline/implementations.go index 015bb9507372f..ef591210b6de7 100644 --- a/op-deployer/pkg/deployer/pipeline/implementations.go +++ b/op-deployer/pkg/deployer/pipeline/implementations.go @@ -67,6 +67,9 @@ func DeployImplementations(env *Env, intent *state.Intent, st *state.State) erro st.ImplementationsDeployment = &state.ImplementationsDeployment{ OpcmAddress: dio.Opcm, + OpcmGameTypeAdderAddress: dio.OpcmGameTypeAdder, + OpcmDeployerAddress: dio.OpcmDeployer, + OpcmUpgraderAddress: dio.OpcmUpgrader, DelayedWETHImplAddress: dio.DelayedWETHImpl, OptimismPortalImplAddress: dio.OptimismPortalImpl, PreimageOracleSingletonAddress: dio.PreimageOracleSingleton, diff --git a/op-deployer/pkg/deployer/state/state.go b/op-deployer/pkg/deployer/state/state.go index e2766eba65ee1..0ec6c923f30bc 100644 --- a/op-deployer/pkg/deployer/state/state.go +++ b/op-deployer/pkg/deployer/state/state.go @@ -71,6 +71,9 @@ type SuperchainDeployment struct { type ImplementationsDeployment struct { OpcmAddress common.Address `json:"opcmAddress"` + OpcmGameTypeAdderAddress common.Address `json:"opcmGameTypeAdderAddress"` + OpcmDeployerAddress common.Address `json:"opcmDeployerAddress"` + OpcmUpgraderAddress common.Address `json:"opcmUpgraderAddress"` DelayedWETHImplAddress common.Address `json:"delayedWETHImplAddress"` OptimismPortalImplAddress common.Address `json:"optimismPortalImplAddress"` PreimageOracleSingletonAddress common.Address `json:"preimageOracleSingletonAddress"` diff --git a/packages/contracts-bedrock/interfaces/L1/IOPContractsManager.sol b/packages/contracts-bedrock/interfaces/L1/IOPContractsManager.sol index d3e92ae006a67..37701010a88b1 100644 --- a/packages/contracts-bedrock/interfaces/L1/IOPContractsManager.sol +++ b/packages/contracts-bedrock/interfaces/L1/IOPContractsManager.sol @@ -10,7 +10,6 @@ import { IDelayedWETH } from "interfaces/dispute/IDelayedWETH.sol"; import { IAnchorStateRegistry } from "interfaces/dispute/IAnchorStateRegistry.sol"; import { IAddressManager } from "interfaces/legacy/IAddressManager.sol"; import { IProxyAdmin } from "interfaces/universal/IProxyAdmin.sol"; -import { IDisputeGame } from "interfaces/dispute/IDisputeGame.sol"; import { IDisputeGameFactory } from "interfaces/dispute/IDisputeGameFactory.sol"; import { IFaultDisputeGame } from "interfaces/dispute/IFaultDisputeGame.sol"; import { IPermissionedDisputeGame } from "interfaces/dispute/IPermissionedDisputeGame.sol"; @@ -23,6 +22,65 @@ import { IL1ERC721Bridge } from "interfaces/L1/IL1ERC721Bridge.sol"; import { IL1StandardBridge } from "interfaces/L1/IL1StandardBridge.sol"; import { IOptimismMintableERC20Factory } from "interfaces/universal/IOptimismMintableERC20Factory.sol"; +interface IOPContractsManagerContractsContainer { + function __constructor__( + IOPContractsManager.Blueprints memory _blueprints, + IOPContractsManager.Implementations memory _implementations + ) + external; + + function blueprints() external view returns (IOPContractsManager.Blueprints memory); + function implementations() external view returns (IOPContractsManager.Implementations memory); +} + +interface IOPContractsManagerGameTypeAdder { + event GameTypeAdded( + uint256 indexed l2ChainId, GameType indexed gameType, address newDisputeGame, address oldDisputeGame + ); + + function __constructor__( + IOPContractsManagerContractsContainer _contractsContainer + ) + external; + + function addGameType(IOPContractsManager.AddGameInput[] memory _gameConfigs, address _superchainConfig) + external + returns (IOPContractsManager.AddGameOutput[] memory); + + function updatePrestate(IOPContractsManager.OpChainConfig[] memory _prestateUpdateInputs, address _superchainConfig) external; + + function contractsContainer() external view returns (IOPContractsManagerContractsContainer); +} + +interface IOPContractsManagerDeployer { + event Deployed(uint256 indexed l2ChainId, address indexed deployer, bytes deployOutput); + + function __constructor__( + IOPContractsManagerContractsContainer _contractsContainer + ) + external; + + function deploy(IOPContractsManager.DeployInput memory _input, address _superchainConfig, address _deployer) + external + returns (IOPContractsManager.DeployOutput memory); + + function contractsContainer() external view returns (IOPContractsManagerContractsContainer); +} + +interface IOPContractsManagerUpgrader { + event Upgraded(uint256 indexed l2ChainId, address indexed systemConfig, address indexed upgrader); + + function __constructor__( + IOPContractsManagerContractsContainer _contractsContainer + ) + external; + + function upgrade(IOPContractsManager.OpChainConfig[] memory _opChainConfigs) external; + + function contractsContainer() external view returns (IOPContractsManagerContractsContainer); +} + + interface IOPContractsManager { // -------- Structs -------- @@ -153,36 +211,8 @@ interface IOPContractsManager { /// version of the L1 smart contracts is deployed. It takes the format of `op-contracts/vX.Y.Z`. function l1ContractsRelease() external view returns (string memory); - // -------- Events -------- - - /// @notice Emitted when a new OP Stack chain is deployed. - /// @param l2ChainId Chain ID of the new chain. - /// @param deployer Address that deployed the chain. - /// @param deployOutput ABI-encoded output of the deployment. - event Deployed(uint256 indexed l2ChainId, address indexed deployer, bytes deployOutput); - - /// @notice Emitted when a chain is upgraded - /// @param systemConfig Address of the chain's SystemConfig contract - /// @param upgrader Address that initiated the upgrade - event Upgraded(uint256 indexed l2ChainId, ISystemConfig indexed systemConfig, address indexed upgrader); - - /// @notice Emitted when a new game type is added to a chain - /// @param l2ChainId Chain ID of the chain - /// @param gameType Type of the game being added - /// @param newDisputeGame Address of the deployed dispute game - /// @param oldDisputeGame Address of the old dispute game - event GameTypeAdded(uint256 indexed l2ChainId, GameType indexed gameType, IDisputeGame newDisputeGame, IDisputeGame oldDisputeGame); - // -------- Errors -------- - error BytesArrayTooLong(); - error DeploymentFailed(); - error EmptyInitcode(); - error IdentityPrecompileCallFailed(); - error NotABlueprint(); - error ReservedBitsSet(); - error UnexpectedPreambleData(bytes data); - error UnsupportedERCVersion(uint8 version); error OnlyUpgradeController(); /// @notice Thrown when an address is the zero address. @@ -219,15 +249,18 @@ interface IOPContractsManager { error PrestateNotSet(); + error PrestateRequired(); + // -------- Methods -------- function __constructor__( + IOPContractsManagerGameTypeAdder _opcmGameTypeAdder, + IOPContractsManagerDeployer _opcmDeployer, + IOPContractsManagerUpgrader _opcmUpgrader, ISuperchainConfig _superchainConfig, IProtocolVersions _protocolVersions, IProxyAdmin _superchainProxyAdmin, string memory _l1ContractsRelease, - Blueprints memory _blueprints, - Implementations memory _implementations, address _upgradeController ) external; @@ -242,6 +275,10 @@ interface IOPContractsManager { /// must be added in ascending GameType order. function addGameType(AddGameInput[] memory _gameConfigs) external returns (AddGameOutput[] memory); + /// @notice Updates the prestate hash for a new game type while keeping all other parameters the same + /// @param _prestateUpdateInputs The new prestate hash to use + function updatePrestate(OpChainConfig[] memory _prestateUpdateInputs) external; + /// @notice Maps an L2 chain ID to an L1 batch inbox address as defined by the standard /// configuration's convention. This convention is `versionByte || keccak256(bytes32(chainId))[:19]`, /// where || denotes concatenation`, versionByte is 0x00, and chainId is a uint256. @@ -251,6 +288,12 @@ interface IOPContractsManager { /// @notice Returns the blueprint contract addresses. function blueprints() external view returns (Blueprints memory); + function opcmDeployer() external view returns (IOPContractsManagerDeployer); + + function opcmUpgrader() external view returns (IOPContractsManagerUpgrader); + + function opcmGameTypeAdder() external view returns (IOPContractsManagerGameTypeAdder); + /// @notice Returns the implementation contract addresses. function implementations() external view returns (Implementations memory); diff --git a/packages/contracts-bedrock/interfaces/L1/IOPContractsManagerInterop.sol b/packages/contracts-bedrock/interfaces/L1/IOPContractsManagerInterop.sol deleted file mode 100644 index 7e323f70de2d3..0000000000000 --- a/packages/contracts-bedrock/interfaces/L1/IOPContractsManagerInterop.sol +++ /dev/null @@ -1,20 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import { ISuperchainConfig } from "interfaces/L1/ISuperchainConfig.sol"; -import { IProtocolVersions } from "interfaces/L1/IProtocolVersions.sol"; -import { IProxyAdmin } from "interfaces/universal/IProxyAdmin.sol"; -import { IOPContractsManager } from "interfaces/L1/IOPContractsManager.sol"; - -interface IOPContractsManagerInterop is IOPContractsManager { - function __constructor__( - ISuperchainConfig _superchainConfig, - IProtocolVersions _protocolVersions, - IProxyAdmin _superchainProxyAdmin, - string memory _l1ContractsRelease, - Blueprints memory _blueprints, - Implementations memory _implementations, - address _upgradeController - ) - external; -} diff --git a/packages/contracts-bedrock/scripts/deploy/DeployImplementations.s.sol b/packages/contracts-bedrock/scripts/deploy/DeployImplementations.s.sol index e94a4c1859392..a8fd5a7430081 100644 --- a/packages/contracts-bedrock/scripts/deploy/DeployImplementations.s.sol +++ b/packages/contracts-bedrock/scripts/deploy/DeployImplementations.s.sol @@ -17,8 +17,13 @@ import { IPreimageOracle } from "interfaces/cannon/IPreimageOracle.sol"; import { IMIPS } from "interfaces/cannon/IMIPS.sol"; import { IDisputeGameFactory } from "interfaces/dispute/IDisputeGameFactory.sol"; import { IAnchorStateRegistry } from "interfaces/dispute/IAnchorStateRegistry.sol"; -import { IOPContractsManager } from "interfaces/L1/IOPContractsManager.sol"; -import { IOPContractsManagerInterop } from "interfaces/L1/IOPContractsManagerInterop.sol"; +import { + IOPContractsManager, + IOPContractsManagerGameTypeAdder, + IOPContractsManagerDeployer, + IOPContractsManagerUpgrader, + IOPContractsManagerContractsContainer +} from "interfaces/L1/IOPContractsManager.sol"; import { IOptimismPortal2 } from "interfaces/L1/IOptimismPortal2.sol"; import { ISystemConfig } from "interfaces/L1/ISystemConfig.sol"; import { IL1CrossDomainMessenger } from "interfaces/L1/IL1CrossDomainMessenger.sol"; @@ -148,6 +153,10 @@ contract DeployImplementationsInput is BaseDeployIO { contract DeployImplementationsOutput is BaseDeployIO { IOPContractsManager internal _opcm; + IOPContractsManagerContractsContainer internal _opcmContractsContainer; + IOPContractsManagerGameTypeAdder internal _opcmGameTypeAdder; + IOPContractsManagerDeployer internal _opcmDeployer; + IOPContractsManagerUpgrader internal _opcmUpgrader; IDelayedWETH internal _delayedWETHImpl; IOptimismPortal2 internal _optimismPortalImpl; IPreimageOracle internal _preimageOracleSingleton; @@ -167,6 +176,10 @@ contract DeployImplementationsOutput is BaseDeployIO { // forgefmt: disable-start if (_sel == this.opcm.selector) _opcm = IOPContractsManager(_addr); + else if (_sel == this.opcmContractsContainer.selector) _opcmContractsContainer = IOPContractsManagerContractsContainer(_addr); + else if (_sel == this.opcmGameTypeAdder.selector) _opcmGameTypeAdder = IOPContractsManagerGameTypeAdder(_addr); + else if (_sel == this.opcmDeployer.selector) _opcmDeployer = IOPContractsManagerDeployer(_addr); + else if (_sel == this.opcmUpgrader.selector) _opcmUpgrader = IOPContractsManagerUpgrader(_addr); else if (_sel == this.superchainConfigImpl.selector) _superchainConfigImpl = ISuperchainConfig(_addr); else if (_sel == this.protocolVersionsImpl.selector) _protocolVersionsImpl = IProtocolVersions(_addr); else if (_sel == this.optimismPortalImpl.selector) _optimismPortalImpl = IOptimismPortal2(payable(_addr)); @@ -217,6 +230,26 @@ contract DeployImplementationsOutput is BaseDeployIO { return _opcm; } + function opcmContractsContainer() public view returns (IOPContractsManagerContractsContainer) { + DeployUtils.assertValidContractAddress(address(_opcmContractsContainer)); + return _opcmContractsContainer; + } + + function opcmGameTypeAdder() public view returns (IOPContractsManagerGameTypeAdder) { + DeployUtils.assertValidContractAddress(address(_opcmGameTypeAdder)); + return _opcmGameTypeAdder; + } + + function opcmDeployer() public view returns (IOPContractsManagerDeployer) { + DeployUtils.assertValidContractAddress(address(_opcmDeployer)); + return _opcmDeployer; + } + + function opcmUpgrader() public view returns (IOPContractsManagerUpgrader) { + DeployUtils.assertValidContractAddress(address(_opcmUpgrader)); + return _opcmUpgrader; + } + function superchainConfigImpl() public view returns (ISuperchainConfig) { DeployUtils.assertValidContractAddress(address(_superchainConfigImpl)); return _superchainConfigImpl; @@ -478,11 +511,6 @@ contract DeployImplementations is Script { virtual returns (IOPContractsManager opcm_) { - ISuperchainConfig superchainConfigProxy = _dii.superchainConfigProxy(); - IProtocolVersions protocolVersionsProxy = _dii.protocolVersionsProxy(); - IProxyAdmin superchainProxyAdmin = _dii.superchainProxyAdmin(); - address upgradeController = _dii.upgradeController(); - IOPContractsManager.Implementations memory implementations = IOPContractsManager.Implementations({ superchainConfigImpl: address(_dio.superchainConfigImpl()), protocolVersionsImpl: address(_dio.protocolVersionsImpl()), @@ -498,6 +526,11 @@ contract DeployImplementations is Script { mipsImpl: address(_dio.mipsSingleton()) }); + deployOPCMBPImplsContainer(_dio, _blueprints, implementations); + deployOPCMGameTypeAdder(_dio); + deployOPCMDeployer(_dio); + deployOPCMUpgrader(_dio); + opcm_ = IOPContractsManager( DeployUtils.createDeterministic({ _name: "OPContractsManager", @@ -505,13 +538,14 @@ contract DeployImplementations is Script { abi.encodeCall( IOPContractsManager.__constructor__, ( - superchainConfigProxy, - protocolVersionsProxy, - superchainProxyAdmin, + _dio.opcmGameTypeAdder(), + _dio.opcmDeployer(), + _dio.opcmUpgrader(), + _dii.superchainConfigProxy(), + _dii.protocolVersionsProxy(), + _dii.superchainProxyAdmin(), _l1ContractsRelease, - _blueprints, - implementations, - upgradeController + _dii.upgradeController() ) ) ), @@ -788,6 +822,68 @@ contract DeployImplementations is Script { _dio.set(_dio.anchorStateRegistryImpl.selector, address(impl)); } + function deployOPCMBPImplsContainer( + DeployImplementationsOutput _dio, + IOPContractsManager.Blueprints memory _blueprints, + IOPContractsManager.Implementations memory _implementations + ) + public + virtual + { + IOPContractsManagerContractsContainer impl = IOPContractsManagerContractsContainer( + DeployUtils.createDeterministic({ + _name: "OPContractsManager.sol:OPContractsManagerContractsContainer", + _args: DeployUtils.encodeConstructor( + abi.encodeCall(IOPContractsManagerContractsContainer.__constructor__, (_blueprints, _implementations)) + ), + _salt: _salt + }) + ); + vm.label(address(impl), "OPContractsManagerBPImplsContainerImpl"); + _dio.set(_dio.opcmContractsContainer.selector, address(impl)); + } + + function deployOPCMGameTypeAdder(DeployImplementationsOutput _dio) public virtual { + IOPContractsManagerGameTypeAdder impl = IOPContractsManagerGameTypeAdder( + DeployUtils.createDeterministic({ + _name: "OPContractsManager.sol:OPContractsManagerGameTypeAdder", + _args: DeployUtils.encodeConstructor( + abi.encodeCall(IOPContractsManagerGameTypeAdder.__constructor__, (_dio.opcmContractsContainer())) + ), + _salt: _salt + }) + ); + vm.label(address(impl), "OPContractsManagerGameTypeAdderImpl"); + _dio.set(_dio.opcmGameTypeAdder.selector, address(impl)); + } + + function deployOPCMDeployer(DeployImplementationsOutput _dio) public virtual { + IOPContractsManagerDeployer impl = IOPContractsManagerDeployer( + DeployUtils.createDeterministic({ + _name: "OPContractsManager.sol:OPContractsManagerDeployer", + _args: DeployUtils.encodeConstructor( + abi.encodeCall(IOPContractsManagerDeployer.__constructor__, (_dio.opcmContractsContainer())) + ), + _salt: _salt + }) + ); + vm.label(address(impl), "OPContractsManagerDeployerImpl"); + _dio.set(_dio.opcmDeployer.selector, address(impl)); + } + + function deployOPCMUpgrader(DeployImplementationsOutput _dio) public virtual { + IOPContractsManagerUpgrader impl = IOPContractsManagerUpgrader( + DeployUtils.createDeterministic({ + _name: "OPContractsManager.sol:OPContractsManagerUpgrader", + _args: DeployUtils.encodeConstructor( + abi.encodeCall(IOPContractsManagerUpgrader.__constructor__, (_dio.opcmContractsContainer())) + ), + _salt: _salt + }) + ); + vm.label(address(impl), "OPContractsManagerUpgraderImpl"); + _dio.set(_dio.opcmUpgrader.selector, address(impl)); + } // -------- Utilities -------- function etchIOContracts() public returns (DeployImplementationsInput dii_, DeployImplementationsOutput dio_) { @@ -845,60 +941,18 @@ contract DeployImplementations is Script { // resolve https://github.com/ethereum-optimism/optimism/issues/11783, we just assume this new role // is the same as the proxy admin owner. contract DeployImplementationsInterop is DeployImplementations { - function createOPCMContract( - DeployImplementationsInput _dii, - DeployImplementationsOutput _dio, - IOPContractsManager.Blueprints memory _blueprints, - string memory _l1ContractsRelease - ) - internal - virtual - override - returns (IOPContractsManager opcm_) - { - ISuperchainConfig superchainConfigProxy = _dii.superchainConfigProxy(); - IProtocolVersions protocolVersionsProxy = _dii.protocolVersionsProxy(); - IProxyAdmin superchainProxyAdmin = _dii.superchainProxyAdmin(); - address upgradeController = _dii.upgradeController(); - - IOPContractsManager.Implementations memory implementations = IOPContractsManager.Implementations({ - superchainConfigImpl: address(_dio.superchainConfigImpl()), - protocolVersionsImpl: address(_dio.protocolVersionsImpl()), - 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()), - anchorStateRegistryImpl: address(_dio.anchorStateRegistryImpl()), - delayedWETHImpl: address(_dio.delayedWETHImpl()), - mipsImpl: address(_dio.mipsSingleton()) - }); - - opcm_ = IOPContractsManager( + function deployOPCMDeployer(DeployImplementationsOutput _dio) public override { + IOPContractsManagerDeployer impl = IOPContractsManagerDeployer( DeployUtils.createDeterministic({ - _name: "OPContractsManagerInterop", + _name: "OPContractsManager.sol:OPContractsManagerDeployerInterop", _args: DeployUtils.encodeConstructor( - abi.encodeCall( - IOPContractsManagerInterop.__constructor__, - ( - superchainConfigProxy, - protocolVersionsProxy, - superchainProxyAdmin, - _l1ContractsRelease, - _blueprints, - implementations, - upgradeController - ) - ) + abi.encodeCall(IOPContractsManagerDeployer.__constructor__, (_dio.opcmContractsContainer())) ), _salt: _salt }) ); - - vm.label(address(opcm_), "OPContractsManager"); - _dio.set(_dio.opcm.selector, address(opcm_)); + vm.label(address(impl), "OPContractsManagerDeployerImpl"); + _dio.set(_dio.opcmDeployer.selector, address(impl)); } function deployOptimismPortalImpl( diff --git a/packages/contracts-bedrock/scripts/deploy/DeployOPPrestateUpdater.s.sol b/packages/contracts-bedrock/scripts/deploy/DeployOPPrestateUpdater.s.sol deleted file mode 100644 index d5915ec761cb1..0000000000000 --- a/packages/contracts-bedrock/scripts/deploy/DeployOPPrestateUpdater.s.sol +++ /dev/null @@ -1,113 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.15; - -import { console2 as console } from "forge-std/console2.sol"; - -// Scripting -import { Script } from "forge-std/Script.sol"; - -// Libraries -import { LibString } from "@solady/utils/LibString.sol"; - -// Scripts -import { DeployUtils } from "scripts/libraries/DeployUtils.sol"; - -// Interfaces -import { ISuperchainConfig } from "interfaces/L1/ISuperchainConfig.sol"; -import { IProtocolVersions } from "interfaces/L1/IProtocolVersions.sol"; -import { IOPContractsManager } from "interfaces/L1/IOPContractsManager.sol"; -import { IOPPrestateUpdater } from "interfaces/L1/IOPPrestateUpdater.sol"; -import { IOPContractsManager180 } from "interfaces/L1/IOPContractsManager180.sol"; - -// Contracts -import { OPPrestateUpdater } from "src/L1/OPPrestateUpdater.sol"; - -contract DeployOPPrestateUpdater is Script { - bytes32 internal _salt = DeployUtils.DEFAULT_SALT; - - function deployOPPrestateUpdater(string memory _baseChain) public returns (OPPrestateUpdater) { - string memory superchainBasePath = "./lib/superchain-registry/superchain/configs/"; - string memory superchainToml = vm.readFile(string.concat(superchainBasePath, _baseChain, "/superchain.toml")); - - // Superchain shared contracts - ISuperchainConfig superchainConfig = - ISuperchainConfig(vm.parseTomlAddress(superchainToml, ".superchain_config_addr")); - IProtocolVersions protocolVersions = - IProtocolVersions(vm.parseTomlAddress(superchainToml, ".protocol_versions_addr")); - - // The existing v1.8.0 OPCM - IOPContractsManager180 opContractsManager180 = - IOPContractsManager180(vm.parseTomlAddress(superchainToml, ".op_contracts_manager_proxy_addr")); - - // Declare a new set of blueprints to store in the OPPrestateUpdater - IOPContractsManager.Blueprints memory blueprints; - blueprints.addressManager = address(0); - blueprints.proxy = address(0); - blueprints.proxyAdmin = address(0); - blueprints.l1ChugSplashProxy = address(0); - blueprints.resolvedDelegateProxy = address(0); - - IOPContractsManager180.Blueprints memory blueprints180 = opContractsManager180.blueprints(); - blueprints.permissionedDisputeGame1 = blueprints180.permissionedDisputeGame1; - blueprints.permissionedDisputeGame2 = blueprints180.permissionedDisputeGame2; - - // forgefmt: disable-start - vm.startBroadcast(msg.sender); - bytes memory faultDisputeGameInitcode = hex"6101c06040523480156200001257600080fd5b506040516200648a3803806200648a833981016040819052620000359162000436565b620000436001607e6200050d565b60ff168811156200006757604051633beff19960e11b815260040160405180910390fd5b600019871480620000845750876200008188600162000533565b10155b15620000a35760405163e62ccf3960e01b815260040160405180910390fd5b6002871015620000c65760405163e62ccf3960e01b815260040160405180910390fd5b6001600160401b038016846001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200010f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200013591906200054e565b6001600160a01b031663f3f480d96040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000173573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200019991906200056e565b1115620001b95760405163b4e1243360e01b815260040160405180910390fd5b6000620001da876001600160401b0316620003e260201b62000c891760201c565b620001f0906001600160401b0316600262000588565b90506000856001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000233573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200025991906200054e565b6001600160a01b031663f3f480d96040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000297573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002bd91906200056e565b620002dc896001600160401b0316620003e260201b62000c891760201c565b6001600160401b0316620002f1919062000533565b905060006200030c8383620003e560201b62003a261760201c565b90506001600160401b03811115620003375760405163235dfb2b60e21b815260040160405180910390fd5b62000356886001600160401b0316620003e260201b62000c891760201c565b6001600160401b0316816001600160401b03161115620003895760405163235dfb2b60e21b815260040160405180910390fd5b50505063ffffffff9099166101205260809790975260a09590955260c0939093526001600160401b039182166101a0521660e0526001600160a01b039081166101005290811661014052166101605261018052620005aa565b90565b600081831015620003f75781620003f9565b825b9392505050565b80516001600160401b03811681146200041857600080fd5b919050565b6001600160a01b03811681146200043357600080fd5b50565b6000806000806000806000806000806101408b8d0312156200045757600080fd5b8a5163ffffffff811681146200046c57600080fd5b809a505060208b0151985060408b0151975060608b015196506200049360808c0162000400565b9550620004a360a08c0162000400565b945060c08b0151620004b5816200041d565b60e08c0151909450620004c8816200041d565b6101008c0151909350620004dc816200041d565b809250506101208b015190509295989b9194979a5092959850565b634e487b7160e01b600052601160045260246000fd5b600060ff821660ff8416808210156200052a576200052a620004f7565b90039392505050565b60008219821115620005495762000549620004f7565b500190565b6000602082840312156200056157600080fd5b8151620003f9816200041d565b6000602082840312156200058157600080fd5b5051919050565b6000816000190483118215151615620005a557620005a5620004f7565b500290565b60805160a05160c05160e05161010051610120516101405161016051610180516101a051615d5a62000730600039600081816106bb01528181611fbb015281816120260152612059015260008181610a1e01526139390152600081816106130152818161178a01526125e80152600081816105270152818161194c01528181612480015281816129ea0152613e1401526000818161088d015281816125a701526139c80152600081816104b401528181611eba015281816132420152613597015260008181610a7101528181610f6001528181611e2a01528181612089015281816120e801528181612bf60152612c38015260008181610aa401528181611c7301528181611d9901528181611ff7015281816130950152818161379601528181613f0b015281816146280152818161475601528181614857015261492c015260008181610b4b01528181611d3c01528181611e8e01528181612d0601528181612d8c01528181612f8b01526130b601526000818161078601526131540152615d5a6000f3fe6080604052600436106102f25760003560e01c806370872aa51161018f578063c6f0308c116100e1578063ec5e63081161008a578063fa24f74311610064578063fa24f74314610b18578063fa315aa914610b3c578063fe2bbeb214610b6f57600080fd5b8063ec5e630814610a95578063eff0f59214610ac8578063f8f43ff614610af857600080fd5b8063d6ae3cd5116100bb578063d6ae3cd514610a0f578063d8cc1a3c14610a42578063dabd396d14610a6257600080fd5b8063c6f0308c14610937578063cf09e0d0146109c1578063d5d44d80146109e257600080fd5b80638d450a9511610143578063bcef3b551161011d578063bcef3b55146108b7578063bd8da956146108f7578063c395e1ca1461091757600080fd5b80638d450a9514610777578063a445ece6146107aa578063bbdc02db1461087657600080fd5b80638129fc1c116101745780638129fc1c1461071a5780638980e0cc146107225780638b85902b1461073757600080fd5b806370872aa5146106f25780637b0f0adc1461070757600080fd5b80633fc8cef3116102485780635c0cba33116101fc5780636361506d116101d65780636361506d1461066c5780636b6716c0146106ac5780636f034409146106df57600080fd5b80635c0cba3314610604578063609d33341461063757806360e274641461064c57600080fd5b806354fd4d501161022d57806354fd4d501461055e57806357da950e146105b45780635a5fa2d9146105e457600080fd5b80633fc8cef314610518578063472777c61461054b57600080fd5b80632810e1d6116102aa57806337b1b2291161028457806337b1b229146104655780633a768463146104a55780633e3ac912146104d857600080fd5b80632810e1d6146103de5780632ad69aeb146103f357806330dbe5701461041357600080fd5b806319effeb4116102db57806319effeb414610339578063200d2ed21461038457806325fc2ace146103bf57600080fd5b806301935130146102f757806303c2924d14610319575b600080fd5b34801561030357600080fd5b506103176103123660046154e2565b610b9f565b005b34801561032557600080fd5b5061031761033436600461553d565b610ec0565b34801561034557600080fd5b506000546103669068010000000000000000900467ffffffffffffffff1681565b60405167ffffffffffffffff90911681526020015b60405180910390f35b34801561039057600080fd5b506000546103b290700100000000000000000000000000000000900460ff1681565b60405161037b919061558e565b3480156103cb57600080fd5b506008545b60405190815260200161037b565b3480156103ea57600080fd5b506103b2611566565b3480156103ff57600080fd5b506103d061040e36600461553d565b61180b565b34801561041f57600080fd5b506001546104409073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161037b565b34801561047157600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90033560601c610440565b3480156104b157600080fd5b507f0000000000000000000000000000000000000000000000000000000000000000610440565b3480156104e457600080fd5b50600054610508907201000000000000000000000000000000000000900460ff1681565b604051901515815260200161037b565b34801561052457600080fd5b507f0000000000000000000000000000000000000000000000000000000000000000610440565b6103176105593660046155cf565b611841565b34801561056a57600080fd5b506105a76040518060400160405280600581526020017f312e332e3100000000000000000000000000000000000000000000000000000081525081565b60405161037b9190615666565b3480156105c057600080fd5b506008546009546105cf919082565b6040805192835260208301919091520161037b565b3480156105f057600080fd5b506103d06105ff366004615679565b611853565b34801561061057600080fd5b507f0000000000000000000000000000000000000000000000000000000000000000610440565b34801561064357600080fd5b506105a761188d565b34801561065857600080fd5b506103176106673660046156b7565b61189b565b34801561067857600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003603401356103d0565b3480156106b857600080fd5b507f0000000000000000000000000000000000000000000000000000000000000000610366565b6103176106ed3660046156e9565b611a42565b3480156106fe57600080fd5b506009546103d0565b6103176107153660046155cf565b61251b565b610317612528565b34801561072e57600080fd5b506002546103d0565b34801561074357600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003605401356103d0565b34801561078357600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006103d0565b3480156107b657600080fd5b506108226107c5366004615679565b6007602052600090815260409020805460019091015460ff821691610100810463ffffffff1691650100000000009091046fffffffffffffffffffffffffffffffff169073ffffffffffffffffffffffffffffffffffffffff1684565b60408051941515855263ffffffff90931660208501526fffffffffffffffffffffffffffffffff9091169183019190915273ffffffffffffffffffffffffffffffffffffffff16606082015260800161037b565b34801561088257600080fd5b5060405163ffffffff7f000000000000000000000000000000000000000000000000000000000000000016815260200161037b565b3480156108c357600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003601401356103d0565b34801561090357600080fd5b50610366610912366004615679565b612a81565b34801561092357600080fd5b506103d0610932366004615728565b612c60565b34801561094357600080fd5b50610957610952366004615679565b612e43565b6040805163ffffffff909816885273ffffffffffffffffffffffffffffffffffffffff968716602089015295909416948601949094526fffffffffffffffffffffffffffffffff9182166060860152608085015291821660a08401521660c082015260e00161037b565b3480156109cd57600080fd5b506000546103669067ffffffffffffffff1681565b3480156109ee57600080fd5b506103d06109fd3660046156b7565b60036020526000908152604090205481565b348015610a1b57600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006103d0565b348015610a4e57600080fd5b50610317610a5d36600461575a565b612eda565b348015610a6e57600080fd5b507f0000000000000000000000000000000000000000000000000000000000000000610366565b348015610aa157600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006103d0565b348015610ad457600080fd5b50610508610ae3366004615679565b60046020526000908152604090205460ff1681565b348015610b0457600080fd5b50610317610b133660046155cf565b613509565b348015610b2457600080fd5b50610b2d6139c6565b60405161037b939291906157e4565b348015610b4857600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006103d0565b348015610b7b57600080fd5b50610508610b8a366004615679565b60066020526000908152604090205460ff1681565b60008054700100000000000000000000000000000000900460ff166002811115610bcb57610bcb61555f565b14610c02576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000547201000000000000000000000000000000000000900460ff1615610c55576040517f0ea2e75200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610c8c367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036014013590565b90565b610ca3610c9e36869003860186615838565b613a41565b14610cda576040517f9cc00b5b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b82606001358282604051610cef9291906158c5565b604051809103902014610d2e576040517fd81d583b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610d77610d7284848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250613a9d92505050565b613b0a565b90506000610d9e82600881518110610d9157610d916158d5565b6020026020010151613cc0565b9050602081511115610ddc576040517fd81d583b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b602081810151825190910360031b1c367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003605401358103610e51576040517fb8ed883000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050600180547fffffffffffffffffffffffff000000000000000000000000000000000000000016331790555050600080547fffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffff1672010000000000000000000000000000000000001790555050565b60008054700100000000000000000000000000000000900460ff166002811115610eec57610eec61555f565b14610f23576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060028381548110610f3857610f386158d5565b906000526020600020906005020190506000610f5384612a81565b905067ffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000081169082161015610fbc576040517ff2440b5300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008481526006602052604090205460ff1615611005576040517ff1a9458100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600084815260056020526040902080548015801561102257508515155b156110bd578354640100000000900473ffffffffffffffffffffffffffffffffffffffff16600081156110555781611071565b600186015473ffffffffffffffffffffffffffffffffffffffff165b905061107d8187613d74565b50505060009485525050600660205250506040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055565b6000868152600760209081526040918290208251608081018452815460ff81161515808352610100820463ffffffff16948301949094526501000000000090046fffffffffffffffffffffffffffffffff16938101939093526001015473ffffffffffffffffffffffffffffffffffffffff166060830152611160576fffffffffffffffffffffffffffffffff6040820152600181526000869003611160578195505b600086826020015163ffffffff166111789190615933565b90506000838211611189578161118b565b835b602084015190915063ffffffff165b818110156112d75760008682815481106111b6576111b66158d5565b6000918252602080832090910154808352600690915260409091205490915060ff1661120e576040517f9a07664600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060028281548110611223576112236158d5565b600091825260209091206005909102018054909150640100000000900473ffffffffffffffffffffffffffffffffffffffff161580156112805750600481015460408701516fffffffffffffffffffffffffffffffff9182169116115b156112c257600181015473ffffffffffffffffffffffffffffffffffffffff16606087015260048101546fffffffffffffffffffffffffffffffff1660408701525b505080806112cf9061594b565b91505061119a565b5063ffffffff818116602085810191825260008c81526007909152604090819020865181549351928801517fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000009094169015157fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000ff161761010092909416918202939093177fffffffffffffffffffffff00000000000000000000000000000000ffffffffff16650100000000006fffffffffffffffffffffffffffffffff909316929092029190911782556060850151600190920180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9093169290921790915584900361155b57606083015160008a815260066020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558915801561145757506000547201000000000000000000000000000000000000900460ff165b156114cc5760015473ffffffffffffffffffffffffffffffffffffffff1661147f818a613d74565b885473ffffffffffffffffffffffffffffffffffffffff909116640100000000027fffffffffffffffff0000000000000000000000000000000000000000ffffffff909116178855611559565b61151373ffffffffffffffffffffffffffffffffffffffff8216156114f1578161150d565b600189015473ffffffffffffffffffffffffffffffffffffffff165b89613d74565b87547fffffffffffffffff0000000000000000000000000000000000000000ffffffff1664010000000073ffffffffffffffffffffffffffffffffffffffff8316021788555b505b505050505050505050565b600080600054700100000000000000000000000000000000900460ff1660028111156115945761159461555f565b146115cb576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000805260066020527f54cdd369e4e8a8515e52ca72ec816c2101831ad1f18bf44102ed171459c9b4f85460ff1661162f576040517f9a07664600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff16600260008154811061165b5761165b6158d5565b6000918252602090912060059091020154640100000000900473ffffffffffffffffffffffffffffffffffffffff1614611696576001611699565b60025b6000805467ffffffffffffffff421668010000000000000000027fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff82168117835592935083927fffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffff000000000000000000ffffffffffffffff9091161770010000000000000000000000000000000083600281111561174a5761174a61555f565b02179055600281111561175f5761175f61555f565b6040517f5e186f09b9c93491f14e277eea7faa5de6a2d4bda75a79af7a3684fbfb42da6090600090a27f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663838c2d1e6040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156117f057600080fd5b505af1158015611804573d6000803e3d6000fd5b5050505090565b6005602052816000526040600020818154811061182757600080fd5b90600052602060002001600091509150505481565b905090565b61184e8383836001611a42565b505050565b6000818152600760209081526040808320600590925282208054825461188490610100900463ffffffff1682615983565b95945050505050565b606061183c60546020613e75565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260036020526040812080549082905590819003611900576040517f17bfe5f700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517ff3fef3a300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8381166004830152602482018390527f0000000000000000000000000000000000000000000000000000000000000000169063f3fef3a390604401600060405180830381600087803b15801561199057600080fd5b505af11580156119a4573d6000803e3d6000fd5b5050505060008273ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d8060008114611a02576040519150601f19603f3d011682016040523d82523d6000602084013e611a07565b606091505b505090508061184e576040517f83e6cc6b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008054700100000000000000000000000000000000900460ff166002811115611a6e57611a6e61555f565b14611aa5576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060028481548110611aba57611aba6158d5565b60009182526020918290206040805160e0810182526005909302909101805463ffffffff8116845273ffffffffffffffffffffffffffffffffffffffff64010000000090910481169484019490945260018101549093169082015260028201546fffffffffffffffffffffffffffffffff908116606083015260038301546080830181905260049093015480821660a084015270010000000000000000000000000000000090041660c082015291508514611ba1576040517f3014033200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60a0810151600083156fffffffffffffffffffffffffffffffff83161760011b90506000611c61826fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff169050861580611c9c5750611c997f00000000000000000000000000000000000000000000000000000000000000006002615933565b81145b8015611ca6575084155b15611cdd576040517fa42637bc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000547201000000000000000000000000000000000000900460ff168015611d03575086155b15611d3a576040517f0ea2e75200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f0000000000000000000000000000000000000000000000000000000000000000811115611d94576040517f56f57b2b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611dbf7f00000000000000000000000000000000000000000000000000000000000000006001615933565b8103611dd157611dd186888588613ec7565b34611ddb83612c60565b14611e12576040517f8620aa1900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000611e1d88612a81565b905067ffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811690821603611e85576040517f3381d11400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000611eb260017f0000000000000000000000000000000000000000000000000000000000000000615983565b8303611ff0577f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa158015611f23573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f47919061599a565b73ffffffffffffffffffffffffffffffffffffffff1663f3f480d96040518163ffffffff1660e01b8152600401602060405180830381865afa158015611f91573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fb591906159b7565b611fe9907f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff166159d0565b9050612083565b61201b60017f0000000000000000000000000000000000000000000000000000000000000000615983565b830361205657611fe97f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1660026159fc565b507f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff165b6120b7817f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff16615a2c565b67ffffffffffffffff166120d28367ffffffffffffffff1690565b67ffffffffffffffff16111561211957612116817f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff16615a2c565b91505b6000604083901b421760008a8152608087901b6fffffffffffffffffffffffffffffffff8d1617602052604081209192509060008181526004602052604090205490915060ff1615612197576040517f80497e3b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60016004600083815260200190815260200160002060006101000a81548160ff02191690831515021790555060026040518060e001604052808d63ffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff1681526020013373ffffffffffffffffffffffffffffffffffffffff168152602001346fffffffffffffffffffffffffffffffff1681526020018c8152602001886fffffffffffffffffffffffffffffffff168152602001846fffffffffffffffffffffffffffffffff16815250908060018154018082558091505060019003906000526020600020906005020160009091909190915060008201518160000160006101000a81548163ffffffff021916908363ffffffff16021790555060208201518160000160046101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060408201518160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060608201518160020160006101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff1602179055506080820151816003015560a08201518160040160006101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff16021790555060c08201518160040160106101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff1602179055505050600560008c8152602001908152602001600020600160028054905061242d9190615983565b81546001810183556000928352602083200155604080517fd0e30db0000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169263d0e30db09234926004808301939282900301818588803b1580156124c557600080fd5b505af11580156124d9573d6000803e3d6000fd5b50506040513393508d92508e91507f9b3245740ec3b155098a55be84957a4da13eaf7f14a8bc6f53126c0b9350f2be90600090a4505050505050505050505050565b61184e8383836000611a42565b60005471010000000000000000000000000000000000900460ff161561257a576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f7258a80700000000000000000000000000000000000000000000000000000000815263ffffffff7f0000000000000000000000000000000000000000000000000000000000000000166004820152600090819073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690637258a807906024016040805180830381865afa15801561262e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126529190615a55565b90925090508161268e576040517f6a6bc3b200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080518082019091528281526020018190526008829055600981905536607a146126c157639824bdab6000526004601cfd5b80367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003605401351161275b576040517ff40239db000000000000000000000000000000000000000000000000000000008152367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036014013560048201526024015b60405180910390fd5b6040805160e08101825263ffffffff8082526000602083018181527ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe369081013560f01c90038035606090811c868801908152346fffffffffffffffffffffffffffffffff81811693890193845260149094013560808901908152600160a08a0181815242871660c08c019081526002805493840181558a529a5160059092027f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace81018054995173ffffffffffffffffffffffffffffffffffffffff908116640100000000027fffffffffffffffff000000000000000000000000000000000000000000000000909b1694909c16939093179890981790915592517f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5acf87018054918a167fffffffffffffffffffffffff000000000000000000000000000000000000000090921691909117905592517f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ad0860180549186167fffffffffffffffffffffffffffffffff0000000000000000000000000000000090921691909117905591517f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ad185015551955182167001000000000000000000000000000000000295909116949094177f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ad29091015580547fffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffff167101000000000000000000000000000000000017815583517fd0e30db000000000000000000000000000000000000000000000000000000000815293517f00000000000000000000000000000000000000000000000000000000000000009092169363d0e30db093926004828101939282900301818588803b158015612a3057600080fd5b505af1158015612a44573d6000803e3d6000fd5b5050600080547fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000164267ffffffffffffffff161790555050505050565b600080600054700100000000000000000000000000000000900460ff166002811115612aaf57612aaf61555f565b14612ae6576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060028381548110612afb57612afb6158d5565b600091825260208220600590910201805490925063ffffffff90811614612b6a57815460028054909163ffffffff16908110612b3957612b396158d5565b906000526020600020906005020160040160109054906101000a90046fffffffffffffffffffffffffffffffff1690505b6004820154600090612ba290700100000000000000000000000000000000900467ffffffffffffffff165b67ffffffffffffffff1690565b612bb69067ffffffffffffffff1642615983565b612bd5612b95846fffffffffffffffffffffffffffffffff1660401c90565b67ffffffffffffffff16612be99190615933565b905067ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001667ffffffffffffffff168167ffffffffffffffff1611612c365780611884565b7f000000000000000000000000000000000000000000000000000000000000000095945050505050565b600080612cff836fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1690507f0000000000000000000000000000000000000000000000000000000000000000811115612d5e576040517f56f57b2b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b642e90edd00062061a806311e1a3006000612d798383615aa8565b9050670de0b6b3a76400006000612db0827f0000000000000000000000000000000000000000000000000000000000000000615abc565b90506000612dce612dc9670de0b6b3a764000086615abc565b614078565b90506000612ddc84846142d3565b90506000612dea8383614322565b90506000612df782614350565b90506000612e1682612e11670de0b6b3a76400008f615abc565b614538565b90506000612e248b83614322565b9050612e30818d615abc565b9f9e505050505050505050505050505050565b60028181548110612e5357600080fd5b60009182526020909120600590910201805460018201546002830154600384015460049094015463ffffffff8416955064010000000090930473ffffffffffffffffffffffffffffffffffffffff908116949216926fffffffffffffffffffffffffffffffff91821692918082169170010000000000000000000000000000000090041687565b60008054700100000000000000000000000000000000900460ff166002811115612f0657612f0661555f565b14612f3d576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060028781548110612f5257612f526158d5565b6000918252602082206005919091020160048101549092506fffffffffffffffffffffffffffffffff16908715821760011b9050612fb17f00000000000000000000000000000000000000000000000000000000000000006001615933565b61304d826fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1614613087576040517f5f53dd9800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080891561317e576130da7f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000615983565b6001901b6130f9846fffffffffffffffffffffffffffffffff16614569565b6fffffffffffffffffffffffffffffffff166131159190615af9565b156131525761314961313a60016fffffffffffffffffffffffffffffffff8716615b0d565b865463ffffffff166000614608565b60030154613174565b7f00000000000000000000000000000000000000000000000000000000000000005b91508490506131a8565b600385015491506131a561313a6fffffffffffffffffffffffffffffffff86166001615b36565b90505b600882901b60088a8a6040516131bf9291906158c5565b6040518091039020901b14613200576040517f696550ff00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061320b8c6146ec565b9050600061321a836003015490565b6040517fe14ced320000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063e14ced3290613294908f908f908f908f908a90600401615baa565b6020604051808303816000875af11580156132b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132d791906159b7565b600485015491149150600090600290613382906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b61341e896fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b6134289190615be4565b6134329190615c07565b60ff161590508115158103613473576040517ffb4e40dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8754640100000000900473ffffffffffffffffffffffffffffffffffffffff16156134ca576040517f9071e6af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505085547fffffffffffffffff0000000000000000000000000000000000000000ffffffff163364010000000002179095555050505050505050505050565b60008054700100000000000000000000000000000000900460ff1660028111156135355761353561555f565b1461356c576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008060008061357b8661471b565b9350935093509350600061359185858585614b24565b905060007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa158015613600573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613624919061599a565b90506001890361371c5773ffffffffffffffffffffffffffffffffffffffff81166352f0f3ad8a84613680367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036034013590565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b16815260048101939093526024830191909152604482015260206064820152608481018a905260a4015b6020604051808303816000875af11580156136f2573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061371691906159b7565b5061155b565b600289036137485773ffffffffffffffffffffffffffffffffffffffff81166352f0f3ad8a8489613680565b600389036137745773ffffffffffffffffffffffffffffffffffffffff81166352f0f3ad8a8487613680565b600489036138fb5760006137ba6fffffffffffffffffffffffffffffffff85167f0000000000000000000000000000000000000000000000000000000000000000614bde565b6009546137c79190615933565b6137d2906001615933565b9050367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c900360540135811061383b57367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036054013561383d565b805b905073ffffffffffffffffffffffffffffffffffffffff82166352f0f3ad8b8560405160e084901b7fffffffff000000000000000000000000000000000000000000000000000000001681526004810192909252602482015260c084901b604482015260086064820152608481018b905260a4016020604051808303816000875af11580156138d0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138f491906159b7565b505061155b565b60058903613994576040517f52f0f3ad000000000000000000000000000000000000000000000000000000008152600481018a9052602481018390527f000000000000000000000000000000000000000000000000000000000000000060c01b6044820152600860648201526084810188905273ffffffffffffffffffffffffffffffffffffffff8216906352f0f3ad9060a4016136d3565b6040517fff137e6500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f0000000000000000000000000000000000000000000000000000000000000000367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003601401356060613a1f61188d565b9050909192565b600081831015613a365781613a38565b825b90505b92915050565b60008160000151826020015183604001518460600151604051602001613a80949392919093845260208401929092526040830152606082015260800190565b604051602081830303815290604052805190602001209050919050565b60408051808201909152600080825260208201528151600003613aec576040517f5ab458fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50604080518082019091528151815260209182019181019190915290565b60606000806000613b1a85614c8c565b919450925090506001816001811115613b3557613b3561555f565b14613b6c576040517f4b9c6abe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8451613b788385615933565b14613baf576040517f5c5537b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516020808252610420820190925290816020015b6040805180820190915260008082526020820152815260200190600190039081613bc65790505093506000835b8651811015613cb457600080613c396040518060400160405280858c60000151613c1d9190615983565b8152602001858c60200151613c329190615933565b9052614c8c565b509150915060405180604001604052808383613c559190615933565b8152602001848b60200151613c6a9190615933565b815250888581518110613c7f57613c7f6158d5565b6020908102919091010152613c95600185615933565b9350613ca18183615933565b613cab9084615933565b92505050613bf3565b50845250919392505050565b60606000806000613cd085614c8c565b919450925090506000816001811115613ceb57613ceb61555f565b14613d22576040517f1ff9b2e400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b613d2c8284615933565b855114613d65576040517f5c5537b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6118848560200151848461512a565b600281015473ffffffffffffffffffffffffffffffffffffffff8316600090815260036020526040812080546fffffffffffffffffffffffffffffffff90931692839290613dc3908490615933565b90915550506040517f7eee288d00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8481166004830152602482018390527f00000000000000000000000000000000000000000000000000000000000000001690637eee288d90604401600060405180830381600087803b158015613e5857600080fd5b505af1158015613e6c573d6000803e3d6000fd5b50505050505050565b604051818152367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90038284820160208401378260208301016000815260208101604052505092915050565b6000613ee66fffffffffffffffffffffffffffffffff84166001615b36565b90506000613ef682866001614608565b9050600086901a8380613fe25750613f2f60027f0000000000000000000000000000000000000000000000000000000000000000615af9565b6004830154600290613fd3906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b613fdd9190615c07565b60ff16145b1561403a5760ff811660011480613ffc575060ff81166002145b614035576040517ff40239db00000000000000000000000000000000000000000000000000000000815260048101889052602401612752565b613e6c565b60ff811615613e6c576040517ff40239db00000000000000000000000000000000000000000000000000000000815260048101889052602401612752565b6fffffffffffffffffffffffffffffffff811160071b81811c67ffffffffffffffff1060061b1781811c63ffffffff1060051b1781811c61ffff1060041b1781811c60ff1060031b17600082136140d757631615e6386000526004601cfd5b7ff8f9f9faf9fdfafbf9fdfcfdfafbfcfef9fafdfafcfcfbfefafafcfbffffffff6f8421084210842108cc6318c6db6d54be83831c1c601f161a1890811b609f90811c6c465772b2bbbb5f824b15207a3081018102606090811d6d0388eaa27412d5aca026815d636e018202811d6d0df99ac502031bf953eff472fdcc018202811d6d13cdffb29d51d99322bdff5f2211018202811d6d0a0f742023def783a307a986912e018202811d6d01920d8043ca89b5239253284e42018202811d6c0b7a86d7375468fac667a0a527016c29508e458543d8aa4df2abee7883018302821d6d0139601a2efabe717e604cbb4894018302821d6d02247f7a7b6594320649aa03aba1018302821d7fffffffffffffffffffffffffffffffffffffff73c0c716a594e00d54e3c4cbc9018302821d7ffffffffffffffffffffffffffffffffffffffdc7b88c420e53a9890533129f6f01830290911d7fffffffffffffffffffffffffffffffffffffff465fda27eb4d63ded474e5f832019091027ffffffffffffffff5f6af8f7b3396644f18e157960000000000000000000000000105711340daa0d5f769dba1915cef59f0815a5506029190037d0267a36c0c95b3975ab3ee5b203a7614a3f75373f047d803ae7b6687f2b302017d57115e47018c7177eebf7cd370a3356a1b7863008a5ae8028c72b88642840160ae1d90565b60007812725dd1d243aba0e75fe645cc4873f9e65afe688c928e1f218311670de0b6b3a76400000215820261431057637c5f487d6000526004601cfd5b50670de0b6b3a7640000919091020490565b6000816000190483118202156143405763bac65e5b6000526004601cfd5b50670de0b6b3a764000091020490565b60007ffffffffffffffffffffffffffffffffffffffffffffffffdc0d0570925a462d7821361437e57919050565b680755bf798b4a1bf1e5821261439c5763a37bfec96000526004601cfd5b6503782dace9d9604e83901b059150600060606bb17217f7d1cf79abc9e3b39884821b056b80000000000000000000000001901d6bb17217f7d1cf79abc9e3b39881029093037fffffffffffffffffffffffffffffffffffffffdbf3ccf1604d263450f02a550481018102606090811d6d0277594991cfc85f6e2461837cd9018202811d7fffffffffffffffffffffffffffffffffffffe5adedaa1cb095af9e4da10e363c018202811d6db1bbb201f443cf962f1a1d3db4a5018202811d7ffffffffffffffffffffffffffffffffffffd38dc772608b0ae56cce01296c0eb018202811d6e05180bb14799ab47a8a8cb2a527d57016d02d16720577bd19bf614176fe9ea6c10fe68e7fd37d0007b713f765084018402831d9081019084017ffffffffffffffffffffffffffffffffffffffe2c69812cf03b0763fd454a8f7e010290911d6e0587f503bb6ea29d25fcb7401964500190910279d835ebba824c98fb31b83b2ca45c000000000000000000000000010574029d9dc38563c32e5c2f6dc192ee70ef65f9978af30260c3939093039290921c92915050565b6000613a38670de0b6b3a76400008361455086614078565b61455a9190615c29565b6145649190615ce5565b614350565b6000806145f6837e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b600160ff919091161b90920392915050565b600080826146515761464c6fffffffffffffffffffffffffffffffff86167f00000000000000000000000000000000000000000000000000000000000000006151bf565b61466c565b61466c856fffffffffffffffffffffffffffffffff1661534b565b905060028481548110614681576146816158d5565b906000526020600020906005020191505b60048201546fffffffffffffffffffffffffffffffff8281169116146146e457815460028054909163ffffffff169081106146cf576146cf6158d5565b90600052602060002090600502019150614692565b509392505050565b60008060008060006146fd8661471b565b935093509350935061471184848484614b24565b9695505050505050565b600080600080600085905060006002828154811061473b5761473b6158d5565b600091825260209091206004600590920201908101549091507f000000000000000000000000000000000000000000000000000000000000000090614812906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff161161484c576040517fb34b5c2200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000815b60048301547f000000000000000000000000000000000000000000000000000000000000000090614913906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff16925082111561498857825463ffffffff166149527f00000000000000000000000000000000000000000000000000000000000000006001615933565b830361495c578391505b6002818154811061496f5761496f6158d5565b9060005260206000209060050201935080945050614850565b600481810154908401546fffffffffffffffffffffffffffffffff91821691166000816fffffffffffffffffffffffffffffffff166149f16149dc856fffffffffffffffffffffffffffffffff1660011c90565b6fffffffffffffffffffffffffffffffff1690565b6fffffffffffffffffffffffffffffffff161490508015614ac0576000614a29836fffffffffffffffffffffffffffffffff16614569565b6fffffffffffffffffffffffffffffffff161115614a94576000614a6b614a6360016fffffffffffffffffffffffffffffffff8616615b0d565b896001614608565b6003810154600490910154909c506fffffffffffffffffffffffffffffffff169a50614a9a9050565b6008549a505b600386015460048701549099506fffffffffffffffffffffffffffffffff169750614b16565b6000614ae2614a636fffffffffffffffffffffffffffffffff85166001615b36565b6003808901546004808b015492840154930154909e506fffffffffffffffffffffffffffffffff9182169d50919b50169850505b505050505050509193509193565b60006fffffffffffffffffffffffffffffffff841615614b915760408051602081018790526fffffffffffffffffffffffffffffffff8087169282019290925260608101859052908316608082015260a00160405160208183030381529060405280519060200120611884565b8282604051602001614bbf9291909182526fffffffffffffffffffffffffffffffff16602082015260400190565b6040516020818303038152906040528051906020012095945050505050565b600080614c6b847e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1690508083036001841b600180831b0386831b17039250505092915050565b60008060008360000151600003614ccf576040517f5ab458fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6020840151805160001a607f8111614cf4576000600160009450945094505050615123565b60b78111614e0a576000614d09608083615983565b905080876000015111614d48576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001838101517fff00000000000000000000000000000000000000000000000000000000000000169082148015614dc057507f80000000000000000000000000000000000000000000000000000000000000007fff000000000000000000000000000000000000000000000000000000000000008216105b15614df7576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5060019550935060009250615123915050565b60bf8111614f68576000614e1f60b783615983565b905080876000015111614e5e576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018301517fff00000000000000000000000000000000000000000000000000000000000000166000819003614ec0576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600184015160088302610100031c60378111614f08576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b614f128184615933565b895111614f4b576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b614f56836001615933565b97509550600094506151239350505050565b60f78111614fcd576000614f7d60c083615983565b905080876000015111614fbc576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600195509350849250615123915050565b6000614fda60f783615983565b905080876000015111615019576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018301517fff0000000000000000000000000000000000000000000000000000000000000016600081900361507b576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600184015160088302610100031c603781116150c3576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6150cd8184615933565b895111615106576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b615111836001615933565b97509550600194506151239350505050565b9193909250565b60608167ffffffffffffffff81111561514557615145615809565b6040519080825280601f01601f19166020018201604052801561516f576020820181803683370190505b50905081156151b85760006151848486615933565b90506020820160005b848110156151a557828101518282015260200161518d565b848111156151b4576000858301525b5050505b9392505050565b60008161525e846fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff16116152745763b34b5c226000526004601cfd5b61527d8361534b565b90508161531c826fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1611613a3b57613a38615332836001615933565b6fffffffffffffffffffffffffffffffff8316906153f0565b600081196001830116816153df827e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff169390931c8015179392505050565b60008061547d847e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff169050808303600180821b0385821b179250505092915050565b60008083601f8401126154ab57600080fd5b50813567ffffffffffffffff8111156154c357600080fd5b6020830191508360208285010111156154db57600080fd5b9250929050565b600080600083850360a08112156154f857600080fd5b608081121561550657600080fd5b50839250608084013567ffffffffffffffff81111561552457600080fd5b61553086828701615499565b9497909650939450505050565b6000806040838503121561555057600080fd5b50508035926020909101359150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60208101600383106155c9577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b91905290565b6000806000606084860312156155e457600080fd5b505081359360208301359350604090920135919050565b6000815180845260005b8181101561562157602081850181015186830182015201615605565b81811115615633576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000613a3860208301846155fb565b60006020828403121561568b57600080fd5b5035919050565b73ffffffffffffffffffffffffffffffffffffffff811681146156b457600080fd5b50565b6000602082840312156156c957600080fd5b81356151b881615692565b803580151581146156e457600080fd5b919050565b600080600080608085870312156156ff57600080fd5b84359350602085013592506040850135915061571d606086016156d4565b905092959194509250565b60006020828403121561573a57600080fd5b81356fffffffffffffffffffffffffffffffff811681146151b857600080fd5b6000806000806000806080878903121561577357600080fd5b86359550615783602088016156d4565b9450604087013567ffffffffffffffff808211156157a057600080fd5b6157ac8a838b01615499565b909650945060608901359150808211156157c557600080fd5b506157d289828a01615499565b979a9699509497509295939492505050565b63ffffffff8416815282602082015260606040820152600061188460608301846155fb565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60006080828403121561584a57600080fd5b6040516080810181811067ffffffffffffffff82111715615894577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b8060405250823581526020830135602082015260408301356040820152606083013560608201528091505092915050565b8183823760009101908152919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000821982111561594657615946615904565b500190565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361597c5761597c615904565b5060010190565b60008282101561599557615995615904565b500390565b6000602082840312156159ac57600080fd5b81516151b881615692565b6000602082840312156159c957600080fd5b5051919050565b600067ffffffffffffffff8083168185168083038211156159f3576159f3615904565b01949350505050565b600067ffffffffffffffff80831681851681830481118215151615615a2357615a23615904565b02949350505050565b600067ffffffffffffffff83811690831681811015615a4d57615a4d615904565b039392505050565b60008060408385031215615a6857600080fd5b505080516020909101519092909150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082615ab757615ab7615a79565b500490565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615615af457615af4615904565b500290565b600082615b0857615b08615a79565b500690565b60006fffffffffffffffffffffffffffffffff83811690831681811015615a4d57615a4d615904565b60006fffffffffffffffffffffffffffffffff8083168185168083038211156159f3576159f3615904565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b606081526000615bbe606083018789615b61565b8281036020840152615bd1818688615b61565b9150508260408301529695505050505050565b600060ff821660ff841680821015615bfe57615bfe615904565b90039392505050565b600060ff831680615c1a57615c1a615a79565b8060ff84160691505092915050565b60007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600084136000841385830485118282161615615c6a57615c6a615904565b7f80000000000000000000000000000000000000000000000000000000000000006000871286820588128184161615615ca557615ca5615904565b60008712925087820587128484161615615cc157615cc1615904565b87850587128184161615615cd757615cd7615904565b505050929093029392505050565b600082615cf457615cf4615a79565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83147f800000000000000000000000000000000000000000000000000000000000000083141615615d4857615d48615904565b50059056fea164736f6c634300080f000a"; - console.log("FaultDisputeGame initCodeHash (compare with https://github.com/ethereum-optimism/optimism/blob/op-contracts/v1.8.0/packages/contracts-bedrock/semver-lock.json#L171):"); - console.logBytes32(keccak256(faultDisputeGameInitcode)); - - (blueprints.permissionlessDisputeGame1, blueprints.permissionlessDisputeGame2) = DeployUtils.createDeterministicBlueprint(faultDisputeGameInitcode, _salt); - - vm.stopBroadcast(); - require( - blueprints.permissionlessDisputeGame2 != address(0), - "DeployOPPrestateUpdater: Second permissionless dispute game not deployed as expected." - ); - // forgefmt: disable-end - - OPPrestateUpdater oppu = OPPrestateUpdater( - DeployUtils.createDeterministic({ - _name: "OPPrestateUpdater", - _args: DeployUtils.encodeConstructor( - abi.encodeCall(IOPPrestateUpdater.__constructor__, (superchainConfig, protocolVersions, blueprints)) - ), - _salt: bytes32(_salt) - }) - ); - - require(address(oppu.superchainConfig()) == address(superchainConfig), "OPPUI-10"); - require(address(oppu.protocolVersions()) == address(protocolVersions), "OPPUI-20"); - require(LibString.eq(oppu.l1ContractsRelease(), "none"), "OPPUI-30"); - - require(oppu.upgradeController() == address(0), "OPPUI-40"); - - // encode decode because oppu.implementations returns IOPPrestateUpdater.Implementations - IOPContractsManager.Implementations memory implementations = - abi.decode(abi.encode(oppu.implementations()), (IOPContractsManager.Implementations)); - require(implementations.l1CrossDomainMessengerImpl == address(0), "OPPUI-120"); - require(implementations.l1StandardBridgeImpl == address(0), "OPPUI-130"); - require(implementations.disputeGameFactoryImpl == address(0), "OPPUI-140"); - require(implementations.optimismMintableERC20FactoryImpl == address(0), "OPPUI-150"); - require(implementations.l1CrossDomainMessengerImpl == address(0), "OPPUI-160"); - require(implementations.l1StandardBridgeImpl == address(0), "OPPUI-170"); - require(implementations.disputeGameFactoryImpl == address(0), "OPPUI-180"); - require(implementations.anchorStateRegistryImpl == address(0), "OPPUI-190"); - require(implementations.delayedWETHImpl == address(0), "OPPUI-200"); - require(implementations.mipsImpl == address(0), "OPPUI-210"); - - IOPContractsManager.Blueprints memory actualBluePrints = - abi.decode(abi.encode(oppu.blueprints()), (IOPContractsManager.Blueprints)); - require(actualBluePrints.addressManager == address(0), "OPPUI-300"); - require(actualBluePrints.proxy == address(0), "OPPUI-310"); - require(actualBluePrints.proxyAdmin == address(0), "OPPUI-320"); - require(actualBluePrints.l1ChugSplashProxy == address(0), "OPPUI-330"); - require(actualBluePrints.resolvedDelegateProxy == address(0), "OPPUI-340"); - require(actualBluePrints.permissionedDisputeGame1 == blueprints180.permissionedDisputeGame1, "OPPUI-350"); - require(actualBluePrints.permissionedDisputeGame2 == blueprints180.permissionedDisputeGame2, "OPPUI-360"); - require(actualBluePrints.permissionlessDisputeGame1 == blueprints.permissionlessDisputeGame1, "OPPUI-370"); - require(actualBluePrints.permissionlessDisputeGame2 == blueprints.permissionlessDisputeGame2, "OPPUI-380"); - - return oppu; - } -} diff --git a/packages/contracts-bedrock/snapshots/abi/OPContractsManager.json b/packages/contracts-bedrock/snapshots/abi/OPContractsManager.json index 22c1d40b77cd2..a12ea8e94117b 100644 --- a/packages/contracts-bedrock/snapshots/abi/OPContractsManager.json +++ b/packages/contracts-bedrock/snapshots/abi/OPContractsManager.json @@ -1,6 +1,21 @@ [ { "inputs": [ + { + "internalType": "contract OPContractsManagerGameTypeAdder", + "name": "_opcmGameTypeAdder", + "type": "address" + }, + { + "internalType": "contract OPContractsManagerDeployer", + "name": "_opcmDeployer", + "type": "address" + }, + { + "internalType": "contract OPContractsManagerUpgrader", + "name": "_opcmUpgrader", + "type": "address" + }, { "internalType": "contract ISuperchainConfig", "name": "_superchainConfig", @@ -21,125 +36,6 @@ "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": "permissionedDisputeGame1", - "type": "address" - }, - { - "internalType": "address", - "name": "permissionedDisputeGame2", - "type": "address" - }, - { - "internalType": "address", - "name": "permissionlessDisputeGame1", - "type": "address" - }, - { - "internalType": "address", - "name": "permissionlessDisputeGame2", - "type": "address" - } - ], - "internalType": "struct OPContractsManager.Blueprints", - "name": "_blueprints", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "address", - "name": "superchainConfigImpl", - "type": "address" - }, - { - "internalType": "address", - "name": "protocolVersionsImpl", - "type": "address" - }, - { - "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": "anchorStateRegistryImpl", - "type": "address" - }, - { - "internalType": "address", - "name": "delayedWETHImpl", - "type": "address" - }, - { - "internalType": "address", - "name": "mipsImpl", - "type": "address" - } - ], - "internalType": "struct OPContractsManager.Implementations", - "name": "_implementations", - "type": "tuple" - }, { "internalType": "address", "name": "_upgradeController", @@ -323,7 +219,7 @@ "type": "address" } ], - "stateMutability": "pure", + "stateMutability": "view", "type": "function" }, { @@ -617,6 +513,45 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "opcmDeployer", + "outputs": [ + { + "internalType": "contract OPContractsManagerDeployer", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "opcmGameTypeAdder", + "outputs": [ + { + "internalType": "contract OPContractsManagerGameTypeAdder", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "opcmUpgrader", + "outputs": [ + { + "internalType": "contract OPContractsManagerUpgrader", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "protocolVersions", @@ -669,6 +604,36 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [ + { + "components": [ + { + "internalType": "contract ISystemConfig", + "name": "systemConfigProxy", + "type": "address" + }, + { + "internalType": "contract IProxyAdmin", + "name": "proxyAdmin", + "type": "address" + }, + { + "internalType": "Claim", + "name": "absolutePrestate", + "type": "bytes32" + } + ], + "internalType": "struct OPContractsManager.OpChainConfig[]", + "name": "_prestateUpdateInputs", + "type": "tuple[]" + } + ], + "name": "updatePrestate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [ { @@ -725,87 +690,6 @@ "stateMutability": "pure", "type": "function" }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "l2ChainId", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "deployer", - "type": "address" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "deployOutput", - "type": "bytes" - } - ], - "name": "Deployed", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "l2ChainId", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "GameType", - "name": "gameType", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "contract IDisputeGame", - "name": "newDisputeGame", - "type": "address" - }, - { - "indexed": false, - "internalType": "contract IDisputeGame", - "name": "oldDisputeGame", - "type": "address" - } - ], - "name": "GameTypeAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "l2ChainId", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "contract ISystemConfig", - "name": "systemConfig", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "upgrader", - "type": "address" - } - ], - "name": "Upgraded", - "type": "event" - }, { "inputs": [ { @@ -833,26 +717,6 @@ "name": "AlreadyReleased", "type": "error" }, - { - "inputs": [], - "name": "BytesArrayTooLong", - "type": "error" - }, - { - "inputs": [], - "name": "DeploymentFailed", - "type": "error" - }, - { - "inputs": [], - "name": "EmptyInitcode", - "type": "error" - }, - { - "inputs": [], - "name": "IdentityPrecompileCallFailed", - "type": "error" - }, { "inputs": [], "name": "InvalidChainId", @@ -884,11 +748,6 @@ "name": "LatestReleaseNotSet", "type": "error" }, - { - "inputs": [], - "name": "NotABlueprint", - "type": "error" - }, { "inputs": [], "name": "OnlyDelegatecall", @@ -906,7 +765,7 @@ }, { "inputs": [], - "name": "ReservedBitsSet", + "name": "PrestateRequired", "type": "error" }, { @@ -924,27 +783,5 @@ "inputs": [], "name": "SuperchainProxyAdminMismatch", "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "UnexpectedPreambleData", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint8", - "name": "version", - "type": "uint8" - } - ], - "name": "UnsupportedERCVersion", - "type": "error" } ] \ No newline at end of file diff --git a/packages/contracts-bedrock/snapshots/abi/OPContractsManagerContractsContainer.json b/packages/contracts-bedrock/snapshots/abi/OPContractsManagerContractsContainer.json new file mode 100644 index 0000000000000..45af4462a5637 --- /dev/null +++ b/packages/contracts-bedrock/snapshots/abi/OPContractsManagerContractsContainer.json @@ -0,0 +1,262 @@ +[ + { + "inputs": [ + { + "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": "permissionedDisputeGame1", + "type": "address" + }, + { + "internalType": "address", + "name": "permissionedDisputeGame2", + "type": "address" + }, + { + "internalType": "address", + "name": "permissionlessDisputeGame1", + "type": "address" + }, + { + "internalType": "address", + "name": "permissionlessDisputeGame2", + "type": "address" + } + ], + "internalType": "struct OPContractsManager.Blueprints", + "name": "_blueprints", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "address", + "name": "superchainConfigImpl", + "type": "address" + }, + { + "internalType": "address", + "name": "protocolVersionsImpl", + "type": "address" + }, + { + "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": "anchorStateRegistryImpl", + "type": "address" + }, + { + "internalType": "address", + "name": "delayedWETHImpl", + "type": "address" + }, + { + "internalType": "address", + "name": "mipsImpl", + "type": "address" + } + ], + "internalType": "struct OPContractsManager.Implementations", + "name": "_implementations", + "type": "tuple" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "blueprints", + "outputs": [ + { + "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": "permissionedDisputeGame1", + "type": "address" + }, + { + "internalType": "address", + "name": "permissionedDisputeGame2", + "type": "address" + }, + { + "internalType": "address", + "name": "permissionlessDisputeGame1", + "type": "address" + }, + { + "internalType": "address", + "name": "permissionlessDisputeGame2", + "type": "address" + } + ], + "internalType": "struct OPContractsManager.Blueprints", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "implementations", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "superchainConfigImpl", + "type": "address" + }, + { + "internalType": "address", + "name": "protocolVersionsImpl", + "type": "address" + }, + { + "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": "anchorStateRegistryImpl", + "type": "address" + }, + { + "internalType": "address", + "name": "delayedWETHImpl", + "type": "address" + }, + { + "internalType": "address", + "name": "mipsImpl", + "type": "address" + } + ], + "internalType": "struct OPContractsManager.Implementations", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + } +] \ No newline at end of file diff --git a/packages/contracts-bedrock/snapshots/abi/OPPrestateUpdater.json b/packages/contracts-bedrock/snapshots/abi/OPContractsManagerDeployer.json similarity index 55% rename from packages/contracts-bedrock/snapshots/abi/OPPrestateUpdater.json rename to packages/contracts-bedrock/snapshots/abi/OPContractsManagerDeployer.json index d44b099737a6f..d543175c82822 100644 --- a/packages/contracts-bedrock/snapshots/abi/OPPrestateUpdater.json +++ b/packages/contracts-bedrock/snapshots/abi/OPContractsManagerDeployer.json @@ -2,66 +2,9 @@ { "inputs": [ { - "internalType": "contract ISuperchainConfig", - "name": "_superchainConfig", + "internalType": "contract OPContractsManagerContractsContainer", + "name": "_contractsContainer", "type": "address" - }, - { - "internalType": "contract IProtocolVersions", - "name": "_protocolVersions", - "type": "address" - }, - { - "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": "permissionedDisputeGame1", - "type": "address" - }, - { - "internalType": "address", - "name": "permissionedDisputeGame2", - "type": "address" - }, - { - "internalType": "address", - "name": "permissionlessDisputeGame1", - "type": "address" - }, - { - "internalType": "address", - "name": "permissionlessDisputeGame2", - "type": "address" - } - ], - "internalType": "struct OPContractsManager.Blueprints", - "name": "_blueprints", - "type": "tuple" } ], "stateMutability": "nonpayable", @@ -70,99 +13,14 @@ { "inputs": [ { - "components": [ - { - "internalType": "string", - "name": "saltMixer", - "type": "string" - }, - { - "internalType": "contract ISystemConfig", - "name": "systemConfig", - "type": "address" - }, - { - "internalType": "contract IProxyAdmin", - "name": "proxyAdmin", - "type": "address" - }, - { - "internalType": "contract IDelayedWETH", - "name": "delayedWETH", - "type": "address" - }, - { - "internalType": "GameType", - "name": "disputeGameType", - "type": "uint32" - }, - { - "internalType": "Claim", - "name": "disputeAbsolutePrestate", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "disputeMaxGameDepth", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "disputeSplitDepth", - "type": "uint256" - }, - { - "internalType": "Duration", - "name": "disputeClockExtension", - "type": "uint64" - }, - { - "internalType": "Duration", - "name": "disputeMaxClockDuration", - "type": "uint64" - }, - { - "internalType": "uint256", - "name": "initialBond", - "type": "uint256" - }, - { - "internalType": "contract IBigStepper", - "name": "vm", - "type": "address" - }, - { - "internalType": "bool", - "name": "permissioned", - "type": "bool" - } - ], - "internalType": "struct OPContractsManager.AddGameInput[]", - "name": "_gameConfigs", - "type": "tuple[]" - } - ], - "name": "addGameType", - "outputs": [ - { - "components": [ - { - "internalType": "contract IDelayedWETH", - "name": "delayedWETH", - "type": "address" - }, - { - "internalType": "contract IFaultDisputeGame", - "name": "faultDisputeGame", - "type": "address" - } - ], - "internalType": "struct OPContractsManager.AddGameOutput[]", - "name": "", - "type": "tuple[]" + "internalType": "address", + "name": "_who", + "type": "address" } ], - "stateMutability": "pure", + "name": "assertValidContractAddress", + "outputs": [], + "stateMutability": "view", "type": "function" }, { @@ -244,6 +102,19 @@ "stateMutability": "pure", "type": "function" }, + { + "inputs": [], + "name": "contractsContainer", + "outputs": [ + { + "internalType": "contract OPContractsManagerContractsContainer", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [ { @@ -349,6 +220,16 @@ "internalType": "struct OPContractsManager.DeployInput", "name": "_input", "type": "tuple" + }, + { + "internalType": "contract ISuperchainConfig", + "name": "_superchainConfig", + "type": "address" + }, + { + "internalType": "address", + "name": "_deployer", + "type": "address" } ], "name": "deploy", @@ -431,7 +312,7 @@ "type": "tuple" } ], - "stateMutability": "pure", + "stateMutability": "nonpayable", "type": "function" }, { @@ -509,170 +390,6 @@ "stateMutability": "view", "type": "function" }, - { - "inputs": [], - "name": "isRC", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "l1ContractsRelease", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [], - "name": "protocolVersions", - "outputs": [ - { - "internalType": "contract IProtocolVersions", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bool", - "name": "_isRC", - "type": "bool" - } - ], - "name": "setRC", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "superchainConfig", - "outputs": [ - { - "internalType": "contract ISuperchainConfig", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "superchainProxyAdmin", - "outputs": [ - { - "internalType": "contract IProxyAdmin", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "contract ISystemConfig", - "name": "systemConfigProxy", - "type": "address" - }, - { - "internalType": "contract IProxyAdmin", - "name": "proxyAdmin", - "type": "address" - }, - { - "internalType": "Claim", - "name": "absolutePrestate", - "type": "bytes32" - } - ], - "internalType": "struct OPContractsManager.OpChainConfig[]", - "name": "_prestateUpdateInputs", - "type": "tuple[]" - } - ], - "name": "updatePrestate", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "contract ISystemConfig", - "name": "systemConfigProxy", - "type": "address" - }, - { - "internalType": "contract IProxyAdmin", - "name": "proxyAdmin", - "type": "address" - }, - { - "internalType": "Claim", - "name": "absolutePrestate", - "type": "bytes32" - } - ], - "internalType": "struct OPContractsManager.OpChainConfig[]", - "name": "_opChainConfigs", - "type": "tuple[]" - } - ], - "name": "upgrade", - "outputs": [], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [], - "name": "upgradeController", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "version", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "pure", - "type": "function" - }, { "anonymous": false, "inputs": [ @@ -698,62 +415,6 @@ "name": "Deployed", "type": "event" }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "l2ChainId", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "GameType", - "name": "gameType", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "contract IDisputeGame", - "name": "newDisputeGame", - "type": "address" - }, - { - "indexed": false, - "internalType": "contract IDisputeGame", - "name": "oldDisputeGame", - "type": "address" - } - ], - "name": "GameTypeAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "l2ChainId", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "contract ISystemConfig", - "name": "systemConfig", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "upgrader", - "type": "address" - } - ], - "name": "Upgraded", - "type": "event" - }, { "inputs": [ { @@ -765,22 +426,6 @@ "name": "AddressHasNoCode", "type": "error" }, - { - "inputs": [ - { - "internalType": "address", - "name": "who", - "type": "address" - } - ], - "name": "AddressNotFound", - "type": "error" - }, - { - "inputs": [], - "name": "AlreadyReleased", - "type": "error" - }, { "inputs": [], "name": "BytesArrayTooLong", @@ -806,11 +451,6 @@ "name": "InvalidChainId", "type": "error" }, - { - "inputs": [], - "name": "InvalidGameConfigs", - "type": "error" - }, { "inputs": [ { @@ -827,62 +467,16 @@ "name": "InvalidStartingAnchorRoot", "type": "error" }, - { - "inputs": [], - "name": "LatestReleaseNotSet", - "type": "error" - }, { "inputs": [], "name": "NotABlueprint", "type": "error" }, - { - "inputs": [], - "name": "NotImplemented", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyDelegatecall", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyUpgradeController", - "type": "error" - }, - { - "inputs": [], - "name": "PrestateNotSet", - "type": "error" - }, - { - "inputs": [], - "name": "PrestateRequired", - "type": "error" - }, { "inputs": [], "name": "ReservedBitsSet", "type": "error" }, - { - "inputs": [ - { - "internalType": "contract ISystemConfig", - "name": "systemConfig", - "type": "address" - } - ], - "name": "SuperchainConfigMismatch", - "type": "error" - }, - { - "inputs": [], - "name": "SuperchainProxyAdminMismatch", - "type": "error" - }, { "inputs": [ { diff --git a/packages/contracts-bedrock/snapshots/abi/OPContractsManagerInterop.json b/packages/contracts-bedrock/snapshots/abi/OPContractsManagerDeployerInterop.json similarity index 52% rename from packages/contracts-bedrock/snapshots/abi/OPContractsManagerInterop.json rename to packages/contracts-bedrock/snapshots/abi/OPContractsManagerDeployerInterop.json index 22c1d40b77cd2..d543175c82822 100644 --- a/packages/contracts-bedrock/snapshots/abi/OPContractsManagerInterop.json +++ b/packages/contracts-bedrock/snapshots/abi/OPContractsManagerDeployerInterop.json @@ -2,147 +2,8 @@ { "inputs": [ { - "internalType": "contract ISuperchainConfig", - "name": "_superchainConfig", - "type": "address" - }, - { - "internalType": "contract IProtocolVersions", - "name": "_protocolVersions", - "type": "address" - }, - { - "internalType": "contract IProxyAdmin", - "name": "_superchainProxyAdmin", - "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": "permissionedDisputeGame1", - "type": "address" - }, - { - "internalType": "address", - "name": "permissionedDisputeGame2", - "type": "address" - }, - { - "internalType": "address", - "name": "permissionlessDisputeGame1", - "type": "address" - }, - { - "internalType": "address", - "name": "permissionlessDisputeGame2", - "type": "address" - } - ], - "internalType": "struct OPContractsManager.Blueprints", - "name": "_blueprints", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "address", - "name": "superchainConfigImpl", - "type": "address" - }, - { - "internalType": "address", - "name": "protocolVersionsImpl", - "type": "address" - }, - { - "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": "anchorStateRegistryImpl", - "type": "address" - }, - { - "internalType": "address", - "name": "delayedWETHImpl", - "type": "address" - }, - { - "internalType": "address", - "name": "mipsImpl", - "type": "address" - } - ], - "internalType": "struct OPContractsManager.Implementations", - "name": "_implementations", - "type": "tuple" - }, - { - "internalType": "address", - "name": "_upgradeController", + "internalType": "contract OPContractsManagerContractsContainer", + "name": "_contractsContainer", "type": "address" } ], @@ -152,99 +13,14 @@ { "inputs": [ { - "components": [ - { - "internalType": "string", - "name": "saltMixer", - "type": "string" - }, - { - "internalType": "contract ISystemConfig", - "name": "systemConfig", - "type": "address" - }, - { - "internalType": "contract IProxyAdmin", - "name": "proxyAdmin", - "type": "address" - }, - { - "internalType": "contract IDelayedWETH", - "name": "delayedWETH", - "type": "address" - }, - { - "internalType": "GameType", - "name": "disputeGameType", - "type": "uint32" - }, - { - "internalType": "Claim", - "name": "disputeAbsolutePrestate", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "disputeMaxGameDepth", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "disputeSplitDepth", - "type": "uint256" - }, - { - "internalType": "Duration", - "name": "disputeClockExtension", - "type": "uint64" - }, - { - "internalType": "Duration", - "name": "disputeMaxClockDuration", - "type": "uint64" - }, - { - "internalType": "uint256", - "name": "initialBond", - "type": "uint256" - }, - { - "internalType": "contract IBigStepper", - "name": "vm", - "type": "address" - }, - { - "internalType": "bool", - "name": "permissioned", - "type": "bool" - } - ], - "internalType": "struct OPContractsManager.AddGameInput[]", - "name": "_gameConfigs", - "type": "tuple[]" - } - ], - "name": "addGameType", - "outputs": [ - { - "components": [ - { - "internalType": "contract IDelayedWETH", - "name": "delayedWETH", - "type": "address" - }, - { - "internalType": "contract IFaultDisputeGame", - "name": "faultDisputeGame", - "type": "address" - } - ], - "internalType": "struct OPContractsManager.AddGameOutput[]", - "name": "", - "type": "tuple[]" + "internalType": "address", + "name": "_who", + "type": "address" } ], - "stateMutability": "nonpayable", + "name": "assertValidContractAddress", + "outputs": [], + "stateMutability": "view", "type": "function" }, { @@ -326,6 +102,19 @@ "stateMutability": "pure", "type": "function" }, + { + "inputs": [], + "name": "contractsContainer", + "outputs": [ + { + "internalType": "contract OPContractsManagerContractsContainer", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [ { @@ -431,6 +220,16 @@ "internalType": "struct OPContractsManager.DeployInput", "name": "_input", "type": "tuple" + }, + { + "internalType": "contract ISuperchainConfig", + "name": "_superchainConfig", + "type": "address" + }, + { + "internalType": "address", + "name": "_deployer", + "type": "address" } ], "name": "deploy", @@ -591,140 +390,6 @@ "stateMutability": "view", "type": "function" }, - { - "inputs": [], - "name": "isRC", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "l1ContractsRelease", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "protocolVersions", - "outputs": [ - { - "internalType": "contract IProtocolVersions", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bool", - "name": "_isRC", - "type": "bool" - } - ], - "name": "setRC", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "superchainConfig", - "outputs": [ - { - "internalType": "contract ISuperchainConfig", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "superchainProxyAdmin", - "outputs": [ - { - "internalType": "contract IProxyAdmin", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "contract ISystemConfig", - "name": "systemConfigProxy", - "type": "address" - }, - { - "internalType": "contract IProxyAdmin", - "name": "proxyAdmin", - "type": "address" - }, - { - "internalType": "Claim", - "name": "absolutePrestate", - "type": "bytes32" - } - ], - "internalType": "struct OPContractsManager.OpChainConfig[]", - "name": "_opChainConfigs", - "type": "tuple[]" - } - ], - "name": "upgrade", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "upgradeController", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "version", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "pure", - "type": "function" - }, { "anonymous": false, "inputs": [ @@ -750,62 +415,6 @@ "name": "Deployed", "type": "event" }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "l2ChainId", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "GameType", - "name": "gameType", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "contract IDisputeGame", - "name": "newDisputeGame", - "type": "address" - }, - { - "indexed": false, - "internalType": "contract IDisputeGame", - "name": "oldDisputeGame", - "type": "address" - } - ], - "name": "GameTypeAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "l2ChainId", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "contract ISystemConfig", - "name": "systemConfig", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "upgrader", - "type": "address" - } - ], - "name": "Upgraded", - "type": "event" - }, { "inputs": [ { @@ -817,22 +426,6 @@ "name": "AddressHasNoCode", "type": "error" }, - { - "inputs": [ - { - "internalType": "address", - "name": "who", - "type": "address" - } - ], - "name": "AddressNotFound", - "type": "error" - }, - { - "inputs": [], - "name": "AlreadyReleased", - "type": "error" - }, { "inputs": [], "name": "BytesArrayTooLong", @@ -858,11 +451,6 @@ "name": "InvalidChainId", "type": "error" }, - { - "inputs": [], - "name": "InvalidGameConfigs", - "type": "error" - }, { "inputs": [ { @@ -879,52 +467,16 @@ "name": "InvalidStartingAnchorRoot", "type": "error" }, - { - "inputs": [], - "name": "LatestReleaseNotSet", - "type": "error" - }, { "inputs": [], "name": "NotABlueprint", "type": "error" }, - { - "inputs": [], - "name": "OnlyDelegatecall", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyUpgradeController", - "type": "error" - }, - { - "inputs": [], - "name": "PrestateNotSet", - "type": "error" - }, { "inputs": [], "name": "ReservedBitsSet", "type": "error" }, - { - "inputs": [ - { - "internalType": "contract ISystemConfig", - "name": "systemConfig", - "type": "address" - } - ], - "name": "SuperchainConfigMismatch", - "type": "error" - }, - { - "inputs": [], - "name": "SuperchainProxyAdminMismatch", - "type": "error" - }, { "inputs": [ { diff --git a/packages/contracts-bedrock/snapshots/abi/OPContractsManagerGameTypeAdder.json b/packages/contracts-bedrock/snapshots/abi/OPContractsManagerGameTypeAdder.json new file mode 100644 index 0000000000000..a2088238caf93 --- /dev/null +++ b/packages/contracts-bedrock/snapshots/abi/OPContractsManagerGameTypeAdder.json @@ -0,0 +1,435 @@ +[ + { + "inputs": [ + { + "internalType": "contract OPContractsManagerContractsContainer", + "name": "_contractsContainer", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "string", + "name": "saltMixer", + "type": "string" + }, + { + "internalType": "contract ISystemConfig", + "name": "systemConfig", + "type": "address" + }, + { + "internalType": "contract IProxyAdmin", + "name": "proxyAdmin", + "type": "address" + }, + { + "internalType": "contract IDelayedWETH", + "name": "delayedWETH", + "type": "address" + }, + { + "internalType": "GameType", + "name": "disputeGameType", + "type": "uint32" + }, + { + "internalType": "Claim", + "name": "disputeAbsolutePrestate", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "disputeMaxGameDepth", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "disputeSplitDepth", + "type": "uint256" + }, + { + "internalType": "Duration", + "name": "disputeClockExtension", + "type": "uint64" + }, + { + "internalType": "Duration", + "name": "disputeMaxClockDuration", + "type": "uint64" + }, + { + "internalType": "uint256", + "name": "initialBond", + "type": "uint256" + }, + { + "internalType": "contract IBigStepper", + "name": "vm", + "type": "address" + }, + { + "internalType": "bool", + "name": "permissioned", + "type": "bool" + } + ], + "internalType": "struct OPContractsManager.AddGameInput[]", + "name": "_gameConfigs", + "type": "tuple[]" + }, + { + "internalType": "contract ISuperchainConfig", + "name": "_superchainConfig", + "type": "address" + } + ], + "name": "addGameType", + "outputs": [ + { + "components": [ + { + "internalType": "contract IDelayedWETH", + "name": "delayedWETH", + "type": "address" + }, + { + "internalType": "contract IFaultDisputeGame", + "name": "faultDisputeGame", + "type": "address" + } + ], + "internalType": "struct OPContractsManager.AddGameOutput[]", + "name": "", + "type": "tuple[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_who", + "type": "address" + } + ], + "name": "assertValidContractAddress", + "outputs": [], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "blueprints", + "outputs": [ + { + "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": "permissionedDisputeGame1", + "type": "address" + }, + { + "internalType": "address", + "name": "permissionedDisputeGame2", + "type": "address" + }, + { + "internalType": "address", + "name": "permissionlessDisputeGame1", + "type": "address" + }, + { + "internalType": "address", + "name": "permissionlessDisputeGame2", + "type": "address" + } + ], + "internalType": "struct OPContractsManager.Blueprints", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_l2ChainId", + "type": "uint256" + } + ], + "name": "chainIdToBatchInboxAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "contractsContainer", + "outputs": [ + { + "internalType": "contract OPContractsManagerContractsContainer", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "implementations", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "superchainConfigImpl", + "type": "address" + }, + { + "internalType": "address", + "name": "protocolVersionsImpl", + "type": "address" + }, + { + "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": "anchorStateRegistryImpl", + "type": "address" + }, + { + "internalType": "address", + "name": "delayedWETHImpl", + "type": "address" + }, + { + "internalType": "address", + "name": "mipsImpl", + "type": "address" + } + ], + "internalType": "struct OPContractsManager.Implementations", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "contract ISystemConfig", + "name": "systemConfigProxy", + "type": "address" + }, + { + "internalType": "contract IProxyAdmin", + "name": "proxyAdmin", + "type": "address" + }, + { + "internalType": "Claim", + "name": "absolutePrestate", + "type": "bytes32" + } + ], + "internalType": "struct OPContractsManager.OpChainConfig[]", + "name": "_prestateUpdateInputs", + "type": "tuple[]" + }, + { + "internalType": "contract ISuperchainConfig", + "name": "_superchainConfig", + "type": "address" + } + ], + "name": "updatePrestate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "l2ChainId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "GameType", + "name": "gameType", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "contract IDisputeGame", + "name": "newDisputeGame", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract IDisputeGame", + "name": "oldDisputeGame", + "type": "address" + } + ], + "name": "GameTypeAdded", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "who", + "type": "address" + } + ], + "name": "AddressHasNoCode", + "type": "error" + }, + { + "inputs": [], + "name": "BytesArrayTooLong", + "type": "error" + }, + { + "inputs": [], + "name": "DeploymentFailed", + "type": "error" + }, + { + "inputs": [], + "name": "EmptyInitcode", + "type": "error" + }, + { + "inputs": [], + "name": "IdentityPrecompileCallFailed", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidGameConfigs", + "type": "error" + }, + { + "inputs": [], + "name": "NotABlueprint", + "type": "error" + }, + { + "inputs": [], + "name": "PrestateRequired", + "type": "error" + }, + { + "inputs": [], + "name": "ReservedBitsSet", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "UnexpectedPreambleData", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "UnsupportedERCVersion", + "type": "error" + } +] \ No newline at end of file diff --git a/packages/contracts-bedrock/snapshots/abi/OPContractsManagerUpgrader.json b/packages/contracts-bedrock/snapshots/abi/OPContractsManagerUpgrader.json new file mode 100644 index 0000000000000..0fd60a240f00c --- /dev/null +++ b/packages/contracts-bedrock/snapshots/abi/OPContractsManagerUpgrader.json @@ -0,0 +1,349 @@ +[ + { + "inputs": [ + { + "internalType": "contract OPContractsManagerContractsContainer", + "name": "_contractsContainer", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_who", + "type": "address" + } + ], + "name": "assertValidContractAddress", + "outputs": [], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "blueprints", + "outputs": [ + { + "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": "permissionedDisputeGame1", + "type": "address" + }, + { + "internalType": "address", + "name": "permissionedDisputeGame2", + "type": "address" + }, + { + "internalType": "address", + "name": "permissionlessDisputeGame1", + "type": "address" + }, + { + "internalType": "address", + "name": "permissionlessDisputeGame2", + "type": "address" + } + ], + "internalType": "struct OPContractsManager.Blueprints", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_l2ChainId", + "type": "uint256" + } + ], + "name": "chainIdToBatchInboxAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "contractsContainer", + "outputs": [ + { + "internalType": "contract OPContractsManagerContractsContainer", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "implementations", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "superchainConfigImpl", + "type": "address" + }, + { + "internalType": "address", + "name": "protocolVersionsImpl", + "type": "address" + }, + { + "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": "anchorStateRegistryImpl", + "type": "address" + }, + { + "internalType": "address", + "name": "delayedWETHImpl", + "type": "address" + }, + { + "internalType": "address", + "name": "mipsImpl", + "type": "address" + } + ], + "internalType": "struct OPContractsManager.Implementations", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "contract ISystemConfig", + "name": "systemConfigProxy", + "type": "address" + }, + { + "internalType": "contract IProxyAdmin", + "name": "proxyAdmin", + "type": "address" + }, + { + "internalType": "Claim", + "name": "absolutePrestate", + "type": "bytes32" + } + ], + "internalType": "struct OPContractsManager.OpChainConfig[]", + "name": "_opChainConfigs", + "type": "tuple[]" + }, + { + "components": [ + { + "internalType": "contract ISuperchainConfig", + "name": "superchainConfig", + "type": "address" + }, + { + "internalType": "contract IProtocolVersions", + "name": "protocolVersions", + "type": "address" + }, + { + "internalType": "contract IProxyAdmin", + "name": "superchainProxyAdmin", + "type": "address" + } + ], + "internalType": "struct OPContractsManagerUpgrader.UpgradeInput", + "name": "_upgradeInput", + "type": "tuple" + } + ], + "name": "upgrade", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "l2ChainId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "contract ISystemConfig", + "name": "systemConfig", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "upgrader", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "who", + "type": "address" + } + ], + "name": "AddressHasNoCode", + "type": "error" + }, + { + "inputs": [], + "name": "BytesArrayTooLong", + "type": "error" + }, + { + "inputs": [], + "name": "DeploymentFailed", + "type": "error" + }, + { + "inputs": [], + "name": "EmptyInitcode", + "type": "error" + }, + { + "inputs": [], + "name": "IdentityPrecompileCallFailed", + "type": "error" + }, + { + "inputs": [], + "name": "NotABlueprint", + "type": "error" + }, + { + "inputs": [], + "name": "PrestateNotSet", + "type": "error" + }, + { + "inputs": [], + "name": "ReservedBitsSet", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "contract ISystemConfig", + "name": "systemConfig", + "type": "address" + } + ], + "name": "SuperchainConfigMismatch", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "UnexpectedPreambleData", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "UnsupportedERCVersion", + "type": "error" + } +] \ No newline at end of file diff --git a/packages/contracts-bedrock/snapshots/semver-lock.json b/packages/contracts-bedrock/snapshots/semver-lock.json index 42eacc880d131..d5d937544c3d0 100644 --- a/packages/contracts-bedrock/snapshots/semver-lock.json +++ b/packages/contracts-bedrock/snapshots/semver-lock.json @@ -16,16 +16,8 @@ "sourceCodeHash": "0x7f614d0c5251365580c02dd898900a583ece2aa28579adea74a3808b575949b4" }, "src/L1/OPContractsManager.sol": { - "initCodeHash": "0xfc2b4c9a4b589d3bd5267a9335b0471d2adb13af3f9ae4c01a74fe7289dc5e48", - "sourceCodeHash": "0xa288e8bbe3cdc5361c904a57c55c0b2a658c1b7148df6592cd2e002ae2e957a0" - }, - "src/L1/OPContractsManagerInterop.sol": { - "initCodeHash": "0x8adc6744a20019ebc1ea77b4a3227d1644e334a6bf3ae5796dd84be10f81d8cf", - "sourceCodeHash": "0x504f8b1ef3fa5920ebab1ca438b1fe6e69587d3502da2b68502b4587f3abb1a4" - }, - "src/L1/OPPrestateUpdater.sol": { - "initCodeHash": "0x687553a705b47a57aa77de1af612913ed73f96b1929a84585b0022a0113203f1", - "sourceCodeHash": "0x7d2ec5f151a244e83f483a9a99598bee4915d0624a7af6c07cc82d82bf0dbb93" + "initCodeHash": "0xdc9f6153bfa79af8c0f0cffacb41d67cb037f334c221df1b306c235c3ceb299b", + "sourceCodeHash": "0x1b170e28f055c1f901c3709d193cbf2995527e66a2d9092ca51b155c8b293886" }, "src/L1/OptimismPortal2.sol": { "initCodeHash": "0x93c5e8ff52ff8b1cedd985b4a8890c12b56d5959832405c7622615c3541908f5", diff --git a/packages/contracts-bedrock/snapshots/storageLayout/OPContractsManager.json b/packages/contracts-bedrock/snapshots/storageLayout/OPContractsManager.json index 3c1445a982928..a22b6b8e38333 100644 --- a/packages/contracts-bedrock/snapshots/storageLayout/OPContractsManager.json +++ b/packages/contracts-bedrock/snapshots/storageLayout/OPContractsManager.json @@ -6,25 +6,11 @@ "slot": "0", "type": "string" }, - { - "bytes": "288", - "label": "blueprint", - "offset": 0, - "slot": "1", - "type": "struct OPContractsManager.Blueprints" - }, - { - "bytes": "384", - "label": "implementation", - "offset": 0, - "slot": "10", - "type": "struct OPContractsManager.Implementations" - }, { "bytes": "1", "label": "isRC", "offset": 0, - "slot": "22", + "slot": "1", "type": "bool" } ] \ No newline at end of file diff --git a/packages/contracts-bedrock/snapshots/storageLayout/OPContractsManagerInterop.json b/packages/contracts-bedrock/snapshots/storageLayout/OPContractsManagerContractsContainer.json similarity index 53% rename from packages/contracts-bedrock/snapshots/storageLayout/OPContractsManagerInterop.json rename to packages/contracts-bedrock/snapshots/storageLayout/OPContractsManagerContractsContainer.json index 3c1445a982928..98248abd1d8c6 100644 --- a/packages/contracts-bedrock/snapshots/storageLayout/OPContractsManagerInterop.json +++ b/packages/contracts-bedrock/snapshots/storageLayout/OPContractsManagerContractsContainer.json @@ -1,30 +1,16 @@ [ - { - "bytes": "32", - "label": "L1_CONTRACTS_RELEASE", - "offset": 0, - "slot": "0", - "type": "string" - }, { "bytes": "288", "label": "blueprint", "offset": 0, - "slot": "1", + "slot": "0", "type": "struct OPContractsManager.Blueprints" }, { "bytes": "384", "label": "implementation", "offset": 0, - "slot": "10", + "slot": "9", "type": "struct OPContractsManager.Implementations" - }, - { - "bytes": "1", - "label": "isRC", - "offset": 0, - "slot": "22", - "type": "bool" } ] \ No newline at end of file diff --git a/packages/contracts-bedrock/snapshots/storageLayout/OPContractsManagerDeployer.json b/packages/contracts-bedrock/snapshots/storageLayout/OPContractsManagerDeployer.json new file mode 100644 index 0000000000000..0637a088a01e8 --- /dev/null +++ b/packages/contracts-bedrock/snapshots/storageLayout/OPContractsManagerDeployer.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/packages/contracts-bedrock/snapshots/storageLayout/OPContractsManagerDeployerInterop.json b/packages/contracts-bedrock/snapshots/storageLayout/OPContractsManagerDeployerInterop.json new file mode 100644 index 0000000000000..0637a088a01e8 --- /dev/null +++ b/packages/contracts-bedrock/snapshots/storageLayout/OPContractsManagerDeployerInterop.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/packages/contracts-bedrock/snapshots/storageLayout/OPContractsManagerGameTypeAdder.json b/packages/contracts-bedrock/snapshots/storageLayout/OPContractsManagerGameTypeAdder.json new file mode 100644 index 0000000000000..0637a088a01e8 --- /dev/null +++ b/packages/contracts-bedrock/snapshots/storageLayout/OPContractsManagerGameTypeAdder.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/packages/contracts-bedrock/snapshots/storageLayout/OPContractsManagerUpgrader.json b/packages/contracts-bedrock/snapshots/storageLayout/OPContractsManagerUpgrader.json new file mode 100644 index 0000000000000..0637a088a01e8 --- /dev/null +++ b/packages/contracts-bedrock/snapshots/storageLayout/OPContractsManagerUpgrader.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/packages/contracts-bedrock/snapshots/storageLayout/OPPrestateUpdater.json b/packages/contracts-bedrock/snapshots/storageLayout/OPPrestateUpdater.json deleted file mode 100644 index 3c1445a982928..0000000000000 --- a/packages/contracts-bedrock/snapshots/storageLayout/OPPrestateUpdater.json +++ /dev/null @@ -1,30 +0,0 @@ -[ - { - "bytes": "32", - "label": "L1_CONTRACTS_RELEASE", - "offset": 0, - "slot": "0", - "type": "string" - }, - { - "bytes": "288", - "label": "blueprint", - "offset": 0, - "slot": "1", - "type": "struct OPContractsManager.Blueprints" - }, - { - "bytes": "384", - "label": "implementation", - "offset": 0, - "slot": "10", - "type": "struct OPContractsManager.Implementations" - }, - { - "bytes": "1", - "label": "isRC", - "offset": 0, - "slot": "22", - "type": "bool" - } -] \ 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 420532132e433..9279bbd312f77 100644 --- a/packages/contracts-bedrock/src/L1/OPContractsManager.sol +++ b/packages/contracts-bedrock/src/L1/OPContractsManager.sol @@ -30,176 +30,237 @@ import { IL1ERC721Bridge } from "interfaces/L1/IL1ERC721Bridge.sol"; import { IL1StandardBridge } from "interfaces/L1/IL1StandardBridge.sol"; import { IOptimismMintableERC20Factory } from "interfaces/universal/IOptimismMintableERC20Factory.sol"; import { IHasSuperchainConfig } from "interfaces/L1/IHasSuperchainConfig.sol"; +import { ISystemConfigInterop } from "interfaces/L1/ISystemConfigInterop.sol"; -contract OPContractsManager is ISemver { - // -------- Structs -------- +contract OPContractsManagerContractsContainer { + /// @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. + OPContractsManager.Blueprints internal blueprint; - /// @notice Represents the roles that can be set when deploying a standard OP Stack chain. - struct Roles { - address opChainProxyAdminOwner; - address systemConfigOwner; - address batcher; - address unsafeBlockSigner; - address proposer; - address challenger; - } + /// @notice Addresses of the latest implementation contracts. + OPContractsManager.Implementations internal implementation; - /// @notice The full set of inputs to deploy a new OP Stack chain. - struct DeployInput { - Roles roles; - uint32 basefeeScalar; - uint32 blobBasefeeScalar; - uint256 l2ChainId; - // The correct type is OutputRoot memory but OP Deployer does not yet support structs. - bytes startingAnchorRoot; - // The salt mixer is used as part of making the resulting salt unique. - string saltMixer; - uint64 gasLimit; - // Configurable dispute game parameters. - GameType disputeGameType; - Claim disputeAbsolutePrestate; - uint256 disputeMaxGameDepth; - uint256 disputeSplitDepth; - Duration disputeClockExtension; - Duration disputeMaxClockDuration; + constructor( + OPContractsManager.Blueprints memory _blueprints, + OPContractsManager.Implementations memory _implementations + ) { + blueprint = _blueprints; + implementation = _implementations; } - /// @notice The full set of outputs from deploying a new OP Stack chain. - struct DeployOutput { - IProxyAdmin opChainProxyAdmin; - IAddressManager addressManager; - IL1ERC721Bridge l1ERC721BridgeProxy; - ISystemConfig systemConfigProxy; - IOptimismMintableERC20Factory optimismMintableERC20FactoryProxy; - IL1StandardBridge l1StandardBridgeProxy; - IL1CrossDomainMessenger l1CrossDomainMessengerProxy; - // Fault proof contracts below. - IOptimismPortal2 optimismPortalProxy; - IDisputeGameFactory disputeGameFactoryProxy; - IAnchorStateRegistry anchorStateRegistryProxy; - IFaultDisputeGame faultDisputeGame; - IPermissionedDisputeGame permissionedDisputeGame; - IDelayedWETH delayedWETHPermissionedGameProxy; - IDelayedWETH delayedWETHPermissionlessGameProxy; + function blueprints() public view returns (OPContractsManager.Blueprints memory) { + return blueprint; } - /// @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 - /// contain the bytecode of every contract it deploys. Therefore we instead use Blueprints to - /// reduce the code size of this contract. - struct Blueprints { - address addressManager; - address proxy; - address proxyAdmin; - address l1ChugSplashProxy; - address resolvedDelegateProxy; - address permissionedDisputeGame1; - address permissionedDisputeGame2; - address permissionlessDisputeGame1; - address permissionlessDisputeGame2; + function implementations() public view returns (OPContractsManager.Implementations memory) { + return implementation; } +} - /// @notice The latest implementation contracts for the OP Stack. - struct Implementations { - address superchainConfigImpl; - address protocolVersionsImpl; - address l1ERC721BridgeImpl; - address optimismPortalImpl; - address systemConfigImpl; - address optimismMintableERC20FactoryImpl; - address l1CrossDomainMessengerImpl; - address l1StandardBridgeImpl; - address disputeGameFactoryImpl; - address anchorStateRegistryImpl; - address delayedWETHImpl; - address mipsImpl; +abstract contract OPContractsManagerBase { + /// @notice The blueprint contract addresses contract. + OPContractsManagerContractsContainer public immutable contractsContainer; + + /// @notice The OPContractsManager contract that is currently being used. + OPContractsManagerBase internal immutable thisOPCM; + + /// @notice Constructor to initialize the immutable thisOPCM variable and contract addresses + /// @param _contractsContainer The blueprint contract addresses and implementation contract addresses + constructor(OPContractsManagerContractsContainer _contractsContainer) { + contractsContainer = _contractsContainer; + thisOPCM = this; } - /// @notice The input required to identify a chain for upgrading, along with new prestate hashes - struct OpChainConfig { - ISystemConfig systemConfigProxy; - IProxyAdmin proxyAdmin; - Claim absolutePrestate; + /// @notice Retrieves the implementation addresses stored in this OPCM contract + function getImplementations() internal view returns (OPContractsManager.Implementations memory) { + return thisOPCM.implementations(); } - struct AddGameInput { - string saltMixer; - ISystemConfig systemConfig; - IProxyAdmin proxyAdmin; - IDelayedWETH delayedWETH; - GameType disputeGameType; - Claim disputeAbsolutePrestate; - uint256 disputeMaxGameDepth; - uint256 disputeSplitDepth; - Duration disputeClockExtension; - Duration disputeMaxClockDuration; - uint256 initialBond; - IBigStepper vm; - bool permissioned; + /// @notice Retrieves the blueprint addresses stored in this OPCM contract + function getBlueprints() internal view returns (OPContractsManager.Blueprints memory) { + return thisOPCM.blueprints(); } - struct AddGameOutput { - IDelayedWETH delayedWETH; - IFaultDisputeGame faultDisputeGame; + /// @notice Retrieves the implementation addresses stored in this OPCM contract + function implementations() public view returns (OPContractsManager.Implementations memory) { + return contractsContainer.implementations(); } - // -------- Constants and Variables -------- + /// @notice Retrieves the blueprint addresses stored in this OPCM contract + function blueprints() public view returns (OPContractsManager.Blueprints memory) { + return contractsContainer.blueprints(); + } - /// @custom:semver 1.6.0 - function version() public pure virtual returns (string memory) { - return "1.6.0"; + /// @notice Maps an L2 chain ID to an L1 batch inbox address as defined by the standard + /// configuration's convention. This convention is `versionByte || keccak256(bytes32(chainId))[:19]`, + /// where || denotes concatenation`, versionByte is 0x00, and chainId is a uint256. + /// https://specs.optimism.io/protocol/configurability.html#consensus-parameters + function chainIdToBatchInboxAddress(uint256 _l2ChainId) public pure returns (address) { + bytes1 versionByte = 0x00; + bytes32 hashedChainId = keccak256(bytes.concat(bytes32(_l2ChainId))); + bytes19 first19Bytes = bytes19(hashedChainId); + return address(uint160(bytes20(bytes.concat(versionByte, first19Bytes)))); } - /// @notice Address of the SuperchainConfig contract shared by all chains. - ISuperchainConfig public immutable superchainConfig; + /// @notice Helper method for computing a salt that's used in CREATE2 deployments. + /// Including the contract name ensures that the resultant address from CREATE2 is unique + /// across our smart contract system. For example, we deploy multiple proxy contracts + /// with the same bytecode from this contract, so they each require a unique salt for determinism. + function computeSalt( + uint256 _l2ChainId, + string memory _saltMixer, + string memory _contractName + ) + internal + pure + returns (bytes32) + { + return keccak256(abi.encode(_l2ChainId, _saltMixer, _contractName)); + } - /// @notice Address of the ProtocolVersions contract shared by all chains. - IProtocolVersions public immutable protocolVersions; + /// @notice Helper method for computing a reusable salt mixer + /// This method should be used as the salt mixer when deploying contracts when there is no user + /// provided salt mixer. This protects against a situation where multiple chains with the same + /// L2 chain ID exist, which would otherwise result in address collisions. + function reusableSaltMixer(OPContractsManager.OpChainConfig memory _opChainConfig) + internal + pure + returns (string memory) + { + return string(bytes.concat(bytes32(uint256(uint160(address(_opChainConfig.systemConfigProxy)))))); + } - /// @notice Address of the SuperchainProxyAdmin contract shared by all chains. - IProxyAdmin public immutable superchainProxyAdmin; + /// @notice Deterministically deploys a new proxy contract owned by the provided ProxyAdmin. + /// The salt is computed as a function of the L2 chain ID, the salt mixer and the contract name. + /// This is required because we deploy many identical proxies, so they each require a unique salt for determinism. + function deployProxy( + uint256 _l2ChainId, + IProxyAdmin _proxyAdmin, + string memory _saltMixer, + string memory _contractName + ) + internal + returns (address) + { + bytes32 salt = computeSalt(_l2ChainId, _saltMixer, _contractName); + return Blueprint.deployFrom(getBlueprints().proxy, salt, abi.encode(_proxyAdmin)); + } - /// @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 internal L1_CONTRACTS_RELEASE; + /// @notice Makes an internal 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 upgradeToAndCall( + IProxyAdmin _proxyAdmin, + address _target, + address _implementation, + bytes memory _data + ) + internal + { + assertValidContractAddress(_implementation); - /// @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. - Blueprints internal blueprint; + _proxyAdmin.upgradeAndCall(payable(address(_target)), _implementation, _data); + } - /// @notice Addresses of the latest implementation contracts. - Implementations internal implementation; + function assertValidContractAddress(address _who) public view { + if (_who.code.length == 0) revert OPContractsManager.AddressHasNoCode(_who); + } - /// @notice The OPContractsManager contract that is currently being used. This is needed in the upgrade function - /// which is intended to be DELEGATECALLed. - OPContractsManager internal immutable thisOPCM; + function encodePermissionlessFDGConstructor(IFaultDisputeGame.GameConstructorParams memory _params) + internal + view + virtual + returns (bytes memory) + { + bytes memory dataWithSelector = abi.encodeCall(IFaultDisputeGame.__constructor__, (_params)); + return Bytes.slice(dataWithSelector, 4); + } - /// @notice The address of the upgrade controller. - address public immutable upgradeController; + function encodePermissionedFDGConstructor( + IFaultDisputeGame.GameConstructorParams memory _params, + address _proposer, + address _challenger + ) + internal + view + virtual + returns (bytes memory) + { + bytes memory dataWithSelector = + abi.encodeCall(IPermissionedDisputeGame.__constructor__, (_params, _proposer, _challenger)); + return Bytes.slice(dataWithSelector, 4); + } - /// @notice Whether this is a release candidate. - bool public isRC = true; + /// @notice Returns the implementation contract address for a given game type. + function getGameImplementation( + IDisputeGameFactory _disputeGameFactory, + GameType _gameType + ) + internal + view + returns (IDisputeGame) + { + return _disputeGameFactory.gameImpls(_gameType); + } - /// @notice Returns the release string. Appends "-rc" if this is a release candidate. - function l1ContractsRelease() external view virtual returns (string memory) { - return isRC ? string.concat(L1_CONTRACTS_RELEASE, "-rc") : L1_CONTRACTS_RELEASE; + /// @notice Retrieves the Anchor State Registry for a given game + function getAnchorStateRegistry(IFaultDisputeGame _disputeGame) internal view returns (IAnchorStateRegistry) { + return _disputeGame.anchorStateRegistry(); } - // -------- Events -------- + /// @notice Retrieves the L2 chain ID for a given game + function getL2ChainId(IFaultDisputeGame _disputeGame) internal view returns (uint256) { + return _disputeGame.l2ChainId(); + } - /// @notice Emitted when a new OP Stack chain is deployed. - /// @param l2ChainId Chain ID of the new chain. - /// @param deployer Address that deployed the chain. - /// @param deployOutput ABI-encoded output of the deployment. - event Deployed(uint256 indexed l2ChainId, address indexed deployer, bytes deployOutput); + /// @notice Retrieves the proposer address for a given game + function getProposer(IPermissionedDisputeGame _disputeGame) internal view returns (address) { + return _disputeGame.proposer(); + } - /// @notice Emitted when a chain is upgraded - /// @param systemConfig Address of the chain's SystemConfig contract - /// @param upgrader Address that initiated the upgrade - event Upgraded(uint256 indexed l2ChainId, ISystemConfig indexed systemConfig, address indexed upgrader); + /// @notice Retrieves the challenger address for a given game + function getChallenger(IPermissionedDisputeGame _disputeGame) internal view returns (address) { + return _disputeGame.challenger(); + } + + /// @notice Retrieves the DisputeGameFactory address for a given SystemConfig + function getDisputeGameFactory(ISystemConfig _systemConfig) internal view returns (IDisputeGameFactory) { + return IDisputeGameFactory(_systemConfig.disputeGameFactory()); + } + + /// @notice Retrieves the constructor params for a given game. + function getGameConstructorParams(IFaultDisputeGame _disputeGame) + internal + view + returns (IFaultDisputeGame.GameConstructorParams memory) + { + IFaultDisputeGame.GameConstructorParams memory params = IFaultDisputeGame.GameConstructorParams({ + gameType: _disputeGame.gameType(), + absolutePrestate: _disputeGame.absolutePrestate(), + maxGameDepth: _disputeGame.maxGameDepth(), + splitDepth: _disputeGame.splitDepth(), + clockExtension: _disputeGame.clockExtension(), + maxClockDuration: _disputeGame.maxClockDuration(), + vm: _disputeGame.vm(), + weth: getWETH(_disputeGame), + anchorStateRegistry: getAnchorStateRegistry(_disputeGame), + l2ChainId: getL2ChainId(_disputeGame) + }); + return params; + } + /// @notice Retrieves the DelayedWETH address for a given game + function getWETH(IFaultDisputeGame _disputeGame) internal view returns (IDelayedWETH) { + return _disputeGame.weth(); + } + + /// @notice Sets a game implementation on the dispute game factory + function setDGFImplementation(IDisputeGameFactory _dgf, GameType _gameType, IDisputeGame _newGame) internal { + _dgf.setImplementation(_gameType, _newGame); + } +} + +contract OPContractsManagerGameTypeAdder is OPContractsManagerBase { /// @notice Emitted when a new game type is added to a chain /// @param l2ChainId Chain ID of the chain /// @param gameType Type of the game being @@ -209,279 +270,289 @@ contract OPContractsManager is ISemver { uint256 indexed l2ChainId, GameType indexed gameType, IDisputeGame newDisputeGame, IDisputeGame oldDisputeGame ); - // -------- Errors -------- + /// @notice Constructor to initialize the immutable thisOPCM variable and contract addresses + /// @param _contractsContainer The blueprint contract addresses and implementation contract addresses + constructor(OPContractsManagerContractsContainer _contractsContainer) OPContractsManagerBase(_contractsContainer) { } - /// @notice Thrown when an address other than the upgrade controller calls the setRC function. - error OnlyUpgradeController(); + /// @notice addGameType deploys a new dispute game and links it to the DisputeGameFactory. The inputted _gameConfigs + /// must be added in ascending GameType order. + function addGameType( + OPContractsManager.AddGameInput[] memory _gameConfigs, + ISuperchainConfig _superchainConfig + ) + public + virtual + returns (OPContractsManager.AddGameOutput[] memory) + { + if (_gameConfigs.length == 0) revert OPContractsManager.InvalidGameConfigs(); - /// @notice Thrown when an address is the zero address. - error AddressNotFound(address who); + OPContractsManager.AddGameOutput[] memory outputs = new OPContractsManager.AddGameOutput[](_gameConfigs.length); + OPContractsManager.Blueprints memory bps = getBlueprints(); - /// @notice Throw when a contract address has no code. - error AddressHasNoCode(address who); + // Store last game config as an int256 so that we can ensure that the same game config is not added twice. + // Using int256 generates cheaper, simpler bytecode. + int256 lastGameConfig = -1; - /// @notice Thrown when a release version is already set. - error AlreadyReleased(); + for (uint256 i = 0; i < _gameConfigs.length; i++) { + OPContractsManager.AddGameInput memory gameConfig = _gameConfigs[i]; - /// @notice Thrown when an invalid `l2ChainId` is provided to `deploy`. - error InvalidChainId(); + // This conversion is safe because the GameType is a uint32, which will always fit in an int256. + int256 gameTypeInt = int256(uint256(gameConfig.disputeGameType.raw())); + // Ensure that the game configs are added in ascending order, and not duplicated. + if (lastGameConfig >= gameTypeInt) revert OPContractsManager.InvalidGameConfigs(); + lastGameConfig = gameTypeInt; - /// @notice Thrown when a role's address is not valid. - error InvalidRoleAddress(string role); + // Grab the permissioned and fault dispute games from the SystemConfig. + // We keep the FDG type as it reduces casting below. + IFaultDisputeGame pdg = IFaultDisputeGame( + address( + getGameImplementation(getDisputeGameFactory(gameConfig.systemConfig), GameTypes.PERMISSIONED_CANNON) + ) + ); + // Pull out the chain ID. + uint256 l2ChainId = getL2ChainId(pdg); - /// @notice Thrown when the latest release is not set upon initialization. - error LatestReleaseNotSet(); + // Deploy a new DelayedWETH proxy for this game if one hasn't already been specified. Leaving + /// gameConfig.delayedWETH as the zero address will cause a new DelayedWETH to be deployed for this game. + if (address(gameConfig.delayedWETH) == address(0)) { + string memory contractName = string.concat( + "DelayedWETH-", + // This is a safe cast because GameType is a uint256 under the hood and no operation has been done + // on it at this point + Strings.toString(uint256(gameTypeInt)) + ); + outputs[i].delayedWETH = IDelayedWETH( + payable(deployProxy(l2ChainId, gameConfig.proxyAdmin, gameConfig.saltMixer, contractName)) + ); - /// @notice Thrown when the starting anchor root is not provided. - error InvalidStartingAnchorRoot(); + // Initialize the proxy. + upgradeToAndCall( + gameConfig.proxyAdmin, + address(outputs[i].delayedWETH), + getImplementations().delayedWETHImpl, + abi.encodeCall(IDelayedWETH.initialize, (gameConfig.proxyAdmin.owner(), _superchainConfig)) + ); + } else { + outputs[i].delayedWETH = gameConfig.delayedWETH; + } - /// @notice Thrown when certain methods are called outside of a DELEGATECALL. - error OnlyDelegatecall(); + // The FDG is only used for the event below, and only if it is being replaced, + // so we declare it here, but only assign it below if needed. + IFaultDisputeGame fdg; - /// @notice Thrown when game configs passed to addGameType are invalid. - error InvalidGameConfigs(); + // The below sections are functionally the same. Both deploy a new dispute game. The dispute game type is + // either permissioned or permissionless depending on game config. + if (gameConfig.permissioned) { + outputs[i].faultDisputeGame = IFaultDisputeGame( + Blueprint.deployFrom( + bps.permissionedDisputeGame1, + bps.permissionedDisputeGame2, + computeSalt(l2ChainId, gameConfig.saltMixer, "PermissionedDisputeGame"), + encodePermissionedFDGConstructor( + IFaultDisputeGame.GameConstructorParams( + gameConfig.disputeGameType, + gameConfig.disputeAbsolutePrestate, + gameConfig.disputeMaxGameDepth, + gameConfig.disputeSplitDepth, + gameConfig.disputeClockExtension, + gameConfig.disputeMaxClockDuration, + gameConfig.vm, + outputs[i].delayedWETH, + getAnchorStateRegistry(pdg), + l2ChainId + ), + getProposer(IPermissionedDisputeGame(address(pdg))), + getChallenger(IPermissionedDisputeGame(address(pdg))) + ) + ) + ); + } else { + fdg = IFaultDisputeGame( + address(getGameImplementation(getDisputeGameFactory(gameConfig.systemConfig), GameTypes.CANNON)) + ); + outputs[i].faultDisputeGame = IFaultDisputeGame( + Blueprint.deployFrom( + bps.permissionlessDisputeGame1, + bps.permissionlessDisputeGame2, + computeSalt(l2ChainId, gameConfig.saltMixer, "PermissionlessDisputeGame"), + encodePermissionlessFDGConstructor( + IFaultDisputeGame.GameConstructorParams( + gameConfig.disputeGameType, + gameConfig.disputeAbsolutePrestate, + gameConfig.disputeMaxGameDepth, + gameConfig.disputeSplitDepth, + gameConfig.disputeClockExtension, + gameConfig.disputeMaxClockDuration, + gameConfig.vm, + outputs[i].delayedWETH, + // We can't assume that there is an existing fault dispute game, + // so get the Anchor State Registry from the permissioned game. + getAnchorStateRegistry(pdg), + l2ChainId + ) + ) + ) + ); + } - /// @notice Thrown when the SuperchainConfig of the chain does not match the SuperchainConfig of this OPCM. - error SuperchainConfigMismatch(ISystemConfig systemConfig); + // As a last step, register the new game type with the DisputeGameFactory. If the game type already exists, + // then its implementation will be overwritten. + IDisputeGameFactory dgf = getDisputeGameFactory(gameConfig.systemConfig); + setDGFImplementation(dgf, gameConfig.disputeGameType, IDisputeGame(address(outputs[i].faultDisputeGame))); + dgf.setInitBond(gameConfig.disputeGameType, gameConfig.initialBond); - /// @notice Thrown when the SuperchainProxyAdmin does not match the SuperchainConfig's admin. - error SuperchainProxyAdminMismatch(); + if (gameConfig.permissioned) { + // Emit event for the newly added game type with the old permissioned dispute game + emit GameTypeAdded( + l2ChainId, gameConfig.disputeGameType, outputs[i].faultDisputeGame, IDisputeGame(address(pdg)) + ); + } else { + // Emit event for the newly added game type with the old fault dispute game + emit GameTypeAdded( + l2ChainId, gameConfig.disputeGameType, outputs[i].faultDisputeGame, IDisputeGame(address(fdg)) + ); + } + } - /// @notice Thrown when a prestate is not set for a game. - error PrestateNotSet(); + return outputs; + } - // -------- Methods -------- + /// @notice Updates the prestate hash for a new game type while keeping all other parameters the same + /// @param _prestateUpdateInputs The new prestate hash to use + function updatePrestate( + OPContractsManager.OpChainConfig[] memory _prestateUpdateInputs, + ISuperchainConfig _superchainConfig + ) + public + { + // Loop through each chain and prestate hash + for (uint256 i = 0; i < _prestateUpdateInputs.length; i++) { + if (Claim.unwrap(_prestateUpdateInputs[i].absolutePrestate) == bytes32(0)) { + revert OPContractsManager.PrestateRequired(); + } - constructor( - ISuperchainConfig _superchainConfig, - IProtocolVersions _protocolVersions, - IProxyAdmin _superchainProxyAdmin, - string memory _l1ContractsRelease, - Blueprints memory _blueprints, - Implementations memory _implementations, - address _upgradeController - ) { - assertValidContractAddress(address(_superchainConfig)); - assertValidContractAddress(address(_protocolVersions)); - superchainConfig = _superchainConfig; - protocolVersions = _protocolVersions; - superchainProxyAdmin = _superchainProxyAdmin; - L1_CONTRACTS_RELEASE = _l1ContractsRelease; - blueprint = _blueprints; - implementation = _implementations; - thisOPCM = this; - upgradeController = _upgradeController; - } + // Get the DisputeGameFactory and existing game implementations + IDisputeGameFactory dgf = + IDisputeGameFactory(_prestateUpdateInputs[i].systemConfigProxy.disputeGameFactory()); + IFaultDisputeGame fdg = IFaultDisputeGame(address(getGameImplementation(dgf, GameTypes.CANNON))); + IPermissionedDisputeGame pdg = + IPermissionedDisputeGame(address(getGameImplementation(dgf, GameTypes.PERMISSIONED_CANNON))); + + // All chains must have a permissioned game, but not all chains must have a fault dispute game. + // Whether a chain has a fault dispute game determines how many AddGameInput objects are needed. + bool hasFDG = address(fdg) != address(0); + + OPContractsManager.AddGameInput[] memory inputs = new OPContractsManager.AddGameInput[](hasFDG ? 2 : 1); + OPContractsManager.AddGameInput memory pdgInput; + OPContractsManager.AddGameInput memory fdgInput; + + // Get the existing game parameters and init bond for the permissioned game + IFaultDisputeGame.GameConstructorParams memory pdgParams = + getGameConstructorParams(IFaultDisputeGame(address(pdg))); + uint256 initBond = dgf.initBonds(GameTypes.PERMISSIONED_CANNON); + + string memory saltMixer = reusableSaltMixer(_prestateUpdateInputs[i]); + // Create game input with updated prestate but same other params + pdgInput = OPContractsManager.AddGameInput({ + disputeAbsolutePrestate: _prestateUpdateInputs[i].absolutePrestate, + saltMixer: saltMixer, + systemConfig: _prestateUpdateInputs[i].systemConfigProxy, + proxyAdmin: _prestateUpdateInputs[i].proxyAdmin, + delayedWETH: IDelayedWETH(payable(address(pdgParams.weth))), + disputeGameType: pdgParams.gameType, + disputeMaxGameDepth: pdgParams.maxGameDepth, + disputeSplitDepth: pdgParams.splitDepth, + disputeClockExtension: pdgParams.clockExtension, + disputeMaxClockDuration: pdgParams.maxClockDuration, + initialBond: initBond, + vm: pdgParams.vm, + permissioned: true + }); - function deploy(DeployInput calldata _input) external virtual returns (DeployOutput memory) { - assertValidInputs(_input); - uint256 l2ChainId = _input.l2ChainId; - string memory saltMixer = _input.saltMixer; - DeployOutput memory output; + // If a fault dispute game exists, create a new game with the same parameters but updated prestate. + if (hasFDG) { + // Get the existing game parameters and init bond for the fault dispute game + IFaultDisputeGame.GameConstructorParams memory fdgParams = + getGameConstructorParams(IFaultDisputeGame(address(fdg))); + initBond = dgf.initBonds(GameTypes.CANNON); + + // Create game input with updated prestate but same other params + fdgInput = OPContractsManager.AddGameInput({ + disputeAbsolutePrestate: _prestateUpdateInputs[i].absolutePrestate, + saltMixer: saltMixer, + systemConfig: _prestateUpdateInputs[i].systemConfigProxy, + proxyAdmin: _prestateUpdateInputs[i].proxyAdmin, + delayedWETH: IDelayedWETH(payable(address(fdgParams.weth))), + disputeGameType: fdgParams.gameType, + disputeMaxGameDepth: fdgParams.maxGameDepth, + disputeSplitDepth: fdgParams.splitDepth, + disputeClockExtension: fdgParams.clockExtension, + disputeMaxClockDuration: fdgParams.maxClockDuration, + initialBond: initBond, + vm: fdgParams.vm, + permissioned: false + }); + } - // -------- Deploy Chain Singletons -------- + // Game inputs must be ordered with increasing game type values. So FDG is first if it exists. + if (hasFDG) { + inputs[0] = fdgInput; + inputs[1] = pdgInput; + } else { + inputs[0] = pdgInput; + } + // Add the new game type with updated prestate + addGameType(inputs, _superchainConfig); + } + } +} - // The AddressManager is used to store the implementation for the L1CrossDomainMessenger - // due to it's usage of the legacy ResolvedDelegateProxy. - output.addressManager = IAddressManager( - Blueprint.deployFrom( - blueprint.addressManager, computeSalt(l2ChainId, saltMixer, "AddressManager"), abi.encode() - ) - ); - // The ProxyAdmin is the owner of all proxies for the chain. We temporarily set the owner to - // this contract, and then transfer ownership to the specified owner at the end of deployment. - output.opChainProxyAdmin = IProxyAdmin( - Blueprint.deployFrom( - blueprint.proxyAdmin, computeSalt(l2ChainId, saltMixer, "ProxyAdmin"), abi.encode(address(this)) - ) - ); - // Set the AddressManager on the ProxyAdmin. - output.opChainProxyAdmin.setAddressManager(output.addressManager); - // Transfer ownership of the AddressManager to the ProxyAdmin. - transferOwnership(address(output.addressManager), address(output.opChainProxyAdmin)); +contract OPContractsManagerUpgrader is OPContractsManagerBase { + struct UpgradeInput { + ISuperchainConfig superchainConfig; + IProtocolVersions protocolVersions; + IProxyAdmin superchainProxyAdmin; + } - // -------- Deploy Proxy Contracts -------- + /// @notice Emitted when a chain is upgraded + /// @param systemConfig Address of the chain's SystemConfig contract + /// @param upgrader Address that initiated the upgrade + event Upgraded(uint256 indexed l2ChainId, ISystemConfig indexed systemConfig, address indexed upgrader); - // Deploy ERC-1967 proxied contracts. - output.l1ERC721BridgeProxy = - IL1ERC721Bridge(deployProxy(l2ChainId, output.opChainProxyAdmin, saltMixer, "L1ERC721Bridge")); - output.optimismPortalProxy = - IOptimismPortal2(payable(deployProxy(l2ChainId, output.opChainProxyAdmin, saltMixer, "OptimismPortal"))); - output.systemConfigProxy = - ISystemConfig(deployProxy(l2ChainId, output.opChainProxyAdmin, saltMixer, "SystemConfig")); - output.optimismMintableERC20FactoryProxy = IOptimismMintableERC20Factory( - deployProxy(l2ChainId, output.opChainProxyAdmin, saltMixer, "OptimismMintableERC20Factory") - ); - output.disputeGameFactoryProxy = - IDisputeGameFactory(deployProxy(l2ChainId, output.opChainProxyAdmin, saltMixer, "DisputeGameFactory")); - output.anchorStateRegistryProxy = - IAnchorStateRegistry(deployProxy(l2ChainId, output.opChainProxyAdmin, saltMixer, "AnchorStateRegistry")); - - // Deploy legacy proxied contracts. - output.l1StandardBridgeProxy = IL1StandardBridge( - payable( - Blueprint.deployFrom( - blueprint.l1ChugSplashProxy, - computeSalt(l2ChainId, saltMixer, "L1StandardBridge"), - 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, - computeSalt(l2ChainId, saltMixer, "L1CrossDomainMessenger"), - abi.encode(output.addressManager, contractName) - ) - ); - output.opChainProxyAdmin.setProxyType( - address(output.l1CrossDomainMessengerProxy), IProxyAdmin.ProxyType.RESOLVED - ); - output.opChainProxyAdmin.setImplementationName(address(output.l1CrossDomainMessengerProxy), contractName); - - // Eventually we will switch from DelayedWETHPermissionedGameProxy to DelayedWETHPermissionlessGameProxy. - output.delayedWETHPermissionedGameProxy = IDelayedWETH( - payable(deployProxy(l2ChainId, output.opChainProxyAdmin, saltMixer, "DelayedWETHPermissionedGame")) - ); - - // While not a proxy, we deploy the PermissionedDisputeGame here as well because it's bespoke per chain. - output.permissionedDisputeGame = IPermissionedDisputeGame( - Blueprint.deployFrom( - blueprint.permissionedDisputeGame1, - blueprint.permissionedDisputeGame2, - computeSalt(l2ChainId, saltMixer, "PermissionedDisputeGame"), - encodePermissionedFDGConstructor( - IFaultDisputeGame.GameConstructorParams({ - gameType: _input.disputeGameType, - absolutePrestate: _input.disputeAbsolutePrestate, - maxGameDepth: _input.disputeMaxGameDepth, - splitDepth: _input.disputeSplitDepth, - clockExtension: _input.disputeClockExtension, - maxClockDuration: _input.disputeMaxClockDuration, - vm: IBigStepper(implementation.mipsImpl), - weth: IDelayedWETH(payable(address(output.delayedWETHPermissionedGameProxy))), - anchorStateRegistry: IAnchorStateRegistry(address(output.anchorStateRegistryProxy)), - l2ChainId: _input.l2ChainId - }), - _input.roles.proposer, - _input.roles.challenger - ) - ) - ); - - // -------- Set and Initialize Proxy Implementations -------- - bytes memory data; - - data = encodeL1ERC721BridgeInitializer(output); - upgradeToAndCall( - output.opChainProxyAdmin, address(output.l1ERC721BridgeProxy), implementation.l1ERC721BridgeImpl, data - ); - - data = encodeOptimismPortalInitializer(output); - upgradeToAndCall( - output.opChainProxyAdmin, address(output.optimismPortalProxy), implementation.optimismPortalImpl, data - ); - - data = encodeSystemConfigInitializer(_input, output); - upgradeToAndCall( - output.opChainProxyAdmin, address(output.systemConfigProxy), implementation.systemConfigImpl, data - ); - - data = encodeOptimismMintableERC20FactoryInitializer(output); - upgradeToAndCall( - output.opChainProxyAdmin, - address(output.optimismMintableERC20FactoryProxy), - implementation.optimismMintableERC20FactoryImpl, - data - ); - - data = encodeL1CrossDomainMessengerInitializer(output); - upgradeToAndCall( - output.opChainProxyAdmin, - address(output.l1CrossDomainMessengerProxy), - implementation.l1CrossDomainMessengerImpl, - data - ); - - data = encodeL1StandardBridgeInitializer(output); - upgradeToAndCall( - output.opChainProxyAdmin, address(output.l1StandardBridgeProxy), implementation.l1StandardBridgeImpl, data - ); - - data = encodeDelayedWETHInitializer(_input); - // Eventually we will switch from DelayedWETHPermissionedGameProxy to DelayedWETHPermissionlessGameProxy. - upgradeToAndCall( - output.opChainProxyAdmin, - address(output.delayedWETHPermissionedGameProxy), - implementation.delayedWETHImpl, - data - ); - - // We set the initial owner to this contract, set game implementations, then transfer ownership. - data = encodeDisputeGameFactoryInitializer(); - upgradeToAndCall( - output.opChainProxyAdmin, - address(output.disputeGameFactoryProxy), - implementation.disputeGameFactoryImpl, - data - ); - setDGFImplementation( - output.disputeGameFactoryProxy, - GameTypes.PERMISSIONED_CANNON, - IDisputeGame(address(output.permissionedDisputeGame)) - ); - - transferOwnership(address(output.disputeGameFactoryProxy), address(_input.roles.opChainProxyAdminOwner)); - - data = encodeAnchorStateRegistryInitializer(_input, output); - upgradeToAndCall( - output.opChainProxyAdmin, - address(output.anchorStateRegistryProxy), - implementation.anchorStateRegistryImpl, - data - ); - - // -------- Finalize Deployment -------- - // Transfer ownership of the ProxyAdmin from this contract to the specified owner. - transferOwnership(address(output.opChainProxyAdmin), _input.roles.opChainProxyAdminOwner); - - emit Deployed(l2ChainId, msg.sender, abi.encode(output)); - return output; - } - - /// @notice Verifies that all OpChainConfig inputs are valid and reverts if any are invalid. - function assertValidOpChainConfig(OpChainConfig memory _config) internal view { - assertValidContractAddress(address(_config.systemConfigProxy)); - assertValidContractAddress(address(_config.proxyAdmin)); - } + constructor(OPContractsManagerContractsContainer _contractsContainer) OPContractsManagerBase(_contractsContainer) { } /// @notice Upgrades a set of chains to the latest implementation contracts /// @param _opChainConfigs Array of OpChain structs, one per chain to upgrade /// @dev This function is intended to be called via DELEGATECALL from the Upgrade Controller Safe - function upgrade(OpChainConfig[] memory _opChainConfigs) external virtual { - if (address(this) == address(thisOPCM)) revert OnlyDelegatecall(); - - // If this is delegatecalled by the upgrade controller, set isRC to false first, else, continue execution. - if (address(this) == upgradeController) { - // Set isRC to false. - // This function asserts that the caller is the upgrade controller. - thisOPCM.setRC(false); - } - - Implementations memory impls = getImplementations(); - Blueprints memory bps = getBlueprints(); + function upgrade( + OPContractsManager.OpChainConfig[] memory _opChainConfigs, + UpgradeInput memory _upgradeInput + ) + external + virtual + { + OPContractsManager.Implementations memory impls = getImplementations(); + OPContractsManager.Blueprints memory bps = getBlueprints(); // If the SuperchainConfig is not already upgraded, upgrade it. - if (superchainProxyAdmin.getProxyImplementation(address(superchainConfig)) != impls.superchainConfigImpl) { + if ( + _upgradeInput.superchainProxyAdmin.getProxyImplementation(address(_upgradeInput.superchainConfig)) + != impls.superchainConfigImpl + ) { // Attempt to upgrade. If the ProxyAdmin is not the SuperchainConfig's admin, this will revert. - upgradeTo(superchainProxyAdmin, address(superchainConfig), impls.superchainConfigImpl); + upgradeTo( + _upgradeInput.superchainProxyAdmin, address(_upgradeInput.superchainConfig), impls.superchainConfigImpl + ); } // If the ProtocolVersions contract is not already upgraded, upgrade it. - if (superchainProxyAdmin.getProxyImplementation(address(protocolVersions)) != impls.protocolVersionsImpl) { - upgradeTo(superchainProxyAdmin, address(protocolVersions), impls.protocolVersionsImpl); + if ( + _upgradeInput.superchainProxyAdmin.getProxyImplementation(address(_upgradeInput.protocolVersions)) + != impls.protocolVersionsImpl + ) { + upgradeTo( + _upgradeInput.superchainProxyAdmin, address(_upgradeInput.protocolVersions), impls.protocolVersionsImpl + ); } for (uint256 i = 0; i < _opChainConfigs.length; i++) { @@ -499,12 +570,12 @@ contract OPContractsManager is ISemver { // Check that all contracts have the correct superchainConfig if ( - getSuperchainConfig(opChainAddrs.optimismPortal) != superchainConfig - || getSuperchainConfig(opChainAddrs.l1CrossDomainMessenger) != superchainConfig - || getSuperchainConfig(opChainAddrs.l1ERC721Bridge) != superchainConfig - || getSuperchainConfig(opChainAddrs.l1StandardBridge) != superchainConfig + getSuperchainConfig(opChainAddrs.optimismPortal) != _upgradeInput.superchainConfig + || getSuperchainConfig(opChainAddrs.l1CrossDomainMessenger) != _upgradeInput.superchainConfig + || getSuperchainConfig(opChainAddrs.l1ERC721Bridge) != _upgradeInput.superchainConfig + || getSuperchainConfig(opChainAddrs.l1StandardBridge) != _upgradeInput.superchainConfig ) { - revert SuperchainConfigMismatch(_opChainConfigs[i].systemConfigProxy); + revert OPContractsManager.SuperchainConfigMismatch(_opChainConfigs[i].systemConfigProxy); } // -------- Upgrade Contracts Stored in SystemConfig -------- @@ -575,7 +646,7 @@ contract OPContractsManager is ISemver { abi.encodeCall( IAnchorStateRegistry.initialize, ( - superchainConfig, + _upgradeInput.superchainConfig, IDisputeGameFactory(opChainAddrs.disputeGameFactory), IOptimismPortal2(payable(opChainAddrs.optimismPortal)), startingAnchorRoot @@ -623,226 +694,375 @@ contract OPContractsManager is ISemver { } } - /// @notice addGameType deploys a new dispute game and links it to the DisputeGameFactory. The inputted _gameConfigs - /// must be added in ascending GameType order. - function addGameType(AddGameInput[] memory _gameConfigs) public virtual returns (AddGameOutput[] memory) { - if (address(this) == address(thisOPCM)) revert OnlyDelegatecall(); - if (_gameConfigs.length == 0) revert InvalidGameConfigs(); + /// @notice Retrieves the Superchain Config for a bridge contract + function getSuperchainConfig(address _hasSuperchainConfig) internal view returns (ISuperchainConfig) { + return IHasSuperchainConfig(_hasSuperchainConfig).superchainConfig(); + } - AddGameOutput[] memory outputs = new AddGameOutput[](_gameConfigs.length); - Blueprints memory bps = getBlueprints(); + /// @notice Updates the implementation of a proxy without calling the initializer. + /// First performs safety checks to ensure the target, implementation, and proxy admin are valid. + function upgradeTo(IProxyAdmin _proxyAdmin, address _target, address _implementation) internal { + assertValidContractAddress(_implementation); - // Store last game config as an int256 so that we can ensure that the same game config is not added twice. - // Using int256 generates cheaper, simpler bytecode. - int256 lastGameConfig = -1; + _proxyAdmin.upgrade(payable(address(_target)), _implementation); + } - for (uint256 i = 0; i < _gameConfigs.length; i++) { - AddGameInput memory gameConfig = _gameConfigs[i]; + /// @notice Verifies that all OpChainConfig inputs are valid and reverts if any are invalid. + function assertValidOpChainConfig(OPContractsManager.OpChainConfig memory _config) internal view { + assertValidContractAddress(address(_config.systemConfigProxy)); + assertValidContractAddress(address(_config.proxyAdmin)); + } - // This conversion is safe because the GameType is a uint32, which will always fit in an int256. - int256 gameTypeInt = int256(uint256(gameConfig.disputeGameType.raw())); - // Ensure that the game configs are added in ascending order, and not duplicated. - if (lastGameConfig >= gameTypeInt) revert InvalidGameConfigs(); - lastGameConfig = gameTypeInt; + /// @notice Deploys and sets a new dispute game implementation + /// @param _l2ChainId The L2 chain ID + /// @param _disputeGame The current dispute game implementation + /// @param _newAnchorStateRegistryProxy The new anchor state registry proxy + /// @param _gameType The type of game to deploy + /// @param _opChainConfig The OP chain configuration + /// @param _blueprints The blueprint addresses + /// @param _implementations The implementation addresses + /// @param _opChainAddrs The OP chain addresses + function deployAndSetNewGameImpl( + uint256 _l2ChainId, + IDisputeGame _disputeGame, + IAnchorStateRegistry _newAnchorStateRegistryProxy, + GameType _gameType, + OPContractsManager.OpChainConfig memory _opChainConfig, + OPContractsManager.Blueprints memory _blueprints, + OPContractsManager.Implementations memory _implementations, + ISystemConfig.Addresses memory _opChainAddrs + ) + internal + { + // independently scoped block to avoid stack too deep + { + // Get and upgrade the WETH proxy + IDelayedWETH delayedWethProxy = getWETH(IFaultDisputeGame(address(_disputeGame))); + upgradeTo(_opChainConfig.proxyAdmin, address(delayedWethProxy), _implementations.delayedWETHImpl); + } - // Grab the permissioned and fault dispute games from the SystemConfig. - // We keep the FDG type as it reduces casting below. - IFaultDisputeGame pdg = IFaultDisputeGame( - address( - getGameImplementation(getDisputeGameFactory(gameConfig.systemConfig), GameTypes.PERMISSIONED_CANNON) + // Get the constructor params for the game + IFaultDisputeGame.GameConstructorParams memory params = + getGameConstructorParams(IFaultDisputeGame(address(_disputeGame))); + + // Modify the params with the new anchorStateRegistry and vm values. + params.anchorStateRegistry = IAnchorStateRegistry(address(_newAnchorStateRegistryProxy)); + params.vm = IBigStepper(_implementations.mipsImpl); + if (Claim.unwrap(_opChainConfig.absolutePrestate) == bytes32(0)) { + revert OPContractsManager.PrestateNotSet(); + } + params.absolutePrestate = _opChainConfig.absolutePrestate; + + IDisputeGame newGame; + if (GameType.unwrap(_gameType) == GameType.unwrap(GameTypes.PERMISSIONED_CANNON)) { + address proposer = getProposer(IPermissionedDisputeGame(address(_disputeGame))); + address challenger = getChallenger(IPermissionedDisputeGame(address(_disputeGame))); + newGame = IDisputeGame( + Blueprint.deployFrom( + _blueprints.permissionedDisputeGame1, + _blueprints.permissionedDisputeGame2, + computeSalt(_l2ChainId, reusableSaltMixer(_opChainConfig), "PermissionedDisputeGame"), + encodePermissionedFDGConstructor(params, proposer, challenger) ) ); - // Pull out the chain ID. - uint256 l2ChainId = getL2ChainId(pdg); + } else { + newGame = IDisputeGame( + Blueprint.deployFrom( + _blueprints.permissionlessDisputeGame1, + _blueprints.permissionlessDisputeGame2, + computeSalt(_l2ChainId, reusableSaltMixer(_opChainConfig), "PermissionlessDisputeGame"), + encodePermissionlessFDGConstructor(params) + ) + ); + } + setDGFImplementation(IDisputeGameFactory(_opChainAddrs.disputeGameFactory), _gameType, IDisputeGame(newGame)); + } +} - // Deploy a new DelayedWETH proxy for this game if one hasn't already been specified. Leaving - /// gameConfig.delayedWETH as the zero address will cause a new DelayedWETH to be deployed for this game. - if (address(gameConfig.delayedWETH) == address(0)) { - string memory contractName = string.concat( - "DelayedWETH-", - // This is a safe cast because GameType is a uint256 under the hood and no operation has been done - // on it at this point - Strings.toString(uint256(gameTypeInt)) - ); - outputs[i].delayedWETH = IDelayedWETH( - payable(deployProxy(l2ChainId, gameConfig.proxyAdmin, gameConfig.saltMixer, contractName)) - ); +contract OPContractsManagerDeployer is OPContractsManagerBase { + /// @notice Emitted when a new OP Stack chain is deployed. + /// @param l2ChainId Chain ID of the new chain. + /// @param deployer Address that deployed the chain. + /// @param deployOutput ABI-encoded output of the deployment. + event Deployed(uint256 indexed l2ChainId, address indexed deployer, bytes deployOutput); - // Initialize the proxy. - upgradeToAndCall( - gameConfig.proxyAdmin, - address(outputs[i].delayedWETH), - getImplementations().delayedWETHImpl, - abi.encodeCall(IDelayedWETH.initialize, (gameConfig.proxyAdmin.owner(), superchainConfig)) - ); - } else { - outputs[i].delayedWETH = gameConfig.delayedWETH; - } + constructor(OPContractsManagerContractsContainer _contractsContainer) OPContractsManagerBase(_contractsContainer) { } - // The FDG is only used for the event below, and only if it is being replaced, - // so we declare it here, but only assign it below if needed. - IFaultDisputeGame fdg; + function deploy( + OPContractsManager.DeployInput calldata _input, + ISuperchainConfig _superchainConfig, + address _deployer + ) + external + virtual + returns (OPContractsManager.DeployOutput memory) + { + assertValidInputs(_input); + OPContractsManager.DeployOutput memory output; + OPContractsManager.Blueprints memory blueprint = getBlueprints(); + OPContractsManager.Implementations memory implementation = getImplementations(); - // The below sections are functionally the same. Both deploy a new dispute game. The dispute game type is - // either permissioned or permissionless depending on game config. - if (gameConfig.permissioned) { - outputs[i].faultDisputeGame = IFaultDisputeGame( - Blueprint.deployFrom( - bps.permissionedDisputeGame1, - bps.permissionedDisputeGame2, - computeSalt(l2ChainId, gameConfig.saltMixer, "PermissionedDisputeGame"), - encodePermissionedFDGConstructor( - IFaultDisputeGame.GameConstructorParams( - gameConfig.disputeGameType, - gameConfig.disputeAbsolutePrestate, - gameConfig.disputeMaxGameDepth, - gameConfig.disputeSplitDepth, - gameConfig.disputeClockExtension, - gameConfig.disputeMaxClockDuration, - gameConfig.vm, - outputs[i].delayedWETH, - getAnchorStateRegistry(pdg), - l2ChainId - ), - getProposer(IPermissionedDisputeGame(address(pdg))), - getChallenger(IPermissionedDisputeGame(address(pdg))) - ) - ) - ); - } else { - fdg = IFaultDisputeGame( - address(getGameImplementation(getDisputeGameFactory(gameConfig.systemConfig), GameTypes.CANNON)) - ); - outputs[i].faultDisputeGame = IFaultDisputeGame( - Blueprint.deployFrom( - bps.permissionlessDisputeGame1, - bps.permissionlessDisputeGame2, - computeSalt(l2ChainId, gameConfig.saltMixer, "PermissionlessDisputeGame"), - encodePermissionlessFDGConstructor( - IFaultDisputeGame.GameConstructorParams( - gameConfig.disputeGameType, - gameConfig.disputeAbsolutePrestate, - gameConfig.disputeMaxGameDepth, - gameConfig.disputeSplitDepth, - gameConfig.disputeClockExtension, - gameConfig.disputeMaxClockDuration, - gameConfig.vm, - outputs[i].delayedWETH, - // We can't assume that there is an existing fault dispute game, - // so get the Anchor State Registry from the permissioned game. - getAnchorStateRegistry(pdg), - l2ChainId - ) - ) - ) - ); - } + // -------- Deploy Chain Singletons -------- - // As a last step, register the new game type with the DisputeGameFactory. If the game type already exists, - // then its implementation will be overwritten. - IDisputeGameFactory dgf = getDisputeGameFactory(gameConfig.systemConfig); - setDGFImplementation(dgf, gameConfig.disputeGameType, IDisputeGame(address(outputs[i].faultDisputeGame))); - dgf.setInitBond(gameConfig.disputeGameType, gameConfig.initialBond); + // The AddressManager is used to store the implementation for the L1CrossDomainMessenger + // due to it's usage of the legacy ResolvedDelegateProxy. + output.addressManager = IAddressManager( + Blueprint.deployFrom( + blueprint.addressManager, + computeSalt(_input.l2ChainId, _input.saltMixer, "AddressManager"), + abi.encode() + ) + ); + // The ProxyAdmin is the owner of all proxies for the chain. We temporarily set the owner to + // this contract, and then transfer ownership to the specified owner at the end of deployment. + output.opChainProxyAdmin = IProxyAdmin( + Blueprint.deployFrom( + blueprint.proxyAdmin, + computeSalt(_input.l2ChainId, _input.saltMixer, "ProxyAdmin"), + abi.encode(address(this)) + ) + ); + // Set the AddressManager on the ProxyAdmin. + output.opChainProxyAdmin.setAddressManager(output.addressManager); + // Transfer ownership of the AddressManager to the ProxyAdmin. + transferOwnership(address(output.addressManager), address(output.opChainProxyAdmin)); - if (gameConfig.permissioned) { - // Emit event for the newly added game type with the old permissioned dispute game - emit GameTypeAdded( - l2ChainId, gameConfig.disputeGameType, outputs[i].faultDisputeGame, IDisputeGame(address(pdg)) - ); - } else { - // Emit event for the newly added game type with the old fault dispute game - emit GameTypeAdded( - l2ChainId, gameConfig.disputeGameType, outputs[i].faultDisputeGame, IDisputeGame(address(fdg)) - ); - } - } + // -------- Deploy Proxy Contracts -------- + + // Deploy ERC-1967 proxied contracts. + output.l1ERC721BridgeProxy = + IL1ERC721Bridge(deployProxy(_input.l2ChainId, output.opChainProxyAdmin, _input.saltMixer, "L1ERC721Bridge")); + output.optimismPortalProxy = IOptimismPortal2( + payable(deployProxy(_input.l2ChainId, output.opChainProxyAdmin, _input.saltMixer, "OptimismPortal")) + ); + output.systemConfigProxy = + ISystemConfig(deployProxy(_input.l2ChainId, output.opChainProxyAdmin, _input.saltMixer, "SystemConfig")); + output.optimismMintableERC20FactoryProxy = IOptimismMintableERC20Factory( + deployProxy(_input.l2ChainId, output.opChainProxyAdmin, _input.saltMixer, "OptimismMintableERC20Factory") + ); + output.disputeGameFactoryProxy = IDisputeGameFactory( + deployProxy(_input.l2ChainId, output.opChainProxyAdmin, _input.saltMixer, "DisputeGameFactory") + ); + output.anchorStateRegistryProxy = IAnchorStateRegistry( + deployProxy(_input.l2ChainId, output.opChainProxyAdmin, _input.saltMixer, "AnchorStateRegistry") + ); + + // Deploy legacy proxied contracts. + output.l1StandardBridgeProxy = IL1StandardBridge( + payable( + Blueprint.deployFrom( + blueprint.l1ChugSplashProxy, + computeSalt(_input.l2ChainId, _input.saltMixer, "L1StandardBridge"), + 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, + computeSalt(_input.l2ChainId, _input.saltMixer, "L1CrossDomainMessenger"), + abi.encode(output.addressManager, contractName) + ) + ); + output.opChainProxyAdmin.setProxyType( + address(output.l1CrossDomainMessengerProxy), IProxyAdmin.ProxyType.RESOLVED + ); + output.opChainProxyAdmin.setImplementationName(address(output.l1CrossDomainMessengerProxy), contractName); + + // Eventually we will switch from DelayedWETHPermissionedGameProxy to DelayedWETHPermissionlessGameProxy. + output.delayedWETHPermissionedGameProxy = IDelayedWETH( + payable( + deployProxy(_input.l2ChainId, output.opChainProxyAdmin, _input.saltMixer, "DelayedWETHPermissionedGame") + ) + ); + + // While not a proxy, we deploy the PermissionedDisputeGame here as well because it's bespoke per chain. + output.permissionedDisputeGame = IPermissionedDisputeGame( + Blueprint.deployFrom( + blueprint.permissionedDisputeGame1, + blueprint.permissionedDisputeGame2, + computeSalt(_input.l2ChainId, _input.saltMixer, "PermissionedDisputeGame"), + encodePermissionedFDGConstructor( + IFaultDisputeGame.GameConstructorParams({ + gameType: _input.disputeGameType, + absolutePrestate: _input.disputeAbsolutePrestate, + maxGameDepth: _input.disputeMaxGameDepth, + splitDepth: _input.disputeSplitDepth, + clockExtension: _input.disputeClockExtension, + maxClockDuration: _input.disputeMaxClockDuration, + vm: IBigStepper(implementation.mipsImpl), + weth: IDelayedWETH(payable(address(output.delayedWETHPermissionedGameProxy))), + anchorStateRegistry: IAnchorStateRegistry(address(output.anchorStateRegistryProxy)), + l2ChainId: _input.l2ChainId + }), + _input.roles.proposer, + _input.roles.challenger + ) + ) + ); + + // -------- Set and Initialize Proxy Implementations -------- + bytes memory data; + + data = encodeL1ERC721BridgeInitializer(output, _superchainConfig); + upgradeToAndCall( + output.opChainProxyAdmin, address(output.l1ERC721BridgeProxy), implementation.l1ERC721BridgeImpl, data + ); + + data = encodeOptimismPortalInitializer(output, _superchainConfig); + upgradeToAndCall( + output.opChainProxyAdmin, address(output.optimismPortalProxy), implementation.optimismPortalImpl, data + ); + + data = encodeSystemConfigInitializer(_input, output); + upgradeToAndCall( + output.opChainProxyAdmin, address(output.systemConfigProxy), implementation.systemConfigImpl, data + ); + + data = encodeOptimismMintableERC20FactoryInitializer(output); + upgradeToAndCall( + output.opChainProxyAdmin, + address(output.optimismMintableERC20FactoryProxy), + implementation.optimismMintableERC20FactoryImpl, + data + ); + + data = encodeL1CrossDomainMessengerInitializer(output, _superchainConfig); + upgradeToAndCall( + output.opChainProxyAdmin, + address(output.l1CrossDomainMessengerProxy), + implementation.l1CrossDomainMessengerImpl, + data + ); + + data = encodeL1StandardBridgeInitializer(output, _superchainConfig); + upgradeToAndCall( + output.opChainProxyAdmin, address(output.l1StandardBridgeProxy), implementation.l1StandardBridgeImpl, data + ); + + data = encodeDelayedWETHInitializer(_input, _superchainConfig); + // Eventually we will switch from DelayedWETHPermissionedGameProxy to DelayedWETHPermissionlessGameProxy. + upgradeToAndCall( + output.opChainProxyAdmin, + address(output.delayedWETHPermissionedGameProxy), + implementation.delayedWETHImpl, + data + ); + + // We set the initial owner to this contract, set game implementations, then transfer ownership. + data = encodeDisputeGameFactoryInitializer(); + upgradeToAndCall( + output.opChainProxyAdmin, + address(output.disputeGameFactoryProxy), + implementation.disputeGameFactoryImpl, + data + ); + setDGFImplementation( + output.disputeGameFactoryProxy, + GameTypes.PERMISSIONED_CANNON, + IDisputeGame(address(output.permissionedDisputeGame)) + ); + + transferOwnership(address(output.disputeGameFactoryProxy), address(_input.roles.opChainProxyAdminOwner)); + + data = encodeAnchorStateRegistryInitializer(_input, _superchainConfig, output); + upgradeToAndCall( + output.opChainProxyAdmin, + address(output.anchorStateRegistryProxy), + implementation.anchorStateRegistryImpl, + data + ); + + // -------- Finalize Deployment -------- + // Transfer ownership of the ProxyAdmin from this contract to the specified owner. + transferOwnership(address(output.opChainProxyAdmin), _input.roles.opChainProxyAdminOwner); + + emit Deployed(_input.l2ChainId, _deployer, abi.encode(output)); + return output; + } + + /// @notice Returns default, standard config arguments for the SystemConfig initializer. + /// This is used by subclasses to reduce code duplication. + function defaultSystemConfigParams( + OPContractsManager.DeployInput memory, /* _input */ + OPContractsManager.DeployOutput memory _output + ) + internal + view + virtual + returns (IResourceMetering.ResourceConfig memory resourceConfig_, ISystemConfig.Addresses memory opChainAddrs_) + { + resourceConfig_ = Constants.DEFAULT_RESOURCE_CONFIG(); + + opChainAddrs_ = ISystemConfig.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) + }); - return outputs; + assertValidContractAddress(opChainAddrs_.l1CrossDomainMessenger); + assertValidContractAddress(opChainAddrs_.l1ERC721Bridge); + assertValidContractAddress(opChainAddrs_.l1StandardBridge); + assertValidContractAddress(opChainAddrs_.disputeGameFactory); + assertValidContractAddress(opChainAddrs_.optimismPortal); + assertValidContractAddress(opChainAddrs_.optimismMintableERC20Factory); } // -------- Utilities -------- /// @notice Verifies that all inputs are valid and reverts if any are invalid. /// Typically the proxy admin owner is expected to have code, but this is not enforced here. - function assertValidInputs(DeployInput calldata _input) internal view { - if (_input.l2ChainId == 0 || _input.l2ChainId == block.chainid) revert InvalidChainId(); - - if (_input.roles.opChainProxyAdminOwner == address(0)) revert InvalidRoleAddress("opChainProxyAdminOwner"); - if (_input.roles.systemConfigOwner == address(0)) revert InvalidRoleAddress("systemConfigOwner"); - if (_input.roles.batcher == address(0)) revert InvalidRoleAddress("batcher"); - if (_input.roles.unsafeBlockSigner == address(0)) revert InvalidRoleAddress("unsafeBlockSigner"); - if (_input.roles.proposer == address(0)) revert InvalidRoleAddress("proposer"); - if (_input.roles.challenger == address(0)) revert InvalidRoleAddress("challenger"); + function assertValidInputs(OPContractsManager.DeployInput calldata _input) internal view { + if (_input.l2ChainId == 0 || _input.l2ChainId == block.chainid) revert OPContractsManager.InvalidChainId(); - if (_input.startingAnchorRoot.length == 0) revert InvalidStartingAnchorRoot(); - if (bytes32(_input.startingAnchorRoot) == bytes32(0)) revert InvalidStartingAnchorRoot(); - } - - /// @notice Maps an L2 chain ID to an L1 batch inbox address as defined by the standard - /// configuration's convention. This convention is `versionByte || keccak256(bytes32(chainId))[:19]`, - /// where || denotes concatenation`, versionByte is 0x00, and chainId is a uint256. - /// https://specs.optimism.io/protocol/configurability.html#consensus-parameters - function chainIdToBatchInboxAddress(uint256 _l2ChainId) public pure returns (address) { - bytes1 versionByte = 0x00; - bytes32 hashedChainId = keccak256(bytes.concat(bytes32(_l2ChainId))); - bytes19 first19Bytes = bytes19(hashedChainId); - return address(uint160(bytes20(bytes.concat(versionByte, first19Bytes)))); - } - - /// @notice Helper method for computing a salt that's used in CREATE2 deployments. - /// Including the contract name ensures that the resultant address from CREATE2 is unique - /// across our smart contract system. For example, we deploy multiple proxy contracts - /// with the same bytecode from this contract, so they each require a unique salt for determinism. - function computeSalt( - uint256 _l2ChainId, - string memory _saltMixer, - string memory _contractName - ) - internal - pure - returns (bytes32) - { - return keccak256(abi.encode(_l2ChainId, _saltMixer, _contractName)); - } + if (_input.roles.opChainProxyAdminOwner == address(0)) { + revert OPContractsManager.InvalidRoleAddress("opChainProxyAdminOwner"); + } + if (_input.roles.systemConfigOwner == address(0)) { + revert OPContractsManager.InvalidRoleAddress("systemConfigOwner"); + } + if (_input.roles.batcher == address(0)) revert OPContractsManager.InvalidRoleAddress("batcher"); + if (_input.roles.unsafeBlockSigner == address(0)) { + revert OPContractsManager.InvalidRoleAddress("unsafeBlockSigner"); + } + if (_input.roles.proposer == address(0)) revert OPContractsManager.InvalidRoleAddress("proposer"); + if (_input.roles.challenger == address(0)) revert OPContractsManager.InvalidRoleAddress("challenger"); - /// @notice Helper method for computing a reusable salt mixer - /// This method should be used as the salt mixer when deploying contracts when there is no user - /// provided salt mixer. This protects against a situation where multiple chains with the same - /// L2 chain ID exist, which would otherwise result in address collisions. - function reusableSaltMixer(OpChainConfig memory _opChainConfig) internal pure returns (string memory) { - return string(bytes.concat(bytes32(uint256(uint160(address(_opChainConfig.systemConfigProxy)))))); + if (_input.startingAnchorRoot.length == 0) revert OPContractsManager.InvalidStartingAnchorRoot(); + if (bytes32(_input.startingAnchorRoot) == bytes32(0)) revert OPContractsManager.InvalidStartingAnchorRoot(); } - /// @notice Deterministically deploys a new proxy contract owned by the provided ProxyAdmin. - /// The salt is computed as a function of the L2 chain ID, the salt mixer and the contract name. - /// This is required because we deploy many identical proxies, so they each require a unique salt for determinism. - function deployProxy( - uint256 _l2ChainId, - IProxyAdmin _proxyAdmin, - string memory _saltMixer, - string memory _contractName - ) - internal - returns (address) - { - bytes32 salt = computeSalt(_l2ChainId, _saltMixer, _contractName); - return Blueprint.deployFrom(getBlueprints().proxy, salt, abi.encode(_proxyAdmin)); + /// @notice Transfers ownership + function transferOwnership(address _target, address _newOwner) internal { + // All transferOwnership targets have the same selector, so we just use IAddressManager + IAddressManager(_target).transferOwnership(_newOwner); } // -------- Initializer Encoding -------- /// @notice Helper method for encoding the L1ERC721Bridge initializer data. - function encodeL1ERC721BridgeInitializer(DeployOutput memory _output) + function encodeL1ERC721BridgeInitializer( + OPContractsManager.DeployOutput memory _output, + ISuperchainConfig _superchainConfig + ) internal view virtual returns (bytes memory) { - return abi.encodeCall(IL1ERC721Bridge.initialize, (_output.l1CrossDomainMessengerProxy, superchainConfig)); + return abi.encodeCall(IL1ERC721Bridge.initialize, (_output.l1CrossDomainMessengerProxy, _superchainConfig)); } /// @notice Helper method for encoding the OptimismPortal initializer data. - function encodeOptimismPortalInitializer(DeployOutput memory _output) + function encodeOptimismPortalInitializer( + OPContractsManager.DeployOutput memory _output, + ISuperchainConfig _superchainConfig + ) internal view virtual @@ -853,7 +1073,7 @@ contract OPContractsManager is ISemver { ( _output.disputeGameFactoryProxy, _output.systemConfigProxy, - superchainConfig, + _superchainConfig, GameTypes.PERMISSIONED_CANNON ) ); @@ -861,8 +1081,8 @@ contract OPContractsManager is ISemver { /// @notice Helper method for encoding the SystemConfig initializer data. function encodeSystemConfigInitializer( - DeployInput memory _input, - DeployOutput memory _output + OPContractsManager.DeployInput memory _input, + OPContractsManager.DeployOutput memory _output ) internal view @@ -889,7 +1109,7 @@ contract OPContractsManager is ISemver { } /// @notice Helper method for encoding the OptimismMintableERC20Factory initializer data. - function encodeOptimismMintableERC20FactoryInitializer(DeployOutput memory _output) + function encodeOptimismMintableERC20FactoryInitializer(OPContractsManager.DeployOutput memory _output) internal pure virtual @@ -899,23 +1119,29 @@ contract OPContractsManager is ISemver { } /// @notice Helper method for encoding the L1CrossDomainMessenger initializer data. - function encodeL1CrossDomainMessengerInitializer(DeployOutput memory _output) + function encodeL1CrossDomainMessengerInitializer( + OPContractsManager.DeployOutput memory _output, + ISuperchainConfig _superchainConfig + ) internal view virtual returns (bytes memory) { - return abi.encodeCall(IL1CrossDomainMessenger.initialize, (superchainConfig, _output.optimismPortalProxy)); + return abi.encodeCall(IL1CrossDomainMessenger.initialize, (_superchainConfig, _output.optimismPortalProxy)); } /// @notice Helper method for encoding the L1StandardBridge initializer data. - function encodeL1StandardBridgeInitializer(DeployOutput memory _output) + function encodeL1StandardBridgeInitializer( + OPContractsManager.DeployOutput memory _output, + ISuperchainConfig _superchainConfig + ) internal view virtual returns (bytes memory) { - return abi.encodeCall(IL1StandardBridge.initialize, (_output.l1CrossDomainMessengerProxy, superchainConfig)); + return abi.encodeCall(IL1StandardBridge.initialize, (_output.l1CrossDomainMessengerProxy, _superchainConfig)); } function encodeDisputeGameFactoryInitializer() internal view virtual returns (bytes memory) { @@ -925,8 +1151,9 @@ contract OPContractsManager is ISemver { } function encodeAnchorStateRegistryInitializer( - DeployInput memory _input, - DeployOutput memory _output + OPContractsManager.DeployInput memory _input, + ISuperchainConfig _superchainConfig, + OPContractsManager.DeployOutput memory _output ) internal view @@ -936,267 +1163,385 @@ contract OPContractsManager is ISemver { OutputRoot memory startingAnchorRoot = abi.decode(_input.startingAnchorRoot, (OutputRoot)); return abi.encodeCall( IAnchorStateRegistry.initialize, - (superchainConfig, _output.disputeGameFactoryProxy, _output.optimismPortalProxy, startingAnchorRoot) + (_superchainConfig, _output.disputeGameFactoryProxy, _output.optimismPortalProxy, startingAnchorRoot) ); } - function encodeDelayedWETHInitializer(DeployInput memory _input) internal view virtual returns (bytes memory) { - return abi.encodeCall(IDelayedWETH.initialize, (_input.roles.opChainProxyAdminOwner, superchainConfig)); - } - - function encodePermissionlessFDGConstructor(IFaultDisputeGame.GameConstructorParams memory _params) + function encodeDelayedWETHInitializer( + OPContractsManager.DeployInput memory _input, + ISuperchainConfig _superchainConfig + ) internal view virtual returns (bytes memory) { - bytes memory dataWithSelector = abi.encodeCall(IFaultDisputeGame.__constructor__, (_params)); - return Bytes.slice(dataWithSelector, 4); + return abi.encodeCall(IDelayedWETH.initialize, (_input.roles.opChainProxyAdminOwner, _superchainConfig)); } +} - function encodePermissionedFDGConstructor( - IFaultDisputeGame.GameConstructorParams memory _params, - address _proposer, - address _challenger +contract OPContractsManagerDeployerInterop is OPContractsManagerDeployer { + constructor(OPContractsManagerContractsContainer _contractsContainer) + OPContractsManagerDeployer(_contractsContainer) + { } + + // The `SystemConfigInterop` contract has an extra `address _dependencyManager` argument + // that we must account for. + function encodeSystemConfigInitializer( + OPContractsManager.DeployInput memory _input, + OPContractsManager.DeployOutput memory _output ) internal view virtual + override returns (bytes memory) { - bytes memory dataWithSelector = - abi.encodeCall(IPermissionedDisputeGame.__constructor__, (_params, _proposer, _challenger)); - return Bytes.slice(dataWithSelector, 4); + (IResourceMetering.ResourceConfig memory referenceResourceConfig, ISystemConfig.Addresses memory opChainAddrs) = + defaultSystemConfigParams(_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 + // to update where this value is pulled from in the future. To support a different dependency + // manager in this contract without an invasive change of redefining the `Roles` struct, + // we will make the change described in https://github.com/ethereum-optimism/optimism/issues/11783. + address dependencyManager = address(_input.roles.systemConfigOwner); + + return abi.encodeCall( + ISystemConfigInterop.initialize, + ( + _input.roles.systemConfigOwner, + _input.basefeeScalar, + _input.blobBasefeeScalar, + bytes32(uint256(uint160(_input.roles.batcher))), // batcherHash + _input.gasLimit, + _input.roles.unsafeBlockSigner, + referenceResourceConfig, + chainIdToBatchInboxAddress(_input.l2ChainId), + opChainAddrs, + dependencyManager + ) + ); } +} - /// @notice Returns default, standard config arguments for the SystemConfig initializer. - /// This is used by subclasses to reduce code duplication. - function defaultSystemConfigParams( - DeployInput memory, /* _input */ - DeployOutput memory _output - ) - internal - view - virtual - returns (IResourceMetering.ResourceConfig memory resourceConfig_, ISystemConfig.Addresses memory opChainAddrs_) - { - resourceConfig_ = Constants.DEFAULT_RESOURCE_CONFIG(); +contract OPContractsManager is ISemver { + // -------- Structs -------- + + /// @notice Represents the roles that can be set when deploying a standard OP Stack chain. + struct Roles { + address opChainProxyAdminOwner; + address systemConfigOwner; + address batcher; + address unsafeBlockSigner; + address proposer; + address challenger; + } + + /// @notice The full set of inputs to deploy a new OP Stack chain. + struct DeployInput { + Roles roles; + uint32 basefeeScalar; + uint32 blobBasefeeScalar; + uint256 l2ChainId; + // The correct type is OutputRoot memory but OP Deployer does not yet support structs. + bytes startingAnchorRoot; + // The salt mixer is used as part of making the resulting salt unique. + string saltMixer; + uint64 gasLimit; + // Configurable dispute game parameters. + GameType disputeGameType; + Claim disputeAbsolutePrestate; + uint256 disputeMaxGameDepth; + uint256 disputeSplitDepth; + Duration disputeClockExtension; + Duration disputeMaxClockDuration; + } + + /// @notice The full set of outputs from deploying a new OP Stack chain. + struct DeployOutput { + IProxyAdmin opChainProxyAdmin; + IAddressManager addressManager; + IL1ERC721Bridge l1ERC721BridgeProxy; + ISystemConfig systemConfigProxy; + IOptimismMintableERC20Factory optimismMintableERC20FactoryProxy; + IL1StandardBridge l1StandardBridgeProxy; + IL1CrossDomainMessenger l1CrossDomainMessengerProxy; + // Fault proof contracts below. + IOptimismPortal2 optimismPortalProxy; + IDisputeGameFactory disputeGameFactoryProxy; + IAnchorStateRegistry anchorStateRegistryProxy; + IFaultDisputeGame faultDisputeGame; + IPermissionedDisputeGame permissionedDisputeGame; + IDelayedWETH delayedWETHPermissionedGameProxy; + IDelayedWETH delayedWETHPermissionlessGameProxy; + } + + /// @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 + /// contain the bytecode of every contract it deploys. Therefore we instead use Blueprints to + /// reduce the code size of this contract. + struct Blueprints { + address addressManager; + address proxy; + address proxyAdmin; + address l1ChugSplashProxy; + address resolvedDelegateProxy; + address permissionedDisputeGame1; + address permissionedDisputeGame2; + address permissionlessDisputeGame1; + address permissionlessDisputeGame2; + } + + /// @notice The latest implementation contracts for the OP Stack. + struct Implementations { + address superchainConfigImpl; + address protocolVersionsImpl; + address l1ERC721BridgeImpl; + address optimismPortalImpl; + address systemConfigImpl; + address optimismMintableERC20FactoryImpl; + address l1CrossDomainMessengerImpl; + address l1StandardBridgeImpl; + address disputeGameFactoryImpl; + address anchorStateRegistryImpl; + address delayedWETHImpl; + address mipsImpl; + } + + /// @notice The input required to identify a chain for upgrading, along with new prestate hashes + struct OpChainConfig { + ISystemConfig systemConfigProxy; + IProxyAdmin proxyAdmin; + Claim absolutePrestate; + } + + struct AddGameInput { + string saltMixer; + ISystemConfig systemConfig; + IProxyAdmin proxyAdmin; + IDelayedWETH delayedWETH; + GameType disputeGameType; + Claim disputeAbsolutePrestate; + uint256 disputeMaxGameDepth; + uint256 disputeSplitDepth; + Duration disputeClockExtension; + Duration disputeMaxClockDuration; + uint256 initialBond; + IBigStepper vm; + bool permissioned; + } + + struct AddGameOutput { + IDelayedWETH delayedWETH; + IFaultDisputeGame faultDisputeGame; + } + + // -------- Constants and Variables -------- + + /// @custom:semver 1.7.0-beta.1 + function version() public pure virtual returns (string memory) { + return "1.7.0-beta.1"; + } + + OPContractsManagerGameTypeAdder public immutable opcmGameTypeAdder; + + OPContractsManagerDeployer public immutable opcmDeployer; + + OPContractsManagerUpgrader public immutable opcmUpgrader; + + /// @notice Address of the SuperchainConfig contract shared by all chains. + ISuperchainConfig public immutable superchainConfig; + + /// @notice Address of the ProtocolVersions contract shared by all chains. + IProtocolVersions public immutable protocolVersions; + + /// @notice Address of the SuperchainProxyAdmin contract shared by all chains. + IProxyAdmin public immutable superchainProxyAdmin; + + /// @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 internal L1_CONTRACTS_RELEASE; + + /// @notice The OPContractsManager contract that is currently being used. This is needed in the upgrade function + /// which is intended to be DELEGATECALLed. + OPContractsManager internal immutable thisOPCM; + + /// @notice The address of the upgrade controller. + address public immutable upgradeController; - opChainAddrs_ = ISystemConfig.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) - }); + /// @notice Whether this is a release candidate. + bool public isRC = true; - assertValidContractAddress(opChainAddrs_.l1CrossDomainMessenger); - assertValidContractAddress(opChainAddrs_.l1ERC721Bridge); - assertValidContractAddress(opChainAddrs_.l1StandardBridge); - assertValidContractAddress(opChainAddrs_.disputeGameFactory); - assertValidContractAddress(opChainAddrs_.optimismPortal); - assertValidContractAddress(opChainAddrs_.optimismMintableERC20Factory); + /// @notice Returns the release string. Appends "-rc" if this is a release candidate. + function l1ContractsRelease() external view virtual returns (string memory) { + return isRC ? string.concat(L1_CONTRACTS_RELEASE, "-rc") : L1_CONTRACTS_RELEASE; } - /// @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 upgradeToAndCall( - IProxyAdmin _proxyAdmin, - address _target, - address _implementation, - bytes memory _data - ) - internal - { - assertValidContractAddress(_implementation); + // -------- Errors -------- - _proxyAdmin.upgradeAndCall(payable(address(_target)), _implementation, _data); - } + /// @notice Thrown when an address other than the upgrade controller calls the setRC function. + error OnlyUpgradeController(); - /// @notice Updates the implementation of a proxy without calling the initializer. - /// First performs safety checks to ensure the target, implementation, and proxy admin are valid. - function upgradeTo(IProxyAdmin _proxyAdmin, address _target, address _implementation) internal { - assertValidContractAddress(_implementation); + /// @notice Thrown when an address is the zero address. + error AddressNotFound(address who); - _proxyAdmin.upgrade(payable(address(_target)), _implementation); - } + /// @notice Throw when a contract address has no code. + error AddressHasNoCode(address who); - function assertValidContractAddress(address _who) internal view { - if (_who.code.length == 0) revert AddressHasNoCode(_who); - } + /// @notice Thrown when a release version is already set. + error AlreadyReleased(); - /// @notice Returns the blueprint contract addresses. - function blueprints() public view returns (Blueprints memory) { - return blueprint; - } + /// @notice Thrown when an invalid `l2ChainId` is provided to `deploy`. + error InvalidChainId(); - /// @notice Returns the implementation contract addresses. - function implementations() public view returns (Implementations memory) { - return implementation; - } + /// @notice Thrown when a role's address is not valid. + error InvalidRoleAddress(string role); - /// @notice Returns the implementation contract address for a given game type. - function getGameImplementation( - IDisputeGameFactory _disputeGameFactory, - GameType _gameType - ) - internal - view - returns (IDisputeGame) - { - return _disputeGameFactory.gameImpls(_gameType); - } + /// @notice Thrown when the latest release is not set upon initialization. + error LatestReleaseNotSet(); - /// @notice Sets the RC flag. - function setRC(bool _isRC) external { - if (msg.sender != upgradeController) revert OnlyUpgradeController(); - isRC = _isRC; - } + /// @notice Thrown when the starting anchor root is not provided. + error InvalidStartingAnchorRoot(); - /// @notice Sets a game implementation on the dispute game factory - function setDGFImplementation(IDisputeGameFactory _dgf, GameType _gameType, IDisputeGame _newGame) internal { - _dgf.setImplementation(_gameType, _newGame); - } + /// @notice Thrown when certain methods are called outside of a DELEGATECALL. + error OnlyDelegatecall(); - /// @notice Transfers ownership - function transferOwnership(address _target, address _newOwner) internal { - // All transferOwnership targets have the same selector, so we just use IAddressManager - IAddressManager(_target).transferOwnership(_newOwner); - } + /// @notice Thrown when game configs passed to addGameType are invalid. + error InvalidGameConfigs(); - /// @notice Retrieves the constructor params for a given game. - function getGameConstructorParams(IFaultDisputeGame _disputeGame) - internal - view - returns (IFaultDisputeGame.GameConstructorParams memory) - { - IFaultDisputeGame.GameConstructorParams memory params = IFaultDisputeGame.GameConstructorParams({ - gameType: _disputeGame.gameType(), - absolutePrestate: _disputeGame.absolutePrestate(), - maxGameDepth: _disputeGame.maxGameDepth(), - splitDepth: _disputeGame.splitDepth(), - clockExtension: _disputeGame.clockExtension(), - maxClockDuration: _disputeGame.maxClockDuration(), - vm: _disputeGame.vm(), - weth: getWETH(_disputeGame), - anchorStateRegistry: getAnchorStateRegistry(_disputeGame), - l2ChainId: getL2ChainId(_disputeGame) - }); - return params; - } + /// @notice Thrown when the SuperchainConfig of the chain does not match the SuperchainConfig of this OPCM. + error SuperchainConfigMismatch(ISystemConfig systemConfig); - /// @notice Retrieves the Superchain Config for a bridge contract - function getSuperchainConfig(address _hasSuperchainConfig) internal view returns (ISuperchainConfig) { - return IHasSuperchainConfig(_hasSuperchainConfig).superchainConfig(); - } + /// @notice Thrown when the SuperchainProxyAdmin does not match the SuperchainConfig's admin. + error SuperchainProxyAdminMismatch(); - /// @notice Retrieves the Anchor State Registry for a given game - function getAnchorStateRegistry(IFaultDisputeGame _disputeGame) internal view returns (IAnchorStateRegistry) { - return _disputeGame.anchorStateRegistry(); - } + /// @notice Thrown when a prestate is not set for a game. + error PrestateNotSet(); - /// @notice Retrieves the DelayedWETH address for a given game - function getWETH(IFaultDisputeGame _disputeGame) internal view returns (IDelayedWETH) { - return _disputeGame.weth(); - } + /// @notice Thrown when the prestate of a permissioned disputed game is 0. + error PrestateRequired(); - /// @notice Retrieves the L2 chain ID for a given game - function getL2ChainId(IFaultDisputeGame _disputeGame) internal view returns (uint256) { - return _disputeGame.l2ChainId(); + // -------- Methods -------- + + constructor( + OPContractsManagerGameTypeAdder _opcmGameTypeAdder, + OPContractsManagerDeployer _opcmDeployer, + OPContractsManagerUpgrader _opcmUpgrader, + ISuperchainConfig _superchainConfig, + IProtocolVersions _protocolVersions, + IProxyAdmin _superchainProxyAdmin, + string memory _l1ContractsRelease, + address _upgradeController + ) { + _opcmDeployer.assertValidContractAddress(address(_superchainConfig)); + _opcmDeployer.assertValidContractAddress(address(_protocolVersions)); + _opcmDeployer.assertValidContractAddress(address(_opcmGameTypeAdder)); + _opcmDeployer.assertValidContractAddress(address(_opcmDeployer)); + _opcmDeployer.assertValidContractAddress(address(_opcmUpgrader)); + opcmGameTypeAdder = _opcmGameTypeAdder; + opcmDeployer = _opcmDeployer; + opcmUpgrader = _opcmUpgrader; + superchainConfig = _superchainConfig; + protocolVersions = _protocolVersions; + superchainProxyAdmin = _superchainProxyAdmin; + L1_CONTRACTS_RELEASE = _l1ContractsRelease; + thisOPCM = this; + upgradeController = _upgradeController; } - /// @notice Retrieves the proposer address for a given game - function getProposer(IPermissionedDisputeGame _disputeGame) internal view returns (address) { - return _disputeGame.proposer(); + function deploy(DeployInput calldata _input) external virtual returns (DeployOutput memory) { + return opcmDeployer.deploy(_input, superchainConfig, msg.sender); } - /// @notice Retrieves the challenger address for a given game - function getChallenger(IPermissionedDisputeGame _disputeGame) internal view returns (address) { - return _disputeGame.challenger(); + /// @notice Upgrades a set of chains to the latest implementation contracts + /// @param _opChainConfigs Array of OpChain structs, one per chain to upgrade + /// @dev This function is intended to be called via DELEGATECALL from the Upgrade Controller Safe + function upgrade(OpChainConfig[] memory _opChainConfigs) external virtual { + if (address(this) == address(thisOPCM)) revert OnlyDelegatecall(); + + // If this is delegatecalled by the upgrade controller, set isRC to false first, else, continue execution. + if (address(this) == upgradeController) { + // Set isRC to false. + // This function asserts that the caller is the upgrade controller. + thisOPCM.setRC(false); + } + + bytes memory data = abi.encodeWithSelector( + OPContractsManagerUpgrader.upgrade.selector, + _opChainConfigs, + OPContractsManagerUpgrader.UpgradeInput({ + superchainConfig: superchainConfig, + protocolVersions: protocolVersions, + superchainProxyAdmin: superchainProxyAdmin + }) + ); + _performDelegateCall(address(opcmUpgrader), data); } - /// @notice Retrieves the DisputeGameFactory address for a given SystemConfig - function getDisputeGameFactory(ISystemConfig _systemConfig) internal view returns (IDisputeGameFactory) { - return IDisputeGameFactory(_systemConfig.disputeGameFactory()); + /// @notice addGameType deploys a new dispute game and links it to the DisputeGameFactory. The inputted _gameConfigs + /// must be added in ascending GameType order. + function addGameType(AddGameInput[] memory _gameConfigs) public virtual returns (AddGameOutput[] memory) { + if (address(this) == address(thisOPCM)) revert OnlyDelegatecall(); + + bytes memory data = + abi.encodeWithSelector(OPContractsManagerGameTypeAdder.addGameType.selector, _gameConfigs, superchainConfig); + + bytes memory returnData = _performDelegateCall(address(opcmGameTypeAdder), data); + return abi.decode(returnData, (AddGameOutput[])); } - /// @notice Retrieves the implementation addresses stored in this OPCM contract - function getImplementations() internal view returns (Implementations memory) { - return thisOPCM.implementations(); + /// @notice Updates the prestate hash for a new game type while keeping all other parameters the same + /// @param _prestateUpdateInputs The new prestate hash to use + function updatePrestate(OpChainConfig[] memory _prestateUpdateInputs) public { + bytes memory data = abi.encodeWithSelector( + OPContractsManagerGameTypeAdder.updatePrestate.selector, _prestateUpdateInputs, superchainConfig + ); + + _performDelegateCall(address(opcmGameTypeAdder), data); } - /// @notice Retrieves the blueprint addresses stored in this OPCM contract - function getBlueprints() internal view returns (Blueprints memory) { - return thisOPCM.blueprints(); + /// @notice Maps an L2 chain ID to an L1 batch inbox address as defined by the standard + /// configuration's convention. This convention is `versionByte || keccak256(bytes32(chainId))[:19]`, + /// where || denotes concatenation`, versionByte is 0x00, and chainId is a uint256. + /// https://specs.optimism.io/protocol/configurability.html#consensus-parameters + function chainIdToBatchInboxAddress(uint256 _l2ChainId) public view returns (address) { + return opcmDeployer.chainIdToBatchInboxAddress(_l2ChainId); } - function getProxyImplementation(IProxyAdmin _proxyAdmin, address _proxy) internal view returns (address) { - return _proxyAdmin.getProxyImplementation(_proxy); + /// @notice Returns the blueprint contract addresses. + function blueprints() public view returns (Blueprints memory) { + return opcmDeployer.blueprints(); } - /// @notice Deploys and sets a new dispute game implementation - /// @param _l2ChainId The L2 chain ID - /// @param _disputeGame The current dispute game implementation - /// @param _newAnchorStateRegistryProxy The new anchor state registry proxy - /// @param _gameType The type of game to deploy - /// @param _opChainConfig The OP chain configuration - /// @param _blueprints The blueprint addresses - /// @param _implementations The implementation addresses - /// @param _opChainAddrs The OP chain addresses - function deployAndSetNewGameImpl( - uint256 _l2ChainId, - IDisputeGame _disputeGame, - IAnchorStateRegistry _newAnchorStateRegistryProxy, - GameType _gameType, - OpChainConfig memory _opChainConfig, - Blueprints memory _blueprints, - Implementations memory _implementations, - ISystemConfig.Addresses memory _opChainAddrs - ) - internal - { - // independently scoped block to avoid stack too deep - { - // Get and upgrade the WETH proxy - IDelayedWETH delayedWethProxy = getWETH(IFaultDisputeGame(address(_disputeGame))); - upgradeTo(_opChainConfig.proxyAdmin, address(delayedWethProxy), _implementations.delayedWETHImpl); - } + /// @notice Returns the implementation contract addresses. + function implementations() public view returns (Implementations memory) { + return opcmDeployer.implementations(); + } - // Get the constructor params for the game - IFaultDisputeGame.GameConstructorParams memory params = - getGameConstructorParams(IFaultDisputeGame(address(_disputeGame))); + /// @notice Sets the RC flag. + function setRC(bool _isRC) external { + if (msg.sender != upgradeController) revert OnlyUpgradeController(); + isRC = _isRC; + } - // Modify the params with the new anchorStateRegistry and vm values. - params.anchorStateRegistry = IAnchorStateRegistry(address(_newAnchorStateRegistryProxy)); - params.vm = IBigStepper(_implementations.mipsImpl); - if (Claim.unwrap(_opChainConfig.absolutePrestate) == bytes32(0)) { - revert PrestateNotSet(); + /// @notice Helper function to perform a delegatecall to a target contract + /// @param _target The target contract address + /// @param _data The calldata to send to the target + /// @return bytes The return data from the delegatecall + function _performDelegateCall(address _target, bytes memory _data) internal returns (bytes memory) { + // Perform the delegatecall + (bool success, bytes memory returnData) = _target.delegatecall(_data); + + // Check if the delegatecall was successful + if (!success) { + // If there was a revert message, bubble it up + assembly { + revert(add(returnData, 32), mload(returnData)) + } } - params.absolutePrestate = _opChainConfig.absolutePrestate; - IDisputeGame newGame; - if (GameType.unwrap(_gameType) == GameType.unwrap(GameTypes.PERMISSIONED_CANNON)) { - address proposer = getProposer(IPermissionedDisputeGame(address(_disputeGame))); - address challenger = getChallenger(IPermissionedDisputeGame(address(_disputeGame))); - newGame = IDisputeGame( - Blueprint.deployFrom( - _blueprints.permissionedDisputeGame1, - _blueprints.permissionedDisputeGame2, - computeSalt(_l2ChainId, reusableSaltMixer(_opChainConfig), "PermissionedDisputeGame"), - encodePermissionedFDGConstructor(params, proposer, challenger) - ) - ); - } else { - newGame = IDisputeGame( - Blueprint.deployFrom( - _blueprints.permissionlessDisputeGame1, - _blueprints.permissionlessDisputeGame2, - computeSalt(_l2ChainId, reusableSaltMixer(_opChainConfig), "PermissionlessDisputeGame"), - encodePermissionlessFDGConstructor(params) - ) - ); - } - setDGFImplementation(IDisputeGameFactory(_opChainAddrs.disputeGameFactory), _gameType, IDisputeGame(newGame)); + return returnData; } } diff --git a/packages/contracts-bedrock/src/L1/OPContractsManagerInterop.sol b/packages/contracts-bedrock/src/L1/OPContractsManagerInterop.sol deleted file mode 100644 index cd4fbcf9f5387..0000000000000 --- a/packages/contracts-bedrock/src/L1/OPContractsManagerInterop.sol +++ /dev/null @@ -1,79 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.15; - -// Contracts -import { OPContractsManager } from "src/L1/OPContractsManager.sol"; - -// Interfaces -import { ISuperchainConfig } from "interfaces/L1/ISuperchainConfig.sol"; -import { IProtocolVersions } from "interfaces/L1/IProtocolVersions.sol"; -import { IResourceMetering } from "interfaces/L1/IResourceMetering.sol"; -import { ISystemConfig } from "interfaces/L1/ISystemConfig.sol"; -import { ISystemConfigInterop } from "interfaces/L1/ISystemConfigInterop.sol"; -import { IProxyAdmin } from "interfaces/universal/IProxyAdmin.sol"; - -contract OPContractsManagerInterop is OPContractsManager { - /// @custom:semver +interop.10 - function version() public pure override returns (string memory) { - return string.concat(super.version(), "+interop.10"); - } - - constructor( - ISuperchainConfig _superchainConfig, - IProtocolVersions _protocolVersions, - IProxyAdmin _superchainProxyAdmin, - string memory _l1ContractsRelease, - Blueprints memory _blueprints, - Implementations memory _implementations, - address _upgradeController - ) - OPContractsManager( - _superchainConfig, - _protocolVersions, - _superchainProxyAdmin, - _l1ContractsRelease, - _blueprints, - _implementations, - _upgradeController - ) - { } - - // The `SystemConfigInterop` contract has an extra `address _dependencyManager` argument - // that we must account for. - function encodeSystemConfigInitializer( - DeployInput memory _input, - DeployOutput memory _output - ) - internal - view - virtual - override - returns (bytes memory) - { - (IResourceMetering.ResourceConfig memory referenceResourceConfig, ISystemConfig.Addresses memory opChainAddrs) = - defaultSystemConfigParams(_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 - // to update where this value is pulled from in the future. To support a different dependency - // manager in this contract without an invasive change of redefining the `Roles` struct, - // we will make the change described in https://github.com/ethereum-optimism/optimism/issues/11783. - address dependencyManager = address(_input.roles.systemConfigOwner); - - return abi.encodeCall( - ISystemConfigInterop.initialize, - ( - _input.roles.systemConfigOwner, - _input.basefeeScalar, - _input.blobBasefeeScalar, - bytes32(uint256(uint160(_input.roles.batcher))), // batcherHash - _input.gasLimit, - _input.roles.unsafeBlockSigner, - referenceResourceConfig, - chainIdToBatchInboxAddress(_input.l2ChainId), - opChainAddrs, - dependencyManager - ) - ); - } -} diff --git a/packages/contracts-bedrock/src/L1/OPPrestateUpdater.sol b/packages/contracts-bedrock/src/L1/OPPrestateUpdater.sol deleted file mode 100644 index 849e8454e68b8..0000000000000 --- a/packages/contracts-bedrock/src/L1/OPPrestateUpdater.sol +++ /dev/null @@ -1,172 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.15; - -// Contracts -import { OPContractsManager } from "src/L1/OPContractsManager.sol"; - -// Interfaces -import { ISuperchainConfig } from "interfaces/L1/ISuperchainConfig.sol"; -import { IProtocolVersions } from "interfaces/L1/IProtocolVersions.sol"; -import { IPermissionedDisputeGame } from "interfaces/dispute/IPermissionedDisputeGame.sol"; -import { IDisputeGameFactory } from "interfaces/dispute/IDisputeGameFactory.sol"; -import { IFaultDisputeGame } from "interfaces/dispute/IFaultDisputeGame.sol"; -import { IDelayedWETH } from "interfaces/dispute/IDelayedWETH.sol"; -import { IProxyAdmin } from "interfaces/universal/IProxyAdmin.sol"; - -// Libraries -import { Claim, GameTypes } from "src/dispute/lib/Types.sol"; - -/// @title OPPrestateUpdater -/// @notice A custom implementation of OPContractsManager that enables updating the prestate hash -/// for the permissioned and fault dispute games on a set of chains. -contract OPPrestateUpdater is OPContractsManager { - /// @notice Thrown when a function from the parent (OPCM) is not implemented. - error NotImplemented(); - - /// @notice Thrown when the prestate of a permissioned disputed game is 0. - error PrestateRequired(); - - // @return Version string - /// @custom:semver 1.7.0 - function version() public pure override returns (string memory) { - return "1.7.0"; - } - - // @notice Constructs the OPPrestateUpdater contract - // @param _superchainConfig Address of the SuperchainConfig contract - // @param _protocolVersions Address of the ProtocolVersions contract - // @param _blueprints Addresses of Blueprint contracts - constructor( - ISuperchainConfig _superchainConfig, - IProtocolVersions _protocolVersions, - Blueprints memory _blueprints - ) - OPContractsManager( - _superchainConfig, - _protocolVersions, - IProxyAdmin(address(0)), - "", - _blueprints, - Implementations( - address(0), //superchainConfigImpl - address(0), //protocolVersionsImpl - address(0), //l1ERC721BridgeImpl - address(0), //optimismPortalImpl - address(0), //systemConfigImpl - address(0), //optimismMintableERC20FactoryImpl - address(0), //l1CrossDomainMessengerImpl - address(0), //l1StandardBridgeImpl - address(0), //disputeGameFactoryImpl - address(0), //anchorStateRegistryImpl - address(0), //delayedWETHImpl - address(0) // mipsImpl - ), - address(0) - ) - { } - - /// @notice Overrides the l1ContractsRelease function to return "none", as this OPCM - /// is not releasing new contracts. - function l1ContractsRelease() external pure override returns (string memory) { - return "none"; - } - - function deploy(DeployInput memory _input) external pure override returns (DeployOutput memory) { - _input; // Silence warning - revert NotImplemented(); - } - - function upgrade(OpChainConfig[] memory _opChainConfigs) external pure override { - _opChainConfigs; // Silence warning - revert NotImplemented(); - } - - function addGameType(AddGameInput[] memory _gameConfigs) public pure override returns (AddGameOutput[] memory) { - _gameConfigs; // Silence warning - revert NotImplemented(); - } - - /// @notice Updates the prestate hash for a new game type while keeping all other parameters the same - /// @param _prestateUpdateInputs The new prestate hash to use - function updatePrestate(OpChainConfig[] memory _prestateUpdateInputs) external { - // Loop through each chain and prestate hash - for (uint256 i = 0; i < _prestateUpdateInputs.length; i++) { - if (Claim.unwrap(_prestateUpdateInputs[i].absolutePrestate) == bytes32(0)) { - revert PrestateRequired(); - } - - // Get the DisputeGameFactory and existing game implementations - IDisputeGameFactory dgf = - IDisputeGameFactory(_prestateUpdateInputs[i].systemConfigProxy.disputeGameFactory()); - IFaultDisputeGame fdg = IFaultDisputeGame(address(getGameImplementation(dgf, GameTypes.CANNON))); - IPermissionedDisputeGame pdg = - IPermissionedDisputeGame(address(getGameImplementation(dgf, GameTypes.PERMISSIONED_CANNON))); - - // All chains must have a permissioned game, but not all chains must have a fault dispute game. - // Whether a chain has a fault dispute game determines how many AddGameInput objects are needed. - bool hasFDG = address(fdg) != address(0); - - AddGameInput[] memory inputs = new AddGameInput[](hasFDG ? 2 : 1); - AddGameInput memory pdgInput; - AddGameInput memory fdgInput; - - // Get the existing game parameters and init bond for the permissioned game - IFaultDisputeGame.GameConstructorParams memory pdgParams = - getGameConstructorParams(IFaultDisputeGame(address(pdg))); - uint256 initBond = dgf.initBonds(GameTypes.PERMISSIONED_CANNON); - - string memory saltMixer = reusableSaltMixer(_prestateUpdateInputs[i]); - // Create game input with updated prestate but same other params - pdgInput = AddGameInput({ - disputeAbsolutePrestate: _prestateUpdateInputs[i].absolutePrestate, - saltMixer: saltMixer, - systemConfig: _prestateUpdateInputs[i].systemConfigProxy, - proxyAdmin: _prestateUpdateInputs[i].proxyAdmin, - delayedWETH: IDelayedWETH(payable(address(pdgParams.weth))), - disputeGameType: pdgParams.gameType, - disputeMaxGameDepth: pdgParams.maxGameDepth, - disputeSplitDepth: pdgParams.splitDepth, - disputeClockExtension: pdgParams.clockExtension, - disputeMaxClockDuration: pdgParams.maxClockDuration, - initialBond: initBond, - vm: pdgParams.vm, - permissioned: true - }); - - // If a fault dispute game exists, create a new game with the same parameters but updated prestate. - if (hasFDG) { - // Get the existing game parameters and init bond for the fault dispute game - IFaultDisputeGame.GameConstructorParams memory fdgParams = - getGameConstructorParams(IFaultDisputeGame(address(fdg))); - initBond = dgf.initBonds(GameTypes.CANNON); - - // Create game input with updated prestate but same other params - fdgInput = AddGameInput({ - disputeAbsolutePrestate: _prestateUpdateInputs[i].absolutePrestate, - saltMixer: saltMixer, - systemConfig: _prestateUpdateInputs[i].systemConfigProxy, - proxyAdmin: _prestateUpdateInputs[i].proxyAdmin, - delayedWETH: IDelayedWETH(payable(address(fdgParams.weth))), - disputeGameType: fdgParams.gameType, - disputeMaxGameDepth: fdgParams.maxGameDepth, - disputeSplitDepth: fdgParams.splitDepth, - disputeClockExtension: fdgParams.clockExtension, - disputeMaxClockDuration: fdgParams.maxClockDuration, - initialBond: initBond, - vm: fdgParams.vm, - permissioned: false - }); - } - - // Game inputs must be ordered with increasing game type values. So FDG is first if it exists. - if (hasFDG) { - inputs[0] = fdgInput; - inputs[1] = pdgInput; - } else { - inputs[0] = pdgInput; - } - // Add the new game type with updated prestate - super.addGameType(inputs); - } - } -} diff --git a/packages/contracts-bedrock/test/L1/OPContractsManager.t.sol b/packages/contracts-bedrock/test/L1/OPContractsManager.t.sol index 0cf5ba4df889b..ea718fd505b46 100644 --- a/packages/contracts-bedrock/test/L1/OPContractsManager.t.sol +++ b/packages/contracts-bedrock/test/L1/OPContractsManager.t.sol @@ -37,11 +37,23 @@ import { IDisputeGame } from "interfaces/dispute/IDisputeGame.sol"; import { IDisputeGameFactory } from "interfaces/dispute/IDisputeGameFactory.sol"; import { IFaultDisputeGame } from "interfaces/dispute/IFaultDisputeGame.sol"; import { ISystemConfig } from "interfaces/L1/ISystemConfig.sol"; -import { IOPContractsManager } from "interfaces/L1/IOPContractsManager.sol"; +import { + IOPContractsManager, + IOPContractsManagerGameTypeAdder, + IOPContractsManagerDeployer, + IOPContractsManagerUpgrader, + IOPContractsManagerContractsContainer +} from "interfaces/L1/IOPContractsManager.sol"; import { ISemver } from "interfaces/universal/ISemver.sol"; // Contracts -import { OPContractsManager } from "src/L1/OPContractsManager.sol"; +import { + OPContractsManager, + OPContractsManagerGameTypeAdder, + OPContractsManagerDeployer, + OPContractsManagerUpgrader, + OPContractsManagerContractsContainer +} from "src/L1/OPContractsManager.sol"; import { Blueprint } from "src/libraries/Blueprint.sol"; import { IBigStepper } from "interfaces/dispute/IBigStepper.sol"; import { GameType, Duration, Hash, Claim } from "src/dispute/lib/LibUDT.sol"; @@ -50,26 +62,28 @@ import { OutputRoot, GameTypes } from "src/dispute/lib/Types.sol"; // Exposes internal functions for testing. contract OPContractsManager_Harness is OPContractsManager { constructor( + OPContractsManagerGameTypeAdder _opcmGameTypeAdder, + OPContractsManagerDeployer _opcmDeployer, + OPContractsManagerUpgrader _opcmUpgrader, ISuperchainConfig _superchainConfig, IProtocolVersions _protocolVersions, IProxyAdmin _superchainProxyAdmin, string memory _l1ContractsRelease, - Blueprints memory _blueprints, - Implementations memory _implementations, address _upgradeController ) OPContractsManager( + _opcmGameTypeAdder, + _opcmDeployer, + _opcmUpgrader, _superchainConfig, _protocolVersions, _superchainProxyAdmin, _l1ContractsRelease, - _blueprints, - _implementations, _upgradeController ) { } - function chainIdToBatchInboxAddress_exposed(uint256 l2ChainId) public pure returns (address) { + function chainIdToBatchInboxAddress_exposed(uint256 l2ChainId) public view returns (address) { return super.chainIdToBatchInboxAddress(l2ChainId); } } @@ -175,13 +189,17 @@ contract OPContractsManager_InternalMethods_Test is Test { vm.etch(address(superchainConfigProxy), hex"01"); vm.etch(address(protocolVersionsProxy), hex"01"); + OPContractsManagerContractsContainer container = + new OPContractsManagerContractsContainer(emptyBlueprints, emptyImpls); + opcmHarness = new OPContractsManager_Harness({ + _opcmGameTypeAdder: new OPContractsManagerGameTypeAdder(container), + _opcmDeployer: new OPContractsManagerDeployer(container), + _opcmUpgrader: new OPContractsManagerUpgrader(container), _superchainConfig: superchainConfigProxy, _protocolVersions: protocolVersionsProxy, _superchainProxyAdmin: superchainProxyAdmin, _l1ContractsRelease: "dev", - _blueprints: emptyBlueprints, - _implementations: emptyImpls, _upgradeController: upgradeController }); } @@ -626,6 +644,51 @@ contract OPContractsManager_AddGameType_Test is Test { vm.etch(address(superchainConfigProxy), hex"01"); vm.etch(address(protocolVersionsProxy), hex"01"); + IOPContractsManagerGameTypeAdder opcmGameTypeAdder = IOPContractsManagerGameTypeAdder( + DeployUtils.createDeterministic({ + _name: "OPContractsManagerGameTypeAdder", + _args: DeployUtils.encodeConstructor( + abi.encodeCall( + IOPContractsManagerGameTypeAdder.__constructor__, + ( + IOPContractsManagerContractsContainer( + DeployUtils.createDeterministic({ + _name: "OPContractsManagerContractsContainer", + _args: DeployUtils.encodeConstructor( + abi.encodeCall( + IOPContractsManagerContractsContainer.__constructor__, (blueprints, impls) + ) + ), + _salt: DeployUtils.DEFAULT_SALT + }) + ) + ) + ) + ), + _salt: DeployUtils.DEFAULT_SALT + }) + ); + + IOPContractsManagerDeployer opcmDeployer = IOPContractsManagerDeployer( + DeployUtils.createDeterministic({ + _name: "OPContractsManagerDeployer", + _args: DeployUtils.encodeConstructor( + abi.encodeCall(IOPContractsManagerDeployer.__constructor__, (opcmGameTypeAdder.contractsContainer())) + ), + _salt: DeployUtils.DEFAULT_SALT + }) + ); + + IOPContractsManagerUpgrader opcmUpgrader = IOPContractsManagerUpgrader( + DeployUtils.createDeterministic({ + _name: "OPContractsManagerUpgrader", + _args: DeployUtils.encodeConstructor( + abi.encodeCall(IOPContractsManagerUpgrader.__constructor__, (opcmGameTypeAdder.contractsContainer())) + ), + _salt: DeployUtils.DEFAULT_SALT + }) + ); + opcm = IOPContractsManager( DeployUtils.createDeterministic({ _name: "OPContractsManager", @@ -633,12 +696,13 @@ contract OPContractsManager_AddGameType_Test is Test { abi.encodeCall( IOPContractsManager.__constructor__, ( + opcmGameTypeAdder, + opcmDeployer, + opcmUpgrader, superchainConfigProxy, protocolVersionsProxy, superchainProxyAdmin, "dev", - blueprints, - impls, address(this) ) ) @@ -855,3 +919,303 @@ contract OPContractsManager_AddGameType_Test is Test { ); } } + +contract OPContractsManager_UpdatePrestate_Test is Test { + IOPContractsManager internal opcm; + IOPContractsManager internal prestateUpdater; + + OPContractsManager.OpChainConfig[] internal opChainConfigs; + OPContractsManager.AddGameInput[] internal gameInput; + + IOPContractsManager.DeployOutput internal chainDeployOutput; + + function setUp() public { + IProxyAdmin superchainProxyAdmin = IProxyAdmin(makeAddr("superchainProxyAdmin")); + ISuperchainConfig superchainConfigProxy = ISuperchainConfig(makeAddr("superchainConfig")); + IProtocolVersions protocolVersionsProxy = IProtocolVersions(makeAddr("protocolVersions")); + bytes32 salt = hex"01"; + IOPContractsManager.Blueprints memory blueprints; + + (blueprints.addressManager,) = Blueprint.create(vm.getCode("AddressManager"), salt); + (blueprints.proxy,) = Blueprint.create(vm.getCode("Proxy"), salt); + (blueprints.proxyAdmin,) = Blueprint.create(vm.getCode("ProxyAdmin"), salt); + (blueprints.l1ChugSplashProxy,) = Blueprint.create(vm.getCode("L1ChugSplashProxy"), salt); + (blueprints.resolvedDelegateProxy,) = Blueprint.create(vm.getCode("ResolvedDelegateProxy"), salt); + (blueprints.permissionedDisputeGame1, blueprints.permissionedDisputeGame2) = + Blueprint.create(vm.getCode("PermissionedDisputeGame"), salt); + (blueprints.permissionlessDisputeGame1, blueprints.permissionlessDisputeGame2) = + Blueprint.create(vm.getCode("FaultDisputeGame"), salt); + + IPreimageOracle oracle = IPreimageOracle( + DeployUtils.create1({ + _name: "PreimageOracle", + _args: DeployUtils.encodeConstructor(abi.encodeCall(IPreimageOracle.__constructor__, (126000, 86400))) + }) + ); + + IOPContractsManager.Implementations memory impls = IOPContractsManager.Implementations({ + superchainConfigImpl: DeployUtils.create1({ + _name: "SuperchainConfig", + _args: DeployUtils.encodeConstructor(abi.encodeCall(ISuperchainConfig.__constructor__, ())) + }), + protocolVersionsImpl: DeployUtils.create1({ + _name: "ProtocolVersions", + _args: DeployUtils.encodeConstructor(abi.encodeCall(IProtocolVersions.__constructor__, ())) + }), + l1ERC721BridgeImpl: DeployUtils.create1({ + _name: "L1ERC721Bridge", + _args: DeployUtils.encodeConstructor(abi.encodeCall(IL1ERC721Bridge.__constructor__, ())) + }), + optimismPortalImpl: DeployUtils.create1({ + _name: "OptimismPortal2", + _args: DeployUtils.encodeConstructor(abi.encodeCall(IOptimismPortal2.__constructor__, (1, 1))) + }), + systemConfigImpl: DeployUtils.create1({ + _name: "SystemConfig", + _args: DeployUtils.encodeConstructor(abi.encodeCall(ISystemConfig.__constructor__, ())) + }), + optimismMintableERC20FactoryImpl: DeployUtils.create1({ + _name: "OptimismMintableERC20Factory", + _args: DeployUtils.encodeConstructor(abi.encodeCall(IOptimismMintableERC20Factory.__constructor__, ())) + }), + l1CrossDomainMessengerImpl: DeployUtils.create1({ + _name: "L1CrossDomainMessenger", + _args: DeployUtils.encodeConstructor(abi.encodeCall(IL1CrossDomainMessenger.__constructor__, ())) + }), + l1StandardBridgeImpl: DeployUtils.create1({ + _name: "L1StandardBridge", + _args: DeployUtils.encodeConstructor(abi.encodeCall(IL1StandardBridge.__constructor__, ())) + }), + disputeGameFactoryImpl: DeployUtils.create1({ + _name: "DisputeGameFactory", + _args: DeployUtils.encodeConstructor(abi.encodeCall(IDisputeGameFactory.__constructor__, ())) + }), + anchorStateRegistryImpl: DeployUtils.create1({ + _name: "AnchorStateRegistry", + _args: DeployUtils.encodeConstructor(abi.encodeCall(IAnchorStateRegistry.__constructor__, ())) + }), + delayedWETHImpl: DeployUtils.create1({ + _name: "DelayedWETH", + _args: DeployUtils.encodeConstructor(abi.encodeCall(IDelayedWETH.__constructor__, (3))) + }), + mipsImpl: DeployUtils.create1({ + _name: "MIPS", + _args: DeployUtils.encodeConstructor(abi.encodeCall(IMIPS.__constructor__, (oracle))) + }) + }); + + vm.etch(address(superchainConfigProxy), hex"01"); + vm.etch(address(protocolVersionsProxy), hex"01"); + + IOPContractsManagerContractsContainer container = IOPContractsManagerContractsContainer( + DeployUtils.createDeterministic({ + _name: "OPContractsManagerContractsContainer", + _args: DeployUtils.encodeConstructor( + abi.encodeCall(IOPContractsManagerContractsContainer.__constructor__, (blueprints, impls)) + ), + _salt: DeployUtils.DEFAULT_SALT + }) + ); + + opcm = IOPContractsManager( + DeployUtils.createDeterministic({ + _name: "OPContractsManager", + _args: DeployUtils.encodeConstructor( + abi.encodeCall( + IOPContractsManager.__constructor__, + ( + IOPContractsManagerGameTypeAdder( + DeployUtils.createDeterministic({ + _name: "OPContractsManagerGameTypeAdder", + _args: DeployUtils.encodeConstructor( + abi.encodeCall(IOPContractsManagerGameTypeAdder.__constructor__, (container)) + ), + _salt: DeployUtils.DEFAULT_SALT + }) + ), + IOPContractsManagerDeployer( + DeployUtils.createDeterministic({ + _name: "OPContractsManagerDeployer", + _args: DeployUtils.encodeConstructor( + abi.encodeCall(IOPContractsManagerDeployer.__constructor__, (container)) + ), + _salt: DeployUtils.DEFAULT_SALT + }) + ), + IOPContractsManagerUpgrader( + DeployUtils.createDeterministic({ + _name: "OPContractsManagerUpgrader", + _args: DeployUtils.encodeConstructor( + abi.encodeCall(IOPContractsManagerUpgrader.__constructor__, (container)) + ), + _salt: DeployUtils.DEFAULT_SALT + }) + ), + superchainConfigProxy, + protocolVersionsProxy, + superchainProxyAdmin, + "dev", + address(this) + ) + ) + ), + _salt: DeployUtils.DEFAULT_SALT + }) + ); + + chainDeployOutput = opcm.deploy( + IOPContractsManager.DeployInput({ + roles: IOPContractsManager.Roles({ + opChainProxyAdminOwner: address(this), + systemConfigOwner: address(this), + batcher: address(this), + unsafeBlockSigner: address(this), + proposer: address(this), + challenger: address(this) + }), + basefeeScalar: 1, + blobBasefeeScalar: 1, + startingAnchorRoot: abi.encode( + OutputRoot({ + root: Hash.wrap(0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef), + l2BlockNumber: 0 + }) + ), + l2ChainId: 100, + saltMixer: "hello", + gasLimit: 30_000_000, + disputeGameType: GameType.wrap(1), + disputeAbsolutePrestate: Claim.wrap( + bytes32(hex"038512e02c4c3f7bdaec27d00edf55b7155e0905301e1a88083e4e0a6764d54c") + ), + disputeMaxGameDepth: 73, + disputeSplitDepth: 30, + disputeClockExtension: Duration.wrap(10800), + disputeMaxClockDuration: Duration.wrap(302400) + }) + ); + + prestateUpdater = opcm; + } + + function test_semver_works() public view { + assertNotEq(abi.encode(prestateUpdater.version()), abi.encode(0)); + } + + function test_updatePrestate_pdgOnlyWithValidInput_succeeds() public { + IOPContractsManager.OpChainConfig[] memory inputs = new IOPContractsManager.OpChainConfig[](1); + inputs[0] = IOPContractsManager.OpChainConfig( + chainDeployOutput.systemConfigProxy, chainDeployOutput.opChainProxyAdmin, Claim.wrap(bytes32(hex"ABBA")) + ); + address proxyAdminOwner = chainDeployOutput.opChainProxyAdmin.owner(); + + vm.etch(address(proxyAdminOwner), vm.getDeployedCode("test/mocks/Callers.sol:DelegateCaller")); + DelegateCaller(proxyAdminOwner).dcForward( + address(prestateUpdater), abi.encodeCall(IOPContractsManager.updatePrestate, (inputs)) + ); + + IPermissionedDisputeGame pdg = IPermissionedDisputeGame( + address( + IDisputeGameFactory(chainDeployOutput.systemConfigProxy.disputeGameFactory()).gameImpls( + GameTypes.PERMISSIONED_CANNON + ) + ) + ); + + assertEq(pdg.absolutePrestate().raw(), inputs[0].absolutePrestate.raw(), "pdg prestate mismatch"); + + // Ensure that the WETH contract is not reverting + pdg.weth().balanceOf(address(0)); + } + + function test_updatePrestate_bothGamesWithValidInput_succeeds() public { + // Also add a permissionless game + IOPContractsManager.AddGameInput memory input = newGameInputFactory({ permissioned: false }); + input.disputeGameType = GameTypes.CANNON; + addGameType(input); + + IOPContractsManager.OpChainConfig[] memory inputs = new IOPContractsManager.OpChainConfig[](1); + inputs[0] = IOPContractsManager.OpChainConfig( + chainDeployOutput.systemConfigProxy, chainDeployOutput.opChainProxyAdmin, Claim.wrap(bytes32(hex"ABBA")) + ); + address proxyAdminOwner = chainDeployOutput.opChainProxyAdmin.owner(); + + vm.etch(address(proxyAdminOwner), vm.getDeployedCode("test/mocks/Callers.sol:DelegateCaller")); + DelegateCaller(proxyAdminOwner).dcForward( + address(prestateUpdater), abi.encodeCall(IOPContractsManager.updatePrestate, (inputs)) + ); + + IPermissionedDisputeGame pdg = IPermissionedDisputeGame( + address( + IDisputeGameFactory(chainDeployOutput.systemConfigProxy.disputeGameFactory()).gameImpls( + GameTypes.PERMISSIONED_CANNON + ) + ) + ); + IPermissionedDisputeGame fdg = IPermissionedDisputeGame( + address( + IDisputeGameFactory(chainDeployOutput.systemConfigProxy.disputeGameFactory()).gameImpls( + GameTypes.CANNON + ) + ) + ); + + assertEq(pdg.absolutePrestate().raw(), inputs[0].absolutePrestate.raw(), "pdg prestate mismatch"); + assertEq(fdg.absolutePrestate().raw(), inputs[0].absolutePrestate.raw(), "fdg prestate mismatch"); + + // Ensure that the WETH contracts are not reverting + pdg.weth().balanceOf(address(0)); + fdg.weth().balanceOf(address(0)); + } + + function test_updatePrestate_whenPDGPrestateIsZero_reverts() public { + IOPContractsManager.OpChainConfig[] memory inputs = new IOPContractsManager.OpChainConfig[](1); + inputs[0] = IOPContractsManager.OpChainConfig({ + systemConfigProxy: chainDeployOutput.systemConfigProxy, + proxyAdmin: chainDeployOutput.opChainProxyAdmin, + absolutePrestate: Claim.wrap(bytes32(0)) + }); + + address proxyAdminOwner = chainDeployOutput.opChainProxyAdmin.owner(); + vm.etch(address(proxyAdminOwner), vm.getDeployedCode("test/mocks/Callers.sol:DelegateCaller")); + + vm.expectRevert(IOPContractsManager.PrestateRequired.selector); + DelegateCaller(proxyAdminOwner).dcForward( + address(prestateUpdater), abi.encodeCall(IOPContractsManager.updatePrestate, (inputs)) + ); + } + + function addGameType(IOPContractsManager.AddGameInput memory input) + internal + returns (IOPContractsManager.AddGameOutput memory) + { + IOPContractsManager.AddGameInput[] memory inputs = new IOPContractsManager.AddGameInput[](1); + inputs[0] = input; + + (bool success, bytes memory rawGameOut) = + address(opcm).delegatecall(abi.encodeCall(IOPContractsManager.addGameType, (inputs))); + assertTrue(success, "addGameType failed"); + + IOPContractsManager.AddGameOutput[] memory addGameOutAll = + abi.decode(rawGameOut, (IOPContractsManager.AddGameOutput[])); + return addGameOutAll[0]; + } + + function newGameInputFactory(bool permissioned) internal view returns (IOPContractsManager.AddGameInput memory) { + return IOPContractsManager.AddGameInput({ + saltMixer: "hello", + systemConfig: chainDeployOutput.systemConfigProxy, + proxyAdmin: chainDeployOutput.opChainProxyAdmin, + delayedWETH: IDelayedWETH(payable(address(0))), + disputeGameType: GameType.wrap(2000), + disputeAbsolutePrestate: Claim.wrap(bytes32(hex"deadbeef1234")), + disputeMaxGameDepth: 73, + disputeSplitDepth: 30, + disputeClockExtension: Duration.wrap(10800), + disputeMaxClockDuration: Duration.wrap(302400), + initialBond: 1 ether, + vm: IBigStepper(address(opcm.implementations().mipsImpl)), + permissioned: permissioned + }); + } +} diff --git a/packages/contracts-bedrock/test/L1/OPPrestateUpdater.t.sol b/packages/contracts-bedrock/test/L1/OPPrestateUpdater.t.sol deleted file mode 100644 index d700efa24e42b..0000000000000 --- a/packages/contracts-bedrock/test/L1/OPPrestateUpdater.t.sol +++ /dev/null @@ -1,385 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.15; - -// Testing -import { Test } from "forge-std/Test.sol"; -import { DelegateCaller } from "test/mocks/Callers.sol"; - -// Scripts -import { DeployUtils } from "scripts/libraries/DeployUtils.sol"; - -// Libraries -import { Blueprint } from "src/libraries/Blueprint.sol"; - -// Interfaces -import { IL1ERC721Bridge } from "interfaces/L1/IL1ERC721Bridge.sol"; -import { IL1StandardBridge } from "interfaces/L1/IL1StandardBridge.sol"; -import { IL1CrossDomainMessenger } from "interfaces/L1/IL1CrossDomainMessenger.sol"; -import { IOptimismMintableERC20Factory } from "interfaces/universal/IOptimismMintableERC20Factory.sol"; -import { IAnchorStateRegistry } from "interfaces/dispute/IAnchorStateRegistry.sol"; -import { IMIPS } from "interfaces/cannon/IMIPS.sol"; -import { IOptimismPortal2 } from "interfaces/L1/IOptimismPortal2.sol"; -import { IProxyAdmin } from "interfaces/universal/IProxyAdmin.sol"; -import { ISuperchainConfig } from "interfaces/L1/ISuperchainConfig.sol"; -import { IProtocolVersions } from "interfaces/L1/IProtocolVersions.sol"; -import { IPreimageOracle } from "interfaces/cannon/IPreimageOracle.sol"; -import { IPermissionedDisputeGame } from "interfaces/dispute/IPermissionedDisputeGame.sol"; -import { IDelayedWETH } from "interfaces/dispute/IDelayedWETH.sol"; -import { IOPContractsManager } from "interfaces/L1/IOPContractsManager.sol"; -import { IDisputeGameFactory } from "interfaces/dispute/IDisputeGameFactory.sol"; -import { ISystemConfig } from "interfaces/L1/ISystemConfig.sol"; -import { IOPPrestateUpdater } from "interfaces/L1/IOPPrestateUpdater.sol"; - -// Contracts -import { OPContractsManager } from "src/L1/OPContractsManager.sol"; -import { OPPrestateUpdater } from "src/L1/OPPrestateUpdater.sol"; -import { Blueprint } from "src/libraries/Blueprint.sol"; -import { IBigStepper } from "interfaces/dispute/IBigStepper.sol"; -import { GameType, Duration, Hash, Claim } from "src/dispute/lib/LibUDT.sol"; -import { OutputRoot, GameTypes } from "src/dispute/lib/Types.sol"; - -contract OPPrestateUpdater_Test is Test { - IOPContractsManager internal opcm; - OPPrestateUpdater internal prestateUpdater; - - OPContractsManager.OpChainConfig[] internal opChainConfigs; - OPContractsManager.AddGameInput[] internal gameInput; - - IOPContractsManager.DeployOutput internal chainDeployOutput; - - function setUp() public { - IProxyAdmin superchainProxyAdmin = IProxyAdmin(makeAddr("superchainProxyAdmin")); - ISuperchainConfig superchainConfigProxy = ISuperchainConfig(makeAddr("superchainConfig")); - IProtocolVersions protocolVersionsProxy = IProtocolVersions(makeAddr("protocolVersions")); - bytes32 salt = hex"01"; - IOPContractsManager.Blueprints memory blueprints; - - (blueprints.addressManager,) = Blueprint.create(vm.getCode("AddressManager"), salt); - (blueprints.proxy,) = Blueprint.create(vm.getCode("Proxy"), salt); - (blueprints.proxyAdmin,) = Blueprint.create(vm.getCode("ProxyAdmin"), salt); - (blueprints.l1ChugSplashProxy,) = Blueprint.create(vm.getCode("L1ChugSplashProxy"), salt); - (blueprints.resolvedDelegateProxy,) = Blueprint.create(vm.getCode("ResolvedDelegateProxy"), salt); - (blueprints.permissionedDisputeGame1, blueprints.permissionedDisputeGame2) = - Blueprint.create(vm.getCode("PermissionedDisputeGame"), salt); - (blueprints.permissionlessDisputeGame1, blueprints.permissionlessDisputeGame2) = - Blueprint.create(vm.getCode("FaultDisputeGame"), salt); - - IPreimageOracle oracle = IPreimageOracle( - DeployUtils.create1({ - _name: "PreimageOracle", - _args: DeployUtils.encodeConstructor(abi.encodeCall(IPreimageOracle.__constructor__, (126000, 86400))) - }) - ); - - IOPContractsManager.Implementations memory impls = IOPContractsManager.Implementations({ - superchainConfigImpl: DeployUtils.create1({ - _name: "SuperchainConfig", - _args: DeployUtils.encodeConstructor(abi.encodeCall(ISuperchainConfig.__constructor__, ())) - }), - protocolVersionsImpl: DeployUtils.create1({ - _name: "ProtocolVersions", - _args: DeployUtils.encodeConstructor(abi.encodeCall(IProtocolVersions.__constructor__, ())) - }), - l1ERC721BridgeImpl: DeployUtils.create1({ - _name: "L1ERC721Bridge", - _args: DeployUtils.encodeConstructor(abi.encodeCall(IL1ERC721Bridge.__constructor__, ())) - }), - optimismPortalImpl: DeployUtils.create1({ - _name: "OptimismPortal2", - _args: DeployUtils.encodeConstructor(abi.encodeCall(IOptimismPortal2.__constructor__, (1, 1))) - }), - systemConfigImpl: DeployUtils.create1({ - _name: "SystemConfig", - _args: DeployUtils.encodeConstructor(abi.encodeCall(ISystemConfig.__constructor__, ())) - }), - optimismMintableERC20FactoryImpl: DeployUtils.create1({ - _name: "OptimismMintableERC20Factory", - _args: DeployUtils.encodeConstructor(abi.encodeCall(IOptimismMintableERC20Factory.__constructor__, ())) - }), - l1CrossDomainMessengerImpl: DeployUtils.create1({ - _name: "L1CrossDomainMessenger", - _args: DeployUtils.encodeConstructor(abi.encodeCall(IL1CrossDomainMessenger.__constructor__, ())) - }), - l1StandardBridgeImpl: DeployUtils.create1({ - _name: "L1StandardBridge", - _args: DeployUtils.encodeConstructor(abi.encodeCall(IL1StandardBridge.__constructor__, ())) - }), - disputeGameFactoryImpl: DeployUtils.create1({ - _name: "DisputeGameFactory", - _args: DeployUtils.encodeConstructor(abi.encodeCall(IDisputeGameFactory.__constructor__, ())) - }), - anchorStateRegistryImpl: DeployUtils.create1({ - _name: "AnchorStateRegistry", - _args: DeployUtils.encodeConstructor(abi.encodeCall(IAnchorStateRegistry.__constructor__, ())) - }), - delayedWETHImpl: DeployUtils.create1({ - _name: "DelayedWETH", - _args: DeployUtils.encodeConstructor(abi.encodeCall(IDelayedWETH.__constructor__, (3))) - }), - mipsImpl: DeployUtils.create1({ - _name: "MIPS", - _args: DeployUtils.encodeConstructor(abi.encodeCall(IMIPS.__constructor__, (oracle))) - }) - }); - - vm.etch(address(superchainConfigProxy), hex"01"); - vm.etch(address(protocolVersionsProxy), hex"01"); - - opcm = IOPContractsManager( - DeployUtils.createDeterministic({ - _name: "OPContractsManager", - _args: DeployUtils.encodeConstructor( - abi.encodeCall( - IOPContractsManager.__constructor__, - ( - superchainConfigProxy, - protocolVersionsProxy, - superchainProxyAdmin, - "dev", - blueprints, - impls, - address(this) - ) - ) - ), - _salt: DeployUtils.DEFAULT_SALT - }) - ); - - chainDeployOutput = opcm.deploy( - IOPContractsManager.DeployInput({ - roles: IOPContractsManager.Roles({ - opChainProxyAdminOwner: address(this), - systemConfigOwner: address(this), - batcher: address(this), - unsafeBlockSigner: address(this), - proposer: address(this), - challenger: address(this) - }), - basefeeScalar: 1, - blobBasefeeScalar: 1, - startingAnchorRoot: abi.encode( - OutputRoot({ - root: Hash.wrap(0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef), - l2BlockNumber: 0 - }) - ), - l2ChainId: 100, - saltMixer: "hello", - gasLimit: 30_000_000, - disputeGameType: GameType.wrap(1), - disputeAbsolutePrestate: Claim.wrap( - bytes32(hex"038512e02c4c3f7bdaec27d00edf55b7155e0905301e1a88083e4e0a6764d54c") - ), - disputeMaxGameDepth: 73, - disputeSplitDepth: 30, - disputeClockExtension: Duration.wrap(10800), - disputeMaxClockDuration: Duration.wrap(302400) - }) - ); - - prestateUpdater = OPPrestateUpdater( - DeployUtils.createDeterministic({ - _name: "OPPrestateUpdater", - _args: DeployUtils.encodeConstructor( - abi.encodeCall( - IOPPrestateUpdater.__constructor__, - (ISuperchainConfig(address(this)), IProtocolVersions(address(this)), blueprints) - ) - ), - _salt: DeployUtils.DEFAULT_SALT - }) - ); - } - - function test_semver_works() public view { - assertNotEq(abi.encode(prestateUpdater.version()), abi.encode(0)); - } - - function test_updatePrestate_pdgOnlyWithValidInput_succeeds() public { - OPContractsManager.OpChainConfig[] memory inputs = new OPContractsManager.OpChainConfig[](1); - inputs[0] = OPContractsManager.OpChainConfig( - chainDeployOutput.systemConfigProxy, chainDeployOutput.opChainProxyAdmin, Claim.wrap(bytes32(hex"ABBA")) - ); - address proxyAdminOwner = chainDeployOutput.opChainProxyAdmin.owner(); - - vm.etch(address(proxyAdminOwner), vm.getDeployedCode("test/mocks/Callers.sol:DelegateCaller")); - DelegateCaller(proxyAdminOwner).dcForward( - address(prestateUpdater), abi.encodeCall(OPPrestateUpdater.updatePrestate, (inputs)) - ); - - IPermissionedDisputeGame pdg = IPermissionedDisputeGame( - address( - IDisputeGameFactory(chainDeployOutput.systemConfigProxy.disputeGameFactory()).gameImpls( - GameTypes.PERMISSIONED_CANNON - ) - ) - ); - - assertEq(pdg.absolutePrestate().raw(), inputs[0].absolutePrestate.raw(), "pdg prestate mismatch"); - - // Ensure that the WETH contract is not reverting - pdg.weth().balanceOf(address(0)); - } - - function test_updatePrestate_bothGamesWithValidInput_succeeds() public { - // Also add a permissionless game - IOPContractsManager.AddGameInput memory input = newGameInputFactory({ permissioned: false }); - input.disputeGameType = GameTypes.CANNON; - addGameType(input); - - OPContractsManager.OpChainConfig[] memory inputs = new OPContractsManager.OpChainConfig[](1); - inputs[0] = OPContractsManager.OpChainConfig( - chainDeployOutput.systemConfigProxy, chainDeployOutput.opChainProxyAdmin, Claim.wrap(bytes32(hex"ABBA")) - ); - address proxyAdminOwner = chainDeployOutput.opChainProxyAdmin.owner(); - - vm.etch(address(proxyAdminOwner), vm.getDeployedCode("test/mocks/Callers.sol:DelegateCaller")); - DelegateCaller(proxyAdminOwner).dcForward( - address(prestateUpdater), abi.encodeCall(OPPrestateUpdater.updatePrestate, (inputs)) - ); - - IPermissionedDisputeGame pdg = IPermissionedDisputeGame( - address( - IDisputeGameFactory(chainDeployOutput.systemConfigProxy.disputeGameFactory()).gameImpls( - GameTypes.PERMISSIONED_CANNON - ) - ) - ); - IPermissionedDisputeGame fdg = IPermissionedDisputeGame( - address( - IDisputeGameFactory(chainDeployOutput.systemConfigProxy.disputeGameFactory()).gameImpls( - GameTypes.CANNON - ) - ) - ); - - assertEq(pdg.absolutePrestate().raw(), inputs[0].absolutePrestate.raw(), "pdg prestate mismatch"); - assertEq(fdg.absolutePrestate().raw(), inputs[0].absolutePrestate.raw(), "fdg prestate mismatch"); - - // Ensure that the WETH contracts are not reverting - pdg.weth().balanceOf(address(0)); - fdg.weth().balanceOf(address(0)); - } - - function test_updatePrestate_whenPDGPrestateIsZero_reverts() public { - OPPrestateUpdater.OpChainConfig[] memory inputs = new OPPrestateUpdater.OpChainConfig[](1); - inputs[0] = OPContractsManager.OpChainConfig({ - systemConfigProxy: chainDeployOutput.systemConfigProxy, - proxyAdmin: chainDeployOutput.opChainProxyAdmin, - absolutePrestate: Claim.wrap(bytes32(0)) - }); - - address proxyAdminOwner = chainDeployOutput.opChainProxyAdmin.owner(); - vm.etch(address(proxyAdminOwner), vm.getDeployedCode("test/mocks/Callers.sol:DelegateCaller")); - - vm.expectRevert(OPPrestateUpdater.PrestateRequired.selector); - DelegateCaller(proxyAdminOwner).dcForward( - address(prestateUpdater), abi.encodeCall(OPPrestateUpdater.updatePrestate, (inputs)) - ); - } - - function test_deploy_notImplemented_reverts() public { - OPContractsManager.DeployInput memory input = OPContractsManager.DeployInput({ - roles: OPContractsManager.Roles({ - opChainProxyAdminOwner: address(0), - systemConfigOwner: address(0), - batcher: address(0), - unsafeBlockSigner: address(0), - proposer: address(0), - challenger: address(0) - }), - basefeeScalar: 0, - blobBasefeeScalar: 0, - l2ChainId: 0, - startingAnchorRoot: bytes(abi.encode(0)), - saltMixer: "", - gasLimit: 0, - disputeGameType: GameType.wrap(0), - disputeAbsolutePrestate: Claim.wrap(0), - disputeMaxGameDepth: 0, - disputeSplitDepth: 0, - disputeClockExtension: Duration.wrap(0), - disputeMaxClockDuration: Duration.wrap(0) - }); - - vm.expectRevert(OPPrestateUpdater.NotImplemented.selector); - prestateUpdater.deploy(input); - } - - function test_upgrade_notImplemented_reverts() public { - opChainConfigs.push( - OPContractsManager.OpChainConfig({ - systemConfigProxy: ISystemConfig(address(0)), - proxyAdmin: IProxyAdmin(address(0)), - absolutePrestate: Claim.wrap(0) - }) - ); - - vm.expectRevert(OPPrestateUpdater.NotImplemented.selector); - prestateUpdater.upgrade(opChainConfigs); - } - - function test_addGameType_notImplemented_reverts() public { - gameInput.push( - OPContractsManager.AddGameInput({ - saltMixer: "hello", - systemConfig: ISystemConfig(address(0)), - proxyAdmin: IProxyAdmin(address(0)), - delayedWETH: IDelayedWETH(payable(address(0))), - disputeGameType: GameType.wrap(2000), - disputeAbsolutePrestate: Claim.wrap(bytes32(hex"deadbeef1234")), - disputeMaxGameDepth: 73, - disputeSplitDepth: 30, - disputeClockExtension: Duration.wrap(10800), - disputeMaxClockDuration: Duration.wrap(302400), - initialBond: 1 ether, - vm: IBigStepper(address(0)), - permissioned: true - }) - ); - - vm.expectRevert(OPPrestateUpdater.NotImplemented.selector); - prestateUpdater.addGameType(gameInput); - } - - function test_l1ContractsRelease_works() public view { - string memory result = "none"; - - assertEq(result, prestateUpdater.l1ContractsRelease()); - } - - function addGameType(IOPContractsManager.AddGameInput memory input) - internal - returns (IOPContractsManager.AddGameOutput memory) - { - IOPContractsManager.AddGameInput[] memory inputs = new IOPContractsManager.AddGameInput[](1); - inputs[0] = input; - - (bool success, bytes memory rawGameOut) = - address(opcm).delegatecall(abi.encodeCall(IOPContractsManager.addGameType, (inputs))); - assertTrue(success, "addGameType failed"); - - IOPContractsManager.AddGameOutput[] memory addGameOutAll = - abi.decode(rawGameOut, (IOPContractsManager.AddGameOutput[])); - return addGameOutAll[0]; - } - - function newGameInputFactory(bool permissioned) internal view returns (IOPContractsManager.AddGameInput memory) { - return IOPContractsManager.AddGameInput({ - saltMixer: "hello", - systemConfig: chainDeployOutput.systemConfigProxy, - proxyAdmin: chainDeployOutput.opChainProxyAdmin, - delayedWETH: IDelayedWETH(payable(address(0))), - disputeGameType: GameType.wrap(2000), - disputeAbsolutePrestate: Claim.wrap(bytes32(hex"deadbeef1234")), - disputeMaxGameDepth: 73, - disputeSplitDepth: 30, - disputeClockExtension: Duration.wrap(10800), - disputeMaxClockDuration: Duration.wrap(302400), - initialBond: 1 ether, - vm: IBigStepper(address(opcm.implementations().mipsImpl)), - permissioned: permissioned - }); - } -} diff --git a/packages/contracts-bedrock/test/universal/Specs.t.sol b/packages/contracts-bedrock/test/universal/Specs.t.sol index 61e1c6a4a0582..63a0b733c0e07 100644 --- a/packages/contracts-bedrock/test/universal/Specs.t.sol +++ b/packages/contracts-bedrock/test/universal/Specs.t.sol @@ -10,7 +10,6 @@ import { ForgeArtifacts, Abi, AbiEntry } from "scripts/libraries/ForgeArtifacts. // Interfaces import { IOPContractsManager } from "interfaces/L1/IOPContractsManager.sol"; -import { IOPPrestateUpdater } from "interfaces/L1/IOPPrestateUpdater.sol"; import { IOptimismPortal2 } from "interfaces/L1/IOptimismPortal2.sol"; import { IOptimismPortalInterop } from "interfaces/L1/IOptimismPortalInterop.sol"; import { ISystemConfig } from "interfaces/L1/ISystemConfig.sol"; @@ -896,49 +895,20 @@ contract Specification_Test is CommonTest { _addSpec({ _name: "OPContractsManager", _sel: _getSel("protocolVersions()") }); _addSpec({ _name: "OPContractsManager", _sel: _getSel("superchainProxyAdmin()") }); _addSpec({ _name: "OPContractsManager", _sel: _getSel("l1ContractsRelease()") }); + _addSpec({ _name: "OPContractsManager", _sel: _getSel("opcmGameTypeAdder()") }); + _addSpec({ _name: "OPContractsManager", _sel: _getSel("opcmDeployer()") }); + _addSpec({ _name: "OPContractsManager", _sel: _getSel("opcmUpgrader()") }); _addSpec({ _name: "OPContractsManager", _sel: IOPContractsManager.deploy.selector }); _addSpec({ _name: "OPContractsManager", _sel: IOPContractsManager.blueprints.selector }); _addSpec({ _name: "OPContractsManager", _sel: IOPContractsManager.chainIdToBatchInboxAddress.selector }); _addSpec({ _name: "OPContractsManager", _sel: IOPContractsManager.implementations.selector }); _addSpec({ _name: "OPContractsManager", _sel: IOPContractsManager.upgrade.selector }); _addSpec({ _name: "OPContractsManager", _sel: IOPContractsManager.addGameType.selector }); + _addSpec({ _name: "OPContractsManager", _sel: IOPContractsManager.updatePrestate.selector }); _addSpec({ _name: "OPContractsManager", _sel: _getSel("isRC()") }); _addSpec({ _name: "OPContractsManager", _sel: _getSel("setRC(bool)") }); _addSpec({ _name: "OPContractsManager", _sel: _getSel("upgradeController()") }); - // OPPrestateUpdate - _addSpec({ _name: "OPPrestateUpdater", _sel: _getSel("version()") }); - _addSpec({ _name: "OPPrestateUpdater", _sel: _getSel("superchainConfig()") }); - _addSpec({ _name: "OPPrestateUpdater", _sel: _getSel("protocolVersions()") }); - _addSpec({ _name: "OPPrestateUpdater", _sel: _getSel("superchainProxyAdmin()") }); - _addSpec({ _name: "OPPrestateUpdater", _sel: _getSel("l1ContractsRelease()") }); - _addSpec({ _name: "OPPrestateUpdater", _sel: IOPContractsManager.deploy.selector }); - _addSpec({ _name: "OPPrestateUpdater", _sel: IOPContractsManager.blueprints.selector }); - _addSpec({ _name: "OPPrestateUpdater", _sel: IOPContractsManager.chainIdToBatchInboxAddress.selector }); - _addSpec({ _name: "OPPrestateUpdater", _sel: IOPContractsManager.implementations.selector }); - _addSpec({ _name: "OPPrestateUpdater", _sel: IOPContractsManager.upgrade.selector }); - _addSpec({ _name: "OPPrestateUpdater", _sel: IOPContractsManager.addGameType.selector }); - _addSpec({ _name: "OPPrestateUpdater", _sel: IOPPrestateUpdater.updatePrestate.selector }); - _addSpec({ _name: "OPPrestateUpdater", _sel: _getSel("isRC()") }); - _addSpec({ _name: "OPPrestateUpdater", _sel: _getSel("setRC(bool)") }); - _addSpec({ _name: "OPPrestateUpdater", _sel: _getSel("upgradeController()") }); - - // OPContractsManagerInterop - _addSpec({ _name: "OPContractsManagerInterop", _sel: _getSel("version()") }); - _addSpec({ _name: "OPContractsManagerInterop", _sel: _getSel("superchainConfig()") }); - _addSpec({ _name: "OPContractsManagerInterop", _sel: _getSel("protocolVersions()") }); - _addSpec({ _name: "OPContractsManagerInterop", _sel: _getSel("superchainProxyAdmin()") }); - _addSpec({ _name: "OPContractsManagerInterop", _sel: _getSel("l1ContractsRelease()") }); - _addSpec({ _name: "OPContractsManagerInterop", _sel: IOPContractsManager.deploy.selector }); - _addSpec({ _name: "OPContractsManagerInterop", _sel: IOPContractsManager.blueprints.selector }); - _addSpec({ _name: "OPContractsManagerInterop", _sel: IOPContractsManager.chainIdToBatchInboxAddress.selector }); - _addSpec({ _name: "OPContractsManagerInterop", _sel: IOPContractsManager.implementations.selector }); - _addSpec({ _name: "OPContractsManagerInterop", _sel: IOPContractsManager.upgrade.selector }); - _addSpec({ _name: "OPContractsManagerInterop", _sel: IOPContractsManager.addGameType.selector }); - _addSpec({ _name: "OPContractsManagerInterop", _sel: _getSel("isRC()") }); - _addSpec({ _name: "OPContractsManagerInterop", _sel: _getSel("setRC(bool)") }); - _addSpec({ _name: "OPContractsManagerInterop", _sel: _getSel("upgradeController()") }); - // DeputyGuardianModule _addSpec({ _name: "DeputyGuardianModule",