Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1489,6 +1489,21 @@ workflows:
fork_op_chain: op
fork_base_chain: mainnet
fork_base_rpc: https://ci-mainnet-l1-archive.optimism.io
- contracts-bedrock-tests-upgrade:
name: contracts-bedrock-tests-upgrade base-mainnet
fork_op_chain: base
fork_base_chain: mainnet
fork_base_rpc: https://ci-mainnet-l1-archive.optimism.io
- contracts-bedrock-tests-upgrade:
name: contracts-bedrock-tests-upgrade ink-mainnet
fork_op_chain: ink
fork_base_chain: mainnet
fork_base_rpc: https://ci-mainnet-l1-archive.optimism.io
- contracts-bedrock-tests-upgrade:
name: contracts-bedrock-tests-upgrade unichain-mainnet
fork_op_chain: unichain
fork_base_chain: mainnet
fork_base_rpc: https://ci-mainnet-l1-archive.optimism.io
- contracts-bedrock-checks:
requires:
- contracts-bedrock-build
Expand Down
1 change: 1 addition & 0 deletions packages/contracts-bedrock/foundry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ fs_permissions = [
{ access='read', path='./kout-deployment' },
{ access='read', path='./test/fixtures' },
{ access='read', path='./lib/superchain-registry/superchain/configs/' },
{ access='read', path='./lib/superchain-registry/validation/standard/' },
]

# 5159 error code is selfdestruct error code
Expand Down
2 changes: 1 addition & 1 deletion packages/contracts-bedrock/lib/superchain-registry
44 changes: 42 additions & 2 deletions packages/contracts-bedrock/test/L1/OPContractsManager.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,7 @@ contract OPContractsManager_Upgrade_Harness is CommonTest {
address upgrader;
IOPContractsManager.OpChainConfig[] opChainConfigs;
Claim absolutePrestate;
string public opChain = vm.envOr("FORK_OP_CHAIN", string("op"));

function setUp() public virtual override {
super.disableUpgradedFork();
Expand Down Expand Up @@ -293,10 +294,25 @@ contract OPContractsManager_Upgrade_Harness is CommonTest {

function runUpgrade13UpgradeAndChecks(address _delegateCaller) public {
// The address below corresponds with the address of the v2.0.0-rc.1 OPCM on mainnet.
IOPContractsManager deployedOPCM = IOPContractsManager(address(0x026b2F158255Beac46c1E7c6b8BbF29A4b6A7B76));
address OPCM_ADDRESS = 0x026b2F158255Beac46c1E7c6b8BbF29A4b6A7B76;

IOPContractsManager deployedOPCM = IOPContractsManager(OPCM_ADDRESS);
IOPCMImplementationsWithoutLockbox.Implementations memory impls =
IOPCMImplementationsWithoutLockbox(address(deployedOPCM)).implementations();

address mainnetPAO = artifacts.mustGetAddress("SuperchainConfigProxy");

// If the delegate caller is not the mainnet PAO, we need to call upgrade as the mainnet PAO first.
if (_delegateCaller != mainnetPAO) {
IOPContractsManager.OpChainConfig[] memory opmChain = new IOPContractsManager.OpChainConfig[](0);
ISuperchainConfig superchainConfig = ISuperchainConfig(mainnetPAO);

address opmUpgrader = IProxyAdmin(EIP1967Helper.getAdmin(address(superchainConfig))).owner();
vm.etch(opmUpgrader, vm.getDeployedCode("test/mocks/Callers.sol:DelegateCaller"));

DelegateCaller(opmUpgrader).dcForward(OPCM_ADDRESS, abi.encodeCall(IOPContractsManager.upgrade, (opmChain)));
}

// Cache the old L1xDM address so we can look for it in the AddressManager's event
address oldL1CrossDomainMessenger = addressManager.getAddress("OVM_L1CrossDomainMessenger");

Expand Down Expand Up @@ -344,6 +360,7 @@ contract OPContractsManager_Upgrade_Harness is CommonTest {
vm.expectEmit(false, true, true, true, address(disputeGameFactory));
emit ImplementationSet(address(0), GameTypes.CANNON);
}

vm.expectEmit(address(_delegateCaller));
emit Upgraded(l2ChainId, opChainConfigs[0].systemConfigProxy, address(_delegateCaller));

Expand Down Expand Up @@ -400,10 +417,25 @@ contract OPContractsManager_Upgrade_Harness is CommonTest {
}

function runUpgrade14UpgradeAndChecks(address _delegateCaller) public {
IOPContractsManager deployedOPCM = IOPContractsManager(address(0x3A1f523a4bc09cd344A2745a108Bb0398288094F));
address OPCM_ADDRESS = 0x3A1f523a4bc09cd344A2745a108Bb0398288094F;

IOPContractsManager deployedOPCM = IOPContractsManager(OPCM_ADDRESS);
IOPCMImplementationsWithoutLockbox.Implementations memory impls =
IOPCMImplementationsWithoutLockbox(address(deployedOPCM)).implementations();

address mainnetPAO = artifacts.mustGetAddress("SuperchainConfigProxy");

// If the delegate caller is not the mainnet PAO, we need to call upgrade as the mainnet PAO first.
if (_delegateCaller != mainnetPAO) {
IOPContractsManager.OpChainConfig[] memory opmChain = new IOPContractsManager.OpChainConfig[](0);
ISuperchainConfig superchainConfig = ISuperchainConfig(mainnetPAO);

address opmUpgrader = IProxyAdmin(EIP1967Helper.getAdmin(address(superchainConfig))).owner();
vm.etch(opmUpgrader, vm.getDeployedCode("test/mocks/Callers.sol:DelegateCaller"));

DelegateCaller(opmUpgrader).dcForward(OPCM_ADDRESS, abi.encodeCall(IOPContractsManager.upgrade, (opmChain)));
}

// sanity check
IPermissionedDisputeGame oldPDG =
IPermissionedDisputeGame(address(disputeGameFactory.gameImpls(GameTypes.PERMISSIONED_CANNON)));
Expand Down Expand Up @@ -589,11 +621,13 @@ contract OPContractsManager_Upgrade_Harness is CommonTest {

contract OPContractsManager_Upgrade_Test is OPContractsManager_Upgrade_Harness {
function test_upgradeOPChainOnly_succeeds() public {
skipIfNotOpFork("test_upgradeOPChainOnly_succeeds");
// Run the upgrade test and checks
runUpgradeTestAndChecks(upgrader);
}

function test_isRcFalseAfterCalledByUpgrader_works() public {
skipIfNotOpFork("test_isRcFalseAfterCalledByUpgrader_works");
assertTrue(opcm.isRC());
bytes memory releaseBytes = bytes(opcm.l1ContractsRelease());
assertEq(Bytes.slice(releaseBytes, releaseBytes.length - 3, 3), "-rc", "release should end with '-rc'");
Expand All @@ -610,6 +644,7 @@ contract OPContractsManager_Upgrade_Test is OPContractsManager_Upgrade_Harness {
)
public
{
skipIfNotOpFork("testFuzz_upgrade_nonUpgradeControllerDelegatecallerShouldNotSetIsRCToFalse_works");
if (
_nonUpgradeController == upgrader || _nonUpgradeController == address(0)
|| _nonUpgradeController < address(0x4200000000000000000000000000000000000000)
Expand Down Expand Up @@ -638,6 +673,8 @@ contract OPContractsManager_Upgrade_Test is OPContractsManager_Upgrade_Harness {
}

function test_upgrade_duplicateL2ChainId_succeeds() public {
skipIfNotOpFork("test_upgrade_duplicateL2ChainId_succeeds");

// Deploy a new OPChain with the same L2 chain ID as the current OPChain
Deploy deploy = Deploy(address(uint160(uint256(keccak256(abi.encode("optimism.deploy"))))));
IOPContractsManager.DeployInput memory deployInput = deploy.getDeployInput();
Expand Down Expand Up @@ -726,6 +763,7 @@ contract OPContractsManager_Upgrade_Test is OPContractsManager_Upgrade_Harness {
contract OPContractsManager_Upgrade_TestFails is OPContractsManager_Upgrade_Harness {
// Upgrade to U14 first
function setUp() public override {
skipIfNotOpFork("test_upgrade_notDelegateCalled_reverts");
super.setUp();
runUpgrade13UpgradeAndChecks(upgrader);
}
Expand Down Expand Up @@ -775,6 +813,8 @@ 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 {
skipIfNotOpFork("test_setRC_succeeds");

vm.prank(upgrader);

opcm.setRC(_isRC);
Expand Down
34 changes: 33 additions & 1 deletion packages/contracts-bedrock/test/setup/ForkLive.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,15 @@ import { Deploy } from "scripts/deploy/Deploy.s.sol";
// Libraries
import { GameTypes, Claim } from "src/dispute/lib/Types.sol";
import { EIP1967Helper } from "test/mocks/EIP1967Helper.sol";
import { LibString } from "solady/src/utils/LibString.sol";

// Interfaces
import { IFaultDisputeGame } from "interfaces/dispute/IFaultDisputeGame.sol";
import { IPermissionedDisputeGame } from "interfaces/dispute/IPermissionedDisputeGame.sol";
import { IDisputeGameFactory } from "interfaces/dispute/IDisputeGameFactory.sol";
import { IAddressManager } from "interfaces/legacy/IAddressManager.sol";
import { ISystemConfig } from "interfaces/L1/ISystemConfig.sol";
import { ISuperchainConfig } from "interfaces/L1/ISuperchainConfig.sol";
import { IProxyAdmin } from "interfaces/universal/IProxyAdmin.sol";
import { IOPContractsManager } from "interfaces/L1/IOPContractsManager.sol";
import { IAnchorStateRegistry } from "interfaces/dispute/IAnchorStateRegistry.sol";
Expand All @@ -39,6 +41,7 @@ import { IOptimismPortal2 } from "interfaces/L1/IOptimismPortal2.sol";

contract ForkLive is Deployer {
using stdToml for string;
using LibString for string;

bool public useOpsRepo;

Expand Down Expand Up @@ -99,16 +102,24 @@ contract ForkLive is Deployer {
/// using either the `saveProxyAndImpl` or `artifacts.save()` functions.
function _readSuperchainRegistry() internal {
string memory superchainBasePath = "./lib/superchain-registry/superchain/configs/";
string memory validationBasePath = "./lib/superchain-registry/validation/standard/";

string memory superchainToml = vm.readFile(string.concat(superchainBasePath, baseChain(), "/superchain.toml"));
string memory opToml = vm.readFile(string.concat(superchainBasePath, baseChain(), "/", opChain(), ".toml"));

string memory standardVersionsToml =
vm.readFile(string.concat(validationBasePath, "standard-versions-", baseChain(), ".toml"));

standardVersionsToml = standardVersionsToml.replace('"op-contracts/v2.0.0-rc.1"', "RELEASE");

// Slightly hacky, we encode the uint chainId as an address to save it in Artifacts
artifacts.save("L2ChainId", address(uint160(vm.parseTomlUint(opToml, ".chain_id"))));
// Superchain shared contracts
saveProxyAndImpl("SuperchainConfig", superchainToml, ".superchain_config_addr");
saveProxyAndImpl("ProtocolVersions", superchainToml, ".protocol_versions_addr");
artifacts.save("OPContractsManager", vm.parseTomlAddress(superchainToml, ".op_contracts_manager_proxy_addr"));
artifacts.save(
"OPContractsManager", vm.parseTomlAddress(standardVersionsToml, "$.RELEASE.op_contracts_manager.address")
);

// Core contracts
artifacts.save("ProxyAdmin", vm.parseTomlAddress(opToml, ".addresses.ProxyAdmin"));
Expand Down Expand Up @@ -192,12 +203,33 @@ contract ForkLive is Deployer {
absolutePrestate: Claim.wrap(bytes32(keccak256("absolutePrestate")))
});

IOPContractsManager.OpChainConfig[] memory opmChain = new IOPContractsManager.OpChainConfig[](0);
// 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 2.0.0 OPCM requires that the SuperchainConfig and ProtocolVersions contracts
// have been upgraded before it will upgrade other contracts.
// Those contracts can only be upgrade by the OP Mainnet ProxyAdminOwner. So for chains which have a different
// ProxyAdminOwner, we first need to call opcm.upgrade from the OP Mainnet PAO.
address mainnetPAO = artifacts.mustGetAddress("SuperchainConfigProxy");

if (upgrader != mainnetPAO) {
ISuperchainConfig superchainConfig = ISuperchainConfig(mainnetPAO);

address opmUpgrader = IProxyAdmin(EIP1967Helper.getAdmin(address(superchainConfig))).owner();
vm.etch(opmUpgrader, vm.getDeployedCode("test/mocks/Callers.sol:DelegateCaller"));

DelegateCaller(opmUpgrader).dcForward(
address(0x026b2F158255Beac46c1E7c6b8BbF29A4b6A7B76),
abi.encodeCall(IOPContractsManager.upgrade, (opmChain))
);
}

// Start by doing Upgrade 13.

DelegateCaller(upgrader).dcForward(
address(0x026b2F158255Beac46c1E7c6b8BbF29A4b6A7B76), abi.encodeCall(IOPContractsManager.upgrade, (opChains))
);
Expand Down
14 changes: 14 additions & 0 deletions packages/contracts-bedrock/test/setup/Setup.sol
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,12 @@ contract Setup {
return vm.envOr("FORK_TEST", false);
}

/// @notice Indicates whether a test is running against a forked network that is OP.
function isOpFork() public view returns (bool) {
string memory opChain = vm.envOr("FORK_OP_CHAIN", string("op"));
return keccak256(bytes(opChain)) == keccak256(bytes("op"));
}

/// @dev Deploys either the Deploy.s.sol or Fork.s.sol contract, by fetching the bytecode dynamically using
/// `vm.getDeployedCode()` and etching it into the state.
/// This enables us to avoid including the bytecode of those contracts in the bytecode of this contract.
Expand Down Expand Up @@ -195,6 +201,14 @@ contract Setup {
}
}

/// @dev Skips tests when running against a forked production network that is not OP.
function skipIfNotOpFork(string memory message) public {
if (isForkTest() && !isOpFork()) {
vm.skip(true);
console.log(string.concat("Skipping non-OP fork test: ", message));
}
}

/// @dev Skips tests when running against a forked production network using the superchain ops repo.
function skipIfOpsRepoTest(string memory message) public {
if (forkLive.useOpsRepo()) {
Expand Down