The graduateAndUpgrade function authorizes an upgrade via _authorizeUpgrade(_levelTwo), but fails to perform the actual upgrade because _upgradeToAndCall is never called. As a result, the contract remains at the same implementation even after the function completes.
In UUPS upgradeable contracts (like OpenZeppelin’s), the upgrade process typically involves two steps:
Authorization via _authorizeUpgrade(address newImplementation),
Execution via upgradeTo or upgradeToAndCall.
This function does only step 1:
But never calls:
_upgradeToAndCall(_levelTwo, data, false); // or true depending on use case
As a result, no upgrade actually takes place.
The contract remains stuck on the current implementation.
Any expected new logic or state from _levelTwo is never reached.
Protocol misbehavior or stalling may occur due to false assumption that upgrade succeeded.
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.