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: 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": "0x5ef30dbac345fadcde0bafdc22aa2d67d5d8d4c8ec9909b070f3d4d6ca765ac4",
"sourceCodeHash": "0xbfa24612855d4bb061c03d83a0380f15b936b50555908a6f52ef143c9f5ef9ba"
"initCodeHash": "0x909a923012cab53fdfc4ea8f9f54173d64d2e3c250e8d69cb10ea226e21a4adf",
"sourceCodeHash": "0x2b338e2c3cb163445841a1bfca2370e731b4cba4be35018cb07b2d22a3465f67"
},
"src/L1/SuperchainConfig.sol:SuperchainConfig": {
"initCodeHash": "0x9b1f3555b499709485d51d5d9665002c0eb1e5eb893be1fb978a30749e894858",
Expand Down
6 changes: 3 additions & 3 deletions src/L1/ProtocolVersions.sol
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ contract ProtocolVersions is ProxyAdminOwnedBase, Initializable, Reinitializable
error ProtocolVersions_TimestampNotAfterPrevious(
uint256 id, uint256 previousId, uint64 previousTimestamp, uint64 timestamp
);
/// @notice Thrown when a non-zero timestamp is not less than the next scheduled upgrade.
/// @notice Thrown when a non-zero timestamp is greater than the next scheduled upgrade.
error ProtocolVersions_TimestampNotBeforeNext(uint256 id, uint256 nextId, uint64 timestamp, uint64 nextTimestamp);
/// @notice Thrown when scheduleId is read before initialize has been called.
error ProtocolVersions_NotInitialized();
Expand Down Expand Up @@ -394,14 +394,14 @@ contract ProtocolVersions is ProxyAdminOwnedBase, Initializable, Reinitializable
}
}

/// @dev Requires `timestamp` to be less than the closest higher-id scheduled upgrade.
/// @dev Requires `timestamp` to be less than or equal to the closest higher-id scheduled upgrade.
function _assertTimestampBeforeNext(uint256 id, uint64 timestamp) private view {
if (timestamp == 0) return;

for (uint256 i = id + 1; i < _timestamps.length; i++) {
uint64 next = _timestamps[i];
if (next != 0) {
if (timestamp >= next) revert ProtocolVersions_TimestampNotBeforeNext(id, i, timestamp, next);
if (timestamp > next) revert ProtocolVersions_TimestampNotBeforeNext(id, i, timestamp, next);
return;
}
}
Expand Down
53 changes: 45 additions & 8 deletions test/L1/ProtocolVersions.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -610,23 +610,40 @@ contract ProtocolVersions_SetTimestamp_Test is ProtocolVersions_TestInit {
protocolVersions.setTimestamp(ECOTONE, previous - 1);
}

/// @notice Tests that `setTimestamp` reverts when the timestamp is not before the next one.
function test_setTimestamp_timestampNotBeforeNext_reverts() external {
/// @notice Tests that `setTimestamp` may share the next scheduled upgrade's timestamp.
function test_setTimestamp_timestampEqualToNext_succeeds() external {
uint64 current = uint64(block.timestamp) + protocolVersions.MIN_NOTICE() + 100;
uint64 next = current + 100;

vm.startPrank(_owner);
protocolVersions.registerUpgrade(current, 0);
protocolVersions.registerUpgrade(next, 0);
protocolVersions.setTimestamp(CANYON, next);
vm.stopPrank();

uint64[] memory schedule = protocolVersions.getSchedule();
assertEq(schedule[CANYON], next);
assertEq(schedule[ECOTONE], next);
}

/// @notice Tests that `setTimestamp` reverts when the timestamp is after the next one.
function test_setTimestamp_timestampAfterNext_reverts() external {
uint64 current = uint64(block.timestamp) + protocolVersions.MIN_NOTICE() + 100;
uint64 next = current + 100;
uint64 afterNext = next + 1;

vm.startPrank(_owner);
protocolVersions.registerUpgrade(current, 0);
protocolVersions.registerUpgrade(next, 0);
vm.stopPrank();

vm.expectRevert(
abi.encodeWithSelector(
IProtocolVersions.ProtocolVersions_TimestampNotBeforeNext.selector, CANYON, ECOTONE, next, next
IProtocolVersions.ProtocolVersions_TimestampNotBeforeNext.selector, CANYON, ECOTONE, afterNext, next
)
);
vm.prank(_owner);
protocolVersions.setTimestamp(CANYON, next);
protocolVersions.setTimestamp(CANYON, afterNext);
}

/// @notice Tests that `setTimestamp` reverts when the upgrade has already activated.
Expand Down Expand Up @@ -766,8 +783,8 @@ contract ProtocolVersions_DelayTimestamp_Test is ProtocolVersions_TestInit {
protocolVersions.delayTimestamp(CANYON, ts);
}

/// @notice Tests that `delayTimestamp` cannot move an upgrade to or beyond its next scheduled successor.
function test_delayTimestamp_timestampNotBeforeNext_reverts() external {
/// @notice Tests that `delayTimestamp` may share the next scheduled upgrade's timestamp.
function test_delayTimestamp_timestampEqualToNext_succeeds() external {
uint64 current = uint64(block.timestamp) + protocolVersions.MIN_NOTICE() + 100;
uint64 next = current + 100;

Expand All @@ -777,13 +794,33 @@ contract ProtocolVersions_DelayTimestamp_Test is ProtocolVersions_TestInit {
protocolVersions.setIncidentResponder(_incidentResponder);
vm.stopPrank();

vm.prank(_incidentResponder);
protocolVersions.delayTimestamp(CANYON, next);

uint64[] memory schedule = protocolVersions.getSchedule();
assertEq(schedule[CANYON], next);
assertEq(schedule[ECOTONE], next);
}

/// @notice Tests that `delayTimestamp` cannot move an upgrade after its next scheduled successor.
function test_delayTimestamp_timestampAfterNext_reverts() external {
uint64 current = uint64(block.timestamp) + protocolVersions.MIN_NOTICE() + 100;
uint64 next = current + 100;
uint64 afterNext = next + 1;

vm.startPrank(_owner);
protocolVersions.registerUpgrade(current, 0);
protocolVersions.registerUpgrade(next, 0);
protocolVersions.setIncidentResponder(_incidentResponder);
vm.stopPrank();

vm.expectRevert(
abi.encodeWithSelector(
IProtocolVersions.ProtocolVersions_TimestampNotBeforeNext.selector, CANYON, ECOTONE, next, next
IProtocolVersions.ProtocolVersions_TimestampNotBeforeNext.selector, CANYON, ECOTONE, afterNext, next
)
);
vm.prank(_incidentResponder);
protocolVersions.delayTimestamp(CANYON, next);
protocolVersions.delayTimestamp(CANYON, afterNext);
}

/// @notice Tests that `delayTimestamp` reverts when the upgrade has no scheduled timestamp.
Expand Down
Loading