The initialize() function lacks proper access control and is prone to unauthorized initialization and reinitialization risk. Bad actors can hijack the contract and reset important parameters such as the principal address and usdc address.
The initialize() function is supposed to be called once during deployment. If it is not protected by a constructor that disables extra initializations, a bad actor can call initialize() repeatedly. This would allow them to set themselves as the principal, use a malicious token address as _usdcAddress and also manipulate the contract to drain funds.
Example of attack:
Initial deployer sets principal
Attacker calls the initialize() again, resetting important parameters.
All the controls and funds after this are then controlled by the attacker.
Attacker can set principal or usdc to a malicious address.
Attacker takes full control of the contract.
Attacker manipulates schoolFees to steal user deposits.
Manual code review
Slither/Static Analysis
Consider locking the implementation contract by using the _disableInitializers() function
This ensures the implementation contract cannot be initialized after deployment, eliminating the risk of unauthorized initialization.
Implement Ownership initialization using __Ownable_init()
Using __Ownable_init() establishes a clear admin for the contract, and thus locks administrative functions.
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.