diff --git a/packages/contracts-bedrock/interfaces/L1/IOptimismPortalInterop.sol b/packages/contracts-bedrock/interfaces/L1/IOptimismPortalInterop.sol index 11cf741f294..0613f735c32 100644 --- a/packages/contracts-bedrock/interfaces/L1/IOptimismPortalInterop.sol +++ b/packages/contracts-bedrock/interfaces/L1/IOptimismPortalInterop.sol @@ -35,6 +35,7 @@ interface IOptimismPortalInterop { error UnexpectedString(); error Unproven(); error LegacyGame(); + error MessageTargetSharedLockbox(); event DisputeGameBlacklisted(IDisputeGame indexed disputeGame); event Initialized(uint8 version); diff --git a/packages/contracts-bedrock/interfaces/L1/ISystemConfigInterop.sol b/packages/contracts-bedrock/interfaces/L1/ISystemConfigInterop.sol deleted file mode 100644 index fabd7eb212b..00000000000 --- a/packages/contracts-bedrock/interfaces/L1/ISystemConfigInterop.sol +++ /dev/null @@ -1,67 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import { ISystemConfig } from "interfaces/L1/ISystemConfig.sol"; -import { IResourceMetering } from "interfaces/L1/IResourceMetering.sol"; - -interface ISystemConfigInterop { - event ConfigUpdate(uint256 indexed version, ISystemConfig.UpdateType indexed updateType, bytes data); - event Initialized(uint8 version); - event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); - - function BATCH_INBOX_SLOT() external view returns (bytes32); - function DISPUTE_GAME_FACTORY_SLOT() external view returns (bytes32); - function L1_CROSS_DOMAIN_MESSENGER_SLOT() external view returns (bytes32); - function L1_ERC_721_BRIDGE_SLOT() external view returns (bytes32); - function L1_STANDARD_BRIDGE_SLOT() external view returns (bytes32); - function OPTIMISM_MINTABLE_ERC20_FACTORY_SLOT() external view returns (bytes32); - function OPTIMISM_PORTAL_SLOT() external view returns (bytes32); - function START_BLOCK_SLOT() external view returns (bytes32); - function UNSAFE_BLOCK_SIGNER_SLOT() external view returns (bytes32); - function VERSION() external view returns (uint256); - function basefeeScalar() external view returns (uint32); - function batchInbox() external view returns (address addr_); - function batcherHash() external view returns (bytes32); - function blobbasefeeScalar() external view returns (uint32); - function disputeGameFactory() external view returns (address addr_); - function gasLimit() external view returns (uint64); - function eip1559Denominator() external view returns (uint32); - function eip1559Elasticity() external view returns (uint32); - function l1CrossDomainMessenger() external view returns (address addr_); - function l1ERC721Bridge() external view returns (address addr_); - function l1StandardBridge() external view returns (address addr_); - function maximumGasLimit() external pure returns (uint64); - function minimumGasLimit() external view returns (uint64); - function optimismMintableERC20Factory() external view returns (address addr_); - function optimismPortal() external view returns (address addr_); - function overhead() external view returns (uint256); - function owner() external view returns (address); - function renounceOwnership() external; - function resourceConfig() external view returns (IResourceMetering.ResourceConfig memory); - function scalar() external view returns (uint256); - function setBatcherHash(bytes32 _batcherHash) external; - function setGasConfig(uint256 _overhead, uint256 _scalar) external; - function setGasConfigEcotone(uint32 _basefeeScalar, uint32 _blobbasefeeScalar) external; - function setGasLimit(uint64 _gasLimit) external; - function setUnsafeBlockSigner(address _unsafeBlockSigner) external; - function setEIP1559Params(uint32 _denominator, uint32 _elasticity) external; - function startBlock() external view returns (uint256 startBlock_); - function transferOwnership(address newOwner) external; // nosemgrep - function unsafeBlockSigner() external view returns (address addr_); - - function initialize( - address _owner, - uint32 _basefeeScalar, - uint32 _blobbasefeeScalar, - bytes32 _batcherHash, - uint64 _gasLimit, - address _unsafeBlockSigner, - IResourceMetering.ResourceConfig memory _config, - address _batchInbox, - ISystemConfig.Addresses memory _addresses - ) - external; - function version() external pure returns (string memory); - - function __constructor__() external; -} diff --git a/packages/contracts-bedrock/scripts/deploy/ChainAssertions.sol b/packages/contracts-bedrock/scripts/deploy/ChainAssertions.sol index 08660150494..2c2e5dd2aa8 100644 --- a/packages/contracts-bedrock/scripts/deploy/ChainAssertions.sol +++ b/packages/contracts-bedrock/scripts/deploy/ChainAssertions.sol @@ -8,7 +8,6 @@ import { EIP1967Helper } from "test/mocks/EIP1967Helper.sol"; // Scripts import { DeployConfig } from "scripts/deploy/DeployConfig.s.sol"; -import { ISystemConfigInterop } from "interfaces/L1/ISystemConfigInterop.sol"; import { DeployUtils } from "scripts/libraries/DeployUtils.sol"; // Libraries @@ -126,26 +125,6 @@ library ChainAssertions { } } - /// @notice Asserts that the SystemConfigInterop is setup correctly - function checkSystemConfigInterop( - Types.ContractSet memory _contracts, - DeployConfig _cfg, - bool _isProxy - ) - internal - view - { - ISystemConfigInterop config = ISystemConfigInterop(_contracts.SystemConfig); - - console.log( - "Running chain assertions on the SystemConfigInterop %s at %s", - _isProxy ? "proxy" : "implementation", - address(config) - ); - - checkSystemConfig(_contracts, _cfg, _isProxy); - } - /// @notice Asserts that the L1CrossDomainMessenger is setup correctly function checkL1CrossDomainMessenger(Types.ContractSet memory _contracts, Vm _vm, bool _isProxy) internal view { IL1CrossDomainMessenger messenger = IL1CrossDomainMessenger(_contracts.L1CrossDomainMessenger); diff --git a/packages/contracts-bedrock/scripts/deploy/Deploy.s.sol b/packages/contracts-bedrock/scripts/deploy/Deploy.s.sol index d142d434522..5c4d5843806 100644 --- a/packages/contracts-bedrock/scripts/deploy/Deploy.s.sol +++ b/packages/contracts-bedrock/scripts/deploy/Deploy.s.sol @@ -406,11 +406,7 @@ contract Deploy is Deployer { _opcm: OPContractsManager(address(dio.opcm())), _mips: IMIPS(address(dio.mipsSingleton())) }); - if (_isInterop) { - ChainAssertions.checkSystemConfigInterop({ _contracts: contracts, _cfg: cfg, _isProxy: false }); - } else { - ChainAssertions.checkSystemConfig({ _contracts: contracts, _cfg: cfg, _isProxy: false }); - } + ChainAssertions.checkSystemConfig({ _contracts: contracts, _cfg: cfg, _isProxy: false }); } /// @notice Deploy all of the OP Chain specific contracts diff --git a/packages/contracts-bedrock/scripts/deploy/DeployImplementations.s.sol b/packages/contracts-bedrock/scripts/deploy/DeployImplementations.s.sol index a40b6ca52aa..c0c097a4a49 100644 --- a/packages/contracts-bedrock/scripts/deploy/DeployImplementations.s.sol +++ b/packages/contracts-bedrock/scripts/deploy/DeployImplementations.s.sol @@ -22,7 +22,6 @@ import { IL1ERC721Bridge } from "interfaces/L1/IL1ERC721Bridge.sol"; import { IL1StandardBridge } from "interfaces/L1/IL1StandardBridge.sol"; import { IOptimismMintableERC20Factory } from "interfaces/universal/IOptimismMintableERC20Factory.sol"; import { IOptimismPortalInterop } from "interfaces/L1/IOptimismPortalInterop.sol"; -import { ISystemConfigInterop } from "interfaces/L1/ISystemConfigInterop.sol"; import { DeployUtils } from "scripts/libraries/DeployUtils.sol"; import { Solarray } from "scripts/libraries/Solarray.sol"; @@ -749,9 +748,6 @@ contract DeployImplementations is Script { // interop as an example, they've made the following changes to L1 contracts: // - `OptimismPortalInterop is OptimismPortal`: A different portal implementation is used, and // it's ABI is the same. -// - `SystemConfigInterop is SystemConfig`: A different system config implementation is used, and -// it's constructor has a different signature. This signature is different because there is a -// new input parameter, the `superchainConfig`. // - Because of the different system config constructor, there is a new input parameter (superchainConfig). // // Similar to how inheritance was used to develop the new portal and system config contracts, we use @@ -759,7 +755,6 @@ contract DeployImplementations is Script { // means is we need: // - A `DeployImplementationsInterop is DeployImplementations` that: // - Deploys OptimismPortalInterop instead of OptimismPortal. -// - Deploys SystemConfigInterop instead of SystemConfig. // // Most of the complexity in the above flow comes from the the new input for the updated SystemConfig // initializer. If all function signatures were the same, all we'd have to change is the contract @@ -792,17 +787,4 @@ contract DeployImplementationsInterop is DeployImplementations { vm.label(address(impl), "OptimismPortalImpl"); _dio.set(_dio.optimismPortalImpl.selector, address(impl)); } - - function deploySystemConfigImpl(DeployImplementationsOutput _dio) public override { - vm.broadcast(msg.sender); - ISystemConfigInterop impl = ISystemConfigInterop( - DeployUtils.createDeterministic({ - _name: "SystemConfigInterop", - _args: DeployUtils.encodeConstructor(abi.encodeCall(ISystemConfigInterop.__constructor__, ())), - _salt: _salt - }) - ); - vm.label(address(impl), "SystemConfigImpl"); - _dio.set(_dio.systemConfigImpl.selector, address(impl)); - } } diff --git a/packages/contracts-bedrock/scripts/deploy/DeploySuperchain.s.sol b/packages/contracts-bedrock/scripts/deploy/DeploySuperchain.s.sol index 00cb31c249d..18f77c374b3 100644 --- a/packages/contracts-bedrock/scripts/deploy/DeploySuperchain.s.sol +++ b/packages/contracts-bedrock/scripts/deploy/DeploySuperchain.s.sol @@ -616,9 +616,10 @@ contract DeploySuperchainInterop is DeploySuperchain { function deploySharedLockboxImplementation(DeploySuperchainOutput _dso) public virtual { vm.broadcast(msg.sender); ISharedLockbox sharedLockboxImpl = ISharedLockbox( - DeployUtils.create1({ + DeployUtils.createDeterministic({ _name: "SharedLockbox", - _args: DeployUtils.encodeConstructor(abi.encodeCall(ISharedLockbox.__constructor__, ())) + _args: DeployUtils.encodeConstructor(abi.encodeCall(ISharedLockbox.__constructor__, ())), + _salt: _salt }) ); @@ -656,9 +657,10 @@ contract DeploySuperchainInterop is DeploySuperchain { function deploySuperchainConfigImplementation(DeploySuperchainOutput _dso) public override { vm.broadcast(msg.sender); ISuperchainConfigInterop superchainConfigImpl = ISuperchainConfigInterop( - DeployUtils.create1({ + DeployUtils.createDeterministic({ _name: "SuperchainConfigInterop", - _args: DeployUtils.encodeConstructor(abi.encodeCall(ISuperchainConfigInterop.__constructor__, ())) + _args: DeployUtils.encodeConstructor(abi.encodeCall(ISuperchainConfigInterop.__constructor__, ())), + _salt: _salt }) ); diff --git a/packages/contracts-bedrock/scripts/deploy/ManageDependencies.s.sol b/packages/contracts-bedrock/scripts/deploy/ManageDependencies.s.sol index 0ed9991cdd9..a2059f2aec6 100644 --- a/packages/contracts-bedrock/scripts/deploy/ManageDependencies.s.sol +++ b/packages/contracts-bedrock/scripts/deploy/ManageDependencies.s.sol @@ -3,12 +3,13 @@ pragma solidity ^0.8.0; import { Script } from "forge-std/Script.sol"; import { BaseDeployIO } from "scripts/deploy/BaseDeployIO.sol"; -import { ISystemConfigInterop } from "interfaces/L1/ISystemConfigInterop.sol"; +import { ISuperchainConfigInterop } from "interfaces/L1/ISuperchainConfigInterop.sol"; +import { ISystemConfig } from "interfaces/L1/ISystemConfig.sol"; contract ManageDependenciesInput is BaseDeployIO { uint256 internal _chainId; - ISystemConfigInterop _systemConfig; - bool internal _remove; + ISystemConfig _systemConfig; + ISuperchainConfigInterop _superchainConfig; // Setter for uint256 type function set(bytes4 _sel, uint256 _value) public { @@ -20,13 +21,8 @@ contract ManageDependenciesInput is BaseDeployIO { function set(bytes4 _sel, address _addr) public { require(_addr != address(0), "ManageDependenciesInput: cannot set zero address"); - if (_sel == this.systemConfig.selector) _systemConfig = ISystemConfigInterop(_addr); - else revert("ManageDependenciesInput: unknown selector"); - } - - // Setter for bool type - function set(bytes4 _sel, bool _value) public { - if (_sel == this.remove.selector) _remove = _value; + if (_sel == this.superchainConfig.selector) _superchainConfig = ISuperchainConfigInterop(_addr); + else if (_sel == this.systemConfig.selector) _systemConfig = ISystemConfig(_addr); else revert("ManageDependenciesInput: unknown selector"); } @@ -36,29 +32,24 @@ contract ManageDependenciesInput is BaseDeployIO { return _chainId; } - function systemConfig() public view returns (ISystemConfigInterop) { - require(address(_systemConfig) != address(0), "ManageDependenciesInput: not set"); - return _systemConfig; + function superchainConfig() public view returns (ISuperchainConfigInterop) { + require(address(_superchainConfig) != address(0), "ManageDependenciesInput: not set"); + return _superchainConfig; } - function remove() public view returns (bool) { - return _remove; + function systemConfig() public view returns (ISystemConfig) { + require(address(_systemConfig) != address(0), "ManageDependenciesInput: not set"); + return _systemConfig; } } contract ManageDependencies is Script { - // TODO: Fix dependency management since SystemConfig does not handle them anymore function run(ManageDependenciesInput _input) public { - // bool remove = _input.remove(); - // uint256 chainId = _input.chainId(); - // ISystemConfigInterop systemConfig = _input.systemConfig(); + uint256 chainId = _input.chainId(); + ISuperchainConfigInterop superchainConfig = _input.superchainConfig(); + ISystemConfig systemConfig = _input.systemConfig(); - // // Call the appropriate function based on the remove flag - // vm.broadcast(msg.sender); - // if (remove) { - // systemConfig.removeDependency(chainId); - // } else { - // systemConfig.addDependency(chainId); - // } + vm.broadcast(msg.sender); + superchainConfig.addDependency(chainId, address(systemConfig)); } } diff --git a/packages/contracts-bedrock/snapshots/abi/OptimismPortalInterop.json b/packages/contracts-bedrock/snapshots/abi/OptimismPortalInterop.json index 5b62be9819c..943b9a7f0f2 100644 --- a/packages/contracts-bedrock/snapshots/abi/OptimismPortalInterop.json +++ b/packages/contracts-bedrock/snapshots/abi/OptimismPortalInterop.json @@ -886,6 +886,11 @@ "name": "LegacyGame", "type": "error" }, + { + "inputs": [], + "name": "MessageTargetSharedLockbox", + "type": "error" + }, { "inputs": [], "name": "NonReentrant", diff --git a/packages/contracts-bedrock/snapshots/abi/SystemConfigInterop.json b/packages/contracts-bedrock/snapshots/abi/SystemConfigInterop.json deleted file mode 100644 index 7d9b35026fb..00000000000 --- a/packages/contracts-bedrock/snapshots/abi/SystemConfigInterop.json +++ /dev/null @@ -1,737 +0,0 @@ -[ - { - "inputs": [], - "name": "BATCH_INBOX_SLOT", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "DISPUTE_GAME_FACTORY_SLOT", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "L1_CROSS_DOMAIN_MESSENGER_SLOT", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "L1_ERC_721_BRIDGE_SLOT", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "L1_STANDARD_BRIDGE_SLOT", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "OPTIMISM_MINTABLE_ERC20_FACTORY_SLOT", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "OPTIMISM_PORTAL_SLOT", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "START_BLOCK_SLOT", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "UNSAFE_BLOCK_SIGNER_SLOT", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "VERSION", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "basefeeScalar", - "outputs": [ - { - "internalType": "uint32", - "name": "", - "type": "uint32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "batchInbox", - "outputs": [ - { - "internalType": "address", - "name": "addr_", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "batcherHash", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "blobbasefeeScalar", - "outputs": [ - { - "internalType": "uint32", - "name": "", - "type": "uint32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "disputeGameFactory", - "outputs": [ - { - "internalType": "address", - "name": "addr_", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "eip1559Denominator", - "outputs": [ - { - "internalType": "uint32", - "name": "", - "type": "uint32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "eip1559Elasticity", - "outputs": [ - { - "internalType": "uint32", - "name": "", - "type": "uint32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "gasLimit", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_owner", - "type": "address" - }, - { - "internalType": "uint32", - "name": "_basefeeScalar", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "_blobbasefeeScalar", - "type": "uint32" - }, - { - "internalType": "bytes32", - "name": "_batcherHash", - "type": "bytes32" - }, - { - "internalType": "uint64", - "name": "_gasLimit", - "type": "uint64" - }, - { - "internalType": "address", - "name": "_unsafeBlockSigner", - "type": "address" - }, - { - "components": [ - { - "internalType": "uint32", - "name": "maxResourceLimit", - "type": "uint32" - }, - { - "internalType": "uint8", - "name": "elasticityMultiplier", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "baseFeeMaxChangeDenominator", - "type": "uint8" - }, - { - "internalType": "uint32", - "name": "minimumBaseFee", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "systemTxMaxGas", - "type": "uint32" - }, - { - "internalType": "uint128", - "name": "maximumBaseFee", - "type": "uint128" - } - ], - "internalType": "struct IResourceMetering.ResourceConfig", - "name": "_config", - "type": "tuple" - }, - { - "internalType": "address", - "name": "_batchInbox", - "type": "address" - }, - { - "components": [ - { - "internalType": "address", - "name": "l1CrossDomainMessenger", - "type": "address" - }, - { - "internalType": "address", - "name": "l1ERC721Bridge", - "type": "address" - }, - { - "internalType": "address", - "name": "l1StandardBridge", - "type": "address" - }, - { - "internalType": "address", - "name": "disputeGameFactory", - "type": "address" - }, - { - "internalType": "address", - "name": "optimismPortal", - "type": "address" - }, - { - "internalType": "address", - "name": "optimismMintableERC20Factory", - "type": "address" - } - ], - "internalType": "struct SystemConfig.Addresses", - "name": "_addresses", - "type": "tuple" - } - ], - "name": "initialize", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "l1CrossDomainMessenger", - "outputs": [ - { - "internalType": "address", - "name": "addr_", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "l1ERC721Bridge", - "outputs": [ - { - "internalType": "address", - "name": "addr_", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "l1StandardBridge", - "outputs": [ - { - "internalType": "address", - "name": "addr_", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "maximumGasLimit", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [], - "name": "minimumGasLimit", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "optimismMintableERC20Factory", - "outputs": [ - { - "internalType": "address", - "name": "addr_", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "optimismPortal", - "outputs": [ - { - "internalType": "address", - "name": "addr_", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "overhead", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "renounceOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "resourceConfig", - "outputs": [ - { - "components": [ - { - "internalType": "uint32", - "name": "maxResourceLimit", - "type": "uint32" - }, - { - "internalType": "uint8", - "name": "elasticityMultiplier", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "baseFeeMaxChangeDenominator", - "type": "uint8" - }, - { - "internalType": "uint32", - "name": "minimumBaseFee", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "systemTxMaxGas", - "type": "uint32" - }, - { - "internalType": "uint128", - "name": "maximumBaseFee", - "type": "uint128" - } - ], - "internalType": "struct IResourceMetering.ResourceConfig", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "scalar", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_batcherHash", - "type": "bytes32" - } - ], - "name": "setBatcherHash", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "_denominator", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "_elasticity", - "type": "uint32" - } - ], - "name": "setEIP1559Params", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_overhead", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_scalar", - "type": "uint256" - } - ], - "name": "setGasConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "_basefeeScalar", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "_blobbasefeeScalar", - "type": "uint32" - } - ], - "name": "setGasConfigEcotone", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "_gasLimit", - "type": "uint64" - } - ], - "name": "setGasLimit", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_unsafeBlockSigner", - "type": "address" - } - ], - "name": "setUnsafeBlockSigner", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "startBlock", - "outputs": [ - { - "internalType": "uint256", - "name": "startBlock_", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "unsafeBlockSigner", - "outputs": [ - { - "internalType": "address", - "name": "addr_", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "version", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "version", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "enum SystemConfig.UpdateType", - "name": "updateType", - "type": "uint8" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "ConfigUpdate", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint8", - "name": "version", - "type": "uint8" - } - ], - "name": "Initialized", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "previousOwner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - } -] \ 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 e20ea5fba04..e4654e9bdd2 100644 --- a/packages/contracts-bedrock/snapshots/semver-lock.json +++ b/packages/contracts-bedrock/snapshots/semver-lock.json @@ -20,12 +20,12 @@ "sourceCodeHash": "0xdfd5c91e5ddbbf2ad82b867cbf7403437decd6ca70b87891eec935665f17ffd5" }, "src/L1/OptimismPortal2.sol": { - "initCodeHash": "0x55cf30cac62bc5bfd1e1a81d690e8658edd8e926ca1654f98eeb89d19ff9d356", - "sourceCodeHash": "0xe1b371241d6410956fbc6a67ae6ae8e6e356bfad566ae2c62f45106f233df3e9" + "initCodeHash": "0x68ec44f18f5618fbdebe9a20b0cb52eacf3582a19347738b516d87bd97def539", + "sourceCodeHash": "0xe6832f65d9ea151842b7402054aed23f0278bb1674f364bb469fc647c6dcf5c1" }, "src/L1/OptimismPortalInterop.sol": { - "initCodeHash": "0x16cb53e5d98f9706b2e650da4b9172d834c345d4a6a5a53acac4e4d78ea1c8a1", - "sourceCodeHash": "0x02ebeb9e6b706287a96c72d573ecba23b5b37b4176ba34eaac70b9888ca09795" + "initCodeHash": "0x23773a99173c3a79996f7e59e429100c64af5a2b8a0bc121f791cf66b805840c", + "sourceCodeHash": "0xd80beec1d5daa84de5db2ff7ae4aca024c7dc063ec790d55b8cb4c73d3ee7b44" }, "src/L1/ProtocolVersions.sol": { "initCodeHash": "0x0000ec89712d8b4609873f1ba76afffd4205bf9110818995c90134dbec12e91e", @@ -37,7 +37,7 @@ }, "src/L1/SuperchainConfig.sol": { "initCodeHash": "0xf20b1ea7a64a32a8cf0cd69f93d27ffd3154b651a9530d2d4d0e8d55d30b53c9", - "sourceCodeHash": "0xed2c0eca24f007f2be7a06422171425b91f5005fe947ecb3a3330bbac1565182" + "sourceCodeHash": "0xd8fede421c0ef226919e954e3e4b3e1fc3eaae1b23a98407f31abe052f23d979" }, "src/L1/SuperchainConfigInterop.sol": { "initCodeHash": "0x8a51d90aaa078feedb078baae78bb1807bb86742f14108d6d7264c4b8437e3f7", @@ -47,10 +47,6 @@ "initCodeHash": "0xf0bfbb889687af7d4e006f40b269bbd9e4d967cdd9c1f29900017ff11b1f5095", "sourceCodeHash": "0x2dde897735c0cd699f15a1927bf6f75c2da220c1934021ee93315708d5b5f995" }, - "src/L1/SystemConfigInterop.sol": { - "initCodeHash": "0x67538cce23fab621b4e4f18edd182fd7d60937c43629d6b7316723c1b3589496", - "sourceCodeHash": "0x31d126afec007d5add180cb2f38ca223c266a882bc8410486254b85587f187c0" - }, "src/L2/BaseFeeVault.sol": { "initCodeHash": "0xc403d4c555d8e69a2699e01d192ae7327136701fa02da10a6d75a584b3c364c9", "sourceCodeHash": "0xfa56426153227e798150f6becc30a33fd20a3c6e0d73c797a3922dd631acbb57" diff --git a/packages/contracts-bedrock/snapshots/storageLayout/SystemConfigInterop.json b/packages/contracts-bedrock/snapshots/storageLayout/SystemConfigInterop.json deleted file mode 100644 index a6184a1f10d..00000000000 --- a/packages/contracts-bedrock/snapshots/storageLayout/SystemConfigInterop.json +++ /dev/null @@ -1,100 +0,0 @@ -[ - { - "bytes": "1", - "label": "_initialized", - "offset": 0, - "slot": "0", - "type": "uint8" - }, - { - "bytes": "1", - "label": "_initializing", - "offset": 1, - "slot": "0", - "type": "bool" - }, - { - "bytes": "1600", - "label": "__gap", - "offset": 0, - "slot": "1", - "type": "uint256[50]" - }, - { - "bytes": "20", - "label": "_owner", - "offset": 0, - "slot": "51", - "type": "address" - }, - { - "bytes": "1568", - "label": "__gap", - "offset": 0, - "slot": "52", - "type": "uint256[49]" - }, - { - "bytes": "32", - "label": "overhead", - "offset": 0, - "slot": "101", - "type": "uint256" - }, - { - "bytes": "32", - "label": "scalar", - "offset": 0, - "slot": "102", - "type": "uint256" - }, - { - "bytes": "32", - "label": "batcherHash", - "offset": 0, - "slot": "103", - "type": "bytes32" - }, - { - "bytes": "8", - "label": "gasLimit", - "offset": 0, - "slot": "104", - "type": "uint64" - }, - { - "bytes": "4", - "label": "basefeeScalar", - "offset": 8, - "slot": "104", - "type": "uint32" - }, - { - "bytes": "4", - "label": "blobbasefeeScalar", - "offset": 12, - "slot": "104", - "type": "uint32" - }, - { - "bytes": "32", - "label": "_resourceConfig", - "offset": 0, - "slot": "105", - "type": "struct IResourceMetering.ResourceConfig" - }, - { - "bytes": "4", - "label": "eip1559Denominator", - "offset": 0, - "slot": "106", - "type": "uint32" - }, - { - "bytes": "4", - "label": "eip1559Elasticity", - "offset": 4, - "slot": "106", - "type": "uint32" - } -] \ No newline at end of file diff --git a/packages/contracts-bedrock/src/L1/OptimismPortal2.sol b/packages/contracts-bedrock/src/L1/OptimismPortal2.sol index e7a96b04505..e375606c1e4 100644 --- a/packages/contracts-bedrock/src/L1/OptimismPortal2.sol +++ b/packages/contracts-bedrock/src/L1/OptimismPortal2.sol @@ -171,8 +171,9 @@ contract OptimismPortal2 is Initializable, ResourceMetering, ISemver { event RespectedGameTypeSet(GameType indexed newGameType, Timestamp indexed updatedAt); /// @notice Reverts when paused. - function _whenNotPaused() internal view { + modifier whenNotPaused() { if (paused()) revert CallPaused(); + _; } /// @notice Semantic version. @@ -292,9 +293,8 @@ contract OptimismPortal2 is Initializable, ResourceMetering, ISemver { bytes[] calldata _withdrawalProof ) external + whenNotPaused { - _whenNotPaused(); - // Prevent users from creating a deposit transaction where this address is the message // sender on L2. Because this is checked here, we do not need to check again in // `finalizeWithdrawalTransaction`. @@ -375,8 +375,7 @@ contract OptimismPortal2 is Initializable, ResourceMetering, ISemver { /// @notice Finalizes a withdrawal transaction. /// @param _tx Withdrawal transaction to finalize. - function finalizeWithdrawalTransaction(Types.WithdrawalTransaction memory _tx) external { - _whenNotPaused(); + function finalizeWithdrawalTransaction(Types.WithdrawalTransaction memory _tx) external whenNotPaused { finalizeWithdrawalTransactionExternalProof(_tx, msg.sender); } @@ -388,9 +387,8 @@ contract OptimismPortal2 is Initializable, ResourceMetering, ISemver { address _proofSubmitter ) public + whenNotPaused { - _whenNotPaused(); - // Make sure that the l2Sender has not yet been set. The l2Sender is set to a value other // than the default value when a withdrawal transaction is being finalized. This check is // a defacto reentrancy guard. @@ -410,7 +408,7 @@ contract OptimismPortal2 is Initializable, ResourceMetering, ISemver { // This function unlocks ETH from the SharedLockbox when using the OptimismPortalInterop contract. // If the interop version is not used, this function is a no-ops. - if (_tx.value != 0) _unlockETH(_tx.value); + _unlockETH(_tx); // Trigger the call to the target contract. We use a custom low level method // SafeCall.callWithMinGas to ensure two key properties @@ -598,6 +596,6 @@ contract OptimismPortal2 is Initializable, ResourceMetering, ISemver { function _lockETH() internal virtual { } /// @notice No-op function to be used to unlock ETH from the SharedLockbox in the interop contract. - /// @param _value Amount of ETH to unlock - function _unlockETH(uint256 _value) internal virtual { } + /// @param _tx Withdrawal transaction to finalize. + function _unlockETH(Types.WithdrawalTransaction memory _tx) internal virtual { } } diff --git a/packages/contracts-bedrock/src/L1/OptimismPortalInterop.sol b/packages/contracts-bedrock/src/L1/OptimismPortalInterop.sol index fcb2dc9535d..336c885c08a 100644 --- a/packages/contracts-bedrock/src/L1/OptimismPortalInterop.sol +++ b/packages/contracts-bedrock/src/L1/OptimismPortalInterop.sol @@ -8,6 +8,7 @@ import { OptimismPortal2 } from "src/L1/OptimismPortal2.sol"; import { Predeploys } from "src/libraries/Predeploys.sol"; import { Constants } from "src/libraries/Constants.sol"; import { Unauthorized } from "src/libraries/PortalErrors.sol"; +import { Types } from "src/libraries/Types.sol"; // Interfaces import { IL1BlockInterop, ConfigType } from "interfaces/L2/IL1BlockInterop.sol"; @@ -27,6 +28,9 @@ contract OptimismPortalInterop is OptimismPortal2 { /// @param amount Amount of ETH migrated. event ETHMigrated(uint256 amount); + /// @notice Error thrown when the withdrawal target is the SharedLockbox. + error MessageTargetSharedLockbox(); + /// @notice Storage slot that the OptimismPortalStorage struct is stored at. /// keccak256(abi.encode(uint256(keccak256("optimismPortal.storage")) - 1)) & ~bytes32(uint256(0xff)); bytes32 internal constant OPTIMISM_PORTAL_STORAGE_SLOT = @@ -94,14 +98,23 @@ contract OptimismPortalInterop is OptimismPortal2 { return _storage().migrated; } - /// @notice Unlock and receive the ETH from the shared lockbox. - /// @param _value Amount of ETH to unlock. - function _unlockETH(uint256 _value) internal virtual override { + /// @notice Unlock and receive the ETH from the SharedLockbox. + /// @param _tx Withdrawal transaction to finalize. + function _unlockETH(Types.WithdrawalTransaction memory _tx) internal virtual override { + // We don't allow the SharedLockbox to be the target of a withdrawal. + // This is to prevent the SharedLockbox from being drained. + // This check needs to be done for every withdrawal. + if (_tx.target == address(sharedLockbox())) revert MessageTargetSharedLockbox(); + OptimismPortalStorage storage s = _storage(); - if (s.migrated) sharedLockbox().unlockETH(_value); + + if (!s.migrated) return; + if (_tx.value == 0) return; + + sharedLockbox().unlockETH(_tx.value); } - /// @notice Locks the ETH in the shared lockbox. + /// @notice Locks the ETH in the SharedLockbox. function _lockETH() internal virtual override { OptimismPortalStorage storage s = _storage(); if (s.migrated) sharedLockbox().lockETH{ value: msg.value }(); diff --git a/packages/contracts-bedrock/src/L1/SuperchainConfig.sol b/packages/contracts-bedrock/src/L1/SuperchainConfig.sol index 526eed8d8d7..17fefa54d5c 100644 --- a/packages/contracts-bedrock/src/L1/SuperchainConfig.sol +++ b/packages/contracts-bedrock/src/L1/SuperchainConfig.sol @@ -54,12 +54,15 @@ contract SuperchainConfig is Initializable, ISemver { } /// @notice Initializer. - /// @param _guardian Address of the guardian, can pause the OptimismPortal. - /// @param _paused Initial paused status. + /// @param _guardian Address of the guardian, can pause the OptimismPortal. + /// @param _paused Initial paused status. function initialize(address _guardian, bool _paused) external initializer { _initialize(_guardian, _paused); } + /// @notice Internal initializer. + /// @param _guardian Address of the guardian, can pause the OptimismPortal. + /// @param _paused Initial paused status. function _initialize(address _guardian, bool _paused) internal { _setGuardian(_guardian); if (_paused) { diff --git a/packages/contracts-bedrock/src/L1/SystemConfigInterop.sol b/packages/contracts-bedrock/src/L1/SystemConfigInterop.sol deleted file mode 100644 index 4eca5346a67..00000000000 --- a/packages/contracts-bedrock/src/L1/SystemConfigInterop.sol +++ /dev/null @@ -1,17 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.15; - -// Contracts -import { SystemConfig } from "src/L1/SystemConfig.sol"; - -/// @custom:proxied true -/// @title SystemConfigInterop -/// @notice The SystemConfig contract is used to manage configuration of an Optimism network. -/// All configuration is stored on L1 and picked up by L2 as part of the derviation of -/// the L2 chain. -contract SystemConfigInterop is SystemConfig { - /// @custom:semver +interop-beta.11 - function version() public pure override returns (string memory) { - return string.concat(super.version(), "+interop-beta.11"); - } -} diff --git a/packages/contracts-bedrock/test/L1/OptimismPortalInterop.t.sol b/packages/contracts-bedrock/test/L1/OptimismPortalInterop.t.sol index b85d383a558..42c18ce1b99 100644 --- a/packages/contracts-bedrock/test/L1/OptimismPortalInterop.t.sol +++ b/packages/contracts-bedrock/test/L1/OptimismPortalInterop.t.sol @@ -7,7 +7,6 @@ import { VmSafe } from "forge-std/Vm.sol"; // Libraries import { Constants } from "src/libraries/Constants.sol"; -import { Predeploys } from "src/libraries/Predeploys.sol"; import "src/libraries/PortalErrors.sol"; import { AddressAliasHelper } from "src/vendor/AddressAliasHelper.sol"; import { Types } from "src/libraries/Types.sol"; @@ -16,7 +15,7 @@ import { Hashing } from "src/libraries/Hashing.sol"; // Interfaces import { IResourceMetering } from "interfaces/L1/IResourceMetering.sol"; import { ISuperchainConfigInterop } from "interfaces/L1/ISuperchainConfigInterop.sol"; -import { IL1BlockInterop, ConfigType } from "interfaces/L2/IL1BlockInterop.sol"; +import { ConfigType } from "interfaces/L2/IL1BlockInterop.sol"; import { IOptimismPortalInterop } from "interfaces/L1/IOptimismPortalInterop.sol"; import { IFaultDisputeGame } from "interfaces/dispute/IFaultDisputeGame.sol"; import { IDisputeGame } from "interfaces/dispute/IDisputeGame.sol"; @@ -43,23 +42,6 @@ contract OptimismPortalInterop_Base_Test is CommonTest { } contract OptimismPortalInterop_Config_Test is OptimismPortalInterop_Base_Test { - /// @dev Tests that the config for the gas paying token can be set. - function testFuzz_setConfig_gasPayingToken_succeeds(bytes calldata _value) public { - vm.expectEmit(address(_optimismPortal())); - emitTransactionDeposited({ - _from: Constants.DEPOSITOR_ACCOUNT, - _to: Predeploys.L1_BLOCK_ATTRIBUTES, - _value: 0, - _mint: 0, - _gasLimit: 200_000, - _isCreation: false, - _data: abi.encodeCall(IL1BlockInterop.setConfig, (ConfigType.SET_GAS_PAYING_TOKEN, _value)) - }); - - vm.prank(address(_optimismPortal().systemConfig())); - _optimismPortal().setConfig(ConfigType.SET_GAS_PAYING_TOKEN, _value); - } - /// @notice Tests that the version function returns a valid string. We avoid testing the /// specific value of the string as it changes frequently. function test_version_succeeds() external view { @@ -393,18 +375,23 @@ contract OptimismPortalInterop_FinalizeWithdrawal_Test is OptimismPortalInterop_ /// @dev Setup the system for a ready-to-use state. function setUp() public virtual override { + // Warp forward in time to ensure that the game is created after the retirement timestamp. + vm.warp(_optimismPortal().respectedGameTypeUpdatedAt() + 1 seconds); + + // Set up the dummy game. _proposedBlockNumber = 0xFF; GameType respectedGameType = _optimismPortal().respectedGameType(); - uint256 bondAmount = disputeGameFactory.initBonds(respectedGameType); game = IFaultDisputeGame( payable( address( - disputeGameFactory.create{ value: bondAmount }( - _optimismPortal().respectedGameType(), Claim.wrap(_outputRoot), abi.encode(_proposedBlockNumber) + disputeGameFactory.create{ value: disputeGameFactory.initBonds(respectedGameType) }( + respectedGameType, Claim.wrap(_outputRoot), abi.encode(_proposedBlockNumber) ) ) ) ); + + // Grab the index of the game we just created. _proposedGameIndex = disputeGameFactory.gameCount() - 1; // Warp beyond the chess clocks and finalize the game. @@ -424,10 +411,68 @@ contract OptimismPortalInterop_FinalizeWithdrawal_Test is OptimismPortalInterop_ assertFalse(_optimismPortal().finalizedWithdrawals(Hashing.hashWithdrawal(_defaultTx))); } + /// @dev Tests that `blacklistDisputeGame` reverts when called by a non-guardian. + function testFuzz_blacklist_onlyGuardian_reverts(address _act) external { + vm.assume(_act != address(_optimismPortal().guardian())); + + vm.expectRevert(Unauthorized.selector); + _optimismPortal().blacklistDisputeGame(IDisputeGame(address(0xdead))); + } + + /// @dev Tests that the guardian role can blacklist any dispute game. + function testFuzz_blacklist_guardian_succeeds(IDisputeGame _addr) external { + vm.expectEmit(address(_optimismPortal())); + emit DisputeGameBlacklisted(_addr); + + vm.prank(_optimismPortal().guardian()); + _optimismPortal().blacklistDisputeGame(_addr); + + assertTrue(_optimismPortal().disputeGameBlacklist(_addr)); + } + + /// @dev Tests that `setRespectedGameType` reverts when called by a non-guardian. + function testFuzz_setRespectedGameType_onlyGuardian_reverts(address _act, GameType _ty) external { + vm.assume(_act != address(_optimismPortal().guardian())); + + vm.prank(_act); + vm.expectRevert(Unauthorized.selector); + _optimismPortal().setRespectedGameType(_ty); + } + + /// @dev Tests that the guardian role can set the respected game type to anything they want. + function testFuzz_setRespectedGameType_guardianCanSetRespectedGameType_succeeds(GameType _ty) external { + vm.assume(_ty.raw() != type(uint32).max); + uint64 respectedGameTypeUpdatedAt = _optimismPortal().respectedGameTypeUpdatedAt(); + vm.expectEmit(address(_optimismPortal())); + emit RespectedGameTypeSet(_ty, Timestamp.wrap(respectedGameTypeUpdatedAt)); + vm.prank(_optimismPortal().guardian()); + _optimismPortal().setRespectedGameType(_ty); + // GameType changes, but the timestamp doesn't. + assertEq(_optimismPortal().respectedGameType().raw(), _ty.raw()); + assertEq(_optimismPortal().respectedGameTypeUpdatedAt(), respectedGameTypeUpdatedAt); + } + + /// @dev Tests that the guardian can set the `respectedGameTypeUpdatedAt` timestamp to current timestamp. + function testFuzz_setRespectedGameType_guardianCanSetRespectedGameTypeUpdatedAt_succeeds(uint64 _elapsed) + external + { + _elapsed = uint64(bound(_elapsed, 0, type(uint64).max - uint64(block.timestamp))); + GameType _ty = GameType.wrap(type(uint32).max); + uint64 _newRespectedGameTypeUpdatedAt = uint64(block.timestamp) + _elapsed; + GameType _existingGameType = _optimismPortal().respectedGameType(); + vm.warp(_newRespectedGameTypeUpdatedAt); + emit RespectedGameTypeSet(_existingGameType, Timestamp.wrap(_newRespectedGameTypeUpdatedAt)); + vm.prank(_optimismPortal().guardian()); + _optimismPortal().setRespectedGameType(_ty); + // GameType doesn't change, but the timestamp does. + assertEq(_optimismPortal().respectedGameType().raw(), _existingGameType.raw()); + assertEq(_optimismPortal().respectedGameTypeUpdatedAt(), _newRespectedGameTypeUpdatedAt); + } + /// @dev Tests that `proveWithdrawalTransaction` reverts when paused. function test_proveWithdrawalTransaction_paused_reverts() external { vm.prank(_optimismPortal().guardian()); - _superchainConfig().pause("identifier"); + superchainConfig.pause("identifier"); vm.expectRevert(CallPaused.selector); _optimismPortal().proveWithdrawalTransaction({ @@ -525,6 +570,60 @@ contract OptimismPortalInterop_FinalizeWithdrawal_Test is OptimismPortalInterop_ }); } + /// @dev Tests that `proveWithdrawalTransaction` reverts if the game was not the respected game type when created. + function test_proveWithdrawalTransaction_wasNotRespectedGameTypeWhenCreated_reverts() external { + vm.mockCall(address(game), abi.encodeCall(game.wasRespectedGameTypeWhenCreated, ()), abi.encode(false)); + vm.expectRevert(InvalidGameType.selector); + _optimismPortal().proveWithdrawalTransaction({ + _tx: _defaultTx, + _disputeGameIndex: _proposedGameIndex, + _outputRootProof: _outputRootProof, + _withdrawalProof: _withdrawalProof + }); + } + + /// @dev Tests that `proveWithdrawalTransaction` reverts if the game is a legacy game that does not implement + /// `wasRespectedGameTypeWhenCreated`. + function test_proveWithdrawalTransaction_legacyGame_reverts() external { + vm.mockCallRevert(address(game), abi.encodeCall(game.wasRespectedGameTypeWhenCreated, ()), ""); + vm.expectRevert(LegacyGame.selector); + _optimismPortal().proveWithdrawalTransaction({ + _tx: _defaultTx, + _disputeGameIndex: _proposedGameIndex, + _outputRootProof: _outputRootProof, + _withdrawalProof: _withdrawalProof + }); + } + + /// @dev Tests that `proveWithdrawalTransaction` succeeds if the game was created after the + /// game retirement timestamp. + function testFuzz_proveWithdrawalTransaction_createdAfterRetirementTimestamp_succeeds(uint64 _createdAt) external { + _createdAt = uint64(bound(_createdAt, _optimismPortal().respectedGameTypeUpdatedAt() + 1, type(uint64).max)); + vm.mockCall(address(game), abi.encodeCall(game.createdAt, ()), abi.encode(uint64(_createdAt))); + _optimismPortal().proveWithdrawalTransaction({ + _tx: _defaultTx, + _disputeGameIndex: _proposedGameIndex, + _outputRootProof: _outputRootProof, + _withdrawalProof: _withdrawalProof + }); + } + + /// @dev Tests that `proveWithdrawalTransaction` reverts if the game was created before or at + /// the game retirement timestamp. + function testFuzz_proveWithdrawalTransaction_createdBeforeOrAtRetirementTimestamp_reverts(uint64 _createdAt) + external + { + _createdAt = uint64(bound(_createdAt, 0, _optimismPortal().respectedGameTypeUpdatedAt())); + vm.mockCall(address(game), abi.encodeCall(game.createdAt, ()), abi.encode(uint64(_createdAt))); + vm.expectRevert("OptimismPortal: dispute game created before respected game type was updated"); + _optimismPortal().proveWithdrawalTransaction({ + _tx: _defaultTx, + _disputeGameIndex: _proposedGameIndex, + _outputRootProof: _outputRootProof, + _withdrawalProof: _withdrawalProof + }); + } + /// @dev Tests that `proveWithdrawalTransaction` can be re-executed if the dispute game proven against has been /// blacklisted. function test_proveWithdrawalTransaction_replayProveBlacklisted_succeeds() external { @@ -612,13 +711,15 @@ contract OptimismPortalInterop_FinalizeWithdrawal_Test is OptimismPortalInterop_ _withdrawalProof: _withdrawalProof }); + // Create a new game. + IDisputeGame newGame = + disputeGameFactory.create(GameType.wrap(0), Claim.wrap(_outputRoot), abi.encode(_proposedBlockNumber + 1)); + // Update the respected game type to 0xbeef. vm.prank(_optimismPortal().guardian()); _optimismPortal().setRespectedGameType(GameType.wrap(0xbeef)); // Create a new game and mock the game type as 0xbeef in the factory. - IDisputeGame newGame = - disputeGameFactory.create(GameType.wrap(0), Claim.wrap(_outputRoot), abi.encode(_proposedBlockNumber + 1)); vm.mockCall( address(disputeGameFactory), abi.encodeCall(disputeGameFactory.gameAtIndex, (_proposedGameIndex + 1)), @@ -757,10 +858,9 @@ contract OptimismPortalInterop_FinalizeWithdrawal_Test is OptimismPortalInterop_ uint256 _proposedGameIndex_noData = disputeGameFactory.gameCount() - 1; // Warp beyond the chess clocks and finalize the game. vm.warp(block.timestamp + game_noData.maxClockDuration().raw() + 1 seconds); - - // Fund the SharedLockbox so that we can withdraw ETH. - vm.deal(address(sharedLockbox), _defaultTx_noData.value); - vm.expectCall(address(sharedLockbox), abi.encodeCall(sharedLockbox.unlockETH, (_defaultTx_noData.value))); + // Fund the portal so that we can withdraw ETH. + vm.store(address(sharedLockbox), bytes32(uint256(61)), bytes32(uint256(0xFFFFFFFF))); + vm.deal(address(sharedLockbox), 0xFFFFFFFF); uint256 bobBalanceBefore = bob.balance; @@ -791,10 +891,6 @@ contract OptimismPortalInterop_FinalizeWithdrawal_Test is OptimismPortalInterop_ function test_finalizeWithdrawalTransaction_provenWithdrawalHashEther_succeeds() external { uint256 bobBalanceBefore = address(bob).balance; - // Fund the SharedLockbox so that we can withdraw ETH. - vm.deal(address(sharedLockbox), _defaultTx.value); - vm.expectCall(address(sharedLockbox), abi.encodeCall(sharedLockbox.unlockETH, (_defaultTx.value))); - vm.expectEmit(address(_optimismPortal())); emit WithdrawalProven(_withdrawalHash, alice, bob); vm.expectEmit(address(_optimismPortal())); @@ -831,10 +927,6 @@ contract OptimismPortalInterop_FinalizeWithdrawal_Test is OptimismPortalInterop_ // Warp 1 second into the future so that the proof is submitted after the timestamp of game creation. vm.warp(block.timestamp + 1 seconds); - // Fund the SharedLockbox so that we can withdraw ETH. - vm.deal(address(sharedLockbox), _defaultTx.value); - vm.expectCall(address(sharedLockbox), abi.encodeCall(sharedLockbox.unlockETH, (_defaultTx.value))); - // Prove the withdrawal transaction against the invalid dispute game, as 0xb0b. vm.expectEmit(true, true, true, true); emit WithdrawalProven(_withdrawalHash, alice, bob); @@ -886,7 +978,7 @@ contract OptimismPortalInterop_FinalizeWithdrawal_Test is OptimismPortalInterop_ /// @dev Tests that `finalizeWithdrawalTransaction` reverts if the contract is paused. function test_finalizeWithdrawalTransaction_paused_reverts() external { vm.prank(_optimismPortal().guardian()); - _superchainConfig().pause("identifier"); + superchainConfig.pause("identifier"); vm.expectRevert(CallPaused.selector); _optimismPortal().finalizeWithdrawalTransaction(_defaultTx); @@ -988,10 +1080,6 @@ contract OptimismPortalInterop_FinalizeWithdrawal_Test is OptimismPortalInterop_ uint256 bobBalanceBefore = address(bob).balance; vm.etch(bob, hex"fe"); // Contract with just the invalid opcode. - // Fund the SharedLockbox so that we can withdraw ETH. - vm.deal(address(sharedLockbox), _defaultTx.value); - vm.expectCall(address(sharedLockbox), abi.encodeCall(sharedLockbox.unlockETH, (_defaultTx.value))); - vm.expectEmit(true, true, true, true); emit WithdrawalProven(_withdrawalHash, alice, bob); vm.expectEmit(true, true, true, true); @@ -1018,10 +1106,6 @@ contract OptimismPortalInterop_FinalizeWithdrawal_Test is OptimismPortalInterop_ /// @dev Tests that `finalizeWithdrawalTransaction` reverts if the withdrawal has already been /// finalized. function test_finalizeWithdrawalTransaction_onReplay_reverts() external { - // Fund the SharedLockbox so that we can withdraw ETH. - vm.deal(address(sharedLockbox), _defaultTx.value); - vm.expectCall(address(sharedLockbox), abi.encodeCall(sharedLockbox.unlockETH, (_defaultTx.value))); - vm.expectEmit(true, true, true, true); emit WithdrawalProven(_withdrawalHash, alice, bob); vm.expectEmit(true, true, true, true); @@ -1119,10 +1203,6 @@ contract OptimismPortalInterop_FinalizeWithdrawal_Test is OptimismPortalInterop_ // Return a mock output root from the game. vm.mockCall(address(game), abi.encodeCall(game.rootClaim, ()), abi.encode(outputRoot)); - // Fund the SharedLockbox so that we can withdraw ETH. - vm.deal(address(sharedLockbox), _testTx.value); - vm.expectCall(address(sharedLockbox), abi.encodeCall(sharedLockbox.unlockETH, (_testTx.value))); - vm.expectEmit(true, true, true, true); emit WithdrawalProven(withdrawalHash, alice, address(this)); vm.expectEmit(true, true, true, true); @@ -1162,8 +1242,84 @@ contract OptimismPortalInterop_FinalizeWithdrawal_Test is OptimismPortalInterop_ // Total ETH supply is currently about 120M ETH. uint256 value = bound(_value, 0, 200_000_000 ether); + vm.deal(address(sharedLockbox), value); + + uint256 gasLimit = bound(_gasLimit, 0, 50_000_000); + uint256 nonce = l2ToL1MessagePasser.messageNonce(); + + // Get a withdrawal transaction and mock proof from the differential testing script. + Types.WithdrawalTransaction memory _tx = Types.WithdrawalTransaction({ + nonce: nonce, + sender: _sender, + target: _target, + value: value, + gasLimit: gasLimit, + data: _data + }); + ( + bytes32 stateRoot, + bytes32 storageRoot, + bytes32 outputRoot, + bytes32 withdrawalHash, + bytes[] memory withdrawalProof + ) = ffi.getProveWithdrawalTransactionInputs(_tx); + + // Create the output root proof + Types.OutputRootProof memory proof = Types.OutputRootProof({ + version: bytes32(uint256(0)), + stateRoot: stateRoot, + messagePasserStorageRoot: storageRoot, + latestBlockhash: bytes32(uint256(0)) + }); - // Add ETH to the SharedLockbox for the portal to withdraw. + // Ensure the values returned from ffi are correct + assertEq(outputRoot, Hashing.hashOutputRootProof(proof)); + assertEq(withdrawalHash, Hashing.hashWithdrawal(_tx)); + + // Setup the dispute game to return the output root + vm.mockCall(address(game), abi.encodeCall(game.rootClaim, ()), abi.encode(outputRoot)); + + // Prove the withdrawal transaction + _optimismPortal().proveWithdrawalTransaction(_tx, _proposedGameIndex, proof, withdrawalProof); + (IDisputeGame _game,) = _optimismPortal().provenWithdrawals(withdrawalHash, address(this)); + assertTrue(_game.rootClaim().raw() != bytes32(0)); + + // Resolve the dispute game + game.resolveClaim(0, 0); + game.resolve(); + + // Warp past the finalization period + vm.warp(block.timestamp + _optimismPortal().proofMaturityDelaySeconds() + 1); + + // Finalize the withdrawal transaction + vm.expectCallMinGas(_tx.target, _tx.value, uint64(_tx.gasLimit), _tx.data); + _optimismPortal().finalizeWithdrawalTransaction(_tx); + assertTrue(_optimismPortal().finalizedWithdrawals(withdrawalHash)); + } + + /// @dev Tests that `finalizeWithdrawalTransaction` succeeds even if the respected game type is changed. + function test_finalizeWithdrawalTransaction_wasRespectedGameType_succeeds( + address _sender, + address _target, + uint256 _value, + uint256 _gasLimit, + bytes memory _data, + GameType _newGameType + ) + external + { + vm.assume( + _target != address(_optimismPortal()) // Cannot call the optimism portal or a contract + && _target.code.length == 0 // No accounts with code + && _target != CONSOLE // The console has no code but behaves like a contract + && uint160(_target) > 9 // No precompiles (or zero address) + ); + + // Bound to prevent changes in respectedGameTypeUpdatedAt + _newGameType = GameType.wrap(uint32(bound(_newGameType.raw(), 0, type(uint32).max - 1))); + + // Total ETH supply is currently about 120M ETH. + uint256 value = bound(_value, 0, 200_000_000 ether); vm.deal(address(sharedLockbox), value); uint256 gasLimit = bound(_gasLimit, 0, 50_000_000); @@ -1213,10 +1369,11 @@ contract OptimismPortalInterop_FinalizeWithdrawal_Test is OptimismPortalInterop_ // Warp past the finalization period vm.warp(block.timestamp + _optimismPortal().proofMaturityDelaySeconds() + 1); - // Expect call to the SharedLockbox to unlock the funds - if (value > 0) vm.expectCall(address(sharedLockbox), abi.encodeCall(sharedLockbox.unlockETH, (value))); + // Change the respectedGameType + vm.prank(_optimismPortal().guardian()); + _optimismPortal().setRespectedGameType(_newGameType); - // Finalize the withdrawal transaction + // Withdrawal transaction still finalizable vm.expectCallMinGas(_tx.target, _tx.value, uint64(_tx.gasLimit), _tx.data); _optimismPortal().finalizeWithdrawalTransaction(_tx); assertTrue(_optimismPortal().finalizedWithdrawals(withdrawalHash)); @@ -1279,12 +1436,12 @@ contract OptimismPortalInterop_FinalizeWithdrawal_Test is OptimismPortalInterop_ assertTrue(_optimismPortal().finalizedWithdrawals(_withdrawalHash)); } - /// @dev Tests that `finalizeWithdrawalTransaction` reverts if the respected game type has changed since the - /// withdrawal was proven. - function test_finalizeWithdrawalTransaction_respectedTypeChangedSinceProving_reverts() external { - vm.expectEmit(true, true, true, true); + /// @dev Tests that `finalizeWithdrawalTransaction` reverts if the respected game type was updated after the + /// dispute game was created. + function test_finalizeWithdrawalTransaction_gameOlderThanRespectedGameTypeUpdate_reverts() external { + vm.expectEmit(address(_optimismPortal())); emit WithdrawalProven(_withdrawalHash, alice, bob); - vm.expectEmit(true, true, true, true); + vm.expectEmit(address(_optimismPortal())); emit WithdrawalProvenExtension1(_withdrawalHash, address(this)); _optimismPortal().proveWithdrawalTransaction({ _tx: _defaultTx, @@ -1300,17 +1457,51 @@ contract OptimismPortalInterop_FinalizeWithdrawal_Test is OptimismPortalInterop_ game.resolveClaim(0, 0); game.resolve(); - // Change the respected game type in the portal. + // Warp past the dispute game finality delay. + vm.warp(block.timestamp + _optimismPortal().disputeGameFinalityDelaySeconds() + 1); + + // Set respectedGameTypeUpdatedAt. vm.prank(_optimismPortal().guardian()); - _optimismPortal().setRespectedGameType(GameType.wrap(0xFF)); + _optimismPortal().setRespectedGameType(GameType.wrap(type(uint32).max)); + + vm.expectRevert("OptimismPortal: dispute game created before respected game type was updated"); + _optimismPortal().finalizeWithdrawalTransaction(_defaultTx); + } + + /// @dev Tests that `finalizeWithdrawalTransaction` reverts if the game was not the respected game type when it was + /// created. `proveWithdrawalTransaction` should already prevent this, but we remove that assumption here. + function test_finalizeWithdrawalTransaction_gameWasNotRespectedGameType_reverts() external { + vm.expectEmit(address(_optimismPortal())); + emit WithdrawalProven(_withdrawalHash, alice, bob); + vm.expectEmit(address(_optimismPortal())); + emit WithdrawalProvenExtension1(_withdrawalHash, address(this)); + _optimismPortal().proveWithdrawalTransaction({ + _tx: _defaultTx, + _disputeGameIndex: _proposedGameIndex, + _outputRootProof: _outputRootProof, + _withdrawalProof: _withdrawalProof + }); + + // Warp past the finalization period. + vm.warp(block.timestamp + _optimismPortal().proofMaturityDelaySeconds() + 1); + + // Resolve the dispute game. + game.resolveClaim(0, 0); + game.resolve(); + + // Warp past the dispute game finality delay. + vm.warp(block.timestamp + _optimismPortal().disputeGameFinalityDelaySeconds() + 1); + + vm.mockCall(address(game), abi.encodeCall(game.wasRespectedGameTypeWhenCreated, ()), abi.encode(false)); vm.expectRevert(InvalidGameType.selector); _optimismPortal().finalizeWithdrawalTransaction(_defaultTx); } - /// @dev Tests that `finalizeWithdrawalTransaction` reverts if the respected game type was updated after the - /// dispute game was created. - function test_finalizeWithdrawalTransaction_gameOlderThanRespectedGameTypeUpdate_reverts() external { + /// @dev Tests that `finalizeWithdrawalTransaction` reverts if the game is a legacy game that does not implement + /// `wasRespectedGameTypeWhenCreated`. `proveWithdrawalTransaction` should already prevent this, but we remove + /// that assumption here. + function test_finalizeWithdrawalTransaction_legacyGame_reverts() external { vm.expectEmit(address(_optimismPortal())); emit WithdrawalProven(_withdrawalHash, alice, bob); vm.expectEmit(address(_optimismPortal())); @@ -1329,14 +1520,12 @@ contract OptimismPortalInterop_FinalizeWithdrawal_Test is OptimismPortalInterop_ game.resolveClaim(0, 0); game.resolve(); - // Change the respected game type in the portal. - vm.prank(_optimismPortal().guardian()); - _optimismPortal().setRespectedGameType(GameType.wrap(0xFF)); + // Warp past the dispute game finality delay. + vm.warp(block.timestamp + _optimismPortal().disputeGameFinalityDelaySeconds() + 1); - // Mock the game's type so that we pass the correct game type check. - vm.mockCall(address(game), abi.encodeCall(game.gameType, ()), abi.encode(GameType.wrap(0xFF))); + vm.mockCallRevert(address(game), abi.encodeCall(game.wasRespectedGameTypeWhenCreated, ()), ""); - vm.expectRevert("OptimismPortal: dispute game created before respected game type was updated"); + vm.expectRevert(LegacyGame.selector); _optimismPortal().finalizeWithdrawalTransaction(_defaultTx); } diff --git a/packages/contracts-bedrock/test/L1/SuperchainConfigInterop.t.sol b/packages/contracts-bedrock/test/L1/SuperchainConfigInterop.t.sol index 28c768bb1f8..0d5d69aa49f 100644 --- a/packages/contracts-bedrock/test/L1/SuperchainConfigInterop.t.sol +++ b/packages/contracts-bedrock/test/L1/SuperchainConfigInterop.t.sol @@ -177,6 +177,7 @@ contract SuperchainConfigInterop_AddDependency_Test is SuperchainConfigInterop_B function test_addDependencyFromPortal_succeeds(uint256 _chainId, uint256 _chainId2) external { vm.assume(!_superchainConfigInterop().isInDependencySet(_chainId)); vm.assume(!_superchainConfigInterop().isInDependencySet(_chainId2)); + vm.assume(_chainId != _chainId2); uint256 currentSize = _superchainConfigInterop().dependencySetSize(); // Add first an authorized portal diff --git a/packages/contracts-bedrock/test/L1/SystemConfigInterop.t.sol b/packages/contracts-bedrock/test/L1/SystemConfigInterop.t.sol deleted file mode 100644 index f9bf70bde28..00000000000 --- a/packages/contracts-bedrock/test/L1/SystemConfigInterop.t.sol +++ /dev/null @@ -1,28 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.15; - -// Testing -import { CommonTest } from "test/setup/CommonTest.sol"; - -// Interfaces -import { ISystemConfigInterop } from "interfaces/L1/ISystemConfigInterop.sol"; - -contract SystemConfigInterop_Test is CommonTest { - /// @notice Marked virtual to be overridden in - /// test/kontrol/deployment/DeploymentSummary.t.sol - function setUp() public virtual override { - super.enableInterop(); - super.setUp(); - } - - /// @notice Tests that the version function returns a valid string. We avoid testing the - /// specific value of the string as it changes frequently. - function test_version_succeeds() external view { - assert(bytes(_systemConfigInterop().version()).length > 0); - } - - /// @dev Returns the SystemConfigInterop instance. - function _systemConfigInterop() internal view returns (ISystemConfigInterop) { - return ISystemConfigInterop(address(systemConfig)); - } -} diff --git a/packages/contracts-bedrock/test/opcm/DeploySuperchain.t.sol b/packages/contracts-bedrock/test/opcm/DeploySuperchain.t.sol index fa20effafb7..105c75b05d8 100644 --- a/packages/contracts-bedrock/test/opcm/DeploySuperchain.t.sol +++ b/packages/contracts-bedrock/test/opcm/DeploySuperchain.t.sol @@ -270,7 +270,7 @@ contract DeploySuperchain_Test is Test { vm.store(address(dsi), bytes32(slot), bytes32(unwrap(defaultRecommendedProtocolVersion))); } - function test_deploySuperchainImplementationContracts_reuseAddresses_succeeds() public { + function test_deploySuperchainImplementationContracts_reuseAddresses_succeeds() public virtual { deploySuperchain.deploySuperchainImplementationContracts(dsi, dso); address originalConfig = address(dso.superchainConfigImpl()); address originalProtocolVersions = address(dso.protocolVersionsImpl()); @@ -313,4 +313,12 @@ contract DeploySuperchainInterop_Test is DeploySuperchain_Test { assertEq(sharedLockboxProxy.admin(), address(dso.superchainProxyAdmin()), "1500"); vm.stopPrank(); } + + function test_deploySuperchainImplementationContracts_reuseAddresses_succeeds() public virtual override { + super.test_deploySuperchainImplementationContracts_reuseAddresses_succeeds(); + + address originalSharedLockbox = address(dso.sharedLockboxImpl()); + deploySuperchain.deploySuperchainImplementationContracts(dsi, dso); + assertEq(address(dso.sharedLockboxImpl()), originalSharedLockbox, "300"); + } } diff --git a/packages/contracts-bedrock/test/opcm/ManageDependencies.t.sol b/packages/contracts-bedrock/test/opcm/ManageDependencies.t.sol index 495a8a9c196..687e13c5190 100644 --- a/packages/contracts-bedrock/test/opcm/ManageDependencies.t.sol +++ b/packages/contracts-bedrock/test/opcm/ManageDependencies.t.sol @@ -8,18 +8,18 @@ contract ManageDependencies_Test is Test { ManageDependencies script; ManageDependenciesInput input; address mockSystemConfig; + address mockSuperchainConfig; uint256 testChainId; - event DependencyAdded(uint256 indexed chainId); - event DependencyRemoved(uint256 indexed chainId); - function setUp() public { script = new ManageDependencies(); input = new ManageDependenciesInput(); mockSystemConfig = makeAddr("systemConfig"); + mockSuperchainConfig = makeAddr("superchainConfig"); testChainId = 123; vm.etch(mockSystemConfig, hex"01"); + vm.etch(mockSuperchainConfig, hex"01"); } } @@ -37,29 +37,33 @@ contract ManageDependenciesInput_Test is Test { vm.expectRevert("ManageDependenciesInput: not set"); input.systemConfig(); - // remove() doesn't revert when not set, returns false - assertFalse(input.remove()); + vm.expectRevert("ManageDependenciesInput: not set"); + input.superchainConfig(); } function test_set_succeeds() public { address systemConfig = makeAddr("systemConfig"); + address superchainConfig = makeAddr("superchainConfig"); uint256 chainId = 123; - bool remove = true; vm.etch(systemConfig, hex"01"); + vm.etch(superchainConfig, hex"01"); input.set(input.systemConfig.selector, systemConfig); + input.set(input.superchainConfig.selector, superchainConfig); input.set(input.chainId.selector, chainId); - input.set(input.remove.selector, remove); assertEq(address(input.systemConfig()), systemConfig); + assertEq(address(input.superchainConfig()), superchainConfig); assertEq(input.chainId(), chainId); - assertTrue(input.remove()); } function test_set_withZeroAddress_reverts() public { vm.expectRevert("ManageDependenciesInput: cannot set zero address"); input.set(input.systemConfig.selector, address(0)); + + vm.expectRevert("ManageDependenciesInput: cannot set zero address"); + input.set(input.superchainConfig.selector, address(0)); } function test_set_withInvalidSelector_reverts() public { @@ -68,8 +72,5 @@ contract ManageDependenciesInput_Test is Test { vm.expectRevert("ManageDependenciesInput: unknown selector"); input.set(bytes4(0xdeadbeef), uint256(1)); - - vm.expectRevert("ManageDependenciesInput: unknown selector"); - input.set(bytes4(0xdeadbeef), true); } } diff --git a/packages/contracts-bedrock/test/universal/Specs.t.sol b/packages/contracts-bedrock/test/universal/Specs.t.sol index 9ccdd01483b..432cb477830 100644 --- a/packages/contracts-bedrock/test/universal/Specs.t.sol +++ b/packages/contracts-bedrock/test/universal/Specs.t.sol @@ -15,7 +15,6 @@ import { OPContractsManager } from "src/L1/OPContractsManager.sol"; import { IOptimismPortal2 } from "interfaces/L1/IOptimismPortal2.sol"; import { IOptimismPortalInterop } from "interfaces/L1/IOptimismPortalInterop.sol"; import { ISystemConfig } from "interfaces/L1/ISystemConfig.sol"; -import { ISystemConfigInterop } from "interfaces/L1/ISystemConfigInterop.sol"; import { IDataAvailabilityChallenge } from "interfaces/L1/IDataAvailabilityChallenge.sol"; import { IProtocolVersions } from "interfaces/L1/IProtocolVersions.sol"; @@ -428,77 +427,6 @@ contract Specification_Test is CommonTest { _addSpec({ _name: "SystemConfig", _sel: _getSel("blobbasefeeScalar()") }); _addSpec({ _name: "SystemConfig", _sel: _getSel("maximumGasLimit()") }); - // SystemConfigInterop - _addSpec({ _name: "SystemConfigInterop", _sel: _getSel("UNSAFE_BLOCK_SIGNER_SLOT()") }); - _addSpec({ _name: "SystemConfigInterop", _sel: _getSel("START_BLOCK_SLOT()") }); - _addSpec({ _name: "SystemConfigInterop", _sel: _getSel("VERSION()") }); - _addSpec({ _name: "SystemConfigInterop", _sel: _getSel("batcherHash()") }); - _addSpec({ _name: "SystemConfigInterop", _sel: _getSel("gasLimit()") }); - _addSpec({ _name: "SystemConfigInterop", _sel: _getSel("eip1559Denominator()") }); - _addSpec({ _name: "SystemConfigInterop", _sel: _getSel("eip1559Elasticity()") }); - _addSpec({ _name: "SystemConfigInterop", _sel: ISystemConfig.initialize.selector }); - _addSpec({ _name: "SystemConfigInterop", _sel: ISystemConfigInterop.minimumGasLimit.selector }); - _addSpec({ _name: "SystemConfigInterop", _sel: _getSel("overhead()") }); - _addSpec({ _name: "SystemConfigInterop", _sel: _getSel("owner()") }); - _addSpec({ _name: "SystemConfigInterop", _sel: _getSel("renounceOwnership()"), _auth: Role.SYSTEMCONFIGOWNER }); - _addSpec({ _name: "SystemConfigInterop", _sel: ISystemConfigInterop.resourceConfig.selector }); - _addSpec({ _name: "SystemConfigInterop", _sel: _getSel("scalar()") }); - _addSpec({ - _name: "SystemConfigInterop", - _sel: ISystemConfigInterop.setBatcherHash.selector, - _auth: Role.SYSTEMCONFIGOWNER - }); - _addSpec({ - _name: "SystemConfigInterop", - _sel: ISystemConfigInterop.setGasConfig.selector, - _auth: Role.SYSTEMCONFIGOWNER - }); - _addSpec({ - _name: "SystemConfigInterop", - _sel: ISystemConfigInterop.setGasLimit.selector, - _auth: Role.SYSTEMCONFIGOWNER - }); - _addSpec({ - _name: "SystemConfigInterop", - _sel: ISystemConfigInterop.setEIP1559Params.selector, - _auth: Role.SYSTEMCONFIGOWNER - }); - _addSpec({ - _name: "SystemConfigInterop", - _sel: ISystemConfigInterop.setUnsafeBlockSigner.selector, - _auth: Role.SYSTEMCONFIGOWNER - }); - _addSpec({ - _name: "SystemConfigInterop", - _sel: _getSel("transferOwnership(address)"), - _auth: Role.SYSTEMCONFIGOWNER - }); - _addSpec({ _name: "SystemConfigInterop", _sel: ISystemConfigInterop.unsafeBlockSigner.selector }); - _addSpec({ _name: "SystemConfigInterop", _sel: _getSel("version()") }); - _addSpec({ _name: "SystemConfigInterop", _sel: _getSel("l1CrossDomainMessenger()") }); - _addSpec({ _name: "SystemConfigInterop", _sel: _getSel("l1ERC721Bridge()") }); - _addSpec({ _name: "SystemConfigInterop", _sel: _getSel("l1StandardBridge()") }); - _addSpec({ _name: "SystemConfigInterop", _sel: _getSel("optimismPortal()") }); - _addSpec({ _name: "SystemConfigInterop", _sel: _getSel("optimismMintableERC20Factory()") }); - _addSpec({ _name: "SystemConfigInterop", _sel: _getSel("batchInbox()") }); - _addSpec({ _name: "SystemConfigInterop", _sel: _getSel("startBlock()") }); - _addSpec({ _name: "SystemConfigInterop", _sel: _getSel("L1_CROSS_DOMAIN_MESSENGER_SLOT()") }); - _addSpec({ _name: "SystemConfigInterop", _sel: _getSel("L1_ERC_721_BRIDGE_SLOT()") }); - _addSpec({ _name: "SystemConfigInterop", _sel: _getSel("L1_STANDARD_BRIDGE_SLOT()") }); - _addSpec({ _name: "SystemConfigInterop", _sel: _getSel("OPTIMISM_PORTAL_SLOT()") }); - _addSpec({ _name: "SystemConfigInterop", _sel: _getSel("OPTIMISM_MINTABLE_ERC20_FACTORY_SLOT()") }); - _addSpec({ _name: "SystemConfigInterop", _sel: _getSel("BATCH_INBOX_SLOT()") }); - _addSpec({ _name: "SystemConfigInterop", _sel: _getSel("DISPUTE_GAME_FACTORY_SLOT()") }); - _addSpec({ _name: "SystemConfigInterop", _sel: _getSel("disputeGameFactory()") }); - _addSpec({ - _name: "SystemConfigInterop", - _sel: _getSel("setGasConfigEcotone(uint32,uint32)"), - _auth: Role.SYSTEMCONFIGOWNER - }); - _addSpec({ _name: "SystemConfigInterop", _sel: _getSel("basefeeScalar()") }); - _addSpec({ _name: "SystemConfigInterop", _sel: _getSel("blobbasefeeScalar()") }); - _addSpec({ _name: "SystemConfigInterop", _sel: _getSel("maximumGasLimit()") }); - // ProxyAdmin _addSpec({ _name: "ProxyAdmin", _sel: _getSel("addressManager()") }); _addSpec({ diff --git a/packages/contracts-bedrock/test/vendor/Initializable.t.sol b/packages/contracts-bedrock/test/vendor/Initializable.t.sol index 56e418fc015..a0ee9e9f5e3 100644 --- a/packages/contracts-bedrock/test/vendor/Initializable.t.sol +++ b/packages/contracts-bedrock/test/vendor/Initializable.t.sol @@ -344,30 +344,30 @@ contract Initializer_Test is CommonTest { /// 3. The `initialize()` function of each contract cannot be called again. function test_cannotReinitialize_succeeds() public { // Collect exclusions. - string[] memory excludes = new string[](11); + uint256 j = 0; + string[] memory excludes = new string[](10); // TODO: Neither of these contracts are labeled properly in the deployment script. Both are // currently being labeled as their non-interop versions. Remove these exclusions once // the deployment script is fixed. - excludes[0] = "src/L1/SystemConfigInterop.sol"; - excludes[1] = "src/L1/OptimismPortalInterop.sol"; - excludes[2] = "src/L1/SuperchainConfigInterop.sol"; + excludes[j++] = "src/L1/OptimismPortalInterop.sol"; + excludes[j++] = "src/L1/SuperchainConfigInterop.sol"; // Contract is currently not being deployed as part of the standard deployment script. - excludes[3] = "src/L2/OptimismSuperchainERC20.sol"; + excludes[j++] = "src/L2/OptimismSuperchainERC20.sol"; // Periphery contracts don't get deployed as part of the standard deployment script. - excludes[4] = "src/periphery/*"; + excludes[j++] = "src/periphery/*"; // TODO: Deployment script is currently "broken" in the sense that it doesn't properly // label the FaultDisputeGame and PermissionedDisputeGame contracts and instead // simply deploys them anonymously. Means that functions like "getInitializedSlot" // don't work properly. Remove these exclusions once the deployment script is fixed. - excludes[5] = "src/dispute/FaultDisputeGame.sol"; - excludes[6] = "src/dispute/PermissionedDisputeGame.sol"; + excludes[j++] = "src/dispute/FaultDisputeGame.sol"; + excludes[j++] = "src/dispute/PermissionedDisputeGame.sol"; // TODO: Eventually remove this exclusion. Same reason as above dispute contracts. - excludes[7] = "src/L1/OPContractsManager.sol"; - excludes[8] = "src/L1/OPContractsManagerInterop.sol"; + excludes[j++] = "src/L1/OPContractsManager.sol"; + excludes[j++] = "src/L1/OPContractsManagerInterop.sol"; // L2 contract initialization is tested in Predeploys.t.sol - excludes[9] = "src/L2/*"; + excludes[j++] = "src/L2/*"; // Exclude SharedLockbox since using OZv5 initializer - excludes[10] = "src/L1/SharedLockbox.sol"; + excludes[j++] = "src/L1/SharedLockbox.sol"; // Get all contract names in the src directory, minus the excluded contracts. string[] memory contractNames = ForgeArtifacts.getContractNames("src/*", excludes);