we must need to have _disableInitializers()
inside the constructor of the LevelOne contract
-> In UUPS proxies, all state lives in the proxy, while the implementation’s functions must be “initialized” via an external initialize() function rather than a constructor. If _disableInitializers() is not called in the implementation contract’s constructor, anyone can call initialize() directly on the implementation, thereby becoming its “owner” and bypassing the proxy’s access controls.
-> Once an attacker controls the implementation, they can invoke upgradeToAndCall() (protected by the malicious owner role) to delegatecall into a contract containing a selfdestruct opcode, effectively deleting the implementation’s code
. After self-destruction, all proxies pointing to that implementation will have no logic to delegate to, breaking the upgrade path.
Deploy the UUPS implementation without _disableInitializers() in its constructor.
Call initialize(attackerAddress) directly on the implementation contract: the attacker becomes owner.
Deploy a malicious upgrade contract with a function that executes selfdestruct(address(proxy)).
As “owner,” the attacker calls upgradeToAndCall(maliciousAddress, data) on the proxy, which delegatecalls into the malicious contract and triggers selfdestruct, wiping the implementation
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.