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
10 changes: 0 additions & 10 deletions interfaces/legacy/ILegacySuperchainConfig.sol

This file was deleted.

2 changes: 2 additions & 0 deletions justfile
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ print-pinned-block-number:
# Prepares the environment for upgrade path variant of contract tests and coverage.
# Env Vars:
# - ETH_RPC_URL must be set to a production (Sepolia or Mainnet) RPC URL.
# - SUPERCHAIN_OPS_ALLOCS_PATH must point to simulated post-upgrade state from superchain-ops.
# - FORK_BLOCK_NUMBER can be set in the env, or else will fallback to the default block number.
# Reusing the default block number greatly speeds up the test execution time by caching the
# rpc call responses in ~/.foundry/cache/rpc. The default block will need to be updated
Expand Down Expand Up @@ -136,6 +137,7 @@ anvil-fork:
anvil --fork-url $ETH_RPC_URL

# Use anvil-fork in a separate terminal before running this command.
# Requires SUPERCHAIN_OPS_ALLOCS_PATH with simulated post-upgrade state from superchain-ops.
# Helpful for debugging.
test-upgrade-against-anvil *ARGS: build-go-ffi
#!/bin/bash
Expand Down
12 changes: 0 additions & 12 deletions scripts/deploy/DeployConfig.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ contract DeployConfig is Script {
address public teeProposer;

bool public fundDevAccounts;
bool public useUpgradedFork;

bytes32 public multiproofConfigHash;
bytes32 public multiproofGenesisOutputRoot;
Expand Down Expand Up @@ -152,15 +151,4 @@ contract DeployConfig is Script {
_protocolVersionsInitialSchedule.push(uint64(schedule[i]));
}
}

/// @notice Allow the `useUpgradedFork` config to be overridden in testing environments
/// @dev When true, the forked system WILL be upgraded in setUp().
/// When false, the forked system WILL NOT be upgraded in setUp().
/// This function does nothing when not testing in a forked environment.
/// Generally the only time you should call this function is if you want to
/// call the upgrade script in the test itself, rather than have the upgraded
/// system be deployed in setUp().
function setUseUpgradedFork(bool _useUpgradedFork) public {
useUpgradedFork = _useUpgradedFork;
}
}
161 changes: 3 additions & 158 deletions scripts/deploy/SystemDeploy.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ import { IOptimismPortal2 as IOptimismPortal } from "interfaces/L1/IOptimismPort
import { IProtocolVersions } from "interfaces/L1/IProtocolVersions.sol";
import { ISystemConfig } from "interfaces/L1/ISystemConfig.sol";
import { IAddressManager } from "interfaces/legacy/IAddressManager.sol";
import { ILegacySuperchainConfig, ILegacySystemConfig } from "interfaces/legacy/ILegacySuperchainConfig.sol";
import { IL1ChugSplashProxy } from "interfaces/legacy/IL1ChugSplashProxy.sol";
import { IResolvedDelegateProxy } from "interfaces/legacy/IResolvedDelegateProxy.sol";
import { IAnchorStateRegistry } from "interfaces/L1/proofs/IAnchorStateRegistry.sol";
Expand All @@ -41,10 +40,9 @@ import { ISP1Verifier } from "interfaces/L1/proofs/zk/ISP1Verifier.sol";
import { ZKVerifier } from "src/L1/proofs/zk/ZKVerifier.sol";
import { Constants } from "src/libraries/Constants.sol";
import { GameType, GameTypes, Hash, Proposal } from "src/libraries/bridge/Types.sol";
import { Claim } from "src/libraries/bridge/LibUDT.sol";

/// @title SystemDeploy
/// @notice Script-level API for deploying or upgrading a complete OP Stack L1 system.
/// @notice Script-level API for deploying a complete OP Stack L1 system.
contract SystemDeploy is Script {
DeployConfig public constant cfg =
DeployConfig(address(uint160(uint256(keccak256(abi.encode("optimism.deployconfig"))))));
Expand Down Expand Up @@ -89,17 +87,6 @@ contract SystemDeploy is Script {
Types.DeployOutput opChain;
}

struct UpgradeInput {
bool saveArtifacts;
Types.Implementations implementations;
ISystemConfig systemConfigProxy;
IProtocolVersions protocolVersionsProxy;
}

struct UpgradeOutput {
bool chainUpgraded;
}

struct AggregateVerifierInput {
GameType multiproofGameType;
IAnchorStateRegistry anchorStateRegistry;
Expand Down Expand Up @@ -127,13 +114,10 @@ contract SystemDeploy is Script {
}

event Deployed(uint256 indexed l2ChainId, address indexed deployer, bytes deployOutput);
event Upgraded(uint256 indexed l2ChainId, ISystemConfig indexed systemConfig, address indexed upgrader);

error InvalidChainId();
error InvalidRoleAddress(string role);
error InvalidStartingAnchorRoot();
error LegacySuperchainConfigPaused();
error MissingImplementations();

/// @notice Sets up the shared deployment config and artifact registry.
function setUp() public virtual {
Expand Down Expand Up @@ -182,32 +166,6 @@ contract SystemDeploy is Script {
_runConfigured();
}

/// @notice Deploys implementation contracts from the active deploy config and saves their artifact names.
function deployImplementations() public returns (Types.Implementations memory output_) {
output_ = _deployImplementations(_configuredImplementationsInput());
_saveUpgradeArtifacts(output_);
}

/// @notice Returns the latest implementation set saved by `deployImplementations` or `run`.
function getImplementations() public view returns (Types.Implementations memory) {
return Types.Implementations({
l1ERC721BridgeImpl: artifacts.mustGetAddress("L1ERC721BridgeImpl"),
optimismPortalImpl: artifacts.mustGetAddress("OptimismPortalImpl"),
systemConfigImpl: artifacts.mustGetAddress("SystemConfigImpl"),
optimismMintableERC20FactoryImpl: artifacts.mustGetAddress("OptimismMintableERC20FactoryImpl"),
l1CrossDomainMessengerImpl: artifacts.mustGetAddress("L1CrossDomainMessengerImpl"),
l1StandardBridgeImpl: artifacts.mustGetAddress("L1StandardBridgeImpl"),
disputeGameFactoryImpl: artifacts.mustGetAddress("DisputeGameFactoryImpl"),
anchorStateRegistryImpl: artifacts.mustGetAddress("AnchorStateRegistryImpl"),
delayedWETHImpl: artifacts.mustGetAddress("DelayedWETHImpl"),
protocolVersionsImpl: artifacts.mustGetAddress("ProtocolVersionsImpl"),
aggregateVerifierImpl: artifacts.getAddress("AggregateVerifier"),
teeProverRegistryImpl: artifacts.getAddress("TEEProverRegistryImpl"),
teeVerifierImpl: artifacts.getAddress("TEEVerifier"),
zkVerifierImpl: artifacts.getAddress("ZKVerifier")
});
}

function _runConfigured() internal returns (DeployOutput memory output_) {
output_ = deploy(_deployInput());

Expand Down Expand Up @@ -315,27 +273,6 @@ contract SystemDeploy is Script {
emit Deployed(_input.opChainInput.l2ChainId, msg.sender, abi.encode(output_.opChain));
}

function upgrade(UpgradeInput memory _input) public returns (UpgradeOutput memory output_) {
_assertValidImplementations(_input.implementations);

if (address(_input.systemConfigProxy) != address(0)) {
ISystemConfig systemConfigProxy = _input.systemConfigProxy;
DeployUtils.assertValidContractAddress(address(systemConfigProxy));

IProtocolVersions protocolVersionsProxy = _input.protocolVersionsProxy;
if (address(protocolVersionsProxy) == address(0) && address(artifacts).code.length != 0) {
protocolVersionsProxy = IProtocolVersions(artifacts.getAddress("ProtocolVersionsProxy"));
}

_upgradeOPChain(systemConfigProxy, _input.implementations, protocolVersionsProxy);
output_.chainUpgraded = true;
}

if (_input.saveArtifacts) {
_saveUpgradeArtifacts(_input.implementations);
}
}

function _deployImplementations(ImplementationInput memory _input)
internal
returns (Types.Implementations memory output_)
Expand Down Expand Up @@ -528,91 +465,6 @@ contract SystemDeploy is Script {
);
}

function _upgradeOPChain(
ISystemConfig _systemConfigProxy,
Types.Implementations memory _impls,
IProtocolVersions _protocolVersionsProxy
)
internal
{
IProxyAdmin proxyAdmin = _systemConfigProxy.proxyAdmin();
uint256 l2ChainId = _systemConfigProxy.l2ChainId();

_assertLegacySuperchainConfigNotPaused(_systemConfigProxy);

_upgradeTo(proxyAdmin, address(_systemConfigProxy), _impls.systemConfigImpl);

IOptimismPortal optimismPortal = IOptimismPortal(payable(_systemConfigProxy.optimismPortal()));
_upgradeTo(proxyAdmin, address(optimismPortal), _impls.optimismPortalImpl);
_upgradeTo(proxyAdmin, address(optimismPortal.anchorStateRegistry()), _impls.anchorStateRegistryImpl);
_upgradeTo(
proxyAdmin, _systemConfigProxy.optimismMintableERC20Factory(), _impls.optimismMintableERC20FactoryImpl
);

IDisputeGameFactory disputeGameFactory = IDisputeGameFactory(_systemConfigProxy.disputeGameFactory());
_upgradeTo(proxyAdmin, address(disputeGameFactory), _impls.disputeGameFactoryImpl);
_upgradeMultiproofContracts(_systemConfigProxy, disputeGameFactory, _impls);

ISystemConfig.Addresses memory opChainAddrs = _systemConfigProxy.getAddresses();
_upgradeTo(proxyAdmin, opChainAddrs.l1CrossDomainMessenger, _impls.l1CrossDomainMessengerImpl);
_upgradeTo(proxyAdmin, opChainAddrs.l1StandardBridge, _impls.l1StandardBridgeImpl);
_upgradeTo(proxyAdmin, opChainAddrs.l1ERC721Bridge, _impls.l1ERC721BridgeImpl);
if (opChainAddrs.delayedWETH != address(0)) {
_upgradeTo(proxyAdmin, opChainAddrs.delayedWETH, _impls.delayedWETHImpl);
}

if (address(_protocolVersionsProxy) != address(0)) {
_upgradeTo(proxyAdmin, address(_protocolVersionsProxy), _impls.protocolVersionsImpl);
}

emit Upgraded(l2ChainId, _systemConfigProxy, msg.sender);
}

/// @notice Rejects a migration from SuperchainConfig until its global and chain-specific pause records are cleared.
/// @dev A pause submitted after this check and before the upgrade can be lost. Either the Guardian or the
/// Incident Responder can pause during that window, so coordinate migrations with both.
function _assertLegacySuperchainConfigNotPaused(ISystemConfig _systemConfigProxy) internal view {
(bool success, bytes memory returndata) =
address(_systemConfigProxy).staticcall(abi.encodeCall(ILegacySystemConfig.superchainConfig, ()));
if (!success || returndata.length != 32) return;

ILegacySuperchainConfig superchainConfig = ILegacySuperchainConfig(abi.decode(returndata, (address)));
if (!superchainConfig.pausable(address(0)) || !superchainConfig.pausable(_systemConfigProxy.optimismPortal())) {
revert LegacySuperchainConfigPaused();
}
}

function _upgradeMultiproofContracts(
ISystemConfig _systemConfigProxy,
IDisputeGameFactory _disputeGameFactory,
Types.Implementations memory _impls
)
internal
{
IDisputeGame currentGameImpl = _disputeGameFactory.gameImpls(GameTypes.AGGREGATE_VERIFIER);
if (address(currentGameImpl) == address(0)) return;

if (_impls.teeProverRegistryImpl != address(0)) {
TEEProverRegistry newTEEProverRegistry = TEEProverRegistry(_impls.teeProverRegistryImpl);
require(
address(newTEEProverRegistry.DISPUTE_GAME_FACTORY()) == address(_disputeGameFactory),
"SystemDeploy: TEEProverRegistry factory mismatch"
);
AggregateVerifier currentAggregateVerifier = AggregateVerifier(address(currentGameImpl));
TEEProverRegistry teeProverRegistry =
TEEVerifier(address(currentAggregateVerifier.TEE_VERIFIER())).TEE_PROVER_REGISTRY();
_upgradeTo(_systemConfigProxy.proxyAdmin(), address(teeProverRegistry), _impls.teeProverRegistryImpl);
}

if (_impls.aggregateVerifierImpl != address(0) && address(currentGameImpl) != _impls.aggregateVerifierImpl) {
DeployUtils.assertValidContractAddress(_impls.aggregateVerifierImpl);
vm.broadcast(msg.sender);
_disputeGameFactory.setImplementation(
GameTypes.AGGREGATE_VERIFIER, IDisputeGame(address(_impls.aggregateVerifierImpl))
);
}
}

function _encodeSystemConfigInitializer(
Types.DeployInput memory _input,
Types.DeployOutput memory _output
Expand Down Expand Up @@ -709,12 +561,6 @@ contract SystemDeploy is Script {
_proxyAdmin.upgradeAndCall(payable(_target), _implementation, _data);
}

function _upgradeTo(IProxyAdmin _proxyAdmin, address _target, address _implementation) internal {
DeployUtils.assertValidContractAddress(_implementation);
vm.broadcast(msg.sender);
_proxyAdmin.upgrade(payable(_target), _implementation);
}

function _deployAddressManager(
Types.DeployInput memory _input,
IProxyAdmin _proxyAdmin
Expand Down Expand Up @@ -1004,7 +850,6 @@ contract SystemDeploy is Script {
}

function _assertValidImplementations(Types.Implementations memory _impls) internal view {
if (_implementationsEmpty(_impls)) revert MissingImplementations();
DeployUtils.assertValidContractAddress(_impls.l1ERC721BridgeImpl);
DeployUtils.assertValidContractAddress(_impls.optimismPortalImpl);
DeployUtils.assertValidContractAddress(_impls.systemConfigImpl);
Expand Down Expand Up @@ -1041,7 +886,7 @@ contract SystemDeploy is Script {
}

function _saveDeployArtifacts(DeployOutput memory _output) internal {
_saveUpgradeArtifacts(_output.impls);
_saveImplementationArtifacts(_output.impls);

Types.DeployOutput memory chain = _output.opChain;
artifacts.save("ProxyAdmin", address(chain.opChainProxyAdmin));
Expand Down Expand Up @@ -1069,7 +914,7 @@ contract SystemDeploy is Script {
}
}

function _saveUpgradeArtifacts(Types.Implementations memory _impls) internal {
function _saveImplementationArtifacts(Types.Implementations memory _impls) internal {
artifacts.save("L1ERC721BridgeImpl", _impls.l1ERC721BridgeImpl);
artifacts.save("OptimismPortalImpl", _impls.optimismPortalImpl);
artifacts.save("SystemConfigImpl", _impls.systemConfigImpl);
Expand Down
2 changes: 1 addition & 1 deletion snapshots/semver-lock.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
},
"src/L1/SystemConfig.sol:SystemConfig": {
"initCodeHash": "0x4a83d1725257aee27f58f9874c543e55b89c3112e190c62ab4858e3c4dbf5bc3",
"sourceCodeHash": "0x04fee741d6628c4b74ec5315e252e5f5e62bdd820740e9ba7bd98525820043da"
"sourceCodeHash": "0x51ee250a08a99b08e366b04fc621bc62918743a263cb3f380732b60677da1957"
},
"src/L1/proofs/AggregateVerifier.sol:AggregateVerifier": {
"initCodeHash": "0x91a51808e37fa282a974cb5028e0ba517e04c903ce594b393cfda9dcc5408188",
Expand Down
2 changes: 1 addition & 1 deletion src/L1/SystemConfig.sol
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import { IOptimismPortal2 } from "interfaces/L1/IOptimismPortal2.sol";
/// the L2 chain. It also owns the pause state for the network, which the Guardian and
/// Incident Responder use to halt withdrawals and message relaying.
/// @dev Upgrading a pre-merge deployment moves pause management from the legacy SuperchainConfig.
/// Use SystemDeploy for that upgrade, which requires legacy pause records to be cleared.
/// Clear legacy pause records before that migration so no active pause is lost.
contract SystemConfig is ProxyAdminOwnedBase, OwnableUpgradeable, ReinitializableBase, ISemver {
/// @notice Enum representing different types of updates.
/// @custom:value BATCHER Represents an update to the batcher hash.
Expand Down
Loading
Loading