The graduateAndUpgrade()
function incorrectly uses the _authorizeUpgrade
internal hook instead of the standard upgradeToAndCall
function, and the Level Two contract is not properly configured for UUPS. This prevents the proxy contract from upgrading correctly to the Level Two implementation, failing the intended transition.
The contract attempts to use the UUPS (Universal Upgradeable Proxy Standard) pattern for upgrades. However, the graduateAndUpgrade()
function in the LevelOne contract misuses the _authorizeUpgrade
function. In the UUPS pattern, _authorizeUpgrade
is designed as an internal hook that is called by the standard upgrade functions like upgradeTo
or upgradeToAndCall
(provided by OpenZeppelin's UUPSUpgradeable
base contract) to perform access control or other pre-upgrade checks. It is not the function intended to trigger the upgrade process itself.
The problematic line is:
Furthermore, for the UUPS pattern to work correctly, the new implementation contract (LevelTwo
) must also inherit from UUPSUpgradeable
and provide its own implementation of the _authorizeUpgrade
hook (even if empty, as shown in the recommended fix). The original LevelTwo
contract did not appear to do this.
This misuse means the OpenZeppelin UUPS proxy logic, which handles updating the proxy's implementation address, is never invoked correctly. The test case provided demonstrates that without the fix, the intended state of Level Two is not reached:
The assertion assertEq(LevelTwo(proxyAddress).TEACHER_WAGE_L2(), levelTwoTeacherWage);
would fail because proxyAddress
is still directing calls to the LevelOne
implementation, which does not have the TEACHER_WAGE_L2()
function or the expected state of the Level Two contract.
The proxy contract's implementation address is not updated to point to the new Level Two contract. Any calls made through the proxy after the failed upgrade attempt will continue to execute the code of the Level One implementation, not the Level Two implementation.
To correctly implement the UUPS upgrade using OpenZeppelin's libraries, modify the graduateAndUpgrade()
function to call upgradeToAndCall()
instead of _authorizeUpgrade()
. Additionally, ensure the LevelTwo
contract correctly inherits from UUPSUpgradeable
and implements the _authorizeUpgrade
hook.
The system doesn't implement UUPS properly.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.