From b2bf6f9200cea7da66d85cc77196138e8f3e97cb Mon Sep 17 00:00:00 2001 From: Maurelian Date: Sat, 21 Dec 2024 00:04:57 -0500 Subject: [PATCH 01/10] WIP POC --- .../contracts-bedrock/scripts/Artifacts.s.sol | 4 +++ .../scripts/deploy/Deploy.s.sol | 4 +++ .../src/L1/OPContractsManager.sol | 25 ++++++++++++++++++- .../test/setup/ForkLive.s.sol | 6 +++++ 4 files changed, 38 insertions(+), 1 deletion(-) diff --git a/packages/contracts-bedrock/scripts/Artifacts.s.sol b/packages/contracts-bedrock/scripts/Artifacts.s.sol index 24ddae4c2853..d284a9d7786a 100644 --- a/packages/contracts-bedrock/scripts/Artifacts.s.sol +++ b/packages/contracts-bedrock/scripts/Artifacts.s.sol @@ -159,6 +159,10 @@ contract Artifacts { revert InvalidDeployment("EmptyName"); } if (bytes(_namedDeployments[_name].name).length > 0) { + // If the deployment already exists, and the address is the same, do nothing. + if (_namedDeployments[_name].addr == _deployed) { + return; + } revert InvalidDeployment("AlreadyExists"); } diff --git a/packages/contracts-bedrock/scripts/deploy/Deploy.s.sol b/packages/contracts-bedrock/scripts/deploy/Deploy.s.sol index 9bbf1d7670d4..4684f2e4f832 100644 --- a/packages/contracts-bedrock/scripts/deploy/Deploy.s.sol +++ b/packages/contracts-bedrock/scripts/deploy/Deploy.s.sol @@ -285,6 +285,10 @@ contract Deploy is Deployer { require(_isInterop == cfg.useInterop(), "Deploy: Interop setting mismatch."); console.log("Deploying implementations"); + if (bytes(_suffix).length > 0) { + console.log("saving with suffix: ", _suffix); + } + DeployImplementations di = new DeployImplementations(); (DeployImplementationsInput dii, DeployImplementationsOutput dio) = di.etchIOContracts(); diff --git a/packages/contracts-bedrock/src/L1/OPContractsManager.sol b/packages/contracts-bedrock/src/L1/OPContractsManager.sol index d09a63aa18e1..c62ffee872b1 100644 --- a/packages/contracts-bedrock/src/L1/OPContractsManager.sol +++ b/packages/contracts-bedrock/src/L1/OPContractsManager.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; - +import { console2 as console } from "forge-std/console2.sol"; // Libraries import { Blueprint } from "src/libraries/Blueprint.sol"; import { Constants } from "src/libraries/Constants.sol"; @@ -150,6 +150,12 @@ contract OPContractsManager is ISemver { uint256 indexed outputVersion, uint256 indexed l2ChainId, address indexed deployer, bytes deployOutput ); + /// @notice Emitted when a chain is upgraded + /// @param l2ChainId Chain ID of the upgraded chain + /// @param systemConfig Address of the chain's SystemConfig contract + /// @param upgrader Address that initiated the upgrade + event Upgraded(uint256 indexed l2ChainId, ISystemConfig indexed systemConfig, address indexed upgrader); + // -------- Errors -------- /// @notice Thrown when an address is the zero address. @@ -363,6 +369,23 @@ contract OPContractsManager is ISemver { return output; } + /// @notice Upgrades a set of chains to the latest implementation contracts + /// @param _systemConfigs Array of SystemConfig contracts, one per chain to upgrade + /// @param _proxyAdmins Array of ProxyAdmin contracts, one per chain to upgrade + /// @dev This function is intended to be called via DELEGATECALL from the Upgrade Controller Safe + function upgrade( + ISystemConfig[] calldata _systemConfigs, + IProxyAdmin[] calldata _proxyAdmins + ) + external + { + for (uint256 i = 0; i < _systemConfigs.length; i++) { + ISystemConfig systemConfig = _systemConfigs[i]; + IProxyAdmin proxyAdmin = _proxyAdmins[i]; + proxyAdmin.upgradeAndCall(payable(address(systemConfig)), implementation.systemConfigImpl, abi.encode()); + } + } + // -------- Utilities -------- /// @notice Verifies that all inputs are valid and reverts if any are invalid. diff --git a/packages/contracts-bedrock/test/setup/ForkLive.s.sol b/packages/contracts-bedrock/test/setup/ForkLive.s.sol index ed8b85705582..988917db08aa 100644 --- a/packages/contracts-bedrock/test/setup/ForkLive.s.sol +++ b/packages/contracts-bedrock/test/setup/ForkLive.s.sol @@ -16,6 +16,9 @@ import { EIP1967Helper } from "test/mocks/EIP1967Helper.sol"; import { IFaultDisputeGame } from "interfaces/dispute/IFaultDisputeGame.sol"; import { IDisputeGameFactory } from "interfaces/dispute/IDisputeGameFactory.sol"; import { IAddressManager } from "interfaces/legacy/IAddressManager.sol"; +import { ISystemConfig } from "interfaces/L1/ISystemConfig.sol"; +import { IProxyAdmin } from "interfaces/universal/IProxyAdmin.sol"; +import { OPContractsManager } from "src/L1/OPContractsManager.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 @@ -52,6 +55,9 @@ contract ForkLive is Deployer { // Now deploy the updated OPCM and implementations of the contracts _deployNewImplementations(); + + // Now upgrade the contracts + _upgrade(); } /// @notice Reads the superchain config files and saves the addresses to disk. From e56de969f1b60d45e743376f11665538f7703559 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Tue, 31 Dec 2024 14:06:29 -0500 Subject: [PATCH 02/10] simplify opcm.upgrade for now --- .../src/L1/OPContractsManager.sol | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/packages/contracts-bedrock/src/L1/OPContractsManager.sol b/packages/contracts-bedrock/src/L1/OPContractsManager.sol index c62ffee872b1..c8e28e9df47b 100644 --- a/packages/contracts-bedrock/src/L1/OPContractsManager.sol +++ b/packages/contracts-bedrock/src/L1/OPContractsManager.sol @@ -1,5 +1,6 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; + import { console2 as console } from "forge-std/console2.sol"; // Libraries import { Blueprint } from "src/libraries/Blueprint.sol"; @@ -373,16 +374,20 @@ contract OPContractsManager is ISemver { /// @param _systemConfigs Array of SystemConfig contracts, one per chain to upgrade /// @param _proxyAdmins Array of ProxyAdmin contracts, one per chain to upgrade /// @dev This function is intended to be called via DELEGATECALL from the Upgrade Controller Safe - function upgrade( - ISystemConfig[] calldata _systemConfigs, - IProxyAdmin[] calldata _proxyAdmins - ) - external - { + function upgrade(ISystemConfig[] calldata _systemConfigs, IProxyAdmin[] calldata _proxyAdmins) external { for (uint256 i = 0; i < _systemConfigs.length; i++) { ISystemConfig systemConfig = _systemConfigs[i]; + ISystemConfig.Addresses memory opChainAddrs = ISystemConfig.Addresses({ + l1CrossDomainMessenger: systemConfig.l1CrossDomainMessenger(), + l1ERC721Bridge: systemConfig.l1ERC721Bridge(), + l1StandardBridge: systemConfig.l1StandardBridge(), + disputeGameFactory: systemConfig.disputeGameFactory(), + optimismPortal: systemConfig.optimismPortal(), + optimismMintableERC20Factory: systemConfig.optimismMintableERC20Factory(), + gasPayingToken: address(0) + }); + IProxyAdmin proxyAdmin = _proxyAdmins[i]; - proxyAdmin.upgradeAndCall(payable(address(systemConfig)), implementation.systemConfigImpl, abi.encode()); } } From ff2b9c86f7e3f54cafa81ac64736645d411bc29b Mon Sep 17 00:00:00 2001 From: Maurelian Date: Tue, 31 Dec 2024 14:06:49 -0500 Subject: [PATCH 03/10] prank delegatecall bug demo --- .../test/setup/ForkLive.s.sol | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/packages/contracts-bedrock/test/setup/ForkLive.s.sol b/packages/contracts-bedrock/test/setup/ForkLive.s.sol index 988917db08aa..e77deb4cb988 100644 --- a/packages/contracts-bedrock/test/setup/ForkLive.s.sol +++ b/packages/contracts-bedrock/test/setup/ForkLive.s.sol @@ -1,6 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; +import { console } from "forge-std/console.sol"; // Testing import { stdJson } from "forge-std/StdJson.sol"; @@ -126,6 +127,34 @@ contract ForkLive is Deployer { deploy.deployImplementations({ _isInterop: false, _suffix: "_NextVersion" }); } + function _upgrade() internal { + OPContractsManager opcm = OPContractsManager(mustGetAddress("OPContractsManager_NextVersion")); + ISystemConfig systemConfig = ISystemConfig(mustGetAddress("SystemConfigProxy")); + IProxyAdmin proxyAdmin = IProxyAdmin(EIP1967Helper.getAdmin(address(systemConfig))); + + address upgrader = proxyAdmin.owner(); + vm.label(upgrader, "ProxyAdmin Owner"); + + ISystemConfig[] memory systemConfigs = new ISystemConfig[](1); + systemConfigs[0] = systemConfig; + IProxyAdmin[] memory proxyAdmins = new IProxyAdmin[](1); + proxyAdmins[0] = proxyAdmin; + + // TODO: Add support for this prank() call to forge-std + console.log("delegatecall with prank"); + (bool success,) = address(vm).call(abi.encodeWithSignature("prank(address,bool)", address(this), true)); + require(success, "ForkLive: Failed to prank"); + + (success,) = + address(opcm).delegatecall(abi.encodeCall(OPContractsManager.upgrade, (systemConfigs, proxyAdmins))); + require(success, "ForkLive: Upgrade failed"); + + console.log("delegatecall without prank"); + (success,) = + address(opcm).delegatecall(abi.encodeCall(OPContractsManager.upgrade, (systemConfigs, proxyAdmins))); + require(success, "ForkLive: Upgrade failed"); + } + /// @notice Saves the proxy and implementation addresses for a contract name /// @param _contractName The name of the contract to save /// @param _tomlPath The path to the superchain config file From 580fd7a6c08bd91c7df61bd9e3f88c7043acf32b Mon Sep 17 00:00:00 2001 From: Maurelian Date: Thu, 2 Jan 2025 14:16:53 -0500 Subject: [PATCH 04/10] feat: add thisOpcm to access state during a delegatecall --- .../src/L1/OPContractsManager.sol | 17 +++++++++ .../test/L1/OPContractsManager.t.sol | 36 ++++++++++++++++++- .../contracts-bedrock/test/mocks/Callers.sol | 7 ++++ .../test/setup/ForkLive.s.sol | 19 ++++------ 4 files changed, 65 insertions(+), 14 deletions(-) diff --git a/packages/contracts-bedrock/src/L1/OPContractsManager.sol b/packages/contracts-bedrock/src/L1/OPContractsManager.sol index c8e28e9df47b..715bd95f4407 100644 --- a/packages/contracts-bedrock/src/L1/OPContractsManager.sol +++ b/packages/contracts-bedrock/src/L1/OPContractsManager.sol @@ -2,6 +2,7 @@ pragma solidity 0.8.15; import { console2 as console } from "forge-std/console2.sol"; + // Libraries import { Blueprint } from "src/libraries/Blueprint.sol"; import { Constants } from "src/libraries/Constants.sol"; @@ -140,6 +141,10 @@ contract OPContractsManager is ISemver { /// @notice Addresses of the latest implementation contracts. Implementations internal implementation; + /// @notice The OPContractsManager contract that is currently being used. This is needed in the upgrade function + /// which is intended to be DELEGATECALLed. + OPContractsManager public immutable thisOPCM; + // -------- Events -------- /// @notice Emitted when a new OP Stack chain is deployed. @@ -197,6 +202,7 @@ contract OPContractsManager is ISemver { blueprint = _blueprints; implementation = _implementations; + thisOPCM = this; } function deploy(DeployInput calldata _input) external returns (DeployOutput memory) { @@ -375,6 +381,8 @@ contract OPContractsManager is ISemver { /// @param _proxyAdmins Array of ProxyAdmin contracts, one per chain to upgrade /// @dev This function is intended to be called via DELEGATECALL from the Upgrade Controller Safe function upgrade(ISystemConfig[] calldata _systemConfigs, IProxyAdmin[] calldata _proxyAdmins) external { + Implementations memory impls = thisOPCM.implementations(); + for (uint256 i = 0; i < _systemConfigs.length; i++) { ISystemConfig systemConfig = _systemConfigs[i]; ISystemConfig.Addresses memory opChainAddrs = ISystemConfig.Addresses({ @@ -388,6 +396,15 @@ contract OPContractsManager is ISemver { }); IProxyAdmin proxyAdmin = _proxyAdmins[i]; + proxyAdmin.upgrade(payable(address(systemConfig)), impls.systemConfigImpl); + proxyAdmin.upgrade(payable(opChainAddrs.l1CrossDomainMessenger), impls.l1CrossDomainMessengerImpl); + proxyAdmin.upgrade(payable(opChainAddrs.l1ERC721Bridge), impls.l1ERC721BridgeImpl); + proxyAdmin.upgrade(payable(opChainAddrs.l1StandardBridge), impls.l1StandardBridgeImpl); + proxyAdmin.upgrade(payable(opChainAddrs.disputeGameFactory), impls.disputeGameFactoryImpl); + proxyAdmin.upgrade(payable(opChainAddrs.optimismPortal), impls.optimismPortalImpl); + proxyAdmin.upgrade( + payable(opChainAddrs.optimismMintableERC20Factory), impls.optimismMintableERC20FactoryImpl + ); } } diff --git a/packages/contracts-bedrock/test/L1/OPContractsManager.t.sol b/packages/contracts-bedrock/test/L1/OPContractsManager.t.sol index 418eebd9e64b..b92e865ceb7b 100644 --- a/packages/contracts-bedrock/test/L1/OPContractsManager.t.sol +++ b/packages/contracts-bedrock/test/L1/OPContractsManager.t.sol @@ -1,11 +1,18 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; +// Testing import { Test, stdStorage, StdStorage } from "forge-std/Test.sol"; +import { CommonTest } from "test/setup/CommonTest.sol"; +import { DeployOPChain_TestBase } from "test/opcm/DeployOPChain.t.sol"; +// Scripts import { DeployOPChainInput } from "scripts/deploy/DeployOPChain.s.sol"; -import { DeployOPChain_TestBase } from "test/opcm/DeployOPChain.t.sol"; +// Libraries +import { EIP1967Helper } from "test/mocks/EIP1967Helper.sol"; + +// Contracts import { OPContractsManager } from "src/L1/OPContractsManager.sol"; import { ISuperchainConfig } from "interfaces/L1/ISuperchainConfig.sol"; import { IProtocolVersions } from "interfaces/L1/IProtocolVersions.sol"; @@ -148,3 +155,30 @@ contract OPContractsManager_InternalMethods_Test is Test { vm.assertEq(expected, actual); } } + +contract OPContractsManager_Upgrade_Test is CommonTest { + function setUp() public override { + super.setUp(); + if (!isForkTest()) { + // This test is only supported in forked tests, as we are testing the upgrade. + vm.skip(true); + } + } + + function test_upgrade_succeeds() public { + // TODO: make a state var for opcm in CommonTest + OPContractsManager opcm = OPContractsManager(deploy.mustGetAddress("OPContractsManager_NextVersion")); + OPContractsManager.Implementations memory impls = opcm.implementations(); + assertEq(impls.systemConfigImpl, EIP1967Helper.getImplementation(address(systemConfig))); + assertEq(impls.l1ERC721BridgeImpl, EIP1967Helper.getImplementation(address(l1ERC721Bridge))); + assertEq(impls.disputeGameFactoryImpl, EIP1967Helper.getImplementation(address(disputeGameFactory))); + assertEq(impls.optimismPortalImpl, EIP1967Helper.getImplementation(address(optimismPortal2))); + assertEq( + impls.optimismMintableERC20FactoryImpl, + EIP1967Helper.getImplementation(address(l1OptimismMintableERC20Factory)) + ); + assertEq(impls.l1StandardBridgeImpl, EIP1967Helper.getImplementation(address(l1StandardBridge))); + + assertEq(impls.l1CrossDomainMessengerImpl, addressManager.getAddress("OVM_L1CrossDomainMessenger")); + } +} diff --git a/packages/contracts-bedrock/test/mocks/Callers.sol b/packages/contracts-bedrock/test/mocks/Callers.sol index b8dd70df15e1..67c724ec1b0b 100644 --- a/packages/contracts-bedrock/test/mocks/Callers.sol +++ b/packages/contracts-bedrock/test/mocks/Callers.sol @@ -91,3 +91,10 @@ contract Reverter { revert(); } } + +contract DelegateCaller { + function dcForward(address _target, bytes calldata _data) external { + (bool success,) = _target.delegatecall(_data); + require(success, "DelegateCaller: Delegatecall failed"); + } +} diff --git a/packages/contracts-bedrock/test/setup/ForkLive.s.sol b/packages/contracts-bedrock/test/setup/ForkLive.s.sol index e77deb4cb988..c97a75c20a91 100644 --- a/packages/contracts-bedrock/test/setup/ForkLive.s.sol +++ b/packages/contracts-bedrock/test/setup/ForkLive.s.sol @@ -4,6 +4,7 @@ pragma solidity ^0.8.0; import { console } from "forge-std/console.sol"; // Testing import { stdJson } from "forge-std/StdJson.sol"; +import { DelegateCaller } from "test/mocks/Callers.sol"; // Scripts import { Deployer } from "scripts/deploy/Deployer.sol"; @@ -129,6 +130,7 @@ contract ForkLive is Deployer { function _upgrade() internal { OPContractsManager opcm = OPContractsManager(mustGetAddress("OPContractsManager_NextVersion")); + ISystemConfig systemConfig = ISystemConfig(mustGetAddress("SystemConfigProxy")); IProxyAdmin proxyAdmin = IProxyAdmin(EIP1967Helper.getAdmin(address(systemConfig))); @@ -140,19 +142,10 @@ contract ForkLive is Deployer { IProxyAdmin[] memory proxyAdmins = new IProxyAdmin[](1); proxyAdmins[0] = proxyAdmin; - // TODO: Add support for this prank() call to forge-std - console.log("delegatecall with prank"); - (bool success,) = address(vm).call(abi.encodeWithSignature("prank(address,bool)", address(this), true)); - require(success, "ForkLive: Failed to prank"); - - (success,) = - address(opcm).delegatecall(abi.encodeCall(OPContractsManager.upgrade, (systemConfigs, proxyAdmins))); - require(success, "ForkLive: Upgrade failed"); - - console.log("delegatecall without prank"); - (success,) = - address(opcm).delegatecall(abi.encodeCall(OPContractsManager.upgrade, (systemConfigs, proxyAdmins))); - require(success, "ForkLive: Upgrade failed"); + vm.etch(upgrader, vm.getDeployedCode("test/mocks/Callers.sol:DelegateCaller")); + DelegateCaller(upgrader).dcForward( + address(opcm), abi.encodeCall(OPContractsManager.upgrade, (systemConfigs, proxyAdmins)) + ); } /// @notice Saves the proxy and implementation addresses for a contract name From 03a160e4c14948708431aa22cd88abb452672918 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Fri, 3 Jan 2025 21:17:11 -0500 Subject: [PATCH 05/10] feat: make thisOPCM internal --- packages/contracts-bedrock/src/L1/OPContractsManager.sol | 4 +--- packages/contracts-bedrock/test/universal/Specs.t.sol | 2 ++ 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/contracts-bedrock/src/L1/OPContractsManager.sol b/packages/contracts-bedrock/src/L1/OPContractsManager.sol index 715bd95f4407..85588daae90a 100644 --- a/packages/contracts-bedrock/src/L1/OPContractsManager.sol +++ b/packages/contracts-bedrock/src/L1/OPContractsManager.sol @@ -1,8 +1,6 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; -import { console2 as console } from "forge-std/console2.sol"; - // Libraries import { Blueprint } from "src/libraries/Blueprint.sol"; import { Constants } from "src/libraries/Constants.sol"; @@ -143,7 +141,7 @@ contract OPContractsManager is ISemver { /// @notice The OPContractsManager contract that is currently being used. This is needed in the upgrade function /// which is intended to be DELEGATECALLed. - OPContractsManager public immutable thisOPCM; + OPContractsManager internal immutable thisOPCM; // -------- Events -------- diff --git a/packages/contracts-bedrock/test/universal/Specs.t.sol b/packages/contracts-bedrock/test/universal/Specs.t.sol index 14dcbc9bc884..55eb075ed8ba 100644 --- a/packages/contracts-bedrock/test/universal/Specs.t.sol +++ b/packages/contracts-bedrock/test/universal/Specs.t.sol @@ -781,6 +781,7 @@ contract Specification_Test is CommonTest { _addSpec({ _name: "OPContractsManager", _sel: OPContractsManager.blueprints.selector }); _addSpec({ _name: "OPContractsManager", _sel: OPContractsManager.chainIdToBatchInboxAddress.selector }); _addSpec({ _name: "OPContractsManager", _sel: OPContractsManager.implementations.selector }); + _addSpec({ _name: "OPContractsManager", _sel: OPContractsManager.upgrade.selector }); // OPContractsManagerInterop _addSpec({ _name: "OPContractsManagerInterop", _sel: _getSel("version()") }); @@ -792,6 +793,7 @@ contract Specification_Test is CommonTest { _addSpec({ _name: "OPContractsManagerInterop", _sel: OPContractsManager.blueprints.selector }); _addSpec({ _name: "OPContractsManagerInterop", _sel: OPContractsManager.chainIdToBatchInboxAddress.selector }); _addSpec({ _name: "OPContractsManagerInterop", _sel: OPContractsManager.implementations.selector }); + _addSpec({ _name: "OPContractsManagerInterop", _sel: OPContractsManager.upgrade.selector }); // DeputyGuardianModule _addSpec({ From cffdbea0a562372f4387404bcc3c94b4d8db0dc2 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Mon, 6 Jan 2025 10:36:37 -0500 Subject: [PATCH 06/10] feat: Update semver and abi locks --- .../snapshots/abi/OPContractsManager.json | 43 +++++++++++++++++++ .../abi/OPContractsManagerInterop.json | 43 +++++++++++++++++++ .../snapshots/semver-lock.json | 5 +-- 3 files changed, 88 insertions(+), 3 deletions(-) diff --git a/packages/contracts-bedrock/snapshots/abi/OPContractsManager.json b/packages/contracts-bedrock/snapshots/abi/OPContractsManager.json index a541ae2e1016..dc82768a2e0f 100644 --- a/packages/contracts-bedrock/snapshots/abi/OPContractsManager.json +++ b/packages/contracts-bedrock/snapshots/abi/OPContractsManager.json @@ -500,6 +500,24 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [ + { + "internalType": "contract ISystemConfig[]", + "name": "_systemConfigs", + "type": "address[]" + }, + { + "internalType": "contract IProxyAdmin[]", + "name": "_proxyAdmins", + "type": "address[]" + } + ], + "name": "upgrade", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [], "name": "version", @@ -544,6 +562,31 @@ "name": "Deployed", "type": "event" }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "l2ChainId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "contract ISystemConfig", + "name": "systemConfig", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "upgrader", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, { "inputs": [ { diff --git a/packages/contracts-bedrock/snapshots/abi/OPContractsManagerInterop.json b/packages/contracts-bedrock/snapshots/abi/OPContractsManagerInterop.json index a541ae2e1016..dc82768a2e0f 100644 --- a/packages/contracts-bedrock/snapshots/abi/OPContractsManagerInterop.json +++ b/packages/contracts-bedrock/snapshots/abi/OPContractsManagerInterop.json @@ -500,6 +500,24 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [ + { + "internalType": "contract ISystemConfig[]", + "name": "_systemConfigs", + "type": "address[]" + }, + { + "internalType": "contract IProxyAdmin[]", + "name": "_proxyAdmins", + "type": "address[]" + } + ], + "name": "upgrade", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [], "name": "version", @@ -544,6 +562,31 @@ "name": "Deployed", "type": "event" }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "l2ChainId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "contract ISystemConfig", + "name": "systemConfig", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "upgrader", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, { "inputs": [ { diff --git a/packages/contracts-bedrock/snapshots/semver-lock.json b/packages/contracts-bedrock/snapshots/semver-lock.json index 05446cdb4a34..2dc026057b90 100644 --- a/packages/contracts-bedrock/snapshots/semver-lock.json +++ b/packages/contracts-bedrock/snapshots/semver-lock.json @@ -16,8 +16,8 @@ "sourceCodeHash": "0xa91b445bdc666a02ba18e3b91ba94b6d54bbe65da714002fc734814201319d57" }, "src/L1/OPContractsManager.sol": { - "initCodeHash": "0x4b413cbe79bd10d41d8f3e9f0408e773dd49ced823d457b9f9aa92f446828105", - "sourceCodeHash": "0xe5179a20ae40d4e4773c52df98bac67e73e04044bec9e8750073b4e2f14fe81b" + "initCodeHash": "0x229b7f02ea7ae123421eeaef9092a8e447f237576f0cd3d43ca81b6ccc9248dc", + "sourceCodeHash": "0x256b6ee64af66ee1628c5ac16eeca406aa9fb19d5e710e24bd6ad84ef14517fe" }, "src/L1/OptimismPortal2.sol": { "initCodeHash": "0x7e533474310583593c2d57d30fcd1ec11e1568dbaaf37a2dd28c5cc574068bac", @@ -219,4 +219,3 @@ "initCodeHash": "0x2bfce526f82622288333d53ca3f43a0a94306ba1bab99241daa845f8f4b18bd4", "sourceCodeHash": "0xf49d7b0187912a6bb67926a3222ae51121e9239495213c975b3b4b217ee57a1b" } -} \ No newline at end of file From 568f7f9036f33eceef9dcd81075b46b6723b6830 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Mon, 6 Jan 2025 15:58:18 -0500 Subject: [PATCH 07/10] fix: OPCM semver --- packages/contracts-bedrock/snapshots/semver-lock.json | 5 +++-- packages/contracts-bedrock/src/L1/OPContractsManager.sol | 4 ++-- packages/contracts-bedrock/test/L1/OPContractsManager.t.sol | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/packages/contracts-bedrock/snapshots/semver-lock.json b/packages/contracts-bedrock/snapshots/semver-lock.json index 2dc026057b90..728b31eb4cbb 100644 --- a/packages/contracts-bedrock/snapshots/semver-lock.json +++ b/packages/contracts-bedrock/snapshots/semver-lock.json @@ -16,8 +16,8 @@ "sourceCodeHash": "0xa91b445bdc666a02ba18e3b91ba94b6d54bbe65da714002fc734814201319d57" }, "src/L1/OPContractsManager.sol": { - "initCodeHash": "0x229b7f02ea7ae123421eeaef9092a8e447f237576f0cd3d43ca81b6ccc9248dc", - "sourceCodeHash": "0x256b6ee64af66ee1628c5ac16eeca406aa9fb19d5e710e24bd6ad84ef14517fe" + "initCodeHash": "0x5456d00538d2feef7346ee55d2f8fb92e3ae11b575b99a2b5c543a3f2d4b76da", + "sourceCodeHash": "0x35ac52d11a87d1da31d6d0edff54bd0cfcb0f6c97d8aeac17400642f960a5681" }, "src/L1/OptimismPortal2.sol": { "initCodeHash": "0x7e533474310583593c2d57d30fcd1ec11e1568dbaaf37a2dd28c5cc574068bac", @@ -219,3 +219,4 @@ "initCodeHash": "0x2bfce526f82622288333d53ca3f43a0a94306ba1bab99241daa845f8f4b18bd4", "sourceCodeHash": "0xf49d7b0187912a6bb67926a3222ae51121e9239495213c975b3b4b217ee57a1b" } +} \ No newline at end of file diff --git a/packages/contracts-bedrock/src/L1/OPContractsManager.sol b/packages/contracts-bedrock/src/L1/OPContractsManager.sol index 85588daae90a..bfe35f1c4f46 100644 --- a/packages/contracts-bedrock/src/L1/OPContractsManager.sol +++ b/packages/contracts-bedrock/src/L1/OPContractsManager.sol @@ -114,8 +114,8 @@ contract OPContractsManager is ISemver { // -------- Constants and Variables -------- - /// @custom:semver 1.0.0-beta.27 - string public constant version = "1.0.0-beta.27"; + /// @custom:semver 1.0.0-beta.28 + string public constant version = "1.0.0-beta.28"; /// @notice Represents the interface version so consumers know how to decode the DeployOutput struct /// that's emitted in the `Deployed` event. Whenever that struct changes, a new version should be used. diff --git a/packages/contracts-bedrock/test/L1/OPContractsManager.t.sol b/packages/contracts-bedrock/test/L1/OPContractsManager.t.sol index b92e865ceb7b..fe56a4c99745 100644 --- a/packages/contracts-bedrock/test/L1/OPContractsManager.t.sol +++ b/packages/contracts-bedrock/test/L1/OPContractsManager.t.sol @@ -165,7 +165,7 @@ contract OPContractsManager_Upgrade_Test is CommonTest { } } - function test_upgrade_succeeds() public { + function test_upgrade_succeeds() public view { // TODO: make a state var for opcm in CommonTest OPContractsManager opcm = OPContractsManager(deploy.mustGetAddress("OPContractsManager_NextVersion")); OPContractsManager.Implementations memory impls = opcm.implementations(); From cf09cf829597b940fb52d0e1e949d6c7c462b85e Mon Sep 17 00:00:00 2001 From: Maurelian Date: Tue, 7 Jan 2025 09:08:37 -0500 Subject: [PATCH 08/10] remove unused import --- packages/contracts-bedrock/test/setup/ForkLive.s.sol | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/contracts-bedrock/test/setup/ForkLive.s.sol b/packages/contracts-bedrock/test/setup/ForkLive.s.sol index c97a75c20a91..2ceba0e96191 100644 --- a/packages/contracts-bedrock/test/setup/ForkLive.s.sol +++ b/packages/contracts-bedrock/test/setup/ForkLive.s.sol @@ -1,7 +1,6 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -import { console } from "forge-std/console.sol"; // Testing import { stdJson } from "forge-std/StdJson.sol"; import { DelegateCaller } from "test/mocks/Callers.sol"; From 1534c07f5372f1f9142317d2c53de62b9ea72f57 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Thu, 9 Jan 2025 00:19:53 -0500 Subject: [PATCH 09/10] fix: compiler errors --- packages/contracts-bedrock/test/setup/ForkLive.s.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/contracts-bedrock/test/setup/ForkLive.s.sol b/packages/contracts-bedrock/test/setup/ForkLive.s.sol index 2ceba0e96191..4411275a13f2 100644 --- a/packages/contracts-bedrock/test/setup/ForkLive.s.sol +++ b/packages/contracts-bedrock/test/setup/ForkLive.s.sol @@ -128,9 +128,9 @@ contract ForkLive is Deployer { } function _upgrade() internal { - OPContractsManager opcm = OPContractsManager(mustGetAddress("OPContractsManager_NextVersion")); + OPContractsManager opcm = OPContractsManager(artifacts.mustGetAddress("OPContractsManager_NextVersion")); - ISystemConfig systemConfig = ISystemConfig(mustGetAddress("SystemConfigProxy")); + ISystemConfig systemConfig = ISystemConfig(artifacts.mustGetAddress("SystemConfigProxy")); IProxyAdmin proxyAdmin = IProxyAdmin(EIP1967Helper.getAdmin(address(systemConfig))); address upgrader = proxyAdmin.owner(); From b35241cd127d5181ef6a6d811dff297a5bad04fe Mon Sep 17 00:00:00 2001 From: Maurelian Date: Thu, 9 Jan 2025 01:38:51 -0500 Subject: [PATCH 10/10] todos --- packages/contracts-bedrock/src/L1/OPContractsManager.sol | 2 ++ packages/contracts-bedrock/test/L1/OPContractsManager.t.sol | 3 +-- packages/contracts-bedrock/test/setup/Setup.sol | 4 ++++ 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/packages/contracts-bedrock/src/L1/OPContractsManager.sol b/packages/contracts-bedrock/src/L1/OPContractsManager.sol index bfe35f1c4f46..d399c066cc07 100644 --- a/packages/contracts-bedrock/src/L1/OPContractsManager.sol +++ b/packages/contracts-bedrock/src/L1/OPContractsManager.sol @@ -379,6 +379,8 @@ contract OPContractsManager is ISemver { /// @param _proxyAdmins Array of ProxyAdmin contracts, one per chain to upgrade /// @dev This function is intended to be called via DELEGATECALL from the Upgrade Controller Safe function upgrade(ISystemConfig[] calldata _systemConfigs, IProxyAdmin[] calldata _proxyAdmins) external { + // TODO: emit the Upgraded event + // TODO: enforce delegatecalling Implementations memory impls = thisOPCM.implementations(); for (uint256 i = 0; i < _systemConfigs.length; i++) { diff --git a/packages/contracts-bedrock/test/L1/OPContractsManager.t.sol b/packages/contracts-bedrock/test/L1/OPContractsManager.t.sol index fe56a4c99745..c122d520c90e 100644 --- a/packages/contracts-bedrock/test/L1/OPContractsManager.t.sol +++ b/packages/contracts-bedrock/test/L1/OPContractsManager.t.sol @@ -166,8 +166,7 @@ contract OPContractsManager_Upgrade_Test is CommonTest { } function test_upgrade_succeeds() public view { - // TODO: make a state var for opcm in CommonTest - OPContractsManager opcm = OPContractsManager(deploy.mustGetAddress("OPContractsManager_NextVersion")); + OPContractsManager opcm = OPContractsManager(artifacts.mustGetAddress("OPContractsManager_NextVersion")); OPContractsManager.Implementations memory impls = opcm.implementations(); assertEq(impls.systemConfigImpl, EIP1967Helper.getImplementation(address(systemConfig))); assertEq(impls.l1ERC721BridgeImpl, EIP1967Helper.getImplementation(address(l1ERC721Bridge))); diff --git a/packages/contracts-bedrock/test/setup/Setup.sol b/packages/contracts-bedrock/test/setup/Setup.sol index 87f0047fe466..c674e4020494 100644 --- a/packages/contracts-bedrock/test/setup/Setup.sol +++ b/packages/contracts-bedrock/test/setup/Setup.sol @@ -20,6 +20,9 @@ import { Preinstalls } from "src/libraries/Preinstalls.sol"; import { AddressAliasHelper } from "src/vendor/AddressAliasHelper.sol"; import { Chains } from "scripts/libraries/Chains.sol"; +// Contracts (TODO: move to interfaces) +import { OPContractsManager } from "src/L1/OPContractsManager.sol"; + // Interfaces import { IOptimismPortal2 } from "interfaces/L1/IOptimismPortal2.sol"; import { IL1CrossDomainMessenger } from "interfaces/L1/IL1CrossDomainMessenger.sol"; @@ -97,6 +100,7 @@ contract Setup { IProtocolVersions protocolVersions; ISuperchainConfig superchainConfig; IDataAvailabilityChallenge dataAvailabilityChallenge; + OPContractsManager opcm; // L2 contracts IL2CrossDomainMessenger l2CrossDomainMessenger =