diff --git a/.semgrep/rules/sol-rules.yaml b/.semgrep/rules/sol-rules.yaml index 6d02834f7a69f..7d67a965f9dec 100644 --- a/.semgrep/rules/sol-rules.yaml +++ b/.semgrep/rules/sol-rules.yaml @@ -372,8 +372,13 @@ rules: message: Event parameters must be named using camelCase and must not be prefixed with underscore pattern-either: # Match parameters with underscore prefix - - pattern-regex: event\s+\w+\s*\([^)]*(?:address|uint\d*|int\d*|bytes\d*|bool|string)\s+(?:indexed\s+)?_\w+ + - pattern-regex: event\s+\w+\s*\([^)]*\b(?:address|uint\d*|int\d*|bytes\d*|bool|string)\s+(?:indexed\s+)?_\w+ # Match unnamed parameters (type with optional indexed but no parameter name before comma or closing paren) - - pattern-regex: event\s+\w+\s*\([^)]*(?:address|uint\d*|int\d*|bytes\d*|bool|string)(?:\s+indexed)?\s*[,)] + - pattern-regex: event\s+\w+\s*\([^)]*\b(?:address|uint\d*|int\d*|bytes\d*|bool|string)\b(?:\s+indexed)?\s*[,)] # Match parameters that are all uppercase (like NEW_OWNER) - - pattern-regex: event\s+\w+\s*\([^)]*(?:address|uint\d*|int\d*|bytes\d*|bool|string)\s+(?:indexed\s+)?[A-Z][A-Z0-9_]*\s*[,)] + - pattern-regex: event\s+\w+\s*\([^)]*\b(?:address|uint\d*|int\d*|bytes\d*|bool|string)\s+(?:indexed\s+)?[A-Z][A-Z0-9_]*\s*[,)] + paths: + exclude: + # LegacyMintableERC20 and the corresponding interface use legacy naming conventions. + - packages/contracts-bedrock/src/legacy/LegacyMintableERC20.sol + - packages/contracts-bedrock/interfaces/legacy/ILegacyMintableERC20Full.sol diff --git a/.semgrep/tests/sol-rules.t.sol b/.semgrep/tests/sol-rules.t.sol index 708c00834f83b..9d0179318c978 100644 --- a/.semgrep/tests/sol-rules.t.sol +++ b/.semgrep/tests/sol-rules.t.sol @@ -725,4 +725,10 @@ contract SemgrepTest__sol_style_event_param_fmt { // ruleid: sol-style-event-param-fmt event OwnerChanged(address NEW_OWNER); + + // ok: sol-style-event-param-fmt + event SomethingWithMint(uint256 mint); + + // ruleid: sol-style-event-param-fmt + event SomethingWithMint(uint256 _mint); } diff --git a/packages/contracts-bedrock/deploy-config/hardhat.json b/packages/contracts-bedrock/deploy-config/hardhat.json index 339a98da80ded..736991c93ba26 100644 --- a/packages/contracts-bedrock/deploy-config/hardhat.json +++ b/packages/contracts-bedrock/deploy-config/hardhat.json @@ -19,7 +19,7 @@ "gasPriceOracleBaseFeeScalar": 1368, "gasPriceOracleBlobBaseFeeScalar": 810949, "l2OutputOracleProposer": "0x70997970C51812dc3A010C7d01b50e0d17dc79C8", - "l2OutputOracleChallenger": "0x6925B8704Ff96DEe942623d6FB5e946EF5884b63", + "l2OutputOracleChallenger": "0x9BA6e03D8B90dE867373Db8cF1A58d2F7F006b3A", "l2GenesisBlockBaseFeePerGas": "0x3B9ACA00", "l2GenesisBlockGasLimit": "0x17D7840", "baseFeeVaultRecipient": "0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc", @@ -53,8 +53,8 @@ "faultGameWithdrawalDelay": 302400, "preimageOracleMinProposalSize": 126000, "preimageOracleChallengePeriod": 86400, - "proofMaturityDelaySeconds": 12, - "disputeGameFinalityDelaySeconds": 6, + "proofMaturityDelaySeconds": 604800, + "disputeGameFinalityDelaySeconds": 302400, "respectedGameType": 0, "useFaultProofs": false, "fundDevAccounts": true, diff --git a/packages/contracts-bedrock/interfaces/L1/IL1CrossDomainMessenger.sol b/packages/contracts-bedrock/interfaces/L1/IL1CrossDomainMessenger.sol index 81d7bcd22abb1..75d61233ae242 100644 --- a/packages/contracts-bedrock/interfaces/L1/IL1CrossDomainMessenger.sol +++ b/packages/contracts-bedrock/interfaces/L1/IL1CrossDomainMessenger.sol @@ -22,7 +22,6 @@ interface IL1CrossDomainMessenger is ICrossDomainMessenger, IProxyAdminOwnedBase function systemConfig() external view returns (ISystemConfig); function version() external view returns (string memory); function superchainConfig() external view returns (ISuperchainConfig); - function upgrade(ISystemConfig _systemConfig) external; function __constructor__() external; } diff --git a/packages/contracts-bedrock/interfaces/L1/IL1ERC721Bridge.sol b/packages/contracts-bedrock/interfaces/L1/IL1ERC721Bridge.sol index ab50cdb244256..a73a743dacd3c 100644 --- a/packages/contracts-bedrock/interfaces/L1/IL1ERC721Bridge.sol +++ b/packages/contracts-bedrock/interfaces/L1/IL1ERC721Bridge.sol @@ -11,7 +11,6 @@ interface IL1ERC721Bridge is IERC721Bridge, IProxyAdminOwnedBase { error ReinitializableBase_ZeroInitVersion(); function initVersion() external view returns (uint8); - function upgrade(ISystemConfig _systemConfig) external; function bridgeERC721( address _localToken, address _remoteToken, diff --git a/packages/contracts-bedrock/interfaces/L1/IL1StandardBridge.sol b/packages/contracts-bedrock/interfaces/L1/IL1StandardBridge.sol index 4ea5e42f1edfe..0e22bb9b9c45c 100644 --- a/packages/contracts-bedrock/interfaces/L1/IL1StandardBridge.sol +++ b/packages/contracts-bedrock/interfaces/L1/IL1StandardBridge.sol @@ -31,7 +31,6 @@ interface IL1StandardBridge is IStandardBridge, IProxyAdminOwnedBase { event ETHWithdrawalFinalized(address indexed from, address indexed to, uint256 amount, bytes extraData); function initVersion() external view returns (uint8); - function upgrade(ISystemConfig _systemConfig) external; function depositERC20( address _l1Token, address _l2Token, diff --git a/packages/contracts-bedrock/interfaces/L1/IOptimismPortal2.sol b/packages/contracts-bedrock/interfaces/L1/IOptimismPortal2.sol index 391c409dbbeff..987450481d6b6 100644 --- a/packages/contracts-bedrock/interfaces/L1/IOptimismPortal2.sol +++ b/packages/contracts-bedrock/interfaces/L1/IOptimismPortal2.sol @@ -100,7 +100,6 @@ interface IOptimismPortal2 is IProxyAdminOwnedBase { function respectedGameType() external view returns (GameType); function respectedGameTypeUpdatedAt() external view returns (uint64); function systemConfig() external view returns (ISystemConfig); - function upgrade(IAnchorStateRegistry _anchorStateRegistry) external; function version() external pure returns (string memory); function __constructor__(uint256 _proofMaturityDelaySeconds) external; diff --git a/packages/contracts-bedrock/interfaces/L1/ISuperchainConfig.sol b/packages/contracts-bedrock/interfaces/L1/ISuperchainConfig.sol index df63c6888873a..73973b52a0fda 100644 --- a/packages/contracts-bedrock/interfaces/L1/ISuperchainConfig.sol +++ b/packages/contracts-bedrock/interfaces/L1/ISuperchainConfig.sol @@ -20,7 +20,6 @@ interface ISuperchainConfig is IProxyAdminOwnedBase { function guardian() external view returns (address); function initialize(address _guardian) external; - function upgrade() external; function pause(address _identifier) external; function unpause(address _identifier) external; function pausable(address _identifier) external view returns (bool); diff --git a/packages/contracts-bedrock/interfaces/L1/ISystemConfig.sol b/packages/contracts-bedrock/interfaces/L1/ISystemConfig.sol index 81c5f554f2d8c..d2543e8bd416c 100644 --- a/packages/contracts-bedrock/interfaces/L1/ISystemConfig.sol +++ b/packages/contracts-bedrock/interfaces/L1/ISystemConfig.sol @@ -89,7 +89,6 @@ interface ISystemConfig is IProxyAdminOwnedBase { function startBlock() external view returns (uint256 startBlock_); function transferOwnership(address newOwner) external; // nosemgrep function unsafeBlockSigner() external view returns (address addr_); - function upgrade(uint256 _l2ChainId, ISuperchainConfig _superchainConfig) external; function version() external pure returns (string memory); function paused() external view returns (bool); function superchainConfig() external view returns (ISuperchainConfig); diff --git a/packages/contracts-bedrock/justfile b/packages/contracts-bedrock/justfile index 666c65f72eb6a..a06fa27b8b960 100644 --- a/packages/contracts-bedrock/justfile +++ b/packages/contracts-bedrock/justfile @@ -63,7 +63,7 @@ test-dev *ARGS: build-go-ffi # Default block number for the forked upgrade path. export sepoliaBlockNumber := "9118951" -export mainnetBlockNumber := "23276717" +export mainnetBlockNumber := "23327678" export pinnedBlockNumber := if env_var_or_default("FORK_BASE_CHAIN", "") == "mainnet" { mainnetBlockNumber diff --git a/packages/contracts-bedrock/scripts/checks/opcm-upgrade-checks/main.go b/packages/contracts-bedrock/scripts/checks/opcm-upgrade-checks/main.go index 227508848cd0f..1b5c6f29d4548 100644 --- a/packages/contracts-bedrock/scripts/checks/opcm-upgrade-checks/main.go +++ b/packages/contracts-bedrock/scripts/checks/opcm-upgrade-checks/main.go @@ -125,7 +125,7 @@ func processFile(artifactPath string) (*common.Void, []error) { }) } else { // Get the AST of OPCM's upgrade function. - opcmUpgradeAst, err := getOpcmUpgradeFunctionAst(opcmAst, "upgrade") + opcmUpgradeAst, err := getOpcmUpgradeFunctionAst(opcmAst, "_doChainUpgrade") if err != nil { return nil, []error{err} } @@ -314,8 +314,7 @@ func getOpcmUpgradeFunctionAst(opcmArtifact *solc.ForgeArtifact, upgradeFunction if astNode.NodeType == "ContractDefinition" && astNode.Name == "OPContractsManagerUpgrader" { for _, node := range astNode.Nodes { if node.NodeType == "FunctionDefinition" && - node.Name == upgradeFunctionName && - node.Visibility == "external" { + node.Name == upgradeFunctionName { opcmUpgradeFunctions = append(opcmUpgradeFunctions, node) } } diff --git a/packages/contracts-bedrock/scripts/checks/opcm-upgrade-checks/main_test.go b/packages/contracts-bedrock/scripts/checks/opcm-upgrade-checks/main_test.go index c26366409d11f..b7b7ef16bea58 100644 --- a/packages/contracts-bedrock/scripts/checks/opcm-upgrade-checks/main_test.go +++ b/packages/contracts-bedrock/scripts/checks/opcm-upgrade-checks/main_test.go @@ -17,7 +17,7 @@ func TestGetOpcmUpgradeFunctionAst(t *testing.T) { expectedError string }{ { - name: "With one external upgrade function", + name: "With one _doChainUpgrade function", opcmArtifact: &solc.ForgeArtifact{ Ast: solc.Ast{ Nodes: []solc.AstNode{ @@ -26,7 +26,7 @@ func TestGetOpcmUpgradeFunctionAst(t *testing.T) { Nodes: []solc.AstNode{ { NodeType: "FunctionDefinition", - Name: "upgrade", + Name: "_doChainUpgrade", Visibility: "external", Nodes: []solc.AstNode{ { @@ -40,10 +40,10 @@ func TestGetOpcmUpgradeFunctionAst(t *testing.T) { }, }, }, - upgradeFunctionName: "upgrade", + upgradeFunctionName: "_doChainUpgrade", expectedAst: &solc.AstNode{ NodeType: "FunctionDefinition", - Name: "upgrade", + Name: "_doChainUpgrade", Visibility: "external", Nodes: []solc.AstNode{ { @@ -54,7 +54,7 @@ func TestGetOpcmUpgradeFunctionAst(t *testing.T) { expectedError: "", }, { - name: "With an upgrade function but public visibility", + name: "With a _doChainUpgrade function but public visibility", opcmArtifact: &solc.ForgeArtifact{ Ast: solc.Ast{ Nodes: []solc.AstNode{ @@ -63,7 +63,7 @@ func TestGetOpcmUpgradeFunctionAst(t *testing.T) { Nodes: []solc.AstNode{ { NodeType: "FunctionDefinition", - Name: "upgrade", + Name: "_doChainUpgrade", Visibility: "public", }, }, @@ -72,12 +72,16 @@ func TestGetOpcmUpgradeFunctionAst(t *testing.T) { }, }, }, - upgradeFunctionName: "upgrade", - expectedAst: nil, - expectedError: "no external upgrade function found in OPContractsManagerUpgrader", + upgradeFunctionName: "_doChainUpgrade", + expectedAst: &solc.AstNode{ + NodeType: "FunctionDefinition", + Name: "_doChainUpgrade", + Visibility: "public", + }, + expectedError: "", }, { - name: "With an upgrade function and irrelevant function selector", + name: "With a _doChainUpgrade function and irrelevant function selector", opcmArtifact: &solc.ForgeArtifact{ Ast: solc.Ast{ Nodes: []solc.AstNode{ @@ -86,7 +90,7 @@ func TestGetOpcmUpgradeFunctionAst(t *testing.T) { Nodes: []solc.AstNode{ { NodeType: "FunctionDefinition", - Name: "upgrade", + Name: "_doChainUpgrade", Visibility: "external", FunctionSelector: "aabbccdd", Nodes: []solc.AstNode{ @@ -101,10 +105,10 @@ func TestGetOpcmUpgradeFunctionAst(t *testing.T) { }, }, }, - upgradeFunctionName: "upgrade", + upgradeFunctionName: "_doChainUpgrade", expectedAst: &solc.AstNode{ NodeType: "FunctionDefinition", - Name: "upgrade", + Name: "_doChainUpgrade", Visibility: "external", FunctionSelector: "aabbccdd", Nodes: []solc.AstNode{ @@ -116,7 +120,7 @@ func TestGetOpcmUpgradeFunctionAst(t *testing.T) { expectedError: "", }, { - name: "With multiple external upgrade functions", + name: "With multiple _doChainUpgrade functions", opcmArtifact: &solc.ForgeArtifact{ Ast: solc.Ast{ Nodes: []solc.AstNode{ @@ -125,12 +129,12 @@ func TestGetOpcmUpgradeFunctionAst(t *testing.T) { Nodes: []solc.AstNode{ { NodeType: "FunctionDefinition", - Name: "upgrade", + Name: "_doChainUpgrade", Visibility: "external", }, { NodeType: "FunctionDefinition", - Name: "upgrade", + Name: "_doChainUpgrade", Visibility: "external", }, }, @@ -139,12 +143,12 @@ func TestGetOpcmUpgradeFunctionAst(t *testing.T) { }, }, }, - upgradeFunctionName: "upgrade", + upgradeFunctionName: "_doChainUpgrade", expectedAst: nil, - expectedError: "multiple external upgrade functions found in OPContractsManagerUpgrader, expected 1", + expectedError: "multiple external _doChainUpgrade functions found in OPContractsManagerUpgrader, expected 1", }, { - name: "With no upgrade function", + name: "With no _doChainUpgrade function", opcmArtifact: &solc.ForgeArtifact{ Ast: solc.Ast{ Nodes: []solc.AstNode{ @@ -167,9 +171,9 @@ func TestGetOpcmUpgradeFunctionAst(t *testing.T) { }, }, }, - upgradeFunctionName: "upgrade", + upgradeFunctionName: "_doChainUpgrade", expectedAst: nil, - expectedError: "no external upgrade function found in OPContractsManagerUpgrader", + expectedError: "no external _doChainUpgrade function found in OPContractsManagerUpgrader", }, { name: "With no contract definition", @@ -178,9 +182,9 @@ func TestGetOpcmUpgradeFunctionAst(t *testing.T) { Nodes: []solc.AstNode{}, }, }, - upgradeFunctionName: "upgrade", + upgradeFunctionName: "_doChainUpgrade", expectedAst: nil, - expectedError: "no external upgrade function found in OPContractsManagerUpgrader", + expectedError: "no external _doChainUpgrade function found in OPContractsManagerUpgrader", }, } diff --git a/packages/contracts-bedrock/snapshots/abi/L1CrossDomainMessenger.json b/packages/contracts-bedrock/snapshots/abi/L1CrossDomainMessenger.json index 487c45491aac6..bc0174b42fa9c 100644 --- a/packages/contracts-bedrock/snapshots/abi/L1CrossDomainMessenger.json +++ b/packages/contracts-bedrock/snapshots/abi/L1CrossDomainMessenger.json @@ -431,19 +431,6 @@ "stateMutability": "view", "type": "function" }, - { - "inputs": [ - { - "internalType": "contract ISystemConfig", - "name": "_systemConfig", - "type": "address" - } - ], - "name": "upgrade", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, { "inputs": [], "name": "version", diff --git a/packages/contracts-bedrock/snapshots/abi/L1ERC721Bridge.json b/packages/contracts-bedrock/snapshots/abi/L1ERC721Bridge.json index 7783e2b38ee4f..7b83c924650b6 100644 --- a/packages/contracts-bedrock/snapshots/abi/L1ERC721Bridge.json +++ b/packages/contracts-bedrock/snapshots/abi/L1ERC721Bridge.json @@ -290,19 +290,6 @@ "stateMutability": "view", "type": "function" }, - { - "inputs": [ - { - "internalType": "contract ISystemConfig", - "name": "_systemConfig", - "type": "address" - } - ], - "name": "upgrade", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, { "inputs": [], "name": "version", diff --git a/packages/contracts-bedrock/snapshots/abi/L1StandardBridge.json b/packages/contracts-bedrock/snapshots/abi/L1StandardBridge.json index 259a0a21bdf5e..78752f602e873 100644 --- a/packages/contracts-bedrock/snapshots/abi/L1StandardBridge.json +++ b/packages/contracts-bedrock/snapshots/abi/L1StandardBridge.json @@ -549,19 +549,6 @@ "stateMutability": "view", "type": "function" }, - { - "inputs": [ - { - "internalType": "contract ISystemConfig", - "name": "_systemConfig", - "type": "address" - } - ], - "name": "upgrade", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, { "inputs": [], "name": "version", diff --git a/packages/contracts-bedrock/snapshots/abi/OptimismPortal2.json b/packages/contracts-bedrock/snapshots/abi/OptimismPortal2.json index 6b3a36bf234ae..49ae551310b01 100644 --- a/packages/contracts-bedrock/snapshots/abi/OptimismPortal2.json +++ b/packages/contracts-bedrock/snapshots/abi/OptimismPortal2.json @@ -614,19 +614,6 @@ "stateMutability": "view", "type": "function" }, - { - "inputs": [ - { - "internalType": "contract IAnchorStateRegistry", - "name": "_anchorStateRegistry", - "type": "address" - } - ], - "name": "upgrade", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, { "inputs": [], "name": "version", diff --git a/packages/contracts-bedrock/snapshots/abi/SuperchainConfig.json b/packages/contracts-bedrock/snapshots/abi/SuperchainConfig.json index ed7ad5c10f978..e430da3ccca4a 100644 --- a/packages/contracts-bedrock/snapshots/abi/SuperchainConfig.json +++ b/packages/contracts-bedrock/snapshots/abi/SuperchainConfig.json @@ -210,13 +210,6 @@ "stateMutability": "nonpayable", "type": "function" }, - { - "inputs": [], - "name": "upgrade", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, { "inputs": [], "name": "version", diff --git a/packages/contracts-bedrock/snapshots/abi/SystemConfig.json b/packages/contracts-bedrock/snapshots/abi/SystemConfig.json index 03f82fcb103f7..6d6cfae48b6b0 100644 --- a/packages/contracts-bedrock/snapshots/abi/SystemConfig.json +++ b/packages/contracts-bedrock/snapshots/abi/SystemConfig.json @@ -873,24 +873,6 @@ "stateMutability": "view", "type": "function" }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_l2ChainId", - "type": "uint256" - }, - { - "internalType": "contract ISuperchainConfig", - "name": "_superchainConfig", - "type": "address" - } - ], - "name": "upgrade", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, { "inputs": [], "name": "version", diff --git a/packages/contracts-bedrock/snapshots/semver-lock.json b/packages/contracts-bedrock/snapshots/semver-lock.json index 69288d2fdbcf3..4c34115d52ee2 100644 --- a/packages/contracts-bedrock/snapshots/semver-lock.json +++ b/packages/contracts-bedrock/snapshots/semver-lock.json @@ -8,44 +8,44 @@ "sourceCodeHash": "0x6c9d3e2dee44c234d59ab93b6564536dfd807f1c4a02a82d5393bc53cb15b8b7" }, "src/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger": { - "initCodeHash": "0x061ef0c599fb9912c65d6b0ff452e7ac59e61940d14cacf4d4708c6d1532c89f", - "sourceCodeHash": "0xae918857dcc5b42eaf4ff3c8751f45861a3ab2450e6338085b478073923b91c4" + "initCodeHash": "0x3dc659aafb03bd357f92abfc6794af89ee0ddd5212364551637422bf8d0b00f9", + "sourceCodeHash": "0xef3d366cd22eac2dfd22a658e003700c679bd9c38758d9c21befa7335bbd82ad" }, "src/L1/L1ERC721Bridge.sol:L1ERC721Bridge": { - "initCodeHash": "0xc5e697485b9161bb723a303ca2adf30c3af0984541f1e7ee415bf2e988f89358", - "sourceCodeHash": "0xe4be59737bca6799348e7ba5c8bc70a2d8cfff5448353959c2208d4b777e713f" + "initCodeHash": "0x6f586bf82f6e89b75c2cc707e16a71ac921a911acf00f1594659f82e5c819fcc", + "sourceCodeHash": "0x4d48a9cf80dd288d1c54c9576a1a8c12c1c5b9f1694246d0ebba60996f786b69" }, "src/L1/L1StandardBridge.sol:L1StandardBridge": { - "initCodeHash": "0x1ee0bff332b25a60be69f63206e0a1c581fdf7a927376fc4be20865e707b947b", - "sourceCodeHash": "0x8eae1c2bbc501b231f75e75cbdbc99d2bbb0cc909ab39e9c473ac90daf1a7add" + "initCodeHash": "0xadd7863f0d14360be0f0c575d07aa304457b190b64a91a8976770fb7c34b28a3", + "sourceCodeHash": "0xfca613b5d055ffc4c3cbccb0773ddb9030abedc1aa6508c9e2e7727cc0cd617b" }, "src/L1/OPContractsManager.sol:OPContractsManager": { - "initCodeHash": "0x8755e500e7905a9bf26939555366639b5e39fa39645665e93d86b47e59867213", - "sourceCodeHash": "0x60cd2ab14324b550b96c90e1af2879198ea00942d70cfa5a915679cc85c47f9c" + "initCodeHash": "0x38dfaa504d646a48b85da1d2cf853263241070ac25a93d16f12468d948aa5f96", + "sourceCodeHash": "0xb5cb0e204bde0e5ab59c3be61e234c2c6b0efa60f9e550c25f64b8d5eeffae4e" }, "src/L1/OPContractsManagerStandardValidator.sol:OPContractsManagerStandardValidator": { - "initCodeHash": "0x2bd2745ff3b7dc42c6ef6c1904bce3d3b6cf3a1ce5b7e2af5597d39e1420ac5c", - "sourceCodeHash": "0x0947a037ff1fb69abb27007b06728c0eab2a2e9d9897803ee754ec1e60f19ea2" + "initCodeHash": "0x17a40747da8a9978f7294f071ea371b8c021504b898919431e6acf62623e8adc", + "sourceCodeHash": "0xa80dcd2ebafc5a6a437f712d8073f8a48998807aa317ad7762b3fc9dc2caa133" }, "src/L1/OptimismPortal2.sol:OptimismPortal2": { - "initCodeHash": "0x0bd9360663627aab37a548aca16e26b1a8017766445b3969e16bc6cca6ec801a", - "sourceCodeHash": "0xe2cc287f8c3caebc3a7e9c849155c9a4820c26ebe231b9959987bb4fb455c2d7" + "initCodeHash": "0x8faaaf0aa74a8f7a98674e94009a516dddae7bb1feb687f4a6d43641c23efe45", + "sourceCodeHash": "0x63002978f0cc521ed4f0572ef81a5d57cd788d2c068ff75fddc71b08c7e92305" }, "src/L1/OptimismPortalInterop.sol:OptimismPortalInterop": { - "initCodeHash": "0x7911f37dc9614291a3dfd76c5434d70ae573bb84f213f1c28baec078a2f4b559", - "sourceCodeHash": "0x0c45914eaf5b99683afda04204c2bac0a29b8907f7b0ed5e25bc76afc1f466b0" + "initCodeHash": "0x087281cd2a48e882648c09fa90bfcca7487d222e16300f9372deba6b2b8ccfad", + "sourceCodeHash": "0x1cc641a4272aea85e13cbf42d9032d1b91ef858eafe3be6b5649cc8504c9cf69" }, "src/L1/ProtocolVersions.sol:ProtocolVersions": { "initCodeHash": "0x5a76c8530cb24cf23d3baacc6eefaac226382af13f1e2a35535d2ec2b0573b29", "sourceCodeHash": "0xb3e32b18c95d4940980333e1e99b4dcf42d8a8bfce78139db4dc3fb06e9349d0" }, "src/L1/SuperchainConfig.sol:SuperchainConfig": { - "initCodeHash": "0x0ea921059d71fd19ac9c6e29c05b9724ad584eb27f74231de6df9551e9b13084", - "sourceCodeHash": "0xad12c20a00dc20683bd3f68e6ee254f968da6cc2d98930be6534107ee5cb11d9" + "initCodeHash": "0xfb8c98028f1a0e70bb1afbbc532035ea71b0724883554eeaae62e1910a6c1cd9", + "sourceCodeHash": "0xbf344c4369b8cb00ec7a3108f72795747f3bc59ab5b37ac18cf21e72e2979dbf" }, "src/L1/SystemConfig.sol:SystemConfig": { - "initCodeHash": "0x48070c60dce026f655fbd31c490673657ed0ee48b90ff399aa5bac60abc0b796", - "sourceCodeHash": "0x27101f76d083e0b15e462932f5a3bfad67c10e033eeb670b76e67c370b7f2b07" + "initCodeHash": "0x96a0b21e2fbb905858b07841eb0a4dc8a9f51ad78d13af888ed8376b8ab28904", + "sourceCodeHash": "0x024929011a436701e99654fe04253ef0f6642e9c8de64ff3a54ce2f83cdb1200" }, "src/L2/BaseFeeVault.sol:BaseFeeVault": { "initCodeHash": "0x9b664e3d84ad510091337b4aacaa494b142512e2f6f7fbcdb6210ed62ca9b885", diff --git a/packages/contracts-bedrock/src/L1/L1CrossDomainMessenger.sol b/packages/contracts-bedrock/src/L1/L1CrossDomainMessenger.sol index f633fb5218abb..b6208c8018091 100644 --- a/packages/contracts-bedrock/src/L1/L1CrossDomainMessenger.sol +++ b/packages/contracts-bedrock/src/L1/L1CrossDomainMessenger.sol @@ -36,8 +36,8 @@ contract L1CrossDomainMessenger is CrossDomainMessenger, ProxyAdminOwnedBase, Re address private spacer_253_0_20; /// @notice Semantic version. - /// @custom:semver 2.10.0 - string public constant version = "2.10.0"; + /// @custom:semver 2.11.0 + string public constant version = "2.11.0"; /// @notice Contract of the SystemConfig. ISystemConfig public systemConfig; @@ -60,16 +60,6 @@ contract L1CrossDomainMessenger is CrossDomainMessenger, ProxyAdminOwnedBase, Re __CrossDomainMessenger_init({ _otherMessenger: CrossDomainMessenger(Predeploys.L2_CROSS_DOMAIN_MESSENGER) }); } - /// @notice Upgrades the contract to have a reference to the SystemConfig. - /// @param _systemConfig The new SystemConfig contract. - function upgrade(ISystemConfig _systemConfig) external reinitializer(initVersion()) { - // Upgrade transactions must come from the ProxyAdmin or its owner. - _assertOnlyProxyAdminOrProxyAdminOwner(); - - // Now perform upgrade logic. - systemConfig = _systemConfig; - } - /// @inheritdoc CrossDomainMessenger function paused() public view override returns (bool) { return systemConfig.paused(); diff --git a/packages/contracts-bedrock/src/L1/L1ERC721Bridge.sol b/packages/contracts-bedrock/src/L1/L1ERC721Bridge.sol index 9daf0dfc8c65e..98c557a603c37 100644 --- a/packages/contracts-bedrock/src/L1/L1ERC721Bridge.sol +++ b/packages/contracts-bedrock/src/L1/L1ERC721Bridge.sol @@ -33,8 +33,8 @@ contract L1ERC721Bridge is ERC721Bridge, ProxyAdminOwnedBase, ReinitializableBas address private spacer_50_0_20; /// @notice Semantic version. - /// @custom:semver 2.8.0 - string public constant version = "2.8.0"; + /// @custom:semver 2.9.0 + string public constant version = "2.9.0"; /// @notice Address of the SystemConfig contract. ISystemConfig public systemConfig; @@ -62,16 +62,6 @@ contract L1ERC721Bridge is ERC721Bridge, ProxyAdminOwnedBase, ReinitializableBas __ERC721Bridge_init({ _messenger: _messenger, _otherBridge: ERC721Bridge(payable(Predeploys.L2_ERC721_BRIDGE)) }); } - /// @notice Upgrades the contract to have a reference to the SystemConfig. - /// @param _systemConfig SystemConfig contract. - function upgrade(ISystemConfig _systemConfig) external reinitializer(initVersion()) { - // Upgrade transactions must come from the ProxyAdmin or its owner. - _assertOnlyProxyAdminOrProxyAdminOwner(); - - // Now perform upgrade logic. - systemConfig = _systemConfig; - } - /// @inheritdoc ERC721Bridge function paused() public view override returns (bool) { return systemConfig.paused(); diff --git a/packages/contracts-bedrock/src/L1/L1StandardBridge.sol b/packages/contracts-bedrock/src/L1/L1StandardBridge.sol index beb3ba8b3d53f..465ec7f7ed5eb 100644 --- a/packages/contracts-bedrock/src/L1/L1StandardBridge.sol +++ b/packages/contracts-bedrock/src/L1/L1StandardBridge.sol @@ -77,8 +77,8 @@ contract L1StandardBridge is StandardBridge, ProxyAdminOwnedBase, Reinitializabl ); /// @notice Semantic version. - /// @custom:semver 2.7.0 - string public constant version = "2.7.0"; + /// @custom:semver 2.8.0 + string public constant version = "2.8.0"; /// @custom:legacy /// @custom:spacer superchainConfig @@ -119,16 +119,6 @@ contract L1StandardBridge is StandardBridge, ProxyAdminOwnedBase, Reinitializabl }); } - /// @notice Upgrades the contract to have a reference to the SystemConfig. - /// @param _systemConfig SystemConfig contract. - function upgrade(ISystemConfig _systemConfig) external reinitializer(initVersion()) { - // Upgrade transactions must come from the ProxyAdmin or its owner. - _assertOnlyProxyAdminOrProxyAdminOwner(); - - // Now perform upgrade logic. - systemConfig = _systemConfig; - } - /// @inheritdoc StandardBridge function paused() public view override returns (bool) { return systemConfig.paused(); diff --git a/packages/contracts-bedrock/src/L1/OPContractsManager.sol b/packages/contracts-bedrock/src/L1/OPContractsManager.sol index b5007d5aabba6..70ac7617970f3 100644 --- a/packages/contracts-bedrock/src/L1/OPContractsManager.sol +++ b/packages/contracts-bedrock/src/L1/OPContractsManager.sol @@ -8,7 +8,7 @@ import { OPContractsManagerStandardValidator } from "src/L1/OPContractsManagerSt import { Blueprint } from "src/libraries/Blueprint.sol"; import { Constants } from "src/libraries/Constants.sol"; import { Bytes } from "src/libraries/Bytes.sol"; -import { Claim, Duration, GameType, Hash, GameTypes, Proposal } from "src/dispute/lib/Types.sol"; +import { Claim, Duration, GameType, GameTypes, Proposal } from "src/dispute/lib/Types.sol"; import { Strings } from "@openzeppelin/contracts/utils/Strings.sol"; import { SemverComp } from "src/libraries/SemverComp.sol"; import { Features } from "src/libraries/Features.sol"; @@ -668,260 +668,152 @@ contract OPContractsManagerUpgrader is OPContractsManagerBase { // Loop through each chain and upgrade. for (uint256 i = 0; i < _opChainConfigs.length; i++) { assertValidOpChainConfig(_opChainConfigs[i]); + uint256 l2ChainId = _opChainConfigs[i].systemConfigProxy.l2ChainId(); - // Pull out the OptimismPortal from the SystemConfig. - IOptimismPortal optimismPortal = - IOptimismPortal(payable(_opChainConfigs[i].systemConfigProxy.optimismPortal())); - - // Get this OPChain's superchainConfig. - ISuperchainConfig superchainConfig = optimismPortal.superchainConfig(); + // Grab the SuperchainConfig. + ISuperchainConfig superchainConfig = _opChainConfigs[i].systemConfigProxy.superchainConfig(); // If the SuperchainConfig is not already upgraded, revert. if (SemverComp.lt(superchainConfig.version(), ISuperchainConfig(impls.superchainConfigImpl).version())) { revert OPContractsManagerUpgrader_SuperchainConfigNeedsUpgrade(i); } - // Use the SystemConfig to grab the DisputeGameFactory address. - IDisputeGameFactory dgf = IDisputeGameFactory(_opChainConfigs[i].systemConfigProxy.disputeGameFactory()); - - // Need to upgrade the DisputeGameFactory implementation, no internal upgrade call. - upgradeTo(_opChainConfigs[i].proxyAdmin, address(dgf), impls.disputeGameFactoryImpl); - - // All chains have the PermissionedDisputeGame, grab that. - IPermissionedDisputeGame permissionedDisputeGame = - IPermissionedDisputeGame(address(getGameImplementation(dgf, GameTypes.PERMISSIONED_CANNON))); + // Do the chain upgrade. + // All of your updates should be done in this internal function unless you're making a + // change to how upgrades work in general. + _doChainUpgrade(impls, _opChainConfigs[i], l2ChainId); - // Grab the L2 chain ID from the PermissionedDisputeGame. - uint256 l2ChainId = getL2ChainId(IFaultDisputeGame(address(permissionedDisputeGame))); - - // Start by upgrading the SystemConfig contract to have the l2ChainId and - // SuperchainConfig. We can get the SuperchainConfig from the existing OptimismPortal, - // we need to inline the call to avoid a stack too deep error. - upgradeToAndCall( - _opChainConfigs[i].proxyAdmin, - address(_opChainConfigs[i].systemConfigProxy), - impls.systemConfigImpl, - abi.encodeCall(ISystemConfig.upgrade, (l2ChainId, superchainConfig)) - ); - - // Try to grab the AnchorStateRegistry from the OptimismPortal contract. This will work - // for any chains that are already on U16. Any chains that are not on U16 will need to - // deploy a new AnchorStateRegistry contract. Note that this is safe from issues with - // EIP-150 because (1) the upgrade controller is trusted and controls the amount of gas - // that gets provided and (2) the absolute worst case scenario is that a new ASR gets - // deployed which invalidates withdrawals but has no other real downsides. - IAnchorStateRegistry anchorStateRegistry; - - // nosemgrep: sol-safety-trycatch-eip150 - try optimismPortal.anchorStateRegistry() returns (IAnchorStateRegistry anchorStateRegistry_) { - anchorStateRegistry = anchorStateRegistry_; - - // Upgrade the ASR implementation anyway. Since the ASR code didn't change, this - // won't have any impact in production but is required because the address is - // different when deployed in a testing environment because the OPCM deployer - // address is different. - upgradeTo(_opChainConfigs[i].proxyAdmin, address(anchorStateRegistry), impls.anchorStateRegistryImpl); - } catch { - // Grab the current respectedGameType from the OptimismPortal contract before the - // upgrade. - GameType respectedGameType = optimismPortal.respectedGameType(); - - // Deploy a new AnchorStateRegistry contract. - anchorStateRegistry = IAnchorStateRegistry( - deployProxy({ - _l2ChainId: l2ChainId, - _proxyAdmin: _opChainConfigs[i].proxyAdmin, - _saltMixer: reusableSaltMixer(_opChainConfigs[i]), - _contractName: "AnchorStateRegistry-U16" - }) - ); + // Emit the upgraded event with the address of the caller. Since this will be a delegatecall, + // the caller will be the value of the ADDRESS opcode. + emit Upgraded(l2ChainId, _opChainConfigs[i].systemConfigProxy, address(this)); + } + } - // Separate context to avoid stack too deep. - { - // Get the existing anchor root from the old AnchorStateRegistry contract. - // Get the AnchorStateRegistry from the PermissionedDisputeGame. - (Hash root, uint256 l2BlockNumber) = getAnchorStateRegistry( - IFaultDisputeGame(address(permissionedDisputeGame)) - ).anchors(respectedGameType); - - // Upgrade and initialize the AnchorStateRegistry contract. - // Since this is a net-new contract, we need to initialize it. - upgradeToAndCall( - _opChainConfigs[i].proxyAdmin, - address(anchorStateRegistry), - impls.anchorStateRegistryImpl, - abi.encodeCall( - IAnchorStateRegistry.initialize, - ( - _opChainConfigs[i].systemConfigProxy, - dgf, - Proposal({ root: root, l2SequenceNumber: l2BlockNumber }), - respectedGameType - ) - ) - ); - } - } + /// @notice Performs an upgrade for a specific chain. + /// @param _impls The implementations of the contracts. + /// @param _opChainConfig The configuration of the chain to upgrade. + /// @param _l2ChainId The L2 chain ID of the chain to upgrade. + function _doChainUpgrade( + OPContractsManager.Implementations memory _impls, + OPContractsManager.OpChainConfig memory _opChainConfig, + uint256 _l2ChainId + ) + internal + { + // Upgrade the SystemConfig first. + upgradeTo(_opChainConfig.proxyAdmin, address(_opChainConfig.systemConfigProxy), _impls.systemConfigImpl); - // This function will work if the chain is already on U16. - // nosemgrep: sol-safety-trycatch-eip150 - try optimismPortal.ethLockbox() returns (IETHLockbox) { - _opChainConfigs[i].systemConfigProxy.setFeature(Features.ETH_LOCKBOX, true); - } catch { - // We don't care. If somehow this failed because of EIP150 and we actually did need - // to enable the feature, we'd get a revert from the OptimismPortal upgrade - // function. - } + // Grab the OptimismPortal contract. + IOptimismPortal optimismPortal = IOptimismPortal(payable(_opChainConfig.systemConfigProxy.optimismPortal())); - // Upgrade path depends on if the OptimismPortalInterop dev feature is enabled. - if (isDevFeatureEnabled(DevFeatures.OPTIMISM_PORTAL_INTEROP)) { - // Upgrade the OptimismPortal contract implementation. - upgradeTo(_opChainConfigs[i].proxyAdmin, address(optimismPortal), impls.optimismPortalInteropImpl); + // Upgrade the OptimismPortal contract. + if (isDevFeatureEnabled(DevFeatures.OPTIMISM_PORTAL_INTEROP)) { + // This does NOT run in production. + // Upgrade the OptimismPortal contract implementation. + upgradeTo(_opChainConfig.proxyAdmin, address(optimismPortal), _impls.optimismPortalInteropImpl); + // If we don't already have an ETHLockbox, deploy and initialize it. + IETHLockbox ethLockbox = optimismPortal.ethLockbox(); + if (address(ethLockbox) == address(0)) { // Deploy the ETHLockbox proxy. - IETHLockbox ethLockbox = IETHLockbox( + ethLockbox = IETHLockbox( deployProxy({ - _l2ChainId: l2ChainId, - _proxyAdmin: _opChainConfigs[i].proxyAdmin, - _saltMixer: reusableSaltMixer(_opChainConfigs[i]), + _l2ChainId: _l2ChainId, + _proxyAdmin: _opChainConfig.proxyAdmin, + _saltMixer: reusableSaltMixer(_opChainConfig), _contractName: "ETHLockbox-U16a" }) ); - // Upgrade the OptimismPortal contract first so that the SystemConfig will have - // the SuperchainConfig reference required in the ETHLockbox. - IOptimismPortalInterop(payable(optimismPortal)).upgrade(anchorStateRegistry, ethLockbox); - // Initialize the ETHLockbox setting the OptimismPortal as an authorized portal. IOptimismPortal[] memory portals = new IOptimismPortal[](1); portals[0] = optimismPortal; upgradeToAndCall( - _opChainConfigs[i].proxyAdmin, + _opChainConfig.proxyAdmin, address(ethLockbox), - impls.ethLockboxImpl, - abi.encodeCall(IETHLockbox.initialize, (_opChainConfigs[i].systemConfigProxy, portals)) + _impls.ethLockboxImpl, + abi.encodeCall(IETHLockbox.initialize, (_opChainConfig.systemConfigProxy, portals)) ); // Migrate liquidity from the OptimismPortal to the ETHLockbox. IOptimismPortalInterop(payable(optimismPortal)).migrateLiquidity(); - } else { - // Upgrade the OptimismPortal contract implementation. - upgradeTo(_opChainConfigs[i].proxyAdmin, address(optimismPortal), impls.optimismPortalImpl); - - // Upgrade the OptimismPortal contract, nothing special required. - optimismPortal.upgrade(anchorStateRegistry); } - // Separate context to avoid stack too deep. - { - // Grab chain addresses here. We need to do this after the SystemConfig upgrade or - // the addresses will be incorrect. - ISystemConfig.Addresses memory opChainAddrs = _opChainConfigs[i].systemConfigProxy.getAddresses(); + // Use the existing AnchorStateRegistry reference. + IAnchorStateRegistry anchorStateRegistry = optimismPortal.anchorStateRegistry(); - // Upgrade the L1CrossDomainMessenger contract. - upgradeToAndCall( - _opChainConfigs[i].proxyAdmin, - address(IL1CrossDomainMessenger(opChainAddrs.l1CrossDomainMessenger)), - impls.l1CrossDomainMessengerImpl, - abi.encodeCall(IL1CrossDomainMessenger.upgrade, (_opChainConfigs[i].systemConfigProxy)) - ); + // Upgrade the OptimismPortal contract first so that the SystemConfig will have + // the SuperchainConfig reference required in the ETHLockbox. + IOptimismPortalInterop(payable(optimismPortal)).upgrade(anchorStateRegistry, ethLockbox); + } else { + // This runs in production. + upgradeTo(_opChainConfig.proxyAdmin, address(optimismPortal), _impls.optimismPortalImpl); + } - // Upgrade the L1StandardBridge contract. - upgradeToAndCall( - _opChainConfigs[i].proxyAdmin, - address(IL1StandardBridge(payable(opChainAddrs.l1StandardBridge))), - impls.l1StandardBridgeImpl, - abi.encodeCall(IL1StandardBridge.upgrade, (_opChainConfigs[i].systemConfigProxy)) - ); + // Use the SystemConfig to grab the DisputeGameFactory address. + IDisputeGameFactory dgf = IDisputeGameFactory(_opChainConfig.systemConfigProxy.disputeGameFactory()); - // Upgrade the L1ERC721Bridge contract. - upgradeToAndCall( - _opChainConfigs[i].proxyAdmin, - address(IL1ERC721Bridge(opChainAddrs.l1ERC721Bridge)), - impls.l1ERC721BridgeImpl, - abi.encodeCall(IL1ERC721Bridge.upgrade, (_opChainConfigs[i].systemConfigProxy)) - ); - } + // Need to upgrade the DisputeGameFactory implementation, no internal upgrade call. + upgradeTo(_opChainConfig.proxyAdmin, address(dgf), _impls.disputeGameFactoryImpl); - // We also need to redeploy the dispute games because the AnchorStateRegistry is new. - // Separate context to avoid stack too deep. - { - // Create a new DelayedWETH for the permissioned game. - IDelayedWETH permissionedDelayedWeth = IDelayedWETH( - payable( - deployProxy({ - _l2ChainId: l2ChainId, - _proxyAdmin: _opChainConfigs[i].proxyAdmin, - _saltMixer: reusableSaltMixer(_opChainConfigs[i]), - _contractName: "PermissionedDelayedWETH-U16a" - }) - ) - ); + // Separate context to avoid stack too deep. + { + // Grab chain addresses here. We need to do this after the SystemConfig upgrade or + // the addresses will be incorrect. + ISystemConfig.Addresses memory opChainAddrs = _opChainConfig.systemConfigProxy.getAddresses(); + + // Upgrade the L1CrossDomainMessenger contract. + upgradeTo( + _opChainConfig.proxyAdmin, + address(IL1CrossDomainMessenger(opChainAddrs.l1CrossDomainMessenger)), + _impls.l1CrossDomainMessengerImpl + ); - // Initialize the DelayedWETH. - upgradeToAndCall( - _opChainConfigs[i].proxyAdmin, - address(permissionedDelayedWeth), - impls.delayedWETHImpl, - abi.encodeCall(IDelayedWETH.initialize, (_opChainConfigs[i].systemConfigProxy)) - ); + // Upgrade the L1StandardBridge contract. + upgradeTo( + _opChainConfig.proxyAdmin, + address(IL1StandardBridge(payable(opChainAddrs.l1StandardBridge))), + _impls.l1StandardBridgeImpl + ); - // Deploy and set a new permissioned game to update its prestate. - deployAndSetNewGameImpl({ - _l2ChainId: l2ChainId, - _disputeGame: IDisputeGame(address(permissionedDisputeGame)), - _newDelayedWeth: permissionedDelayedWeth, - _newAnchorStateRegistryProxy: anchorStateRegistry, - _gameType: GameTypes.PERMISSIONED_CANNON, - _opChainConfig: _opChainConfigs[i] - }); - } + // Upgrade the L1ERC721Bridge contract. + upgradeTo( + _opChainConfig.proxyAdmin, + address(IL1ERC721Bridge(opChainAddrs.l1ERC721Bridge)), + _impls.l1ERC721BridgeImpl + ); + } - // Separate context to avoid stack too deep. - { - // Now retrieve the permissionless game. - IFaultDisputeGame permissionlessDisputeGame = - IFaultDisputeGame(address(getGameImplementation(dgf, GameTypes.CANNON))); - - // If it exists, replace its implementation. - if (address(permissionlessDisputeGame) != address(0)) { - // Create a new DelayedWETH for the permissionless game. - IDelayedWETH permissionlessDelayedWeth = IDelayedWETH( - payable( - deployProxy({ - _l2ChainId: l2ChainId, - _proxyAdmin: _opChainConfigs[i].proxyAdmin, - _saltMixer: reusableSaltMixer(_opChainConfigs[i]), - _contractName: "PermissionlessDelayedWETH-U16a" - }) - ) - ); - - // Initialize the DelayedWETH. - upgradeToAndCall( - _opChainConfigs[i].proxyAdmin, - address(permissionlessDelayedWeth), - impls.delayedWETHImpl, - abi.encodeCall(IDelayedWETH.initialize, (_opChainConfigs[i].systemConfigProxy)) - ); - - // Fix for stack too deep - OPContractsManager.OpChainConfig memory opChainConfig = _opChainConfigs[i]; - // Deploy and set a new permissionless game to update its prestate - deployAndSetNewGameImpl({ - _l2ChainId: l2ChainId, - _disputeGame: IDisputeGame(address(permissionlessDisputeGame)), - _newDelayedWeth: permissionlessDelayedWeth, - _newAnchorStateRegistryProxy: anchorStateRegistry, - _gameType: GameTypes.CANNON, - _opChainConfig: opChainConfig - }); - } - } + // All chains have the PermissionedDisputeGame, grab that. + IPermissionedDisputeGame permissionedDisputeGame = + IPermissionedDisputeGame(address(getGameImplementation(dgf, GameTypes.PERMISSIONED_CANNON))); + + // Update the PermissionedDisputeGame. + // We're reusing the same DelayedWETH and ASR contracts. + deployAndSetNewGameImpl({ + _l2ChainId: _l2ChainId, + _disputeGame: IDisputeGame(address(permissionedDisputeGame)), + _newDelayedWeth: permissionedDisputeGame.weth(), + _newAnchorStateRegistryProxy: permissionedDisputeGame.anchorStateRegistry(), + _gameType: GameTypes.PERMISSIONED_CANNON, + _opChainConfig: _opChainConfig + }); - // Emit the upgraded event with the address of the caller. Since this will be a delegatecall, - // the caller will be the value of the ADDRESS opcode. - emit Upgraded(l2ChainId, _opChainConfigs[i].systemConfigProxy, address(this)); + // Now retrieve the permissionless game. + IFaultDisputeGame permissionlessDisputeGame = + IFaultDisputeGame(address(getGameImplementation(dgf, GameTypes.CANNON))); + + // If it exists, replace its implementation. + // We're reusing the same DelayedWETH and ASR contracts. + if (address(permissionlessDisputeGame) != address(0)) { + deployAndSetNewGameImpl({ + _l2ChainId: _l2ChainId, + _disputeGame: IDisputeGame(address(permissionlessDisputeGame)), + _newDelayedWeth: permissionlessDisputeGame.weth(), + _newAnchorStateRegistryProxy: permissionlessDisputeGame.anchorStateRegistry(), + _gameType: GameTypes.CANNON, + _opChainConfig: _opChainConfig + }); } } @@ -944,12 +836,7 @@ contract OPContractsManagerUpgrader is OPContractsManagerBase { OPContractsManager.Implementations memory impls = getImplementations(); // Attempt to upgrade. If the ProxyAdmin is not the SuperchainConfig's admin, this will revert. - upgradeToAndCall( - _superchainProxyAdmin, - address(_superchainConfig), - impls.superchainConfigImpl, - abi.encodeCall(ISuperchainConfig.upgrade, ()) - ); + upgradeTo(_superchainProxyAdmin, address(_superchainConfig), impls.superchainConfigImpl); } /// @notice Updates the implementation of a proxy without calling the initializer. @@ -1899,9 +1786,9 @@ contract OPContractsManager is ISemver { // -------- Constants and Variables -------- - /// @custom:semver 3.2.0 + /// @custom:semver 3.3.0 function version() public pure virtual returns (string memory) { - return "3.2.0"; + return "3.3.0"; } OPContractsManagerGameTypeAdder public immutable opcmGameTypeAdder; diff --git a/packages/contracts-bedrock/src/L1/OPContractsManagerStandardValidator.sol b/packages/contracts-bedrock/src/L1/OPContractsManagerStandardValidator.sol index c13d51d8ba358..f4ad8630b71a2 100644 --- a/packages/contracts-bedrock/src/L1/OPContractsManagerStandardValidator.sol +++ b/packages/contracts-bedrock/src/L1/OPContractsManagerStandardValidator.sol @@ -38,8 +38,8 @@ import { IProxyAdminOwnedBase } from "interfaces/L1/IProxyAdminOwnedBase.sol"; /// before and after an upgrade. contract OPContractsManagerStandardValidator is ISemver { /// @notice The semantic version of the OPContractsManagerStandardValidator contract. - /// @custom:semver 1.15.0 - string public constant version = "1.15.0"; + /// @custom:semver 1.16.0 + string public constant version = "1.16.0"; /// @notice The SuperchainConfig contract. ISuperchainConfig public superchainConfig; @@ -394,7 +394,7 @@ contract OPContractsManagerStandardValidator is ISemver { if (DevFeatures.isDevFeatureEnabled(devFeatureBitmap, DevFeatures.OPTIMISM_PORTAL_INTEROP)) { _errors = internalRequire( - LibString.eq(getVersion(address(_portal)), string.concat(getVersion(optimismPortalImpl), "+interop")), + LibString.eq(getVersion(address(_portal)), string.concat(getVersion(optimismPortalInteropImpl))), "PORTAL-10", _errors ); diff --git a/packages/contracts-bedrock/src/L1/OptimismPortal2.sol b/packages/contracts-bedrock/src/L1/OptimismPortal2.sol index 36f69639d6ffe..9229283194760 100644 --- a/packages/contracts-bedrock/src/L1/OptimismPortal2.sol +++ b/packages/contracts-bedrock/src/L1/OptimismPortal2.sol @@ -205,9 +205,9 @@ contract OptimismPortal2 is Initializable, ResourceMetering, ReinitializableBase error OptimismPortal_InvalidLockboxState(); /// @notice Semantic version. - /// @custom:semver 5.0.0 + /// @custom:semver 5.1.0 function version() public pure virtual returns (string memory) { - return "5.0.0"; + return "5.1.0"; } /// @param _proofMaturityDelaySeconds The proof maturity delay in seconds. @@ -246,19 +246,6 @@ contract OptimismPortal2 is Initializable, ResourceMetering, ReinitializableBase __ResourceMetering_init(); } - /// @notice Upgrades the OptimismPortal contract to have a reference to the AnchorStateRegistry and SystemConfig - /// @param _anchorStateRegistry AnchorStateRegistry contract. - function upgrade(IAnchorStateRegistry _anchorStateRegistry) external reinitializer(initVersion()) { - // Upgrade transactions must come from the ProxyAdmin or its owner. - _assertOnlyProxyAdminOrProxyAdminOwner(); - - // Assert that the lockbox state is valid. - _assertValidLockboxState(); - - // Now perform upgrade logic. - anchorStateRegistry = _anchorStateRegistry; - } - /// @notice Getter for the current paused status. function paused() public view returns (bool) { return systemConfig.paused(); diff --git a/packages/contracts-bedrock/src/L1/OptimismPortalInterop.sol b/packages/contracts-bedrock/src/L1/OptimismPortalInterop.sol index 94a24e5074bd5..54db98d889f8f 100644 --- a/packages/contracts-bedrock/src/L1/OptimismPortalInterop.sol +++ b/packages/contracts-bedrock/src/L1/OptimismPortalInterop.sol @@ -229,13 +229,13 @@ contract OptimismPortalInterop is Initializable, ResourceMetering, Reinitializab error OptimismPortal_MigratingToSameRegistry(); /// @notice Semantic version. - /// @custom:semver 5.0.0+interop + /// @custom:semver 5.1.0+interop function version() public pure virtual returns (string memory) { - return "5.0.0+interop"; + return "5.1.0+interop"; } /// @param _proofMaturityDelaySeconds The proof maturity delay in seconds. - constructor(uint256 _proofMaturityDelaySeconds) ReinitializableBase(3) { + constructor(uint256 _proofMaturityDelaySeconds) ReinitializableBase(4) { PROOF_MATURITY_DELAY_SECONDS = _proofMaturityDelaySeconds; _disableInitializers(); } diff --git a/packages/contracts-bedrock/src/L1/SuperchainConfig.sol b/packages/contracts-bedrock/src/L1/SuperchainConfig.sol index 870a35e134428..c0157fef35cfa 100644 --- a/packages/contracts-bedrock/src/L1/SuperchainConfig.sol +++ b/packages/contracts-bedrock/src/L1/SuperchainConfig.sol @@ -9,9 +9,6 @@ import { ReinitializableBase } from "src/universal/ReinitializableBase.sol"; // Interfaces import { ISemver } from "interfaces/universal/ISemver.sol"; -// Libraries -import { Storage } from "src/libraries/Storage.sol"; - /// @custom:proxied true /// @custom:audit none This contracts is not yet audited. /// @title SuperchainConfig @@ -59,8 +56,8 @@ contract SuperchainConfig is ProxyAdminOwnedBase, Initializable, Reinitializable event ConfigUpdate(UpdateType indexed updateType, bytes data); /// @notice Semantic version. - /// @custom:semver 2.3.0 - string public constant version = "2.3.0"; + /// @custom:semver 2.4.0 + string public constant version = "2.4.0"; /// @notice Constructs the SuperchainConfig contract. constructor() ReinitializableBase(2) { @@ -77,28 +74,6 @@ contract SuperchainConfig is ProxyAdminOwnedBase, Initializable, Reinitializable _setGuardian(_guardian); } - /// @notice Upgrades the SuperchainConfig contract. - function upgrade() external reinitializer(initVersion()) { - // Upgrade transactions must come from the ProxyAdmin or its owner. - _assertOnlyProxyAdminOrProxyAdminOwner(); - - // Now perform upgrade logic. - // Transfer the guardian into the new variable and clear the old storage slot. - // We generally do not clear out old storage slots but in the case of the SuperchainConfig - // these are the only spacer slots, they aren't cleanly represented by spacer variables, - // and we can get rid of them now and never think about them again later. - bytes32 guardianSlot = bytes32(uint256(keccak256("superchainConfig.guardian")) - 1); - _setGuardian(Storage.getAddress(guardianSlot)); - Storage.setBytes32(guardianSlot, bytes32(0)); - - // Clear the old paused slot. - // Note that if the pause was active while the upgrade was happening, the system will no - // longer be paused after the upgrade. Upgrades should generally not ever be executed while - // the system is paused, but it's worth noting that this is the case. - bytes32 pausedSlot = bytes32(uint256(keccak256("superchainConfig.paused")) - 1); - Storage.setBytes32(pausedSlot, bytes32(0)); - } - /// @notice Returns the duration after which a pause expires. /// @return The duration after which a pause expires. function pauseExpiry() external pure returns (uint256) { diff --git a/packages/contracts-bedrock/src/L1/SystemConfig.sol b/packages/contracts-bedrock/src/L1/SystemConfig.sol index 7910e6f9d073f..472c7997b6bc8 100644 --- a/packages/contracts-bedrock/src/L1/SystemConfig.sol +++ b/packages/contracts-bedrock/src/L1/SystemConfig.sol @@ -154,9 +154,9 @@ contract SystemConfig is ProxyAdminOwnedBase, OwnableUpgradeable, Reinitializabl error SystemConfig_InvalidFeatureState(); /// @notice Semantic version. - /// @custom:semver 3.7.0 + /// @custom:semver 3.8.0 function version() public pure virtual returns (string memory) { - return "3.7.0"; + return "3.8.0"; } /// @notice Constructs the SystemConfig contract. @@ -225,27 +225,6 @@ contract SystemConfig is ProxyAdminOwnedBase, OwnableUpgradeable, Reinitializabl superchainConfig = _superchainConfig; } - /// @notice Upgrades the SystemConfig by adding a reference to the SuperchainConfig. - /// @param _l2ChainId The L2 chain ID that this SystemConfig configures. - /// @param _superchainConfig The SuperchainConfig contract address. - function upgrade(uint256 _l2ChainId, ISuperchainConfig _superchainConfig) external reinitializer(initVersion()) { - // Upgrade transactions must come from the ProxyAdmin or its owner. - _assertOnlyProxyAdminOrProxyAdminOwner(); - - // Now perform upgrade logic. - // Set the L2 chain ID. - l2ChainId = _l2ChainId; - - // Set the SuperchainConfig contract. - superchainConfig = _superchainConfig; - - // Clear out the old dispute game factory address, it's derived now. We get rid of this - // storage slot because it doesn't use structured storage and we can't use a spacer - // variable to block it off. - bytes32 disputeGameFactorySlot = bytes32(uint256(keccak256("systemconfig.disputegamefactory")) - 1); - Storage.setBytes32(disputeGameFactorySlot, bytes32(0)); - } - /// @notice Returns the minimum L2 gas limit that can be safely set for the system to /// operate. The L2 gas limit must be larger than or equal to the amount of /// gas that is allocated for deposits per block plus the amount of gas that diff --git a/packages/contracts-bedrock/test/L1/L1CrossDomainMessenger.t.sol b/packages/contracts-bedrock/test/L1/L1CrossDomainMessenger.t.sol index a48bc710d3e9c..ea464f5ae595e 100644 --- a/packages/contracts-bedrock/test/L1/L1CrossDomainMessenger.t.sol +++ b/packages/contracts-bedrock/test/L1/L1CrossDomainMessenger.t.sol @@ -166,81 +166,6 @@ contract L1CrossDomainMessenger_Initialize_Test is L1CrossDomainMessenger_TestIn } } -/// @title L1CrossDomainMessenger_Upgrade_Test -/// @notice Reusable test for the current `upgrade` function in the L1CrossDomainMessenger -/// contract. If the `upgrade` function is changed, tests inside of this contract should be -/// updated to reflect the new function. If the `upgrade` function is removed, remove the -/// corresponding tests but leave this contract in place so it\'s easy to add tests back -/// in the future. -contract L1CrossDomainMessenger_Upgrade_Test is L1CrossDomainMessenger_TestInit { - /// @notice Tests that the upgrade() function succeeds. - function test_upgrade_succeeds() external { - // Get the slot for _initial. - StorageSlot memory slot = ForgeArtifacts.getSlot("L1CrossDomainMessenger", "_initialized"); - - // Set the initialized slot to 0. - vm.store(address(l1CrossDomainMessenger), bytes32(slot.slot), bytes32(0)); - - // Verify the initial systemConfig slot is non-zero. - StorageSlot memory systemConfigSlot = ForgeArtifacts.getSlot("L1CrossDomainMessenger", "systemConfig"); - vm.store(address(l1CrossDomainMessenger), bytes32(systemConfigSlot.slot), bytes32(uint256(1))); - assertNotEq(address(l1CrossDomainMessenger.systemConfig()), address(0)); - assertNotEq(vm.load(address(l1CrossDomainMessenger), bytes32(systemConfigSlot.slot)), bytes32(0)); - - ISystemConfig newSystemConfig = ISystemConfig(address(0xdeadbeef)); - - // Trigger upgrade(). - vm.prank(address(l1CrossDomainMessenger.proxyAdmin())); - l1CrossDomainMessenger.upgrade(newSystemConfig); - - // Verify that the systemConfig was updated. - assertEq(address(l1CrossDomainMessenger.systemConfig()), address(newSystemConfig)); - } - - /// @notice Tests that the upgrade() function reverts if called a second time. - function test_upgrade_upgradeTwice_reverts() external { - // Get the slot for _initialized. - StorageSlot memory slot = ForgeArtifacts.getSlot("L1CrossDomainMessenger", "_initialized"); - - // Set the initialized slot to 0. - vm.store(address(l1CrossDomainMessenger), bytes32(slot.slot), bytes32(0)); - - // Create a new SystemConfig contract - ISystemConfig newSystemConfig = ISystemConfig(address(0xdeadbeef)); - - // Trigger first upgrade. - vm.prank(address(l1CrossDomainMessenger.proxyAdmin())); - l1CrossDomainMessenger.upgrade(newSystemConfig); - - // Try to trigger second upgrade. - vm.prank(address(l1CrossDomainMessenger.proxyAdmin())); - vm.expectRevert("Initializable: contract is already initialized"); - l1CrossDomainMessenger.upgrade(newSystemConfig); - } - - /// @notice Tests that the upgrade() function reverts if called by a non-proxy admin or owner. - /// @param _sender The address of the sender to test. - function testFuzz_upgrade_notProxyAdminOrProxyAdminOwner_reverts(address _sender) public { - // Prank as the not ProxyAdmin or ProxyAdmin owner. - vm.assume(_sender != address(proxyAdmin) && _sender != proxyAdminOwner); - - // Get the slot for _initialized. - StorageSlot memory slot = ForgeArtifacts.getSlot("L1CrossDomainMessenger", "_initialized"); - - // Set the initialized slot to 0. - vm.store(address(l1CrossDomainMessenger), bytes32(slot.slot), bytes32(0)); - - // Create a new SystemConfig contract - ISystemConfig newSystemConfig = ISystemConfig(address(0xdeadbeef)); - - // Call the `upgrade` function with the sender - // Expect the revert with `ProxyAdminOwnedBase_NotProxyAdminOrProxyAdminOwner` selector - vm.prank(_sender); - vm.expectRevert(IProxyAdminOwnedBase.ProxyAdminOwnedBase_NotProxyAdminOrProxyAdminOwner.selector); - l1CrossDomainMessenger.upgrade(newSystemConfig); - } -} - /// @title L1CrossDomainMessenger_Paused_Test /// @notice Tests for the `paused` functionality of the L1CrossDomainMessenger. contract L1CrossDomainMessenger_Paused_Test is L1CrossDomainMessenger_TestInit { diff --git a/packages/contracts-bedrock/test/L1/L1ERC721Bridge.t.sol b/packages/contracts-bedrock/test/L1/L1ERC721Bridge.t.sol index 21bdf66369746..8bf3d99f0f69a 100644 --- a/packages/contracts-bedrock/test/L1/L1ERC721Bridge.t.sol +++ b/packages/contracts-bedrock/test/L1/L1ERC721Bridge.t.sol @@ -139,78 +139,6 @@ contract L1ERC721Bridge_Initialize_Test is L1ERC721Bridge_TestInit { } } -/// @title L1ERC721Bridge_Upgrade_Test -/// @notice Reusable test for the current upgrade() function in the L1ERC721Bridge contract. If -/// the upgrade() function is changed, tests inside of this contract should be updated to -/// reflect the new function. If the upgrade() function is removed, remove the -/// corresponding tests but leave this contract in place so it's easy to add tests back -/// in the future. -contract L1ERC721Bridge_Upgrade_Test is L1ERC721Bridge_TestInit { - /// @notice Tests that the upgrade() function succeeds. - function test_upgrade_succeeds() external { - // Get the slot for _initialized. - StorageSlot memory slot = ForgeArtifacts.getSlot("L1ERC721Bridge", "_initialized"); - - // Set the initialized slot to 0. - vm.store(address(l1ERC721Bridge), bytes32(slot.slot), bytes32(0)); - - // Verify the initial systemConfig slot is non-zero. - StorageSlot memory systemConfigSlot = ForgeArtifacts.getSlot("L1ERC721Bridge", "systemConfig"); - vm.store(address(l1ERC721Bridge), bytes32(systemConfigSlot.slot), bytes32(uint256(1))); - assertNotEq(address(l1ERC721Bridge.systemConfig()), address(0)); - assertNotEq(vm.load(address(l1ERC721Bridge), bytes32(systemConfigSlot.slot)), bytes32(0)); - - ISystemConfig newSystemConfig = ISystemConfig(address(0xdeadbeef)); - - // Trigger upgrade(). - vm.prank(address(l1ERC721Bridge.proxyAdmin())); - l1ERC721Bridge.upgrade(newSystemConfig); - - // Verify that the systemConfig was updated. - assertEq(address(l1ERC721Bridge.systemConfig()), address(newSystemConfig)); - } - - /// @notice Tests that the upgrade() function reverts if called a second time. - function test_upgrade_upgradeTwice_reverts() external { - // Get the slot for _initialized. - StorageSlot memory slot = ForgeArtifacts.getSlot("L1ERC721Bridge", "_initialized"); - - // Set the initialized slot to 0. - vm.store(address(l1ERC721Bridge), bytes32(slot.slot), bytes32(0)); - - ISystemConfig newSystemConfig = ISystemConfig(address(0xdeadbeef)); - - // Trigger first upgrade. - vm.prank(address(l1ERC721Bridge.proxyAdmin())); - l1ERC721Bridge.upgrade(newSystemConfig); - - // Try to trigger second upgrade. - vm.prank(address(l1ERC721Bridge.proxyAdmin())); - vm.expectRevert("Initializable: contract is already initialized"); - l1ERC721Bridge.upgrade(newSystemConfig); - } - - /// @notice Tests that the upgrade() function reverts if called by a non-proxy admin or owner. - /// @param _sender The address of the sender to test. - function testFuzz_upgrade_notProxyAdminOrProxyAdminOwner_reverts(address _sender) public { - // Prank as the not ProxyAdmin or ProxyAdmin owner. - vm.assume(_sender != address(proxyAdmin) && _sender != proxyAdminOwner); - - // Get the slot for _initialized. - StorageSlot memory slot = ForgeArtifacts.getSlot("L1ERC721Bridge", "_initialized"); - - // Set the initialized slot to 0. - vm.store(address(l1ERC721Bridge), bytes32(slot.slot), bytes32(0)); - - // Expect the revert with `ProxyAdminOwnedBase_NotProxyAdminOrProxyAdminOwner` selector - vm.expectRevert(IProxyAdminOwnedBase.ProxyAdminOwnedBase_NotProxyAdminOrProxyAdminOwner.selector); - - // Call the `upgrade` function with the sender - vm.prank(_sender); - l1ERC721Bridge.upgrade(ISystemConfig(address(0xdeadbeef))); - } -} - /// @title L1ERC721Bridge_SuperchainConfig_Test /// @notice Test contract for L1ERC721Bridge `superchainConfig` function. contract L1ERC721Bridge_SuperchainConfig_Test is L1ERC721Bridge_TestInit { diff --git a/packages/contracts-bedrock/test/L1/L1StandardBridge.t.sol b/packages/contracts-bedrock/test/L1/L1StandardBridge.t.sol index 15847cadb8036..03ebb72969608 100644 --- a/packages/contracts-bedrock/test/L1/L1StandardBridge.t.sol +++ b/packages/contracts-bedrock/test/L1/L1StandardBridge.t.sol @@ -218,71 +218,6 @@ contract L1StandardBridge_Initialize_Test is CommonTest { } } -/// @title L1StandardBridge_Upgrade_Test -/// @notice Reusable test for the current upgrade() function in the L1StandardBridge contract. If -/// the upgrade() function is changed, tests inside of this contract should be updated to -/// reflect the new function. If the upgrade() function is removed, remove the -/// corresponding tests but leave this contract in place so it's easy to add tests back -/// in the future. -contract L1StandardBridge_Upgrade_Test is CommonTest { - /// @notice Tests that the upgrade() function succeeds. - function test_upgrade_succeeds() external { - // Get the slot for _initialized. - StorageSlot memory slot = ForgeArtifacts.getSlot("L1StandardBridge", "_initialized"); - - // Set the initialized slot to 0. - vm.store(address(l1StandardBridge), bytes32(slot.slot), bytes32(0)); - - // Verify the initial systemConfig slot is non-zero. - StorageSlot memory systemConfigSlot = ForgeArtifacts.getSlot("L1StandardBridge", "systemConfig"); - vm.store(address(l1StandardBridge), bytes32(systemConfigSlot.slot), bytes32(uint256(1))); - assertNotEq(address(l1StandardBridge.systemConfig()), address(0)); - assertNotEq(vm.load(address(l1StandardBridge), bytes32(systemConfigSlot.slot)), bytes32(0)); - - ISystemConfig newSystemConfig = ISystemConfig(address(0xdeadbeef)); - - // Trigger upgrade(). - vm.prank(address(l1StandardBridge.proxyAdmin())); - l1StandardBridge.upgrade(newSystemConfig); - - // Verify that the systemConfig was updated. - assertEq(address(l1StandardBridge.systemConfig()), address(newSystemConfig)); - } - - /// @notice Tests that the upgrade() function reverts if called a second time. - function test_upgrade_upgradeTwice_reverts() external { - // Get the slot for _initialized. - StorageSlot memory slot = ForgeArtifacts.getSlot("L1StandardBridge", "_initialized"); - - // Set the initialized slot to 0. - vm.store(address(l1StandardBridge), bytes32(slot.slot), bytes32(0)); - - ISystemConfig newSystemConfig = ISystemConfig(address(0xdeadbeef)); - - // Trigger first upgrade. - vm.prank(address(l1StandardBridge.proxyAdmin())); - l1StandardBridge.upgrade(newSystemConfig); - - // Try to trigger second upgrade. - vm.prank(address(l1StandardBridge.proxyAdmin())); - vm.expectRevert("Initializable: contract is already initialized"); - l1StandardBridge.upgrade(newSystemConfig); - } - - /// @notice Verifies upgrade reverts with random unauthorized addresses - /// @param _sender Random address for access control test - function testFuzz_upgrade_notProxyAdminOrProxyAdminOwner_reverts(address _sender) public { - vm.assume(_sender != address(proxyAdmin) && _sender != proxyAdminOwner); - - StorageSlot memory slot = ForgeArtifacts.getSlot("L1StandardBridge", "_initialized"); - vm.store(address(l1StandardBridge), bytes32(slot.slot), bytes32(0)); - - vm.expectRevert(IProxyAdminOwnedBase.ProxyAdminOwnedBase_NotProxyAdminOrProxyAdminOwner.selector); - vm.prank(_sender); - l1StandardBridge.upgrade(ISystemConfig(address(0xdeadbeef))); - } -} - /// @title L1StandardBridge_Paused_Test /// @notice Tests the `paused` function of the `L1StandardBridge` contract. contract L1StandardBridge_Paused_Test is CommonTest { diff --git a/packages/contracts-bedrock/test/L1/OPContractsManager.t.sol b/packages/contracts-bedrock/test/L1/OPContractsManager.t.sol index ed5b4b495e516..4df6358cae141 100644 --- a/packages/contracts-bedrock/test/L1/OPContractsManager.t.sol +++ b/packages/contracts-bedrock/test/L1/OPContractsManager.t.sol @@ -17,7 +17,6 @@ import { Config } from "scripts/libraries/Config.sol"; // Libraries import { EIP1967Helper } from "test/mocks/EIP1967Helper.sol"; -import { Blueprint } from "src/libraries/Blueprint.sol"; import { GameType, Duration, Hash, Claim } from "src/dispute/lib/LibUDT.sol"; import { Proposal, GameTypes } from "src/dispute/lib/Types.sol"; import { DevFeatures } from "src/libraries/DevFeatures.sol"; @@ -25,7 +24,6 @@ import { DevFeatures } from "src/libraries/DevFeatures.sol"; // Interfaces import { IAnchorStateRegistry } from "interfaces/dispute/IAnchorStateRegistry.sol"; import { IOptimismPortal2 } from "interfaces/L1/IOptimismPortal2.sol"; -import { IProxy } from "interfaces/universal/IProxy.sol"; import { IProxyAdmin } from "interfaces/universal/IProxyAdmin.sol"; import { ISuperchainConfig } from "interfaces/L1/ISuperchainConfig.sol"; import { IProtocolVersions } from "interfaces/L1/IProtocolVersions.sol"; @@ -41,7 +39,7 @@ import { IOPContractsManagerInteropMigrator, IOPContractsManagerUpgrader } from "interfaces/L1/IOPContractsManager.sol"; -import { ISemver } from "interfaces/universal/ISemver.sol"; +import { IOPContractsManagerStandardValidator } from "interfaces/L1/IOPContractsManagerStandardValidator.sol"; import { IETHLockbox } from "interfaces/L1/IETHLockbox.sol"; import { IBigStepper } from "interfaces/dispute/IBigStepper.sol"; import { ISuperFaultDisputeGame } from "interfaces/dispute/ISuperFaultDisputeGame.sol"; @@ -110,6 +108,9 @@ contract OPContractsManager_Upgrade_Harness is CommonTest { // The ImplementationSet event emitted by the DisputeGameFactory contract. event ImplementationSet(address indexed impl, GameType indexed gameType); + /// @notice Thrown when testing with an unsupported chain ID. + error UnsupportedChainId(); + uint256 l2ChainId; address upgrader; IOPContractsManager.OpChainConfig[] opChainConfigs; @@ -166,157 +167,142 @@ contract OPContractsManager_Upgrade_Harness is CommonTest { vm.store(address(superchainConfig), bytes32(0), slot0); } - function expectEmitUpgraded(address impl, address proxy) public { - vm.expectEmit(proxy); - emit Upgraded(impl); - } - - function runUpgrade16aUpgradeAndChecks(address _delegateCaller) public { - IOPContractsManager.Implementations memory impls = opcm.implementations(); - - // Always trigger U16a firstly by calling upgradeSuperchainConfig to ensure that the - // SuperchainConfig contract is upgraded. - { - ISuperchainConfig superchainConfig = ISuperchainConfig(artifacts.mustGetAddress("SuperchainConfigProxy")); - expectEmitUpgraded(impls.superchainConfigImpl, address(superchainConfig)); - - address superchainPAO = IProxyAdmin(EIP1967Helper.getAdmin(address(superchainConfig))).owner(); - vm.etch(superchainPAO, vm.getDeployedCode("test/mocks/Callers.sol:DelegateCaller")); - - vm.mockCall(address(superchainConfig), abi.encodeCall(ISuperchainConfig.version, ()), abi.encode("2.2.0")); - DelegateCaller(superchainPAO).dcForward( - address(opcm), - abi.encodeCall(IOPContractsManager.upgradeSuperchainConfig, (superchainConfig, superchainProxyAdmin)) - ); - vm.mockCall(address(superchainConfig), abi.encodeCall(ISuperchainConfig.version, ()), abi.encode("2.3.0")); - } + /// @notice Helper function that runs an OPCM upgrade, asserts that the upgrade was successful, + /// asserts that it fits within a certain amount of gas, and runs the StandardValidator + /// over the result. + /// @param _opcm The OPCM contract to upgrade with. + /// @param _delegateCaller The address of the delegate caller to use for the upgrade. + /// @param _revertBytes The bytes of the revert to expect. + function _runOpcmUpgradeAndChecks( + IOPContractsManager _opcm, + address _delegateCaller, + bytes memory _revertBytes + ) + internal + { + // Always start by upgrading the SuperchainConfig contract. + // Temporarily replace the superchainPAO with a DelegateCaller. + address superchainPAO = IProxyAdmin(EIP1967Helper.getAdmin(address(superchainConfig))).owner(); + bytes memory superchainPAOCode = address(superchainPAO).code; + vm.etch(superchainPAO, vm.getDeployedCode("test/mocks/Callers.sol:DelegateCaller")); - // Predict the address of the new AnchorStateRegistry proxy. - // Subcontext to avoid stack too deep. - address asr; - try optimismPortal2.anchorStateRegistry() returns (IAnchorStateRegistry asr_) { - asr = address(asr_); - } catch { - // Compute the salt using the system config address. - bytes32 salt = keccak256( - abi.encode( - l2ChainId, - string.concat(string(bytes.concat(bytes32(uint256(uint160(address(systemConfig))))))), - "AnchorStateRegistry-U16" - ) + // Execute the SuperchainConfig upgrade. + // nosemgrep: sol-safety-trycatch-eip150 + try DelegateCaller(superchainPAO).dcForward( + address(_opcm), + abi.encodeCall(IOPContractsManager.upgradeSuperchainConfig, (superchainConfig, superchainProxyAdmin)) + ) { + // Great, the upgrade succeeded. + } catch (bytes memory reason) { + // Only acceptable revert reason is the SuperchainConfig already being up to date. This + // try/catch is better than checking the version via the implementations struct because + // the implementations struct interface can change between OPCM versions which would + // cause the test to break and be a pain to resolve. + assertTrue( + bytes4(reason) + == IOPContractsManagerUpgrader.OPContractsManagerUpgrader_SuperchainConfigAlreadyUpToDate.selector, + "Revert reason other than SuperchainConfigAlreadyUpToDate" ); - - // Use the actual proxy instead of the local code so we can reuse this test. - address proxyBp = opcm.blueprints().proxy; - Blueprint.Preamble memory preamble = Blueprint.parseBlueprintPreamble(proxyBp.code); - bytes memory initCode = bytes.concat(preamble.initcode, abi.encode(proxyAdmin)); - asr = vm.computeCreate2Address(salt, keccak256(initCode), _delegateCaller); - vm.label(asr, "NewAnchorStateRegistryProxy"); } - // Grab the PermissionedDisputeGame and FaultDisputeGame implementations before upgrade. - address oldPDGImpl = address(disputeGameFactory.gameImpls(GameTypes.PERMISSIONED_CANNON)); - address oldFDGImpl = address(disputeGameFactory.gameImpls(GameTypes.CANNON)); - IPermissionedDisputeGame oldPDG = IPermissionedDisputeGame(oldPDGImpl); - IFaultDisputeGame oldFDG = IFaultDisputeGame(oldFDGImpl); + // Reset the superchainPAO to the original code. + vm.etch(superchainPAO, superchainPAOCode); - // Expect the SystemConfig upgraded. - expectEmitUpgraded(impls.systemConfigImpl, address(systemConfig)); - - // Expect the OptimismPortal to be upgraded, impl depends on interop feature. - if (opcm.isDevFeatureEnabled(DevFeatures.OPTIMISM_PORTAL_INTEROP)) { - expectEmitUpgraded(impls.optimismPortalInteropImpl, address(optimismPortal2)); - } else { - expectEmitUpgraded(impls.optimismPortalImpl, address(optimismPortal2)); - } - - // We always expect the PermissionedDisputeGame to be deployed. We don't yet know the - // address of the new permissionedGame which will be deployed by the - // OPContractsManager.upgrade() call, so ignore the first topic. - vm.expectEmit(false, true, true, true, address(disputeGameFactory)); - emit ImplementationSet(address(0), GameTypes.PERMISSIONED_CANNON); - - // If the old FaultDisputeGame exists, we expect it to be upgraded. - if (address(oldFDG) != address(0)) { - // Ignore the first topic for the same reason as the previous comment. - vm.expectEmit(false, true, true, true, address(disputeGameFactory)); - emit ImplementationSet(address(0), GameTypes.CANNON); - } - - vm.expectEmit(address(_delegateCaller)); - emit Upgraded(l2ChainId, systemConfig, address(_delegateCaller)); - - // Temporarily replace the upgrader with a DelegateCaller so we can test the upgrade, - // then reset its code to the original code. + // Temporarily replace the upgrader with a DelegateCaller. bytes memory delegateCallerCode = address(_delegateCaller).code; vm.etch(_delegateCaller, vm.getDeployedCode("test/mocks/Callers.sol:DelegateCaller")); - // Execute the upgrade. - // We use the new format here, not the legacy one. + // Expect the revert if one is specified. + if (_revertBytes.length > 0) { + vm.expectRevert(_revertBytes); + } + + // Execute the chain upgrade. DelegateCaller(_delegateCaller).dcForward( - address(opcm), abi.encodeCall(IOPContractsManager.upgrade, (opChainConfigs)) + address(_opcm), abi.encodeCall(IOPContractsManager.upgrade, (opChainConfigs)) ); - // Less than 90% of the gas target of 20M to account for the gas used by using Safe. + // Return early if a revert was expected. Otherwise we'll get errors below. + if (_revertBytes.length > 0) { + return; + } + + // Less than 90% of the gas target of 2**24 (EIP-7825) to account for the gas used by + // using Safe. + uint256 fusakaLimit = 2 ** 24; VmSafe.Gas memory gas = vm.lastCallGas(); - assertLt(gas.gasTotalUsed, 0.9 * 20_000_000, "Upgrade exceeds gas target of 15M"); + assertLt(gas.gasTotalUsed, fusakaLimit * 9 / 10, "Upgrade exceeds gas target of 90% of 2**24 (EIP-7825)"); - // Reset the upgrader's code to the original code. + // Reset the upgrader to the original code. vm.etch(_delegateCaller, delegateCallerCode); - // Grab the new implementations. - address newPDGImpl = address(disputeGameFactory.gameImpls(GameTypes.PERMISSIONED_CANNON)); - IPermissionedDisputeGame pdg = IPermissionedDisputeGame(newPDGImpl); - address newFDGImpl = address(disputeGameFactory.gameImpls(GameTypes.CANNON)); - IFaultDisputeGame fdg = IFaultDisputeGame(newFDGImpl); - - // Check that the PermissionedDisputeGame is upgraded to the expected version, references - // the correct anchor state and has the mipsImpl. Although Upgrade 15 doesn't actually - // change any of this, we might as well check it again. - assertEq(ISemver(address(pdg)).version(), "1.8.0"); - assertEq(address(pdg.vm()), impls.mipsImpl); - assertEq(pdg.l2ChainId(), oldPDG.l2ChainId()); - - // If the old FaultDisputeGame exists, we expect it to be upgraded. Check same as above. - if (address(oldFDG) != address(0)) { - assertEq(ISemver(address(fdg)).version(), "1.8.0"); - assertEq(address(fdg.vm()), impls.mipsImpl); - assertEq(fdg.l2ChainId(), oldFDG.l2ChainId()); + // We expect there to only be one chain config for these tests, you will have to rework + // this test if you add more. + assertEq(opChainConfigs.length, 1); + + // Coverage changes bytecode, so we get various errors. We can safely ignore the result of + // the standard validator in the coverage case, if the validator is failing in coverage + // then it will also fail in other CI tests (unless it's the expected issues, in which case + // we can safely skip). + if (vm.isContext(VmSafe.ForgeContext.Coverage)) { + return; } - // Make sure that the SystemConfig is upgraded to the right version. It must also have the - // right l2ChainId and must be properly initialized. - assertEq(ISemver(address(systemConfig)).version(), "3.7.0"); - assertEq(impls.systemConfigImpl, EIP1967Helper.getImplementation(address(systemConfig))); - assertEq(systemConfig.l2ChainId(), l2ChainId); - DeployUtils.assertInitialized({ _contractAddress: address(systemConfig), _isProxy: true, _slot: 0, _offset: 0 }); - - // Make sure that the OptimismPortal is upgraded correctly. - assertEq(address(optimismPortal2.anchorStateRegistry()), address(asr)); - DeployUtils.assertInitialized({ - _contractAddress: address(optimismPortal2), - _isProxy: true, - _slot: 0, - _offset: 0 - }); + // Grab the validator before we do the error assertion because otherwise the assertion will + // try to apply to this function call instead. + IOPContractsManagerStandardValidator validator = _opcm.opcmStandardValidator(); + + // If the absolute prestate is zero, we will always get a PDDG-40,PLDG-40 error here in the + // standard validator. This happens because an absolute prestate of zero means that the + // user is requesting to use the existing prestate. We could avoid the error by grabbing + // the prestate from the actual contracts, but that doesn't actually give us any valuable + // checks. Easier to just expect the error in this case. + if (opChainConfigs[0].absolutePrestate.raw() == bytes32(0)) { + vm.expectRevert("OPContractsManagerStandardValidator: PDDG-40,PLDG-40"); + } - if (opcm.isDevFeatureEnabled(DevFeatures.OPTIMISM_PORTAL_INTEROP)) { - assertEq(ISemver(address(optimismPortal2)).version(), "5.0.0+interop"); - assertEq(impls.optimismPortalInteropImpl, EIP1967Helper.getImplementation(address(optimismPortal2))); + // Run the StandardValidator checks. + validator.validate( + IOPContractsManagerStandardValidator.ValidationInput({ + proxyAdmin: opChainConfigs[0].proxyAdmin, + sysCfg: opChainConfigs[0].systemConfigProxy, + absolutePrestate: opChainConfigs[0].absolutePrestate.raw(), + l2ChainID: l2ChainId + }), + false + ); + } + + /// @notice Executes all past upgrades that have not yet been executed on mainnet as of the + /// current simulation block defined in the justfile for this package. This function + /// might be empty if there are no previous upgrades to execute. You should remove + /// upgrades from this function once they've been executed on mainnet and the + /// simulation block has been bumped beyond the execution block. + /// @param _delegateCaller The address of the delegate caller to use for the upgrade. + function runPastUpgrades(address _delegateCaller) internal { + // Run past upgrades depending on network. + if (block.chainid == 1) { + // Mainnet + // U16a + _runOpcmUpgradeAndChecks( + IOPContractsManager(0x8123739C1368C2DEDc8C564255bc417FEEeBFF9D), _delegateCaller, bytes("") + ); } else { - assertEq(ISemver(address(optimismPortal2)).version(), "5.0.0"); - assertEq(impls.optimismPortalImpl, EIP1967Helper.getImplementation(address(optimismPortal2))); + revert UnsupportedChainId(); } + } - // Make sure the new AnchorStateRegistry has the right version and is initialized. - assertEq(ISemver(address(asr)).version(), "3.5.0"); - vm.prank(address(proxyAdmin)); - assertEq(IProxy(payable(asr)).admin(), address(proxyAdmin)); - DeployUtils.assertInitialized({ _contractAddress: address(asr), _isProxy: true, _slot: 0, _offset: 0 }); + /// @notice Executes the current upgrade and checks the results. + /// @param _delegateCaller The address of the delegate caller to use for the upgrade. + function runCurrentUpgrade(address _delegateCaller) public { + _runOpcmUpgradeAndChecks(opcm, _delegateCaller, bytes("")); } - function runUpgradeTestAndChecks(address _delegateCaller) public { - runUpgrade16aUpgradeAndChecks(_delegateCaller); + /// @notice Executes the current upgrade and expects reverts. + /// @param _delegateCaller The address of the delegate caller to use for the upgrade. + /// @param _revertBytes The bytes of the revert to expect. + function runCurrentUpgrade(address _delegateCaller, bytes memory _revertBytes) public { + _runOpcmUpgradeAndChecks(opcm, _delegateCaller, _revertBytes); } } @@ -983,11 +969,14 @@ contract OPContractsManager_Upgrade_Test is OPContractsManager_Upgrade_Harness { function setUp() public override { skipIfNotOpFork("OPContractsManager_Upgrade_Test"); super.setUp(); + + // Run all past upgrades. + runPastUpgrades(upgrader); } function test_upgradeOPChainOnly_succeeds() public { // Run the upgrade test and checks - runUpgradeTestAndChecks(upgrader); + runCurrentUpgrade(upgrader); } function test_verifyOpcmCorrectness_succeeds() public { @@ -1000,7 +989,7 @@ contract OPContractsManager_Upgrade_Test is OPContractsManager_Upgrade_Harness { vm.setEnv("EXPECTED_UPGRADE_CONTROLLER", vm.toString(opcm.upgradeController())); // Run the upgrade test and checks - runUpgradeTestAndChecks(upgrader); + runCurrentUpgrade(upgrader); // Run the verification script without etherscan verification. Hard to run with etherscan // verification in these tests, can do it but means we add even more dependencies to the @@ -1018,7 +1007,7 @@ contract OPContractsManager_Upgrade_Test is OPContractsManager_Upgrade_Harness { opcm.deploy(deployInput); // Try to upgrade the current OPChain - runUpgradeTestAndChecks(upgrader); + runCurrentUpgrade(upgrader); } /// @notice Tests that the absolute prestate can be overridden using the upgrade config. @@ -1037,8 +1026,8 @@ contract OPContractsManager_Upgrade_Test is OPContractsManager_Upgrade_Harness { // Set the absolute prestate input to something non-zero. opChainConfigs[0].absolutePrestate = Claim.wrap(bytes32(uint256(1))); - // Now run Upgrade 16a. - runUpgrade16aUpgradeAndChecks(upgrader); + // Run the upgrade. + runCurrentUpgrade(upgrader); // Get the absolute prestate after the upgrade Claim pdgPrestateAfter = IPermissionedDisputeGame( @@ -1069,8 +1058,8 @@ contract OPContractsManager_Upgrade_Test is OPContractsManager_Upgrade_Harness { // Set the absolute prestate input to zero. opChainConfigs[0].absolutePrestate = Claim.wrap(bytes32(0)); - // Now run Upgrade 16a. - runUpgrade16aUpgradeAndChecks(upgrader); + // Run the upgrade. + runCurrentUpgrade(upgrader); // Get the absolute prestate after the upgrade Claim pdgPrestateAfter = IPermissionedDisputeGame( @@ -1091,31 +1080,18 @@ contract OPContractsManager_Upgrade_Test is OPContractsManager_Upgrade_Harness { } function test_upgrade_notProxyAdminOwner_reverts() public { - ISuperchainConfig superchainConfig = ISuperchainConfig(artifacts.mustGetAddress("SuperchainConfigProxy")); - // Mock the call to superchainConfig version so that it passes the assertion that the superchainConfig is - // already upgraded. - vm.mockCall(address(superchainConfig), abi.encodeCall(ISuperchainConfig.version, ()), abi.encode("2.3.0")); - address delegateCaller = makeAddr("delegateCaller"); vm.etch(delegateCaller, vm.getDeployedCode("test/mocks/Callers.sol:DelegateCaller")); assertNotEq(superchainProxyAdmin.owner(), delegateCaller); assertNotEq(proxyAdmin.owner(), delegateCaller); - vm.expectRevert("Ownable: caller is not the owner"); - DelegateCaller(delegateCaller).dcForward( - address(opcm), abi.encodeCall(IOPContractsManager.upgrade, (opChainConfigs)) - ); + runCurrentUpgrade(delegateCaller, bytes("Ownable: caller is not the owner")); } /// @notice Tests that upgrade reverts when absolutePrestate is zero and the existing game also /// has an absolute prestate of zero. function test_upgrade_absolutePrestateNotSet_reverts() public { - ISuperchainConfig superchainConfig = ISuperchainConfig(artifacts.mustGetAddress("SuperchainConfigProxy")); - // Mock the call to superchainConfig version so that it passes the assertion that the superchainConfig is - // already upgraded. - vm.mockCall(address(superchainConfig), abi.encodeCall(ISuperchainConfig.version, ()), abi.encode("2.3.0")); - // Set the config to try to update the absolutePrestate to zero. opChainConfigs[0].absolutePrestate = Claim.wrap(bytes32(0)); @@ -1131,21 +1107,23 @@ contract OPContractsManager_Upgrade_Test is OPContractsManager_Upgrade_Harness { ); // Expect the upgrade to revert with PrestateNotSet. - vm.expectRevert(IOPContractsManager.PrestateNotSet.selector); - DelegateCaller(upgrader).dcForward(address(opcm), abi.encodeCall(IOPContractsManager.upgrade, (opChainConfigs))); + // nosemgrep: sol-style-use-abi-encodecall + runCurrentUpgrade(upgrader, abi.encodeWithSelector(IOPContractsManager.PrestateNotSet.selector)); } /// @notice Tests that the upgrade function reverts when the superchainConfig is not at the expected target version. function test_upgrade_superchainConfigNeedsUpgrade_reverts() public { - vm.mockCall(address(superchainConfig), abi.encodeCall(ISuperchainConfig.version, ()), abi.encode("2.2.0")); + // Force the SuperchainConfig to return an obviously outdated version. + vm.mockCall(address(superchainConfig), abi.encodeCall(ISuperchainConfig.version, ()), abi.encode("0.0.0")); // Try upgrading an OPChain without upgrading its superchainConfig. - vm.expectRevert( + // nosemgrep: sol-style-use-abi-encodecall + runCurrentUpgrade( + upgrader, abi.encodeWithSelector( - IOPContractsManagerUpgrader.OPContractsManagerUpgrader_SuperchainConfigNeedsUpgrade.selector, 0 + IOPContractsManagerUpgrader.OPContractsManagerUpgrader_SuperchainConfigNeedsUpgrade.selector, (0) ) ); - DelegateCaller(upgrader).dcForward(address(opcm), abi.encodeCall(IOPContractsManager.upgrade, (opChainConfigs))); } } @@ -1164,11 +1142,12 @@ contract OPContractsManager_UpgradeSuperchainConfig_Test is OPContractsManager_U IOPContractsManager.Implementations memory impls = opcm.implementations(); ISuperchainConfig superchainConfig = ISuperchainConfig(artifacts.mustGetAddress("SuperchainConfigProxy")); - expectEmitUpgraded(impls.superchainConfigImpl, address(superchainConfig)); address superchainPAO = IProxyAdmin(EIP1967Helper.getAdmin(address(superchainConfig))).owner(); vm.etch(superchainPAO, vm.getDeployedCode("test/mocks/Callers.sol:DelegateCaller")); + vm.expectEmit(address(superchainConfig)); + emit Upgraded(impls.superchainConfigImpl); DelegateCaller(superchainPAO).dcForward( address(opcm), abi.encodeCall(IOPContractsManager.upgradeSuperchainConfig, (superchainConfig, superchainProxyAdmin)) @@ -1209,15 +1188,10 @@ contract OPContractsManager_UpgradeSuperchainConfig_Test is OPContractsManager_U // Set the version of the superchain config to a version that is the target version. vm.clearMockedCalls(); - vm.expectRevert(IOPContractsManagerUpgrader.OPContractsManagerUpgrader_SuperchainConfigAlreadyUpToDate.selector); - DelegateCaller(upgrader).dcForward( - address(opcm), - abi.encodeCall(IOPContractsManager.upgradeSuperchainConfig, (superchainConfig, superchainProxyAdmin)) - ); - - // Set the version of the superchain config to a version that is higher than the target version. - vm.mockCall(address(superchainConfig), abi.encodeCall(ISuperchainConfig.version, ()), abi.encode("3.0.0")); + // Mock the SuperchainConfig to return a very large version. + vm.mockCall(address(superchainConfig), abi.encodeCall(ISuperchainConfig.version, ()), abi.encode("99.99.99")); + // Try to upgrade the SuperchainConfig contract again, should fail. vm.expectRevert(IOPContractsManagerUpgrader.OPContractsManagerUpgrader_SuperchainConfigAlreadyUpToDate.selector); DelegateCaller(upgrader).dcForward( address(opcm), diff --git a/packages/contracts-bedrock/test/L1/OptimismPortal2.t.sol b/packages/contracts-bedrock/test/L1/OptimismPortal2.t.sol index 623f622fcb22d..90691b95afa8f 100644 --- a/packages/contracts-bedrock/test/L1/OptimismPortal2.t.sol +++ b/packages/contracts-bedrock/test/L1/OptimismPortal2.t.sol @@ -326,126 +326,6 @@ contract OptimismPortal2_Initialize_Test is OptimismPortal2_TestInit { } } -/// @title OptimismPortal2_Upgrade_Test -/// @notice Reusable test for the current upgrade() function in the OptimismPortal2 contract. If -/// the upgrade() function is changed, tests inside of this contract should be updated to -/// reflect the new function. If the upgrade() function is removed, remove the -/// corresponding tests but leave this contract in place so it's easy to add tests back -/// in the future. -contract OptimismPortal2_Upgrade_Test is CommonTest { - function setUp() public virtual override { - super.setUp(); - skipIfDevFeatureEnabled(DevFeatures.OPTIMISM_PORTAL_INTEROP); - } - - /// @notice Tests that the upgrade() function succeeds. - function testFuzz_upgrade_succeeds(address _newAnchorStateRegistry, uint256 _balance) external { - // Prevent overflow on an upgrade context - _balance = bound(_balance, 0, type(uint256).max - address(ethLockbox).balance); - - // Get the slot for _initialized. - StorageSlot memory slot = ForgeArtifacts.getSlot("OptimismPortal2", "_initialized"); - - // Set the initialized slot to 0. - vm.store(address(optimismPortal2), bytes32(slot.slot), bytes32(0)); - - // Call the upgrade function. - vm.prank(address(optimismPortal2.proxyAdmin())); - optimismPortal2.upgrade(IAnchorStateRegistry(_newAnchorStateRegistry)); - - // Verify that the initialized slot was updated. - bytes32 initializedSlotAfter = vm.load(address(optimismPortal2), bytes32(slot.slot)); - assertEq(initializedSlotAfter, bytes32(uint256(3))); - - // Assert the portal is properly upgraded. - assertEq(address(optimismPortal2.anchorStateRegistry()), _newAnchorStateRegistry); - } - - /// @notice Tests that the upgrade() function reverts if called a second time. - function test_upgrade_upgradeTwice_reverts() external { - // Get the slot for _initialized. - StorageSlot memory slot = ForgeArtifacts.getSlot("OptimismPortal2", "_initialized"); - - // Set the initialized slot to 0. - vm.store(address(optimismPortal2), bytes32(slot.slot), bytes32(0)); - - // Trigger first upgrade. - vm.prank(address(optimismPortal2.proxyAdmin())); - optimismPortal2.upgrade(IAnchorStateRegistry(address(0xdeadbeef))); - - // Try to trigger second upgrade. - vm.prank(address(optimismPortal2.proxyAdmin())); - vm.expectRevert("Initializable: contract is already initialized"); - optimismPortal2.upgrade(IAnchorStateRegistry(address(0xdeadbeef))); - } - - /// @notice Tests that the upgrade() function reverts if called after initialization. - function test_upgrade_afterInitialization_reverts() external { - // Get the slot for _initialized. - StorageSlot memory slot = ForgeArtifacts.getSlot("OptimismPortal2", "_initialized"); - - // Slot value should be set to 3 (already initialized). - bytes32 initializedSlotBefore = vm.load(address(optimismPortal2), bytes32(slot.slot)); - assertEq(initializedSlotBefore, bytes32(uint256(3))); - - // AnchorStateRegistry address should be non-zero. - assertNotEq(address(optimismPortal2.anchorStateRegistry()), address(0)); - - // SystemConfig address should be non-zero. - assertNotEq(address(optimismPortal2.systemConfig()), address(0)); - - // Try to trigger upgrade(). - vm.expectRevert("Initializable: contract is already initialized"); - optimismPortal2.upgrade(IAnchorStateRegistry(address(0xdeadbeef))); - } - - /// @notice Tests that the upgrade() function reverts if called by a non-proxy admin or owner. - /// @param _sender The address of the sender to test. - function testFuzz_upgrade_notProxyAdminOrProxyAdminOwner_reverts(address _sender) public { - // Prank as the not ProxyAdmin or ProxyAdmin owner. - vm.assume(_sender != address(proxyAdmin) && _sender != proxyAdminOwner); - - // Get the slot for _initialized. - StorageSlot memory slot = ForgeArtifacts.getSlot("OptimismPortal2", "_initialized"); - - // Set the initialized slot to 0. - vm.store(address(optimismPortal2), bytes32(slot.slot), bytes32(0)); - - // Expect the revert with `ProxyAdminOwnedBase_NotProxyAdminOrProxyAdminOwner` selector. - vm.expectRevert(IProxyAdminOwnedBase.ProxyAdminOwnedBase_NotProxyAdminOrProxyAdminOwner.selector); - - // Call the `upgrade` function with the sender - vm.prank(_sender); - optimismPortal2.upgrade(IAnchorStateRegistry(address(0xdeadbeef))); - } - - /// @notice Tests that the upgrade() function reverts when lockbox state is invalid. - function test_upgrade_invalidLockboxState_reverts() external { - skipIfDevFeatureEnabled(DevFeatures.OPTIMISM_PORTAL_INTEROP); - - // Get the slot for _initialized. - StorageSlot memory slot = ForgeArtifacts.getSlot("OptimismPortal2", "_initialized"); - - // Set the initialized slot to 0. - vm.store(address(optimismPortal2), bytes32(slot.slot), bytes32(0)); - - // Disable ETH_LOCKBOX feature but set a lockbox address to create invalid state. - if (systemConfig.isFeatureEnabled(Features.ETH_LOCKBOX)) { - vm.prank(address(proxyAdmin)); - systemConfig.setFeature(Features.ETH_LOCKBOX, false); - } - - // Set a non-zero lockbox address. - StorageSlot memory lockboxSlot = ForgeArtifacts.getSlot("OptimismPortal2", "ethLockbox"); - vm.store(address(optimismPortal2), bytes32(lockboxSlot.slot), bytes32(uint256(uint160(address(0xdeadbeef))))); - - // Call the `upgrade` function - vm.prank(address(optimismPortal2.proxyAdmin())); - vm.expectRevert(IOptimismPortal.OptimismPortal_InvalidLockboxState.selector); - optimismPortal2.upgrade(IAnchorStateRegistry(address(0xdeadbeef))); - } -} - /// @title OptimismPortal2_UpgradeInterop_Test /// @notice Reusable test for the current upgrade() function in the OptimismPortal2 contract. If /// the upgrade() function is changed, tests inside of this contract should be updated to @@ -484,7 +364,7 @@ contract OptimismPortal2_UpgradeInterop_Test is CommonTest { // Verify that the initialized slot was updated. bytes32 initializedSlotAfter = vm.load(address(optimismPortal2), bytes32(slot.slot)); - assertEq(initializedSlotAfter, bytes32(uint256(3))); + assertEq(initializedSlotAfter, bytes32(uint256(optimismPortal2.initVersion()))); // Assert the portal is properly upgraded. assertEq(address(optimismPortal2.ethLockbox()), address(ethLockbox)); @@ -530,9 +410,9 @@ contract OptimismPortal2_UpgradeInterop_Test is CommonTest { // Get the slot for _initialized. StorageSlot memory slot = ForgeArtifacts.getSlot("OptimismPortal2", "_initialized"); - // Slot value should be set to 3 (already initialized). + // Slot value should be set to already initialized. bytes32 initializedSlotBefore = vm.load(address(optimismPortal2), bytes32(slot.slot)); - assertEq(initializedSlotBefore, bytes32(uint256(3))); + assertEq(initializedSlotBefore, bytes32(uint256(optimismPortal2.initVersion()))); // AnchorStateRegistry address should be non-zero. assertNotEq(address(optimismPortal2.anchorStateRegistry()), address(0)); @@ -2897,7 +2777,7 @@ contract OptimismPortal2_Params_Test is CommonTest { // The value passed to the initialize must be larger than the last value // that initialize was called with. IProxy(payable(address(optimismPortal2))).upgradeToAndCall( - address(nextImpl), abi.encodeCall(NextImpl.initialize, (4)) + address(nextImpl), abi.encodeCall(NextImpl.initialize, (optimismPortal2.initVersion() + 1)) ); assertEq(IProxy(payable(address(optimismPortal2))).implementation(), address(nextImpl)); diff --git a/packages/contracts-bedrock/test/L1/SuperchainConfig.t.sol b/packages/contracts-bedrock/test/L1/SuperchainConfig.t.sol index b304d8ad42d41..ce63b4a503756 100644 --- a/packages/contracts-bedrock/test/L1/SuperchainConfig.t.sol +++ b/packages/contracts-bedrock/test/L1/SuperchainConfig.t.sol @@ -7,7 +7,6 @@ import { CommonTest } from "test/setup/CommonTest.sol"; // Libraries import { DeployUtils } from "scripts/libraries/DeployUtils.sol"; import { ForgeArtifacts, StorageSlot } from "scripts/libraries/ForgeArtifacts.sol"; -import { Constants } from "src/libraries/Constants.sol"; // Interfaces import { IProxy } from "interfaces/universal/IProxy.sol"; @@ -94,77 +93,6 @@ contract SuperchainConfig_Initialize_Test is SuperchainConfig_TestInit { } } -/// @title SuperchainConfig_Upgrade_Test -/// @notice Test contract for SuperchainConfig `upgrade` function. -contract SuperchainConfig_Upgrade_Test is SuperchainConfig_TestInit { - /// @notice Tests that `upgrade` successfully upgrades the contract. - function test_upgrade_succeeds() external { - // Get the slot for _initialized. - StorageSlot memory slot = ForgeArtifacts.getSlot("SuperchainConfig", "_initialized"); - - // Set the initialized slot to 0. - vm.store(address(superchainConfig), bytes32(slot.slot), bytes32(0)); - - // Get the slot for the SuperchainConfig's ProxyAdmin. - address proxyAdminAddress = - address(uint160(uint256(vm.load(address(superchainConfig), Constants.PROXY_OWNER_ADDRESS)))); - - // Upgrade the contract. - vm.prank(proxyAdminAddress); - superchainConfig.upgrade(); - - // Check that the guardian slot was updated. - bytes32 guardianSlot = bytes32(uint256(keccak256("superchainConfig.guardian")) - 1); - assertEq(vm.load(address(superchainConfig), guardianSlot), bytes32(0)); - - // Check that the paused slot was cleared. - bytes32 pausedSlot = bytes32(uint256(keccak256("superchainConfig.paused")) - 1); - assertEq(vm.load(address(superchainConfig), pausedSlot), bytes32(0)); - } - - /// @notice Tests that `upgrade` reverts when called a second time. - function test_upgrade_upgradeTwice_reverts() external { - // Get the slot for _initialized. - StorageSlot memory slot = ForgeArtifacts.getSlot("SuperchainConfig", "_initialized"); - - // Set the initialized slot to 0. - vm.store(address(superchainConfig), bytes32(slot.slot), bytes32(0)); - - // Get the slot for the SuperchainConfig's ProxyAdmin. - address proxyAdminAddress = - address(uint160(uint256(vm.load(address(superchainConfig), Constants.PROXY_OWNER_ADDRESS)))); - - // Trigger first upgrade. - vm.prank(proxyAdminAddress); - superchainConfig.upgrade(); - - // Trigger second upgrade. - vm.prank(proxyAdminAddress); - vm.expectRevert("Initializable: contract is already initialized"); - superchainConfig.upgrade(); - } - - /// @notice Tests that `upgrade` reverts when called by a non-proxy admin or owner. - /// @param _sender The address of the sender to test. - function testFuzz_upgrade_notProxyAdminOrProxyAdminOwner_reverts(address _sender) public { - // Prank as the not ProxyAdmin or ProxyAdmin owner. - vm.assume(_sender != address(superchainProxyAdmin) && _sender != superchainProxyAdminOwner); - - // Get the slot for _initialized. - StorageSlot memory slot = ForgeArtifacts.getSlot("SuperchainConfig", "_initialized"); - - // Set the initialized slot to 0. - vm.store(address(superchainConfig), bytes32(slot.slot), bytes32(0)); - - // Expect the revert with `ProxyAdminOwnedBase_NotProxyAdminOrProxyAdminOwner` selector. - vm.expectRevert(IProxyAdminOwnedBase.ProxyAdminOwnedBase_NotProxyAdminOrProxyAdminOwner.selector); - - // Call the `upgrade` function with the sender - vm.prank(_sender); - superchainConfig.upgrade(); - } -} - /// @title SuperchainConfig_PauseExpiry_Test /// @notice Test contract for SuperchainConfig `pauseExpiry` function. contract SuperchainConfig_PauseExpiry_Test is SuperchainConfig_TestInit { @@ -434,9 +362,9 @@ contract SuperchainConfig_PauseTimestamps_Test is SuperchainConfig_TestInit { /// @title SuperchainConfig_Version_Test /// @notice Test contract for SuperchainConfig `version` getter function. contract SuperchainConfig_Version_Test is SuperchainConfig_TestInit { - /// @notice Tests that `version` returns the correct version string. + /// @notice Tests that `version` returns a version string. function test_version_succeeds() external view { - assertEq(superchainConfig.version(), "2.3.0"); + assert(bytes(superchainConfig.version()).length > 0); } } diff --git a/packages/contracts-bedrock/test/L1/SystemConfig.t.sol b/packages/contracts-bedrock/test/L1/SystemConfig.t.sol index 84c56d3597c08..23ce0f005762c 100644 --- a/packages/contracts-bedrock/test/L1/SystemConfig.t.sol +++ b/packages/contracts-bedrock/test/L1/SystemConfig.t.sol @@ -228,99 +228,6 @@ contract SystemConfig_Initialize_Test is SystemConfig_TestInit { } } -/// @title SystemConfig_upgrade_Test -/// @notice Reusable test for the current upgrade() function in the SystemConfig contract. If -/// the upgrade() function is changed, tests inside of this contract should be updated to -/// reflect the new function. If the upgrade() function is removed, remove the -/// corresponding tests but leave this contract in place so it's easy to add tests back -/// in the future. -contract SystemConfig_Upgrade_Test is SystemConfig_TestInit { - /// @notice Tests that the upgrade() function succeeds. - function test_upgrade_succeeds() external { - // Get the slot for _initialized. - StorageSlot memory slot = ForgeArtifacts.getSlot("SystemConfig", "_initialized"); - - // Set the initialized slot to 0. - vm.store(address(systemConfig), bytes32(slot.slot), bytes32(0)); - - // Verify the initial dispute game factory slot is non-zero. - // We set a value here since it seems this defaults to zero. - bytes32 disputeGameFactorySlot = bytes32(uint256(keccak256("systemconfig.disputegamefactory")) - 1); - vm.store(address(systemConfig), disputeGameFactorySlot, bytes32(uint256(1))); - assertNotEq(systemConfig.disputeGameFactory(), address(0)); - assertNotEq(vm.load(address(systemConfig), disputeGameFactorySlot), bytes32(0)); - - // Trigger upgrade(). - vm.prank(address(systemConfig.proxyAdmin())); - systemConfig.upgrade(1234, ISuperchainConfig(address(0xdeadbeef))); - - // Verify that the initialized slot was updated. - bytes32 initializedSlotAfter = vm.load(address(systemConfig), bytes32(slot.slot)); - assertEq(initializedSlotAfter, bytes32(uint256(3))); - - // Verify that the l2ChainId was updated. - assertEq(systemConfig.l2ChainId(), 1234); - - // Verify that the dispute game factory address was cleared. - assertEq(vm.load(address(systemConfig), disputeGameFactorySlot), bytes32(0)); - } - - /// @notice Tests that the upgrade() function reverts if called a second time. - function test_upgrade_upgradeTwice_reverts() external { - // Get the slot for _initialized. - StorageSlot memory slot = ForgeArtifacts.getSlot("SystemConfig", "_initialized"); - - // Set the initialized slot to 0. - vm.store(address(systemConfig), bytes32(slot.slot), bytes32(0)); - - // Trigger first upgrade. - vm.prank(address(systemConfig.proxyAdmin())); - systemConfig.upgrade(1234, ISuperchainConfig(address(0xdeadbeef))); - - // Try to trigger second upgrade. - vm.prank(address(systemConfig.proxyAdmin())); - vm.expectRevert("Initializable: contract is already initialized"); - systemConfig.upgrade(1234, ISuperchainConfig(address(0xdeadbeef))); - } - - /// @notice Tests that the upgrade() function reverts if called after initialization. - function test_upgrade_afterInitialization_reverts() external { - // Get the slot for _initialized. - StorageSlot memory slot = ForgeArtifacts.getSlot("SystemConfig", "_initialized"); - - // Slot value should be set to 3 (already initialized). - bytes32 initializedSlotBefore = vm.load(address(systemConfig), bytes32(slot.slot)); - assertEq(initializedSlotBefore, bytes32(uint256(3))); - - // l2ChainId should be non-zero. - assertNotEq(systemConfig.l2ChainId(), 0); - - // Try to trigger upgrade(). - vm.expectRevert("Initializable: contract is already initialized"); - systemConfig.upgrade(1234, ISuperchainConfig(address(0xdeadbeef))); - } - - /// @notice Tests that the upgrade() function reverts if called by a non-proxy admin or owner. - /// @param _sender The address of the sender to test. - function testFuzz_upgrade_notProxyAdminOrProxyAdminOwner_reverts(address _sender) public { - // Prank as the not ProxyAdmin or ProxyAdmin owner. - vm.assume(_sender != address(systemConfig.proxyAdmin()) && _sender != systemConfig.proxyAdminOwner()); - - // Get the slot for _initialized. - StorageSlot memory slot = ForgeArtifacts.getSlot("SystemConfig", "_initialized"); - - // Set the initialized slot to 0. - vm.store(address(systemConfig), bytes32(slot.slot), bytes32(0)); - - // Expect the revert with `ProxyAdminOwnedBase_NotProxyAdminOrProxyAdminOwner` selector. - vm.expectRevert(IProxyAdminOwnedBase.ProxyAdminOwnedBase_NotProxyAdminOrProxyAdminOwner.selector); - - // Call the `upgrade` function with the sender - vm.prank(_sender); - systemConfig.upgrade(1234, ISuperchainConfig(address(0xdeadbeef))); - } -} - /// @title SystemConfig_StartBlock_Test /// @notice Test contract for SystemConfig `startBlock` function. contract SystemConfig_StartBlock_Test is SystemConfig_TestInit { diff --git a/packages/contracts-bedrock/test/L2/GasPriceOracle.t.sol b/packages/contracts-bedrock/test/L2/GasPriceOracle.t.sol index 8b92a7dbd5e14..95053e369da11 100644 --- a/packages/contracts-bedrock/test/L2/GasPriceOracle.t.sol +++ b/packages/contracts-bedrock/test/L2/GasPriceOracle.t.sol @@ -9,10 +9,6 @@ import { Fork } from "scripts/libraries/Config.sol"; import { Encoding } from "src/libraries/Encoding.sol"; contract GasPriceOracle_Test is CommonTest { - event OverheadUpdated(uint256); - event ScalarUpdated(uint256); - event DecimalsUpdated(uint256); - address depositor; // The initial L1 context values diff --git a/packages/contracts-bedrock/test/safe/DeputyPauseModule.t.sol b/packages/contracts-bedrock/test/safe/DeputyPauseModule.t.sol index ab651861063b3..3302e301ffc4c 100644 --- a/packages/contracts-bedrock/test/safe/DeputyPauseModule.t.sol +++ b/packages/contracts-bedrock/test/safe/DeputyPauseModule.t.sol @@ -17,8 +17,8 @@ import { ISuperchainConfig } from "interfaces/L1/ISuperchainConfig.sol"; contract DeputyPauseModule_TestInit is CommonTest, SafeTestTools { using SafeTestLib for SafeInstance; - event ExecutionFromModuleSuccess(address indexed); - event DeputySet(address indexed); + event ExecutionFromModuleSuccess(address indexed module); + event DeputySet(address indexed deputy); event PauseTriggered(address indexed deputy, bytes32 nonce, address identifier); IDeputyPauseModule deputyPauseModule; diff --git a/packages/contracts-bedrock/test/setup/ForkLive.s.sol b/packages/contracts-bedrock/test/setup/ForkLive.s.sol index ecb8511f03af0..4c12d6661dc69 100644 --- a/packages/contracts-bedrock/test/setup/ForkLive.s.sol +++ b/packages/contracts-bedrock/test/setup/ForkLive.s.sol @@ -2,6 +2,7 @@ pragma solidity ^0.8.0; import { console2 as console } from "forge-std/console2.sol"; +import { StdAssertions } from "forge-std/StdAssertions.sol"; // Testing import { stdToml } from "forge-std/StdToml.sol"; @@ -18,6 +19,7 @@ import { EIP1967Helper } from "test/mocks/EIP1967Helper.sol"; import { LibString } from "solady/src/utils/LibString.sol"; // Interfaces +import { ISuperchainConfig } from "interfaces/L1/ISuperchainConfig.sol"; import { IFaultDisputeGame } from "interfaces/dispute/IFaultDisputeGame.sol"; import { IPermissionedDisputeGame } from "interfaces/dispute/IPermissionedDisputeGame.sol"; import { IDisputeGameFactory } from "interfaces/dispute/IDisputeGameFactory.sol"; @@ -29,6 +31,7 @@ import { IOPContractsManager } from "interfaces/L1/IOPContractsManager.sol"; import { IAnchorStateRegistry } from "interfaces/dispute/IAnchorStateRegistry.sol"; import { IETHLockbox } from "interfaces/L1/IETHLockbox.sol"; import { IOptimismPortal2 } from "interfaces/L1/IOptimismPortal2.sol"; +import { IOPContractsManagerUpgrader } from "interfaces/L1/IOPContractsManager.sol"; /// @title ForkLive /// @notice This script is called by Setup.sol as a preparation step for the foundry test suite, and is run as an @@ -40,12 +43,15 @@ import { IOptimismPortal2 } from "interfaces/L1/IOptimismPortal2.sol"; /// superchain-registry. /// This contract must not have constructor logic because it is set into state using `etch`. -contract ForkLive is Deployer { +contract ForkLive is Deployer, StdAssertions { using stdToml for string; using LibString for string; bool public useOpsRepo; + /// @notice Thrown when testing with an unsupported chain ID. + error UnsupportedChainId(); + /// @notice Returns the base chain name to use for forking /// @return The base chain name as a string function baseChain() internal view returns (string memory) { @@ -187,16 +193,13 @@ contract ForkLive is Deployer { deploy.deployImplementations({ _isInterop: false }); } - /// @notice Upgrades the contracts using the OPCM. - function _upgrade() internal { - IOPContractsManager opcm = IOPContractsManager(artifacts.mustGetAddress("OPContractsManager")); - + /// @notice Performs a single OPCM upgrade. + /// @param _opcm The OPCM contract to upgrade. + /// @param _delegateCaller The address of the upgrader to use for the upgrade. + function _doUpgrade(IOPContractsManager _opcm, address _delegateCaller) internal { ISystemConfig systemConfig = ISystemConfig(artifacts.mustGetAddress("SystemConfigProxy")); IProxyAdmin proxyAdmin = IProxyAdmin(EIP1967Helper.getAdmin(address(systemConfig))); - address upgrader = proxyAdmin.owner(); - vm.label(upgrader, "ProxyAdmin Owner"); - IOPContractsManager.OpChainConfig[] memory opChains = new IOPContractsManager.OpChainConfig[](1); opChains[0] = IOPContractsManager.OpChainConfig({ systemConfigProxy: systemConfig, @@ -204,22 +207,71 @@ contract ForkLive is Deployer { absolutePrestate: Claim.wrap(bytes32(keccak256("absolutePrestate"))) }); + // Turn the SuperchainPAO into a DelegateCaller so we can try to upgrade the + // SuperchainConfig contract. + ISuperchainConfig superchainConfig = ISuperchainConfig(artifacts.mustGetAddress("SuperchainConfigProxy")); + IProxyAdmin superchainProxyAdmin = IProxyAdmin(EIP1967Helper.getAdmin(address(superchainConfig))); + address superchainPAO = superchainProxyAdmin.owner(); + bytes memory superchainPAOCode = address(superchainPAO).code; + vm.etch(superchainPAO, vm.getDeployedCode("test/mocks/Callers.sol:DelegateCaller")); + + // Always try to upgrade the SuperchainConfig. Not always necessary but easier to do it + // every time rather than adding or removing this code for each upgrade. + try DelegateCaller(superchainPAO).dcForward( + address(_opcm), + abi.encodeCall(IOPContractsManager.upgradeSuperchainConfig, (superchainConfig, superchainProxyAdmin)) + ) { + // Great, the upgrade succeeded. + } catch (bytes memory reason) { + // Only acceptable revert reason is the SuperchainConfig already being up to date. + assertTrue( + bytes4(reason) + == IOPContractsManagerUpgrader.OPContractsManagerUpgrader_SuperchainConfigAlreadyUpToDate.selector, + "Revert reason other than SuperchainConfigAlreadyUpToDate" + ); + } + + // Reset the superchainPAO to the original code. + vm.etch(superchainPAO, superchainPAOCode); + // Temporarily replace the upgrader with a DelegateCaller so we can test the upgrade, // then reset its code to the original code. - bytes memory upgraderCode = address(upgrader).code; - vm.etch(upgrader, vm.getDeployedCode("test/mocks/Callers.sol:DelegateCaller")); - - // The 4.1.0 OPCM requires that the SuperchainConfig contracts have been upgraded before it will upgrade other - // contracts. For this v4.1.0, OP Mainnet's superchainConfig is already at the expected version. So we do not - // need to upgrade it. + bytes memory upgraderCode = address(_delegateCaller).code; + vm.etch(_delegateCaller, vm.getDeployedCode("test/mocks/Callers.sol:DelegateCaller")); // Upgrade the chain. - DelegateCaller(upgrader).dcForward(address(opcm), abi.encodeCall(IOPContractsManager.upgrade, (opChains))); + DelegateCaller(_delegateCaller).dcForward( + address(_opcm), abi.encodeCall(IOPContractsManager.upgrade, (opChains)) + ); // Reset the upgrader to the original code. - vm.etch(upgrader, upgraderCode); + vm.etch(_delegateCaller, upgraderCode); + } + + /// @notice Upgrades the contracts using the OPCM. + function _upgrade() internal { + IOPContractsManager opcm = IOPContractsManager(artifacts.mustGetAddress("OPContractsManager")); + + ISystemConfig systemConfig = ISystemConfig(artifacts.mustGetAddress("SystemConfigProxy")); + IProxyAdmin proxyAdmin = IProxyAdmin(EIP1967Helper.getAdmin(address(systemConfig))); + + address upgrader = proxyAdmin.owner(); + vm.label(upgrader, "ProxyAdmin Owner"); + + // Run past upgrades depending on network. + if (block.chainid == 1) { + // Mainnet + // U16a. + _doUpgrade(IOPContractsManager(0x8123739C1368C2DEDc8C564255bc417FEEeBFF9D), upgrader); + } else { + revert UnsupportedChainId(); + } + + // Current upgrade. + _doUpgrade(opcm, upgrader); console.log("ForkLive: Saving newly deployed contracts"); + // A new ASR and new dispute games were deployed, so we need to update them IDisputeGameFactory disputeGameFactory = IDisputeGameFactory(artifacts.mustGetAddress("DisputeGameFactoryProxy"));