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
4 changes: 3 additions & 1 deletion interfaces/L1/IProtocolVersions.sol
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ interface IProtocolVersions is IProxyAdminOwnedBase, ISemver, IReinitializableBa
error ProtocolVersions_UnknownUpgrade(uint256 id);
error ProtocolVersions_InvalidProtocolVersion();
error ProtocolVersions_ActivationAlreadyPassed(uint256 id, uint64 activationTimestamp);
error ProtocolVersions_ActivationFrozen(uint256 id, uint64 activationTimestamp);
error ProtocolVersions_NotIncidentResponder();
error ProtocolVersions_NotScheduled(uint256 id);
error ProtocolVersions_DelayMustBeLater(uint64 currentTimestamp, uint64 newTimestamp);
Expand All @@ -29,14 +30,15 @@ interface IProtocolVersions is IProxyAdminOwnedBase, ISemver, IReinitializableBa
error ProtocolVersions_NotInitialized();
error ProtocolVersions_InsufficientNotice(uint64 timestamp);

function initialize(address _incidentResponder) external;
function initialize(address _incidentResponder, uint64[] calldata _initialSchedule) external;
function registerUpgrade(uint64 timestamp, uint256 minProtocolVersion) external returns (uint256);
function setMinimumProtocolVersion(uint256 protocolVersion) external;
function setTimestamp(uint256 id, uint64 timestamp) external;
function setIncidentResponder(address newIncidentResponder) external;
function delayTimestamp(uint256 id, uint64 newTimestamp) external;

function MIN_NOTICE() external view returns (uint64);
function FREEZE_WINDOW() external view returns (uint64);
function minimumProtocolVersion() external view returns (uint256);
function incidentResponder() external view returns (address);
function scheduleId() external view returns (bytes32);
Expand Down
22 changes: 22 additions & 0 deletions scripts/deploy/DeployConfig.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,14 @@ contract DeployConfig is Script {
uint256 public sequencerFeeVaultMinimumWithdrawalAmount;
uint256 public sequencerFeeVaultWithdrawalNetwork;

uint64[] internal _protocolVersionsInitialSchedule;

/// @notice The chain's existing hardfork activation timestamps, used to seed `ProtocolVersions`.
/// @dev Chains with no upgrade history leave this unset and start with an empty registry.
function protocolVersionsInitialSchedule() public view returns (uint64[] memory) {
return _protocolVersionsInitialSchedule;
}

function read(string memory _path) public {
console.log("DeployConfig: reading file %s", _path);
string memory _json = vm.readFile(_path);
Expand Down Expand Up @@ -116,6 +124,20 @@ contract DeployConfig is Script {
respectedGameType = _json.readUintOr("$.respectedGameType", 0);
sequencerFeeVaultMinimumWithdrawalAmount = _json.readUint("$.sequencerFeeVaultMinimumWithdrawalAmount");
sequencerFeeVaultWithdrawalNetwork = _json.readUint("$.sequencerFeeVaultWithdrawalNetwork");

_readProtocolVersionsInitialSchedule(_json);
}

/// @dev Read separately so a rerun of `read` replaces the previous schedule rather than appending
/// to it, and so an out-of-range timestamp fails loudly instead of silently truncating.
function _readProtocolVersionsInitialSchedule(string memory _json) internal {
uint256[] memory schedule = _json.readUintArrayOr("$.protocolVersionsInitialSchedule", new uint256[](0));

delete _protocolVersionsInitialSchedule;
for (uint256 i = 0; i < schedule.length; i++) {
require(schedule[i] <= type(uint64).max, "DeployConfig: initial schedule timestamp exceeds uint64");
_protocolVersionsInitialSchedule.push(uint64(schedule[i]));
}
}

/// @notice Allow the `useUpgradedFork` config to be overridden in testing environments
Expand Down
10 changes: 8 additions & 2 deletions scripts/deploy/SystemDeploy.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,8 @@ contract SystemDeploy is Script {
root: Hash.wrap(cfg.multiproofGenesisOutputRoot()), l2SequenceNumber: cfg.multiproofGenesisBlockNumber()
}),
saltMixer: "salt mixer",
gasLimit: uint64(cfg.l2GenesisBlockGasLimit())
gasLimit: uint64(cfg.l2GenesisBlockGasLimit()),
initialUpgradeSchedule: cfg.protocolVersionsInitialSchedule()
});
}

Expand Down Expand Up @@ -636,11 +637,16 @@ contract SystemDeploy is Script {
_encodeAnchorStateRegistryInitializer(_input, _output)
);

// Fresh systems start with no upgrade history. A chain that already has one imports it by
// passing its activation timestamps here, which is the only way to enter activations that
// cannot clear MIN_NOTICE.
_upgradeToAndCall(
_output.opChainProxyAdmin,
address(_output.protocolVersionsProxy),
_impls.protocolVersionsImpl,
abi.encodeCall(IProtocolVersions.initialize, (_input.roles.incidentResponder))
abi.encodeCall(
IProtocolVersions.initialize, (_input.roles.incidentResponder, _input.initialUpgradeSchedule)
)
);
}

Expand Down
5 changes: 5 additions & 0 deletions scripts/libraries/Types.sol
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ library Types {
}

/// @notice The full set of inputs to deploy a new OP Stack chain.
/// @custom:field initialUpgradeSchedule The chain's hardfork activation timestamps, one entry per
/// upgrade in the node's fork order, zero for unscheduled ones. Seeds
/// `ProtocolVersions` at initialization, which is the only way to enter
/// activations that are already in the past.
struct DeployInput {
Roles roles;
uint32 basefeeScalar;
Expand All @@ -40,6 +44,7 @@ library Types {
Proposal startingAnchorRoot;
string saltMixer;
uint64 gasLimit;
uint64[] initialUpgradeSchedule;
}

/// @notice The full set of outputs from deploying a new OP Stack chain.
Expand Down
3 changes: 2 additions & 1 deletion scripts/multiproof/DeployDevBase.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,8 @@ abstract contract DeployDevBase is Script {

Proxy protocolVersionsProxy = new Proxy(msg.sender);
protocolVersionsProxy.upgradeToAndCall(
address(new ProtocolVersions()), abi.encodeCall(IProtocolVersions.initialize, (address(0)))
address(new ProtocolVersions()),
abi.encodeCall(IProtocolVersions.initialize, (address(0), cfg.protocolVersionsInitialSchedule()))
);
protocolVersionsProxy.changeAdmin(address(proxyAdmin));

Expand Down
1 change: 1 addition & 0 deletions scripts/multiproof/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ Other relevant fields:
| `multiproofGameType` | Game type ID for the dispute game |
| `multiproofGenesisOutputRoot` | Initial anchor output root |
| `multiproofGenesisBlockNumber` | Initial anchor L2 block number |
| `protocolVersionsInitialSchedule` | Hardfork activation timestamps in the node's fork order, `0` for unscheduled forks. Omit for a chain with no history; past activations cannot be added after deployment |

### Step 2: Deploy contracts

Expand Down
34 changes: 34 additions & 0 deletions snapshots/abi/ProtocolVersions.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,19 @@
"stateMutability": "nonpayable",
"type": "constructor"
},
{
"inputs": [],
"name": "FREEZE_WINDOW",
"outputs": [
{
"internalType": "uint64",
"name": "",
"type": "uint64"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "MIN_NOTICE",
Expand Down Expand Up @@ -99,6 +112,11 @@
"internalType": "address",
"name": "_incidentResponder",
"type": "address"
},
{
"internalType": "uint64[]",
"name": "_initialSchedule",
"type": "uint64[]"
}
],
"name": "initialize",
Expand Down Expand Up @@ -364,6 +382,22 @@
"name": "ProtocolVersions_ActivationAlreadyPassed",
"type": "error"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "id",
"type": "uint256"
},
{
"internalType": "uint64",
"name": "activationTimestamp",
"type": "uint64"
}
],
"name": "ProtocolVersions_ActivationFrozen",
"type": "error"
},
{
"inputs": [
{
Expand Down
4 changes: 2 additions & 2 deletions snapshots/semver-lock.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@
"sourceCodeHash": "0x811596e7486cab9ceeeb61405b9ae510d93fcbbdfa11949201a367506c53194a"
},
"src/L1/ProtocolVersions.sol:ProtocolVersions": {
"initCodeHash": "0xd762af325410baea14f927f4292ef9ee2bb13b52d72034d6d129eb1e518dfedd",
"sourceCodeHash": "0x5a06b3ae5f442f3e3f3dba6f78b9c3e3ce5abd7218ccb13d477c067f61187dc5"
"initCodeHash": "0x746f2c953680f6675e13be55678f546e9779b3903b385399cdc8890e7c46ec64",
"sourceCodeHash": "0xffe5ecd626c4895d336f696e679063711a2846f1f59c677aff9eb8dc35ac3dfb"
},
"src/L1/SuperchainConfig.sol:SuperchainConfig": {
"initCodeHash": "0x9b1f3555b499709485d51d5d9665002c0eb1e5eb893be1fb978a30749e894858",
Expand Down
Loading
Loading