Hawk High

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

Missing Review Count Validation in Upgrade

Summary

The graduateAndUpgrade function in LevelOne.sol lacks validation to ensure students have received all required reviews before graduation. This allows students to graduate without meeting the review requirements specified in the invariants.

Vulnerability Details

The contract's invariants state that "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)". However, the graduateAndUpgrade function does not validate the reviewCount mapping before proceeding with the upgrade.
Key code in LevelOne.sol:

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);
}

Impact

Impact

  • Students can graduate without receiving all required reviews

  • Violates the core invariant of the system

  • Could lead to unfair graduation of students who haven't completed their review requirements

  • May result in students advancing to LevelTwo without proper evaluation

Proof of Concept

function test_graduate_without_all_reviews() public schoolInSession {
// Give only 2 reviews to a student
vm.warp(block.timestamp + 1 weeks);
vm.prank(alice);
levelOneProxy.giveReview(harriet, true);
vm.warp(block.timestamp + 1 weeks);
vm.prank(alice);
levelOneProxy.giveReview(harriet, true);
// Try to upgrade before all reviews are given
levelTwoImplementation = new LevelTwo();
levelTwoImplementationAddress = address(levelTwoImplementation);
bytes memory data = abi.encodeCall(LevelTwo.graduate, ());
vm.prank(principal);
levelOneProxy.graduateAndUpgrade(levelTwoImplementationAddress, data);
// Student graduated without all reviews
LevelTwo levelTwoProxy = LevelTwo(proxyAddress);
assert(levelTwoProxy.isStudent(harriet));
}

Tools Used

  • Manual code review

  • Foundry for testing

Recommendations

Add validation in the graduateAndUpgrade function to ensure all students have received their required reviews, like iterate over listOfStudents.length and require(reviewCount[listOfStudents[i]] == 4, "Student missing reviews")

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.

Support

FAQs

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