The graduateAndUpgrade()
function implies that it both processes the end-of-session payments and performs a contract upgrade to a new implementation (_levelTwo
). However, the function fails to actually perform the upgrade. It only calls _authorizeUpgrade(...)
, which is a permission check and does not change the implementation.
The function:
...only triggers the access control logic. It does not invoke any upgrade mechanism such as:
upgradeToAndCall(...)
or _upgradeToAndCallUUPS(...)
As a result, the contract remains at LevelOne
and the version()
function continues to return "LevelOne"
even after a successful call to graduateAndUpgrade()
.
This was verified on-chain via a proxy setup using OpenZeppelin’s ERC1967Proxy
.
Function does not fulfill its name or intended behavior
Creates developer confusion or false sense of upgrade safety
Future upgrades may be mistakenly assumed completed
Could lead to logic inconsistencies if LevelTwo
contains critical updates that are never applied
Manual review of UUPSUpgradeable.sol
OpenZeppelin documentation
Remix test deployment using ERC1967Proxy
Replace the permission-only call with a real upgrade using OpenZeppelin’s internal upgrade function:
Ensure that this line comes after all state and payment logic to maintain upgrade safety.
Here's how you should modifiy your code to actually perform to upgrade :
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.