Skip to content

Commit 350e902

Browse files
committed
feat: reset scheduled implementations on upgrade execution
1 parent e32f98c commit 350e902

File tree

2 files changed

+48
-1
lines changed

2 files changed

+48
-1
lines changed

src/XanV1.sol

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -384,7 +384,7 @@ contract XanV1 is
384384

385385
/// @notice Authorizes an upgrade.
386386
/// @param newImpl The new implementation to authorize the upgrade to.
387-
function _authorizeUpgrade(address newImpl) internal view override {
387+
function _authorizeUpgrade(address newImpl) internal override {
388388
if (newImpl == address(0)) {
389389
revert ImplementationZero();
390390
}
@@ -410,6 +410,10 @@ contract XanV1 is
410410
revert QuorumOrMinLockedSupplyNotReached(mostVotedImpl);
411411
}
412412
_checkDelayCriterion({endTime: votingData.scheduledEndTime});
413+
414+
// Reset the scheduled upgrade
415+
votingData.scheduledImpl = address(0);
416+
votingData.scheduledEndTime = 0;
413417
} else if (isScheduledByCouncil) {
414418
// Check if the best ranked implementation exists.
415419
if (mostVotedImpl != address(0)) {
@@ -420,6 +424,10 @@ contract XanV1 is
420424
}
421425
}
422426
_checkDelayCriterion({endTime: councilData.scheduledEndTime});
427+
428+
// Reset the scheduled upgrade
429+
councilData.scheduledImpl = address(0);
430+
councilData.scheduledEndTime = 0;
423431
} else {
424432
revert UpgradeNotScheduled(newImpl);
425433
}

test/XanV1.upgrade.t.sol

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,45 @@ contract XanV1UpgradeTest is Test {
219219
_xanProxy.upgradeToAndCall({newImplementation: _councilProposedImpl, data: ""});
220220
}
221221

222+
function test_authorizeUpgrade_resets_the_scheduled_council_upgrade_data_on_upgrade_execution() public {
223+
// Cache the current implementation
224+
address currentImpl = _xanProxy.implementation();
225+
226+
// Schedule and upgrade to the current implementation as the council
227+
vm.prank(_COUNCIL);
228+
_xanProxy.scheduleCouncilUpgrade(currentImpl);
229+
(, uint48 endTime) = _xanProxy.scheduledCouncilUpgrade();
230+
skip(endTime);
231+
_xanProxy.upgradeToAndCall({newImplementation: currentImpl, data: ""});
232+
assertEq(_xanProxy.implementation(), currentImpl);
233+
234+
// Check that the scheduled upgrade has been reset to 0
235+
(address scheduledImplPostUpgrade, uint48 scheduledEndTimePostUpgrade) = _xanProxy.scheduledCouncilUpgrade();
236+
assertEq(scheduledImplPostUpgrade, address(0));
237+
assertEq(scheduledEndTimePostUpgrade, 0);
238+
}
239+
240+
function test_authorizeUpgrade_resets_the_scheduled_voter_body_upgrade_data_on_upgrade_execution() public {
241+
// Cache the current implementation
242+
address currentImpl = _xanProxy.implementation();
243+
244+
// Schedule and upgrade to the current implementation as the voter body
245+
vm.startPrank(_defaultSender);
246+
_xanProxy.lock(Parameters.MIN_LOCKED_SUPPLY);
247+
_xanProxy.castVote(currentImpl);
248+
vm.stopPrank();
249+
_xanProxy.scheduleVoterBodyUpgrade();
250+
(, uint48 endTime) = _xanProxy.scheduledVoterBodyUpgrade();
251+
skip(endTime);
252+
_xanProxy.upgradeToAndCall({newImplementation: currentImpl, data: ""});
253+
assertEq(_xanProxy.implementation(), currentImpl);
254+
255+
// Check that the scheduled upgrade has been reset to 0
256+
(address scheduledImplPostUpgrade, uint48 scheduledEndTimePostUpgrade) = _xanProxy.scheduledVoterBodyUpgrade();
257+
assertEq(scheduledImplPostUpgrade, address(0));
258+
assertEq(scheduledEndTimePostUpgrade, 0);
259+
}
260+
222261
function test_upgradeToAndCall_emits_the_Upgraded_event() public {
223262
vm.prank(_COUNCIL);
224263
_xanProxy.scheduleCouncilUpgrade(_councilProposedImpl);

0 commit comments

Comments
 (0)