Hawk High

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

LevelTwo Missing Required UUPSUpgradeable Inheritance

Summary

LevelTwo contract does not inherit from UUPSUpgradeable, which is required for any implementation contract in the UUPS upgrade pattern, even if it's intended to be the final implementation. This will cause the upgrade from LevelOne to LevelTwo to fail in production.

Vulnerability Details

In the UUPS (Universal Upgradeable Proxy Standard) pattern, all implementation contracts must inherit from UUPSUpgradeable, even if they are intended as "final" implementations with no further upgrades planned. This is because the upgrade process itself requires the new implementation to support the UUPS interface.

LevelOne correctly inherits from UUPSUpgradeable:

contract LevelOne is Initializable, UUPSUpgradeable {
// ...
}

However, LevelTwo does not:

contract LevelTwo is Initializable {
// ...
}

The upgrade process uses IERC1822Proxiable(newImplementation).proxiableUUID() to verify that the new implementation supports the UUPS pattern. Without inheriting from UUPSUpgradeable, LevelTwo doesn't implement this function, and the upgrade will fail with the error:

// The implementation is not UUPS
revert ERC1967Utils.ERC1967InvalidImplementation(newImplementation);

This is evident from the OpenZeppelin UUPSUpgradeable implementation:

function _upgradeToAndCallUUPS(address newImplementation, bytes memory data) private {
try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) {
if (slot != ERC1967Utils.IMPLEMENTATION_SLOT) {
revert UUPSUnsupportedProxiableUUID(slot);
}
ERC1967Utils.upgradeToAndCall(newImplementation, data);
} catch {
// The implementation is not UUPS
revert ERC1967Utils.ERC1967InvalidImplementation(newImplementation);
}
}

Impact

The upgrade from LevelOne to LevelTwo will fail in production. The school system will be unable to complete its upgrade cycle, which is a core feature of the platform. This means:

  1. The system will be stuck at LevelOne

  2. Teachers and principal cannot receive their wages (which are paid during upgrade)

  3. Students cannot graduate

  4. The entire business logic of the platform breaks down

Tools Used

  • Manual code review

Recommendations

LevelTwo must inherit from UUPSUpgradeable and implement the required functions, even if it's intended as the final implementation:

contract LevelTwo is Initializable, UUPSUpgradeable {
// ... existing code ...
function _authorizeUpgrade(address newImplementation) internal override onlyPrincipal {
// This can be empty if no further upgrades are planned, but it must be implemented
revert("Upgrades not supported");
}
function graduate() public reinitializer(2) {
__UUPSUpgradeable_init();
// Other migration logic
}
}

If LevelTwo is intended as the final implementation, the _authorizeUpgrade function can be implemented to revert, which would prevent any further upgrades while still satisfying the UUPS pattern requirements.

Updates

Lead Judging Commences

yeahchibyke Lead Judge 7 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.

Give us feedback!