Commit de3865c0 authored by Michael Amadi's avatar Michael Amadi Committed by GitHub

-rc is removed when upgrade() is called by the Upgrade Controller (#13863)

* append -rc if not upgraded yet

* append -rc if not upgraded yet

* fix tests

* fix tests

* fixes

* try fix go tests

* fix contracts tests

* fixes

* fixes

* fixes

* fixes
parent 4a154126
......@@ -171,6 +171,7 @@ func DeploySuperchainToL1(l1Host *script.Host, superCfg *SuperchainConfig) (*Sup
L1ContractsRelease: superCfg.Implementations.L1ContractsRelease,
SuperchainConfigProxy: superDeployment.SuperchainConfigProxy,
ProtocolVersionsProxy: superDeployment.ProtocolVersionsProxy,
UpgradeController: superCfg.ProxyAdminOwner,
UseInterop: superCfg.Implementations.UseInterop,
})
if err != nil {
......
......@@ -39,6 +39,7 @@ type ImplementationsConfig struct {
DisputeGameFinalityDelaySeconds uint64 `cli:"dispute-game-finality-delay-seconds"`
SuperchainConfigProxy common.Address `cli:"superchain-config-proxy"`
ProtocolVersionsProxy common.Address `cli:"protocol-versions-proxy"`
UpgradeController common.Address `cli:"upgrade-controller"`
UseInterop bool `cli:"use-interop"`
Logger log.Logger
......@@ -192,6 +193,7 @@ func Implementations(ctx context.Context, cfg ImplementationsConfig) (opcm.Deplo
L1ContractsRelease: cfg.L1ContractsRelease,
SuperchainConfigProxy: cfg.SuperchainConfigProxy,
ProtocolVersionsProxy: cfg.ProtocolVersionsProxy,
UpgradeController: cfg.UpgradeController,
UseInterop: cfg.UseInterop,
},
); err != nil {
......
......@@ -70,6 +70,8 @@ func testImplementations(t *testing.T, forkRPCURL string) {
loc, _ := testutil.LocalArtifacts(t)
proxyAdminOwner, err := standard.L1ProxyAdminOwner(uint64(chainID.Uint64()))
require.NoError(t, err)
deploy := func() opcm.DeployImplementationsOutput {
out, err := Implementations(ctx, ImplementationsConfig{
L1RPCUrl: runner.RPCUrl(),
......@@ -85,6 +87,7 @@ func testImplementations(t *testing.T, forkRPCURL string) {
MIPSVersion: 1,
SuperchainConfigProxy: common.Address(*superchain.Config.SuperchainConfigAddr),
ProtocolVersionsProxy: common.Address(*superchain.Config.ProtocolVersionsAddr),
UpgradeController: proxyAdminOwner,
UseInterop: false,
})
require.NoError(t, err)
......
......@@ -20,6 +20,7 @@ type DeployImplementationsInput struct {
L1ContractsRelease string
SuperchainConfigProxy common.Address
ProtocolVersionsProxy common.Address
UpgradeController common.Address
UseInterop bool // if true, deploy Interop implementations
}
......
......@@ -11,6 +11,7 @@ type DeployOPCMInput struct {
SuperchainConfig common.Address
ProtocolVersions common.Address
L1ContractsRelease string
UpgradeController common.Address
AddressManagerBlueprint common.Address
ProxyBlueprint common.Address
......
......@@ -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,
UpgradeController: intent.SuperchainRoles.ProxyAdminOwner,
UseInterop: intent.UseInterop,
},
)
......
......@@ -170,6 +170,7 @@ interface IOPContractsManager {
error ReservedBitsSet();
error UnexpectedPreambleData(bytes data);
error UnsupportedERCVersion(uint8 version);
error OnlyUpgradeController();
/// @notice Thrown when an address is the zero address.
error AddressNotFound(address who);
......@@ -208,7 +209,8 @@ interface IOPContractsManager {
IProtocolVersions _protocolVersions,
string memory _l1ContractsRelease,
Blueprints memory _blueprints,
Implementations memory _implementations
Implementations memory _implementations,
address _upgradeController
)
external;
......@@ -234,4 +236,10 @@ interface IOPContractsManager {
/// @notice Returns the implementation contract addresses.
function implementations() external view returns (Implementations memory);
function upgradeController() external view returns (address);
function isRC() external view returns (bool);
function setRC(bool _isRC) external;
}
......@@ -11,7 +11,8 @@ interface IOPContractsManagerInterop is IOPContractsManager {
IProtocolVersions _protocolVersions,
string memory _l1ContractsRelease,
Blueprints memory _blueprints,
Implementations memory _implementations
Implementations memory _implementations,
address _upgradeController
)
external;
}
......@@ -292,6 +292,10 @@ contract Deploy is Deployer {
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()
);
if (_isInterop) {
di = DeployImplementations(new DeployImplementationsInterop());
......
......@@ -45,6 +45,7 @@ contract DeployImplementationsInput is BaseDeployIO {
// Outputs from DeploySuperchain.s.sol.
ISuperchainConfig internal _superchainConfigProxy;
IProtocolVersions internal _protocolVersionsProxy;
address internal _upgradeController;
function set(bytes4 _sel, uint256 _value) public {
require(_value != 0, "DeployImplementationsInput: cannot set zero value");
......@@ -77,6 +78,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.upgradeController.selector) _upgradeController = _addr;
else revert("DeployImplementationsInput: unknown selector");
}
......@@ -127,6 +129,11 @@ contract DeployImplementationsInput is BaseDeployIO {
require(address(_protocolVersionsProxy) != address(0), "DeployImplementationsInput: not set");
return _protocolVersionsProxy;
}
function upgradeController() public view returns (address) {
require(address(_upgradeController) != address(0), "DeployImplementationsInput: not set");
return _upgradeController;
}
}
contract DeployImplementationsOutput is BaseDeployIO {
......@@ -269,6 +276,7 @@ contract DeployImplementationsOutput is BaseDeployIO {
IOPContractsManager impl = IOPContractsManager(address(opcm()));
require(address(impl.superchainConfig()) == address(_dii.superchainConfigProxy()), "OPCMI-10");
require(address(impl.protocolVersions()) == address(_dii.protocolVersionsProxy()), "OPCMI-20");
require(impl.upgradeController() == _dii.upgradeController(), "OPCMI-30");
}
function assertValidOptimismPortalImpl(DeployImplementationsInput) internal view {
......@@ -444,6 +452,7 @@ contract DeployImplementations is Script {
{
ISuperchainConfig superchainConfigProxy = _dii.superchainConfigProxy();
IProtocolVersions protocolVersionsProxy = _dii.protocolVersionsProxy();
address upgradeController = _dii.upgradeController();
IOPContractsManager.Implementations memory implementations = IOPContractsManager.Implementations({
l1ERC721BridgeImpl: address(_dio.l1ERC721BridgeImpl()),
......@@ -465,7 +474,14 @@ contract DeployImplementations is Script {
_args: DeployUtils.encodeConstructor(
abi.encodeCall(
IOPContractsManager.__constructor__,
(superchainConfigProxy, protocolVersionsProxy, _l1ContractsRelease, _blueprints, implementations)
(
superchainConfigProxy,
protocolVersionsProxy,
_l1ContractsRelease,
_blueprints,
implementations,
upgradeController
)
)
),
_salt: _salt
......@@ -790,6 +806,7 @@ contract DeployImplementationsInterop is DeployImplementations {
{
ISuperchainConfig superchainConfigProxy = _dii.superchainConfigProxy();
IProtocolVersions protocolVersionsProxy = _dii.protocolVersionsProxy();
address upgradeController = _dii.upgradeController();
IOPContractsManager.Implementations memory implementations = IOPContractsManager.Implementations({
l1ERC721BridgeImpl: address(_dio.l1ERC721BridgeImpl()),
......@@ -811,7 +828,14 @@ contract DeployImplementationsInterop is DeployImplementations {
_args: DeployUtils.encodeConstructor(
abi.encodeCall(
IOPContractsManagerInterop.__constructor__,
(superchainConfigProxy, protocolVersionsProxy, _l1ContractsRelease, _blueprints, implementations)
(
superchainConfigProxy,
protocolVersionsProxy,
_l1ContractsRelease,
_blueprints,
implementations,
upgradeController
)
)
),
_salt: _salt
......
......@@ -16,6 +16,7 @@ contract DeployOPCMInput is BaseDeployIO {
ISuperchainConfig internal _superchainConfig;
IProtocolVersions internal _protocolVersions;
string internal _l1ContractsRelease;
address internal _upgradeController;
address internal _addressManagerBlueprint;
address internal _proxyBlueprint;
......@@ -42,6 +43,7 @@ contract DeployOPCMInput is BaseDeployIO {
if (_sel == this.superchainConfig.selector) _superchainConfig = ISuperchainConfig(_addr);
else if (_sel == this.protocolVersions.selector) _protocolVersions = IProtocolVersions(_addr);
else if (_sel == this.upgradeController.selector) _upgradeController = _addr;
else if (_sel == this.addressManagerBlueprint.selector) _addressManagerBlueprint = _addr;
else if (_sel == this.proxyBlueprint.selector) _proxyBlueprint = _addr;
else if (_sel == this.proxyAdminBlueprint.selector) _proxyAdminBlueprint = _addr;
......@@ -85,6 +87,11 @@ contract DeployOPCMInput is BaseDeployIO {
return _l1ContractsRelease;
}
function upgradeController() public view returns (address) {
require(_upgradeController != address(0), "DeployOPCMInput: not set");
return _upgradeController;
}
function addressManagerBlueprint() public view returns (address) {
require(_addressManagerBlueprint != address(0), "DeployOPCMInput: not set");
return _addressManagerBlueprint;
......@@ -215,7 +222,12 @@ contract DeployOPCM is Script {
});
IOPContractsManager opcm_ = deployOPCM(
_doi.superchainConfig(), _doi.protocolVersions(), blueprints, implementations, _doi.l1ContractsRelease()
_doi.superchainConfig(),
_doi.protocolVersions(),
blueprints,
implementations,
_doi.l1ContractsRelease(),
_doi.upgradeController()
);
_doo.set(_doo.opcm.selector, address(opcm_));
......@@ -227,7 +239,8 @@ contract DeployOPCM is Script {
IProtocolVersions _protocolVersions,
IOPContractsManager.Blueprints memory _blueprints,
IOPContractsManager.Implementations memory _implementations,
string memory _l1ContractsRelease
string memory _l1ContractsRelease,
address _upgradeController
)
public
returns (IOPContractsManager opcm_)
......@@ -239,7 +252,14 @@ contract DeployOPCM is Script {
_args: DeployUtils.encodeConstructor(
abi.encodeCall(
IOPContractsManager.__constructor__,
(_superchainConfig, _protocolVersions, _l1ContractsRelease, _blueprints, _implementations)
(
_superchainConfig,
_protocolVersions,
_l1ContractsRelease,
_blueprints,
_implementations,
_upgradeController
)
)
),
_salt: DeployUtils.DEFAULT_SALT
......@@ -252,7 +272,9 @@ contract DeployOPCM is Script {
IOPContractsManager impl = IOPContractsManager(address(_doo.opcm()));
require(address(impl.superchainConfig()) == address(_doi.superchainConfig()), "OPCMI-10");
require(address(impl.protocolVersions()) == address(_doi.protocolVersions()), "OPCMI-20");
require(LibString.eq(impl.l1ContractsRelease(), _doi.l1ContractsRelease()), "OPCMI-30");
require(LibString.eq(impl.l1ContractsRelease(), string.concat(_doi.l1ContractsRelease(), "-rc")), "OPCMI-30");
require(impl.upgradeController() == _doi.upgradeController(), "OPCMI-40");
IOPContractsManager.Blueprints memory blueprints = impl.blueprints();
require(blueprints.addressManager == _doi.addressManagerBlueprint(), "OPCMI-40");
......
......@@ -124,6 +124,11 @@
"internalType": "struct OPContractsManager.Implementations",
"name": "_implementations",
"type": "tuple"
},
{
"internalType": "address",
"name": "_upgradeController",
"type": "address"
}
],
"stateMutability": "nonpayable",
......@@ -561,6 +566,19 @@
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "isRC",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "l1ContractsRelease",
......@@ -587,6 +605,19 @@
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "bool",
"name": "_isRC",
"type": "bool"
}
],
"name": "setRC",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "superchainConfig",
......@@ -625,6 +656,19 @@
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "upgradeController",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "version",
......@@ -776,6 +820,11 @@
"name": "OnlyDelegatecall",
"type": "error"
},
{
"inputs": [],
"name": "OnlyUpgradeController",
"type": "error"
},
{
"inputs": [],
"name": "ReservedBitsSet",
......
......@@ -124,6 +124,11 @@
"internalType": "struct OPContractsManager.Implementations",
"name": "_implementations",
"type": "tuple"
},
{
"internalType": "address",
"name": "_upgradeController",
"type": "address"
}
],
"stateMutability": "nonpayable",
......@@ -561,6 +566,19 @@
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "isRC",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "l1ContractsRelease",
......@@ -587,6 +605,19 @@
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "bool",
"name": "_isRC",
"type": "bool"
}
],
"name": "setRC",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "superchainConfig",
......@@ -625,6 +656,19 @@
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "upgradeController",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "version",
......@@ -776,6 +820,11 @@
"name": "OnlyDelegatecall",
"type": "error"
},
{
"inputs": [],
"name": "OnlyUpgradeController",
"type": "error"
},
{
"inputs": [],
"name": "ReservedBitsSet",
......
......@@ -16,12 +16,12 @@
"sourceCodeHash": "0xc6613d35d1ad95cbef26a503a10b5dd8663ceb80426f8c528835d39f79e4b4cf"
},
"src/L1/OPContractsManager.sol": {
"initCodeHash": "0xa277d25e1aae34f68e9e8a0814c34f6adada5248992dc5e62831ef0082f130fb",
"sourceCodeHash": "0xaa2c1ae210bf8c53b21e8fe3280bf17040118530eafd1f33e8ed64bc17ee4a17"
"initCodeHash": "0x9fc601820098fb3308ece91087c9209a4bff049f1f8d1e7c33a7a7a27cf5f96f",
"sourceCodeHash": "0xcfd0f82cb6481c22841747d9ed9022dc9e6b01a7e03edffb13587bfeae8eaee8"
},
"src/L1/OPContractsManagerInterop.sol": {
"initCodeHash": "0x5cbfb22cb4ca0465a0bc8d87034763f9a103384ff60ac88af8a4c2ced7c96b7d",
"sourceCodeHash": "0x1bbe8f918f1d5b1cc75924cdf23b10664b890fd306c2aa5d195a7b4177670431"
"initCodeHash": "0xc7f77833e13a5aa7460df755c60d36068bc10868f9071b4350b139eaa391c071",
"sourceCodeHash": "0x5a9180a546a0c79baae5f2b42f5110bcae15d3ae8a3e05fa536eb8659774b733"
},
"src/L1/OptimismPortal2.sol": {
"initCodeHash": "0x969e3687d4497cc168af61e610ba0ae187e80f86aaa7b5d5bb598de19f279f08",
......
[
{
"bytes": "32",
"label": "l1ContractsRelease",
"label": "L1_CONTRACTS_RELEASE",
"offset": 0,
"slot": "0",
"type": "string"
......@@ -19,5 +19,12 @@
"offset": 0,
"slot": "10",
"type": "struct OPContractsManager.Implementations"
},
{
"bytes": "1",
"label": "isRC",
"offset": 0,
"slot": "20",
"type": "bool"
}
]
\ No newline at end of file
[
{
"bytes": "32",
"label": "l1ContractsRelease",
"label": "L1_CONTRACTS_RELEASE",
"offset": 0,
"slot": "0",
"type": "string"
......@@ -19,5 +19,12 @@
"offset": 0,
"slot": "10",
"type": "struct OPContractsManager.Implementations"
},
{
"bytes": "1",
"label": "isRC",
"offset": 0,
"slot": "20",
"type": "bool"
}
]
\ No newline at end of file
......@@ -141,9 +141,9 @@ contract OPContractsManager is ISemver {
// -------- Constants and Variables --------
/// @custom:semver 1.0.0-beta.33
/// @custom:semver 1.0.0-beta.34
function version() public pure virtual returns (string memory) {
return "1.0.0-beta.33";
return "1.0.0-beta.34";
}
/// @notice Address of the SuperchainConfig contract shared by all chains.
......@@ -154,7 +154,7 @@ contract OPContractsManager is ISemver {
/// @notice L1 smart contracts release deployed by this version of OPCM. This is used in opcm to signal which
/// version of the L1 smart contracts is deployed. It takes the format of `op-contracts/vX.Y.Z`.
string public l1ContractsRelease;
string internal L1_CONTRACTS_RELEASE;
/// @notice Addresses of the Blueprint contracts.
/// This is internal because if public the autogenerated getter method would return a tuple of
......@@ -168,6 +168,17 @@ contract OPContractsManager is ISemver {
/// which is intended to be DELEGATECALLed.
OPContractsManager internal immutable thisOPCM;
/// @notice The address of the upgrade controller.
address public immutable upgradeController;
/// @notice Whether this is a release candidate.
bool public isRC = true;
/// @notice Returns the release string. Appends "-rc" if this is a release candidate.
function l1ContractsRelease() external view returns (string memory) {
return isRC ? string.concat(L1_CONTRACTS_RELEASE, "-rc") : L1_CONTRACTS_RELEASE;
}
// -------- Events --------
/// @notice Emitted when a new OP Stack chain is deployed.
......@@ -183,6 +194,9 @@ contract OPContractsManager is ISemver {
// -------- Errors --------
/// @notice Thrown when an address other than the upgrade controller calls the setRC function.
error OnlyUpgradeController();
/// @notice Thrown when an address is the zero address.
error AddressNotFound(address who);
......@@ -220,17 +234,19 @@ contract OPContractsManager is ISemver {
IProtocolVersions _protocolVersions,
string memory _l1ContractsRelease,
Blueprints memory _blueprints,
Implementations memory _implementations
Implementations memory _implementations,
address _upgradeController
) {
assertValidContractAddress(address(_superchainConfig));
assertValidContractAddress(address(_protocolVersions));
superchainConfig = _superchainConfig;
protocolVersions = _protocolVersions;
l1ContractsRelease = _l1ContractsRelease;
L1_CONTRACTS_RELEASE = _l1ContractsRelease;
blueprint = _blueprints;
implementation = _implementations;
thisOPCM = this;
upgradeController = _upgradeController;
}
function deploy(DeployInput calldata _input) external returns (DeployOutput memory) {
......@@ -416,6 +432,13 @@ contract OPContractsManager is ISemver {
function upgrade(OpChain[] memory _opChains) external {
if (address(this) == address(thisOPCM)) revert OnlyDelegatecall();
// If this is delegatecalled by the upgrade controller, set isRC to false first, else, continue execution.
if (address(this) == upgradeController) {
// Set isRC to false.
// This function asserts that the caller is the upgrade controller.
thisOPCM.setRC(false);
}
Implementations memory impls = thisOPCM.implementations();
// TODO: upgrading the SuperchainConfig and ProtocolVersions (in a new function)
......@@ -874,4 +897,10 @@ contract OPContractsManager is ISemver {
{
return _disputeGameFactory.gameImpls(_gameType);
}
/// @notice Sets the RC flag.
function setRC(bool _isRC) external {
if (msg.sender != upgradeController) revert OnlyUpgradeController();
isRC = _isRC;
}
}
......@@ -12,9 +12,9 @@ import { ISystemConfig } from "interfaces/L1/ISystemConfig.sol";
import { ISystemConfigInterop } from "interfaces/L1/ISystemConfigInterop.sol";
contract OPContractsManagerInterop is OPContractsManager {
/// @custom:semver +interop-beta.1
/// @custom:semver +interop-beta.2
function version() public pure override returns (string memory) {
return string.concat(super.version(), "+interop-beta.1");
return string.concat(super.version(), "+interop-beta.2");
}
constructor(
......@@ -22,9 +22,17 @@ contract OPContractsManagerInterop is OPContractsManager {
IProtocolVersions _protocolVersions,
string memory _l1ContractsRelease,
Blueprints memory _blueprints,
Implementations memory _implementations
Implementations memory _implementations,
address _upgradeController
)
OPContractsManager(_superchainConfig, _protocolVersions, _l1ContractsRelease, _blueprints, _implementations)
OPContractsManager(
_superchainConfig,
_protocolVersions,
_l1ContractsRelease,
_blueprints,
_implementations,
_upgradeController
)
{ }
// The `SystemConfigInterop` contract has an extra `address _dependencyManager` argument
......
......@@ -15,6 +15,7 @@ import { DeployUtils } from "scripts/libraries/DeployUtils.sol";
import { EIP1967Helper } from "test/mocks/EIP1967Helper.sol";
import { Blueprint } from "src/libraries/Blueprint.sol";
import { ForgeArtifacts } from "scripts/libraries/ForgeArtifacts.sol";
import { Bytes } from "src/libraries/Bytes.sol";
// Interfaces
import { IProxyAdmin } from "interfaces/universal/IProxyAdmin.sol";
......@@ -53,9 +54,17 @@ contract OPContractsManager_Harness is OPContractsManager {
IProtocolVersions _protocolVersions,
string memory _l1ContractsRelease,
Blueprints memory _blueprints,
Implementations memory _implementations
Implementations memory _implementations,
address _upgradeController
)
OPContractsManager(_superchainConfig, _protocolVersions, _l1ContractsRelease, _blueprints, _implementations)
OPContractsManager(
_superchainConfig,
_protocolVersions,
_l1ContractsRelease,
_blueprints,
_implementations,
_upgradeController
)
{ }
function chainIdToBatchInboxAddress_exposed(uint256 l2ChainId) public pure returns (address) {
......@@ -157,6 +166,7 @@ contract OPContractsManager_InternalMethods_Test is Test {
function setUp() public {
ISuperchainConfig superchainConfigProxy = ISuperchainConfig(makeAddr("superchainConfig"));
IProtocolVersions protocolVersionsProxy = IProtocolVersions(makeAddr("protocolVersions"));
address upgradeController = makeAddr("upgradeController");
OPContractsManager.Blueprints memory emptyBlueprints;
OPContractsManager.Implementations memory emptyImpls;
vm.etch(address(superchainConfigProxy), hex"01");
......@@ -167,7 +177,8 @@ contract OPContractsManager_InternalMethods_Test is Test {
_protocolVersions: protocolVersionsProxy,
_l1ContractsRelease: "dev",
_blueprints: emptyBlueprints,
_implementations: emptyImpls
_implementations: emptyImpls,
_upgradeController: upgradeController
});
}
......@@ -229,8 +240,12 @@ contract OPContractsManager_Upgrade_Harness is CommonTest {
}
contract OPContractsManager_Upgrade_Test is OPContractsManager_Upgrade_Harness {
function test_upgrade_succeeds() public {
vm.etch(upgrader, vm.getDeployedCode("test/mocks/Callers.sol:DelegateCaller"));
function runUpgradeTestAndChecks(address delegateCaller) public {
assertTrue(opcm.isRC(), "isRC should be true");
bytes memory releaseBytes = bytes(opcm.l1ContractsRelease());
assertEq(Bytes.slice(releaseBytes, releaseBytes.length - 3, 3), "-rc", "release should end with '-rc'");
vm.etch(delegateCaller, vm.getDeployedCode("test/mocks/Callers.sol:DelegateCaller"));
IOPContractsManager.Implementations memory impls = opcm.implementations();
address oldL1CrossDomainMessenger = addressManager.getAddress("OVM_L1CrossDomainMessenger");
......@@ -248,10 +263,18 @@ contract OPContractsManager_Upgrade_Test is OPContractsManager_Upgrade_Harness {
if (address(delayedWeth) != address(0)) {
expectEmitUpgraded(impls.delayedWETHImpl, address(delayedWeth));
}
vm.expectEmit(true, true, true, true, address(upgrader));
emit Upgraded(l2ChainId, opChains[0].systemConfigProxy, address(upgrader));
DelegateCaller(upgrader).dcForward(address(opcm), abi.encodeCall(IOPContractsManager.upgrade, (opChains)));
vm.expectEmit(true, true, true, true, address(delegateCaller));
emit Upgraded(l2ChainId, opChains[0].systemConfigProxy, address(delegateCaller));
DelegateCaller(delegateCaller).dcForward(address(opcm), abi.encodeCall(IOPContractsManager.upgrade, (opChains)));
vm.stopPrank();
if (delegateCaller == upgrader) {
assertFalse(opcm.isRC(), "isRC should be false");
releaseBytes = bytes(opcm.l1ContractsRelease());
assertNotEq(
Bytes.slice(releaseBytes, releaseBytes.length - 3, 3), "-rc", "release should not end with '-rc'"
);
}
assertEq(impls.systemConfigImpl, EIP1967Helper.getImplementation(address(systemConfig)));
assertEq(impls.l1ERC721BridgeImpl, EIP1967Helper.getImplementation(address(l1ERC721Bridge)));
assertEq(impls.disputeGameFactoryImpl, EIP1967Helper.getImplementation(address(disputeGameFactory)));
......@@ -272,6 +295,32 @@ contract OPContractsManager_Upgrade_Test is OPContractsManager_Upgrade_Harness {
// TODO: ensure dispute games are updated (upcoming PR)
}
function test_upgrade_succeeds() public {
// Run the upgrade test and checks
runUpgradeTestAndChecks(upgrader);
}
function test_upgrade_nonUpgradeControllerDelegatecallerShouldNotSetIsRCToFalse_works(address _nonUpgradeController)
public
{
if (
_nonUpgradeController == upgrader || _nonUpgradeController == address(0)
|| _nonUpgradeController < address(0x4200000000000000000000000000000000000000)
|| _nonUpgradeController > address(0x4200000000000000000000000000000000000800)
|| _nonUpgradeController == address(vm)
|| _nonUpgradeController == 0x000000000000000000636F6e736F6c652e6c6f67
|| _nonUpgradeController == 0x4e59b44847b379578588920cA78FbF26c0B4956C
) {
_nonUpgradeController = makeAddr("nonUpgradeController");
}
// Set the proxy admin owner to be the non-upgrade controller
vm.store(address(proxyAdmin), bytes32(0), bytes32(uint256(uint160(_nonUpgradeController))));
// Run the upgrade test and checks
runUpgradeTestAndChecks(_nonUpgradeController);
}
function expectEmitUpgraded(address impl, address proxy) public {
vm.expectEmit(proxy);
emit Upgraded(impl);
......@@ -286,6 +335,7 @@ contract OPContractsManager_Upgrade_TestFails is OPContractsManager_Upgrade_Harn
}
function test_upgrade_superchainConfigMismatch_reverts() public {
upgrader = proxyAdmin.owner();
vm.etch(upgrader, vm.getDeployedCode("test/mocks/Callers.sol:DelegateCaller"));
// Set the superchainConfig to a different address in the OptimismPortal2 contract.
vm.store(
......@@ -301,6 +351,43 @@ contract OPContractsManager_Upgrade_TestFails is OPContractsManager_Upgrade_Harn
}
}
contract OPContractsManager_SetRC_Test is OPContractsManager_Upgrade_Harness {
/// @notice Tests the setRC function can be set by the upgrade controller.
function test_setRC_succeeds(bool _isRC) public {
vm.prank(upgrader);
opcm.setRC(_isRC);
assertTrue(opcm.isRC() == _isRC, "isRC should be true");
bytes memory releaseBytes = bytes(opcm.l1ContractsRelease());
if (_isRC) {
assertEq(Bytes.slice(releaseBytes, releaseBytes.length - 3, 3), "-rc", "release should end with '-rc'");
} else {
assertNotEq(
Bytes.slice(releaseBytes, releaseBytes.length - 3, 3), "-rc", "release should not end with '-rc'"
);
}
}
/// @notice Tests the setRC function can not be set by non-upgrade controller.
function test_setRC_nonUpgradeController_reverts(address _nonUpgradeController) public {
if (
_nonUpgradeController == upgrader || _nonUpgradeController == address(0)
|| _nonUpgradeController < address(0x4200000000000000000000000000000000000000)
|| _nonUpgradeController > address(0x4200000000000000000000000000000000000800)
|| _nonUpgradeController == address(vm)
|| _nonUpgradeController == 0x000000000000000000636F6e736F6c652e6c6f67
|| _nonUpgradeController == 0x4e59b44847b379578588920cA78FbF26c0B4956C
) {
_nonUpgradeController = makeAddr("nonUpgradeController");
}
vm.prank(_nonUpgradeController);
vm.expectRevert(IOPContractsManager.OnlyUpgradeController.selector);
opcm.setRC(true);
}
}
contract OPContractsManager_AddGameType_Test is Test {
IOPContractsManager internal opcm;
......@@ -345,7 +432,7 @@ contract OPContractsManager_AddGameType_Test is Test {
_args: DeployUtils.encodeConstructor(
abi.encodeCall(
IOPContractsManager.__constructor__,
(superchainConfigProxy, protocolVersionsProxy, "dev", blueprints, impls)
(superchainConfigProxy, protocolVersionsProxy, "dev", blueprints, impls, address(this))
)
),
_salt: DeployUtils.DEFAULT_SALT
......
......@@ -69,6 +69,9 @@ contract DeployImplementationsInput_Test is Test {
vm.expectRevert("DeployImplementationsInput: not set");
dii.protocolVersionsProxy();
vm.expectRevert("DeployImplementationsInput: not set");
dii.upgradeController();
}
}
......@@ -228,6 +231,7 @@ contract DeployImplementations_Test is Test {
uint256 disputeGameFinalityDelaySeconds = 500;
ISuperchainConfig superchainConfigProxy = ISuperchainConfig(makeAddr("superchainConfigProxy"));
IProtocolVersions protocolVersionsProxy = IProtocolVersions(makeAddr("protocolVersionsProxy"));
address upgradeController = makeAddr("upgradeController");
function setUp() public virtual {
vm.etch(address(superchainConfigProxy), hex"01");
......@@ -263,6 +267,7 @@ contract DeployImplementations_Test is Test {
dii.set(dii.mipsVersion.selector, 1);
dii.set(dii.superchainConfigProxy.selector, address(superchainConfigProxy));
dii.set(dii.protocolVersionsProxy.selector, address(protocolVersionsProxy));
dii.set(dii.upgradeController.selector, upgradeController);
// Perform the initial deployment.
deployImplementations.deploySystemConfigImpl(dio);
......@@ -363,6 +368,7 @@ contract DeployImplementations_Test is Test {
dii.set(dii.l1ContractsRelease.selector, release);
dii.set(dii.superchainConfigProxy.selector, address(superchainConfigProxy));
dii.set(dii.protocolVersionsProxy.selector, address(protocolVersionsProxy));
dii.set(dii.upgradeController.selector, upgradeController);
deployImplementations.run(dii, dio);
......@@ -376,6 +382,7 @@ contract DeployImplementations_Test is Test {
assertEq(release, dii.l1ContractsRelease(), "525");
assertEq(address(superchainConfigProxy), address(dii.superchainConfigProxy()), "550");
assertEq(address(protocolVersionsProxy), address(dii.protocolVersionsProxy()), "575");
assertEq(upgradeController, dii.upgradeController(), "600");
// Architecture assertions.
assertEq(address(dio.mipsSingleton().oracle()), address(dio.preimageOracleSingleton()), "600");
......
......@@ -82,6 +82,7 @@ contract DeployOPCMInput_Test is Test {
function test_set_part1_succeeds() public {
ISuperchainConfig superchainConfig = ISuperchainConfig(makeAddr("superchainConfig"));
IProtocolVersions protocolVersions = IProtocolVersions(makeAddr("protocolVersions"));
address upgradeController = makeAddr("upgradeController");
address addressManagerBlueprint = makeAddr("addressManagerBlueprint");
address proxyBlueprint = makeAddr("proxyBlueprint");
address proxyAdminBlueprint = makeAddr("proxyAdminBlueprint");
......@@ -93,6 +94,7 @@ contract DeployOPCMInput_Test is Test {
dii.set(dii.superchainConfig.selector, address(superchainConfig));
dii.set(dii.protocolVersions.selector, address(protocolVersions));
dii.set(dii.l1ContractsRelease.selector, release);
dii.set(dii.upgradeController.selector, upgradeController);
dii.set(dii.addressManagerBlueprint.selector, addressManagerBlueprint);
dii.set(dii.proxyBlueprint.selector, proxyBlueprint);
dii.set(dii.proxyAdminBlueprint.selector, proxyAdminBlueprint);
......@@ -111,6 +113,7 @@ contract DeployOPCMInput_Test is Test {
assertEq(dii.resolvedDelegateProxyBlueprint(), resolvedDelegateProxyBlueprint, "400");
assertEq(dii.permissionedDisputeGame1Blueprint(), permissionedDisputeGame1Blueprint, "500");
assertEq(dii.permissionedDisputeGame2Blueprint(), permissionedDisputeGame2Blueprint, "550");
assertEq(dii.upgradeController(), upgradeController, "600");
}
function test_set_part2_succeeds() public {
......@@ -207,6 +210,7 @@ contract DeployOPCMTest is Test {
ISuperchainConfig superchainConfigProxy = ISuperchainConfig(makeAddr("superchainConfigProxy"));
IProtocolVersions protocolVersionsProxy = IProtocolVersions(makeAddr("protocolVersionsProxy"));
address upgradeController = makeAddr("upgradeController");
function setUp() public virtual {
deployOPCM = new DeployOPCM();
......@@ -217,6 +221,7 @@ contract DeployOPCMTest is Test {
doi.set(doi.superchainConfig.selector, address(superchainConfigProxy));
doi.set(doi.protocolVersions.selector, address(protocolVersionsProxy));
doi.set(doi.l1ContractsRelease.selector, "1.0.0");
doi.set(doi.upgradeController.selector, upgradeController);
// Set and etch blueprints
doi.set(doi.addressManagerBlueprint.selector, makeAddr("addressManagerBlueprint"));
......@@ -242,6 +247,7 @@ contract DeployOPCMTest is Test {
// Etch all addresses with dummy bytecode
vm.etch(address(doi.superchainConfig()), hex"01");
vm.etch(address(doi.protocolVersions()), hex"01");
vm.etch(address(doi.upgradeController()), hex"01");
vm.etch(doi.addressManagerBlueprint(), hex"01");
vm.etch(doi.proxyBlueprint(), hex"01");
......
......@@ -315,7 +315,7 @@ contract DeployOPChain_TestBase is Test {
string release = "dev-release"; // this means implementation contracts will be deployed
ISuperchainConfig superchainConfigProxy;
IProtocolVersions protocolVersionsProxy;
address upgradeController;
// Define default inputs for DeployOPChain.
// `opcm` is set during `setUp` since it is an output of the previous step.
address opChainProxyAdminOwner = makeAddr("defaultOPChainProxyAdminOwner");
......@@ -356,6 +356,7 @@ contract DeployOPChain_TestBase is Test {
// Populate the inputs for DeployImplementations based on the output of DeploySuperchain.
superchainConfigProxy = dso.superchainConfigProxy();
protocolVersionsProxy = dso.protocolVersionsProxy();
upgradeController = dso.superchainProxyAdmin().owner();
// Configure and deploy Implementation contracts
DeployImplementations deployImplementations = createDeployImplementationsContract();
......@@ -370,6 +371,7 @@ contract DeployOPChain_TestBase is Test {
dii.set(dii.l1ContractsRelease.selector, release);
dii.set(dii.superchainConfigProxy.selector, address(superchainConfigProxy));
dii.set(dii.protocolVersionsProxy.selector, address(protocolVersionsProxy));
dii.set(dii.upgradeController.selector, upgradeController);
deployImplementations.run(dii, dio);
......
......@@ -785,6 +785,9 @@ contract Specification_Test is CommonTest {
_addSpec({ _name: "OPContractsManager", _sel: IOPContractsManager.implementations.selector });
_addSpec({ _name: "OPContractsManager", _sel: IOPContractsManager.upgrade.selector });
_addSpec({ _name: "OPContractsManager", _sel: IOPContractsManager.addGameType.selector });
_addSpec({ _name: "OPContractsManager", _sel: _getSel("isRC()") });
_addSpec({ _name: "OPContractsManager", _sel: _getSel("setRC(bool)") });
_addSpec({ _name: "OPContractsManager", _sel: _getSel("upgradeController()") });
// OPContractsManagerInterop
_addSpec({ _name: "OPContractsManagerInterop", _sel: _getSel("version()") });
......@@ -797,6 +800,9 @@ contract Specification_Test is CommonTest {
_addSpec({ _name: "OPContractsManagerInterop", _sel: IOPContractsManager.implementations.selector });
_addSpec({ _name: "OPContractsManagerInterop", _sel: IOPContractsManager.upgrade.selector });
_addSpec({ _name: "OPContractsManagerInterop", _sel: IOPContractsManager.addGameType.selector });
_addSpec({ _name: "OPContractsManagerInterop", _sel: _getSel("isRC()") });
_addSpec({ _name: "OPContractsManagerInterop", _sel: _getSel("setRC(bool)") });
_addSpec({ _name: "OPContractsManagerInterop", _sel: _getSel("upgradeController()") });
// DeputyGuardianModule
_addSpec({
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment