The graduateAndUpgrade function in LevelOne.sol and the LevelTwo.sol contract lack mechanisms to transfer or initialize the remaining 60% of the bursary after the system upgrade, violating the project's invariant that 60% of the bursary should be reflected in the new contract post-upgrade.
According to the project invariants, after paying 5% to the principal and 35% to teachers, the remaining 60% of the bursary should be available in the LevelTwo contract after the system upgrade. However:
In LevelOne.sol, the graduateAndUpgrade function does not include logic to transfer the remaining 60% of the bursary (in USDC tokens) to the proxy or LevelTwo contract.
In LevelTwo.sol, the graduate function (with reinitializer(2)) does not initialize the bursary variable with the remaining funds, leaving it at its default value of zero.
Relevant code in graduateAndUpgrade:
No logic transfers the remaining 60% of the bursary. In LevelTwo.sol, the bursary variable is not initialized:
Impact: High
This vulnerability directly puts funds at risk, as the remaining 60% of the bursary is not transferred or accessible in LevelTwo, effectively locking or losing a significant portion of the protocol's funds. This renders the upgraded system financially non-functional, as LevelTwo starts with a bursary of zero, severely disrupting protocol operations.
Likelihood: High
The issue is automatic and inevitable during the upgrade process, as the lack of transfer or initialization logic is embedded in the contracts. It occurs every time graduateAndUpgrade is called, requiring no malicious intent.
Manual code analysis
Implement logic to transfer and initialize the remaining 60% of the bursary in LevelTwo. Suggested modifications:
In LevelOne.sol, calculate and transfer the remaining 60% to the proxy or LevelTwo:
Funds are stuck in `LevelOne()` contract after upgrade.
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.