Hawk High

First Flight #39
Beginner FriendlySolidity
100 EXP
View results
Submission Details
Impact: medium
Likelihood: high
Invalid

[M-2] Missing Cutoff‑Score and Student Review Enforcement in `LevelOne::graduateAndUpgrade`

Summary

A missing enforcement of both the cutoff‑score and the required four weekly reviews in the graduateAndUpgrade function allows under‑performing and under‑reviewed students to advance.

Vulnerability Details

The graduateAndUpgrade routine contains no logic to exclude students whose studentScore falls below cutOffScore nor any guardrail to ensure each student has received at least four giveReview calls before upgrading. As a result, every enrolled student—regardless of score or number of reviews—gets migrated into LevelTwo without filtering or validation.

Impact

Any student can graduate no matter their score or number of reviews.

Tools Used

  • Foundry

  • Manual Review

Proof of Concept

Place the following test in LevelOneAndGraduateTest.t.sol:

function test_lowScore_and_underReviewed_student_still_upgraded() public {
// 1) Setup: add teachers and enroll students
_teachersAdded();
_studentsEnrolled();
// 2) Start session with a high cutoff
vm.prank(principal);
levelOneProxy.startSession(95);
// 3) Give two bad reviews to Eli (100 → 90 → 80)
vm.warp(block.timestamp + 1 weeks);
vm.prank(alice);
levelOneProxy.giveReview(eli, false);
assertEq(levelOneProxy.studentScore(eli), 90);
vm.warp(block.timestamp + 1 weeks);
vm.prank(bob);
levelOneProxy.giveReview(eli, false);
assertEq(levelOneProxy.studentScore(eli), 80);
// 4) Perform the UUPS upgrade
levelTwoImplementation = new LevelTwo();
bytes memory data = abi.encodeCall(LevelTwo.graduate, ());
vm.prank(principal);
levelOneProxy.graduateAndUpgrade(address(levelTwoImplementation), data);
// 5) Verify Eli appears in LevelTwo despite low score and only 2 reviews
LevelTwo l2 = LevelTwo(proxyAddress);
address[] memory upgraded = l2.getListOfStudents();
bool foundEli = false;
for (uint i = 0; i < upgraded.length; i++) {
if (upgraded[i] == eli) { foundEli = true; break; }
}
assertEq(foundEli,true);
}

Recommendations

Consider adding a pre‑upgrade filter in graduateAndUpgrade that iterates through listOfStudents, checks each student’s studentScore and reviewCount, and for anyone who falls below cutOffScore or hasn’t hit four reviews, deletes their mapping entries and removes them from the array so they can’t be migrated to LevelTwo.

Bellow is an example:


  • ```diff function graduateAndUpgrade(address _levelTwo, bytes memory) public onlyPrincipal { if (_levelTwo == address(0)) { revert HH__ZeroAddress(); }
    •    for (uint256 i = 0; i < listOfStudents.length; i++) {
      
    •        address s = listOfStudents[i];
      
    •        // drop anyone below cutoff or with fewer than 4 reviews
      
    •        if (studentScore[s] < cutOffScore || reviewCount[s] < 4) {
      
    •            // mark as no longer a student
      
    •            isStudent[s] = false;
      
    •            // clear their score and review count
      
    •            delete studentScore[s];      
      
    •            delete reviewCount[s];
      
    •            // remove from array by swapping in last element
      
    •            listOfStudents[i] = listOfStudents[listOfStudents.length - 1];
      
    •            listOfStudents.pop();        
      
    •            i--;  
      
    •        }
      
    •    }
      
      .....rest of code.....
      
Updates

Lead Judging Commences

yeahchibyke Lead Judge about 1 month ago
Submission Judgement Published
Invalidated
Reason: Lack of quality
yeahchibyke Lead Judge about 1 month ago
Submission Judgement Published
Invalidated
Reason: Lack of quality

Support

FAQs

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