Hawk High

First Flight #39
Beginner FriendlySolidity
100 EXP
View results
Submission Details
Severity: high
Valid

Misused UUPS Upgrade Flow

Description: Inside LevelOne::graduateAndUpgrade, the code calls _authorizeUpgrade(_levelTwo) directly instead of performing 'upgradeToAndCall' on the proxy. The signature doesn't accept the 'bytes data' parameter and the redundant _authorizeUpgrade(_levelTwo) is never sufficient to change implementation.

Impact: Students never actually get upgraded to LevelTwo, the intended proxy call is never invoked. This breaks the upgrade flow and leaves the contract in an inconsistent state.

Proof of Concept: Include the following test in the LevelOneAndGraduateTest.t.sol file:

function testNoUpgradePerformed() public schoolInSession {
levelTwoImplementation = new LevelTwo();
levelTwoImplementationAddress = address(levelTwoImplementation);
vm.prank(principal);
levelOneProxy.graduateAndUpgrade(levelTwoImplementationAddress, "");
LevelTwo levelTwoProxy = LevelTwo(proxyAddress);
vm.expectRevert();
levelTwoProxy.TEACHER_WAGE_L2();
}

Recommended Mitigation:

  • Change signature to function graduateAndUpgrade(address _levelTwo, bytes memory data)

  • Remove direct _authorizeUpgrade(_levelTwo) call

  • Use upgradeToAndCall(_levelTwo, data) on the proxy so that _authorizeUpgrade is invoked internally and the new implementation is executed immediately.

- function graduateAndUpgrade(address _levelTwo, bytes memory) public onlyPrincipal {
+ function graduateAndUpgrade(address _levelTwo, bytes memory data) public onlyPrincipal {
- _authorizeUpgrade(_levelTwo);
+ upgradeToAndCall(_levelTwo, data);
}
Updates

Lead Judging Commences

yeahchibyke Lead Judge 3 months ago
Submission Judgement Published
Validated
Assigned finding tags:

failed upgrade

The system doesn't implement UUPS properly.

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.