The LevelOne
smart contract, which is built using OpenZeppelin's upgradeable pattern, lacks a call to _disableInitializers()
in its constructor. This omission introduces a critical security risk: it allows the implementation contract to be initialized directly, potentially enabling attackers to take ownership and manipulate the contract's state.
The contract uses the Initializable
and UUPSUpgradeable
patterns, indicating it is meant to be deployed behind a proxy. However, the constructor does not include _disableInitializers()
.
Without this, the implementation contract is left unprotected and can be initialized by anyone. If a malicious actor calls the initialize()
function on the implementation contract directly, they could:
Become the principal
(owner/admin)
Set arbitrary values for usdc
or other critical contract variables
Completely compromise the contract's logic and security assumptions
This is a well-known vulnerability in upgradeable smart contracts when using the UUPS (Universal Upgradeable Proxy Standard) pattern.
Become the principal
, thus gaining full administrative control over the contract.
Steal deposited funds or manipulate student and teacher records.
Manual Review
Add _disableInitializers()
to the constructor to prevent the implementation contract from being initialized:
This ensures that only the proxy contract can initialize the implementation logic, protecting against direct usage and unauthorized access.
Also, consider reviewing all upgradeable contracts in your codebase to ensure they follow this security best practice.
The system can be re-initialized by an attacker and its integrity tampered with due to lack of `disableInitializer()`
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.