The StabilityPool
contract implements Openzeppelin’s upgradeable pattern (OwnableUpgradeable
, PausableUpgradeable
) but uses the ReentrancyGuard
instead of ReentrancyGuardUpgradeable
which is supposed to be used in upgradeable contracts. It also does not call _disableInitializers
in the constructor which could be exploited by an attacker.
The StabilityPool
uses ReentrancyGuard
instead of ReentrancyGuardUpgradeable
:
The contract doesn't lock the initializer functions after contract deployment, leaving the contract vulnerable to an attacker that could front run the initialize function:
Using ReentrancyGuard
in an upgradeable contract can lead to several critical issues:
Initialization Failure:
No constructor means the reentrancy state won't be properly set up
Potential vulnerability to reentrancy attacks
Storage Collision:
Non-upgradeable version uses constructor-based storage initialization
Upgradeable contracts require specific storage layout initialization
Compilation/Deployment Errors:
Likely to cause compilation errors due to incompatible initialization mechanisms
Upgradeable contracts require explicit initializer methods
Correct approach is always to use ReentrancyGuardUpgradeable
in proxy/upgradeable contracts, ensuring proper initialization and storage management.
Leaving the contract uninitialized could be used by the attacker to potentially hijack the contracts core functionalities.
Manual Review
Replace ReentrancyGuard with ReentrancyGuardUpgradeable
Lock the contract, to prevent any future reinitialization:
Adjust the initialize function:
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.