Hawk High

First Flight #39
Beginner FriendlySolidity
100 EXP
View results
Submission Details
Severity: high
Valid

`LevelOne.sol:graduateAndUpgrade()` breaks protocol invariants due to missing validation checks

Summary

LevelOne.sol:graduateAndUpgrade() should work only if the following
conditions are satisfied :

  • Students must have gotten all reviews before system upgrade. System upgrade should not occur if any student has not gotten 4 reviews (one for each week)

  • Any student who doesn't meet the cutOffScore should not be upgraded

  • System upgrade cannot take place unless school's sessionEnd has reached

Vulnerability Details

LevelOne.sol:graduateAndUpgrade() will execute successfully without validating the above conditions. This allows the graduateAndUpgrade() function to run even before the requirements are satisfied.

Here is the vulnerable code:

function graduateAndUpgrade(address _levelTwo, bytes memory) public onlyPrincipal {
if (_levelTwo == address(0)) {
revert HH__ZeroAddress();
}
uint256 totalTeachers = listOfTeachers.length;
uint256 payPerTeacher = (bursary * TEACHER_WAGE) / PRECISION;
uint256 principalPay = (bursary * PRINCIPAL_WAGE) / PRECISION;
_authorizeUpgrade(_levelTwo);
for (uint256 n = 0; n < totalTeachers; n++) {
usdc.safeTransfer(listOfTeachers[n], payPerTeacher);
}
usdc.safeTransfer(principal, principalPay);
}

It lacks the following validations

  • Students must have received all four weekly reviews before the upgrade.

  • Students below the cutOffScore threshold should not be upgraded.

  • The upgrade must not occur before the school's sessionEnd .

Here is the Proof Of Code :

place this test in LevelOneAndGraduateTest.t.sol and run it

function test_confirm_upgrade_breaks_invariants() public schoolInSession {
// students enrolled , teachers added, school session started
levelTwoImplementation = new LevelTwo();
levelTwoImplementationAddress = address(levelTwoImplementation);
// students upgraded with even 0 reviews
// cuttOffScore is also not checking before upgrade
// system is upgraded even before the session ends
vm.startPrank(principal);
levelOneProxy.graduateAndUpgrade(levelTwoImplementationAddress,"");
}

Impact

  • System can be upgraded even if the school's sessionEnd has not reached

  • All the students even who did not meet the cutOffScore will be upgraded

  • System can be upgraded even before not getting all the 4 reviews

Tools Used

  • Manual analysis

  • Foundry

Recommendations

Implement the valid checks in LevelOne.sol:graduateAndUpgrade() as specified below

function graduateAndUpgrade(address _levelTwo, bytes memory) public onlyPrincipal {
if (_levelTwo == address(0)) {
revert HH__ZeroAddress();
}
+ if(block.timestamp < sessionEnd) {
+ revert("Session not ended yet");
+ }
+ uint256 studentsCount = istOfStudents.length;
+
+ for(uint256 n = 0; n <studentsCount; n++) {
+ if(reviewCount[listOfStudents[n]] != 4){
+ revert("Student review count not met");
+ }
+ if (studentScore[listOfStudents[n]] < cutOffScore) {
+ revert("Student did not meet cut off score");
+ }
+ }
uint256 totalTeachers = listOfTeachers.length;
uint256 payPerTeacher = (bursary * TEACHER_WAGE) / PRECISION;
uint256 principalPay = (bursary * PRINCIPAL_WAGE) / PRECISION;
_authorizeUpgrade(_levelTwo);
for (uint256 n = 0; n < totalTeachers; n++) {
usdc.safeTransfer(listOfTeachers[n], payPerTeacher);
}
usdc.safeTransfer(principal, principalPay);
}
Updates

Lead Judging Commences

yeahchibyke Lead Judge about 1 month ago
Submission Judgement Published
Validated
Assigned finding tags:

cut-off criteria not applied

All students are graduated when the graduation function is called as the cut-off criteria is not applied.

can graduate without session end

`graduateAndUpgrade()` can be called successfully even when the school session has not ended

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.