Skip to content

Commit

Permalink
OPCM upgrade: Add MTCannon to OPCM (#13979)
Browse files Browse the repository at this point in the history
* mtcannon upgrade notes

* mtcannon upgrade strawman impl

* rename mips to mips64

* feat: rename _currentGame to _disputeGame

* feat: Move has input into the OpChain struct, and take one per game

* bump semvers

* feat: rename OpChains to OpChainConfigs and mips to mips64

* feat: Add PrestateNotSet error and tests

* test fixes

* fix snapshots and interfaces

* fix empty prestate tests

* semver

* update arg name to _opChainConfig

* Deploy Mips64 in test

* Address feedback in OPCM.t.sol

* refactor: only take one absolute prestate per chain

* feat: Move superchainProxy admin from opcm upgrade() to constructor()

* Make use of named variable in deploy.s.sol

* feat: Add state var checks to ChainAssertsion.checkOPCM

* wip: adding SuperchainProxyAdmin to op-deployer

* fix: Correct check of scc and pv impls in chainAssertions.opcm

* lint and fix unused import

---------

Co-authored-by: Matt Solomon <[email protected]>
  • Loading branch information
maurelian and mds1 authored Jan 27, 2025
1 parent 8d5850c commit 51b2632
Show file tree
Hide file tree
Showing 21 changed files with 342 additions and 175 deletions.
1 change: 1 addition & 0 deletions op-deployer/pkg/deployer/opcm/implementations.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ type DeployImplementationsInput struct {
L1ContractsRelease string
SuperchainConfigProxy common.Address
ProtocolVersionsProxy common.Address
SuperchainProxyAdmin common.Address
UpgradeController common.Address
UseInterop bool // if true, deploy Interop implementations
}
Expand Down
1 change: 1 addition & 0 deletions op-deployer/pkg/deployer/pipeline/implementations.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ func DeployImplementations(env *Env, intent *state.Intent, st *state.State) erro
L1ContractsRelease: contractsRelease,
SuperchainConfigProxy: st.SuperchainDeployment.SuperchainConfigProxyAddress,
ProtocolVersionsProxy: st.SuperchainDeployment.ProtocolVersionsProxyAddress,
SuperchainProxyAdmin: st.SuperchainDeployment.ProxyAdminAddress,
UpgradeController: intent.SuperchainRoles.ProxyAdminOwner,
UseInterop: intent.UseInterop,
},
Expand Down
16 changes: 11 additions & 5 deletions packages/contracts-bedrock/interfaces/L1/IOPContractsManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -105,13 +105,14 @@ interface IOPContractsManager {
address disputeGameFactoryImpl;
address anchorStateRegistryImpl;
address delayedWETHImpl;
address mipsImpl;
address mips64Impl;
}

/// @notice The input required to identify a chain for upgrading.
struct OpChain {
struct OpChainConfig {
ISystemConfig systemConfigProxy;
IProxyAdmin proxyAdmin;
Claim absolutePrestate;
}

struct AddGameInput {
Expand Down Expand Up @@ -145,6 +146,9 @@ interface IOPContractsManager {
/// @notice Address of the ProtocolVersions contract shared by all chains.
function protocolVersions() external view returns (IProtocolVersions);

/// @notice Address of the ProxyAdmin contract shared by all chains.
function superchainProxyAdmin() external view returns (IProxyAdmin);

/// @notice L1 smart contracts release deployed by this version of OPCM. This is used in opcm to signal which
/// version of the L1 smart contracts is deployed. It takes the format of `op-contracts/vX.Y.Z`.
function l1ContractsRelease() external view returns (string memory);
Expand Down Expand Up @@ -206,11 +210,14 @@ interface IOPContractsManager {

error SuperchainProxyAdminMismatch();

error PrestateNotSet();

// -------- Methods --------

function __constructor__(
ISuperchainConfig _superchainConfig,
IProtocolVersions _protocolVersions,
IProxyAdmin _superchainProxyAdmin,
string memory _l1ContractsRelease,
Blueprints memory _blueprints,
Implementations memory _implementations,
Expand All @@ -221,9 +228,8 @@ interface IOPContractsManager {
function deploy(DeployInput calldata _input) external returns (DeployOutput memory);

/// @notice Upgrades the implementation of all proxies in the specified chains
/// @param _superchainProxyAdmin The proxy admin that owns all of the proxies
/// @param _opChains The chains to upgrade
function upgrade(IProxyAdmin _superchainProxyAdmin, OpChain[] memory _opChains) external;
/// @param _opChainConfigs The chains to upgrade
function upgrade(OpChainConfig[] memory _opChainConfigs) external;

/// @notice addGameType deploys a new dispute game and links it to the DisputeGameFactory. The inputted _gameConfigs
/// must be added in ascending GameType order.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@ pragma solidity ^0.8.0;

import { ISuperchainConfig } from "interfaces/L1/ISuperchainConfig.sol";
import { IProtocolVersions } from "interfaces/L1/IProtocolVersions.sol";
import { IProxyAdmin } from "interfaces/universal/IProxyAdmin.sol";
import { IOPContractsManager } from "interfaces/L1/IOPContractsManager.sol";

interface IOPContractsManagerInterop is IOPContractsManager {
function __constructor__(
ISuperchainConfig _superchainConfig,
IProtocolVersions _protocolVersions,
IProxyAdmin _superchainProxyAdmin,
string memory _l1ContractsRelease,
Blueprints memory _blueprints,
Implementations memory _implementations,
Expand Down
42 changes: 21 additions & 21 deletions packages/contracts-bedrock/scripts/deploy/ChainAssertions.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ pragma solidity ^0.8.0;
// Testing
import { Vm } from "forge-std/Vm.sol";
import { console2 as console } from "forge-std/console2.sol";
import { EIP1967Helper } from "test/mocks/EIP1967Helper.sol";

// Scripts
import { DeployConfig } from "scripts/deploy/DeployConfig.s.sol";
Expand Down Expand Up @@ -32,6 +31,7 @@ import { IDelayedWETH } from "interfaces/dispute/IDelayedWETH.sol";
import { IOptimismMintableERC20Factory } from "interfaces/universal/IOptimismMintableERC20Factory.sol";
import { IPreimageOracle } from "interfaces/cannon/IPreimageOracle.sol";
import { IMIPS } from "interfaces/cannon/IMIPS.sol";
import { IProxyAdmin } from "interfaces/universal/IProxyAdmin.sol";

library ChainAssertions {
Vm internal constant vm = Vm(0x7109709ECfa91a80626fF3989D68f67F5b1DD12D);
Expand Down Expand Up @@ -469,39 +469,39 @@ library ChainAssertions {

/// @notice Asserts that the OPContractsManager is setup correctly
function checkOPContractsManager(
Types.ContractSet memory _contracts,
Types.ContractSet memory _impls,
Types.ContractSet memory _proxies,
IOPContractsManager _opcm,
IMIPS _mips
IMIPS _mips,
IProxyAdmin _superchainProxyAdmin
)
internal
view
{
console.log("Running chain assertions on the OPContractsManager at %s", address(_opcm));
require(address(_opcm) != address(0), "CHECK-OPCM-10");

require(
address(EIP1967Helper.getImplementation(address(_opcm.superchainConfig())))
== address(_contracts.SuperchainConfig),
"CHECK-OPCM-20"
);
require(
EIP1967Helper.getImplementation(address(_opcm.protocolVersions())) == address(_contracts.ProtocolVersions),
"CHECK-OPCM-30"
);
require(bytes(_opcm.version()).length > 0, "CHECK-OPCM-15");
require(bytes(_opcm.l1ContractsRelease()).length > 0, "CHECK-OPCM-16");
require(address(_opcm.protocolVersions()) == _proxies.ProtocolVersions, "CHECK-OPCM-17");
require(address(_opcm.superchainProxyAdmin()) == address(_superchainProxyAdmin), "CHECK-OPCM-18");
require(address(_opcm.superchainConfig()) == _proxies.SuperchainConfig, "CHECK-OPCM-19");

require(bytes(_opcm.l1ContractsRelease()).length > 0, "CHECK-OPCM-40");

// Ensure that the OPCM impls are correctly saved
IOPContractsManager.Implementations memory impls = _opcm.implementations();
require(impls.l1ERC721BridgeImpl == _contracts.L1ERC721Bridge, "CHECK-OPCM-50");
require(impls.optimismPortalImpl == _contracts.OptimismPortal, "CHECK-OPCM-60");
require(impls.systemConfigImpl == _contracts.SystemConfig, "CHECK-OPCM-70");
require(impls.optimismMintableERC20FactoryImpl == _contracts.OptimismMintableERC20Factory, "CHECK-OPCM-80");
require(impls.l1CrossDomainMessengerImpl == _contracts.L1CrossDomainMessenger, "CHECK-OPCM-90");
require(impls.l1StandardBridgeImpl == _contracts.L1StandardBridge, "CHECK-OPCM-100");
require(impls.disputeGameFactoryImpl == _contracts.DisputeGameFactory, "CHECK-OPCM-110");
require(impls.delayedWETHImpl == _contracts.DelayedWETH, "CHECK-OPCM-120");
require(impls.mipsImpl == address(_mips), "CHECK-OPCM-130");
require(impls.l1ERC721BridgeImpl == _impls.L1ERC721Bridge, "CHECK-OPCM-50");
require(impls.optimismPortalImpl == _impls.OptimismPortal, "CHECK-OPCM-60");
require(impls.systemConfigImpl == _impls.SystemConfig, "CHECK-OPCM-70");
require(impls.optimismMintableERC20FactoryImpl == _impls.OptimismMintableERC20Factory, "CHECK-OPCM-80");
require(impls.l1CrossDomainMessengerImpl == _impls.L1CrossDomainMessenger, "CHECK-OPCM-90");
require(impls.l1StandardBridgeImpl == _impls.L1StandardBridge, "CHECK-OPCM-100");
require(impls.disputeGameFactoryImpl == _impls.DisputeGameFactory, "CHECK-OPCM-110");
require(impls.delayedWETHImpl == _impls.DelayedWETH, "CHECK-OPCM-120");
require(impls.mips64Impl == address(_mips), "CHECK-OPCM-130");
require(impls.superchainConfigImpl == _impls.SuperchainConfig, "CHECK-OPCM-140");
require(impls.protocolVersionsImpl == _impls.ProtocolVersions, "CHECK-OPCM-150");

// Verify that initCode is correctly set into the blueprints
IOPContractsManager.Blueprints memory blueprints = _opcm.blueprints();
Expand Down
50 changes: 25 additions & 25 deletions packages/contracts-bedrock/scripts/deploy/Deploy.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -284,12 +284,16 @@ contract Deploy is Deployer {
dii.set(dii.mipsVersion.selector, Config.useMultithreadedCannon() ? 2 : 1);
string memory release = "dev";
dii.set(dii.l1ContractsRelease.selector, release);
dii.set(dii.superchainConfigProxy.selector, artifacts.mustGetAddress("SuperchainConfigProxy"));
dii.set(dii.protocolVersionsProxy.selector, artifacts.mustGetAddress("ProtocolVersionsProxy"));
dii.set(
dii.upgradeController.selector,
IProxyAdmin(EIP1967Helper.getAdmin(artifacts.mustGetAddress("SuperchainConfigProxy"))).owner()
);

ISuperchainConfig superchainConfig = ISuperchainConfig(artifacts.mustGetAddress("SuperchainConfigProxy"));
dii.set(dii.superchainConfigProxy.selector, address(superchainConfig));

IProxyAdmin superchainProxyAdmin = IProxyAdmin(EIP1967Helper.getAdmin(address(superchainConfig)));
dii.set(dii.superchainProxyAdmin.selector, address(superchainProxyAdmin));

// I think this was a bug
dii.set(dii.upgradeController.selector, superchainProxyAdmin.owner());

if (_isInterop) {
di = DeployImplementations(new DeployImplementationsInterop());
Expand All @@ -303,7 +307,7 @@ contract Deploy is Deployer {
artifacts.save("DelayedWETHImpl", address(dio.delayedWETHImpl()));

// Get a contract set from the implementation addresses which were just deployed.
Types.ContractSet memory contracts = Types.ContractSet({
Types.ContractSet memory impls = Types.ContractSet({
L1CrossDomainMessenger: address(dio.l1CrossDomainMessengerImpl()),
L1StandardBridge: address(dio.l1StandardBridgeImpl()),
L2OutputOracle: address(0),
Expand All @@ -315,23 +319,17 @@ contract Deploy is Deployer {
OptimismPortal: address(dio.optimismPortalImpl()),
SystemConfig: address(dio.systemConfigImpl()),
L1ERC721Bridge: address(dio.l1ERC721BridgeImpl()),
// We didn't deploy new versions of these in this function, so just read the existing ones.
ProtocolVersions: artifacts.mustGetAddress("ProtocolVersionsImpl"),
SuperchainConfig: artifacts.mustGetAddress("SuperchainConfigImpl")
ProtocolVersions: address(dio.protocolVersionsImpl()),
SuperchainConfig: address(dio.superchainConfigImpl())
});

ChainAssertions.checkL1CrossDomainMessenger({ _contracts: contracts, _vm: vm, _isProxy: false });
ChainAssertions.checkL1StandardBridge({ _contracts: contracts, _isProxy: false });
ChainAssertions.checkL1ERC721Bridge({ _contracts: contracts, _isProxy: false });
ChainAssertions.checkOptimismPortal2({ _contracts: contracts, _cfg: cfg, _isProxy: false });
ChainAssertions.checkOptimismMintableERC20Factory({ _contracts: contracts, _isProxy: false });
ChainAssertions.checkDisputeGameFactory({ _contracts: contracts, _expectedOwner: address(0), _isProxy: false });
ChainAssertions.checkDelayedWETH({
_contracts: contracts,
_cfg: cfg,
_isProxy: false,
_expectedOwner: address(0)
});
ChainAssertions.checkL1CrossDomainMessenger({ _contracts: impls, _vm: vm, _isProxy: false });
ChainAssertions.checkL1StandardBridge({ _contracts: impls, _isProxy: false });
ChainAssertions.checkL1ERC721Bridge({ _contracts: impls, _isProxy: false });
ChainAssertions.checkOptimismPortal2({ _contracts: impls, _cfg: cfg, _isProxy: false });
ChainAssertions.checkOptimismMintableERC20Factory({ _contracts: impls, _isProxy: false });
ChainAssertions.checkDisputeGameFactory({ _contracts: impls, _expectedOwner: address(0), _isProxy: false });
ChainAssertions.checkDelayedWETH({ _contracts: impls, _cfg: cfg, _isProxy: false, _expectedOwner: address(0) });
ChainAssertions.checkPreimageOracle({
_oracle: IPreimageOracle(address(dio.preimageOracleSingleton())),
_cfg: cfg
Expand All @@ -341,14 +339,16 @@ contract Deploy is Deployer {
_oracle: IPreimageOracle(address(dio.preimageOracleSingleton()))
});
ChainAssertions.checkOPContractsManager({
_contracts: contracts,
_impls: impls,
_proxies: _proxies(),
_opcm: IOPContractsManager(address(dio.opcm())),
_mips: IMIPS(address(dio.mipsSingleton()))
_mips: IMIPS(address(dio.mipsSingleton())),
_superchainProxyAdmin: superchainProxyAdmin
});
if (_isInterop) {
ChainAssertions.checkSystemConfigInterop({ _contracts: contracts, _cfg: cfg, _isProxy: false });
ChainAssertions.checkSystemConfigInterop({ _contracts: impls, _cfg: cfg, _isProxy: false });
} else {
ChainAssertions.checkSystemConfig({ _contracts: contracts, _cfg: cfg, _isProxy: false });
ChainAssertions.checkSystemConfig({ _contracts: impls, _cfg: cfg, _isProxy: false });
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import { IL1StandardBridge } from "interfaces/L1/IL1StandardBridge.sol";
import { IOptimismMintableERC20Factory } from "interfaces/universal/IOptimismMintableERC20Factory.sol";
import { IOptimismPortalInterop } from "interfaces/L1/IOptimismPortalInterop.sol";
import { ISystemConfigInterop } from "interfaces/L1/ISystemConfigInterop.sol";

import { IProxyAdmin } from "interfaces/universal/IProxyAdmin.sol";
import { DeployUtils } from "scripts/libraries/DeployUtils.sol";
import { Solarray } from "scripts/libraries/Solarray.sol";
import { BaseDeployIO } from "scripts/deploy/BaseDeployIO.sol";
Expand All @@ -45,6 +45,7 @@ contract DeployImplementationsInput is BaseDeployIO {
// Outputs from DeploySuperchain.s.sol.
ISuperchainConfig internal _superchainConfigProxy;
IProtocolVersions internal _protocolVersionsProxy;
IProxyAdmin internal _superchainProxyAdmin;
address internal _upgradeController;

function set(bytes4 _sel, uint256 _value) public {
Expand Down Expand Up @@ -78,6 +79,7 @@ contract DeployImplementationsInput is BaseDeployIO {
require(_addr != address(0), "DeployImplementationsInput: cannot set zero address");
if (_sel == this.superchainConfigProxy.selector) _superchainConfigProxy = ISuperchainConfig(_addr);
else if (_sel == this.protocolVersionsProxy.selector) _protocolVersionsProxy = IProtocolVersions(_addr);
else if (_sel == this.superchainProxyAdmin.selector) _superchainProxyAdmin = IProxyAdmin(_addr);
else if (_sel == this.upgradeController.selector) _upgradeController = _addr;
else revert("DeployImplementationsInput: unknown selector");
}
Expand Down Expand Up @@ -130,6 +132,11 @@ contract DeployImplementationsInput is BaseDeployIO {
return _protocolVersionsProxy;
}

function superchainProxyAdmin() public view returns (IProxyAdmin) {
require(address(_superchainProxyAdmin) != address(0), "DeployImplementationsInput: not set");
return _superchainProxyAdmin;
}

function upgradeController() public view returns (address) {
require(address(_upgradeController) != address(0), "DeployImplementationsInput: not set");
return _upgradeController;
Expand Down Expand Up @@ -470,6 +477,7 @@ contract DeployImplementations is Script {
{
ISuperchainConfig superchainConfigProxy = _dii.superchainConfigProxy();
IProtocolVersions protocolVersionsProxy = _dii.protocolVersionsProxy();
IProxyAdmin superchainProxyAdmin = _dii.superchainProxyAdmin();
address upgradeController = _dii.upgradeController();

IOPContractsManager.Implementations memory implementations = IOPContractsManager.Implementations({
Expand All @@ -484,7 +492,7 @@ contract DeployImplementations is Script {
disputeGameFactoryImpl: address(_dio.disputeGameFactoryImpl()),
anchorStateRegistryImpl: address(_dio.anchorStateRegistryImpl()),
delayedWETHImpl: address(_dio.delayedWETHImpl()),
mipsImpl: address(_dio.mipsSingleton())
mips64Impl: address(_dio.mipsSingleton())
});

vm.broadcast(msg.sender);
Expand All @@ -497,6 +505,7 @@ contract DeployImplementations is Script {
(
superchainConfigProxy,
protocolVersionsProxy,
superchainProxyAdmin,
_l1ContractsRelease,
_blueprints,
implementations,
Expand Down Expand Up @@ -852,6 +861,7 @@ contract DeployImplementationsInterop is DeployImplementations {
{
ISuperchainConfig superchainConfigProxy = _dii.superchainConfigProxy();
IProtocolVersions protocolVersionsProxy = _dii.protocolVersionsProxy();
IProxyAdmin superchainProxyAdmin = _dii.superchainProxyAdmin();
address upgradeController = _dii.upgradeController();

IOPContractsManager.Implementations memory implementations = IOPContractsManager.Implementations({
Expand All @@ -866,7 +876,7 @@ contract DeployImplementationsInterop is DeployImplementations {
disputeGameFactoryImpl: address(_dio.disputeGameFactoryImpl()),
anchorStateRegistryImpl: address(_dio.anchorStateRegistryImpl()),
delayedWETHImpl: address(_dio.delayedWETHImpl()),
mipsImpl: address(_dio.mipsSingleton())
mips64Impl: address(_dio.mipsSingleton())
});

vm.broadcast(msg.sender);
Expand All @@ -879,6 +889,7 @@ contract DeployImplementationsInterop is DeployImplementations {
(
superchainConfigProxy,
protocolVersionsProxy,
superchainProxyAdmin,
_l1ContractsRelease,
_blueprints,
implementations,
Expand Down
Loading

0 comments on commit 51b2632

Please sign in to comment.