Hawk High

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

Review Count Not Incremented, Allowing Unlimited Student Reviews.

Summary

reviewCount mapping is used in an access control check but never updated, allowing infinite reviews per student.

Vulnerability Details

The LevelOne.sol contract has the following check in the giveReview() function:

require(reviewCount[_student] < 5, "Student review count exceeded!!!");

However, reviewCount[_student] is never incremented anywhere in the codebase. This means that for any _student, reviewCount[_student] will always remain 0, effectively bypassing the review limit check. That is reviewCount[_student] will always be less than 5.

As a result:

  • Teachers can call giveReview() unlimited times.

  • They can arbitrarily reduce a student’s studentScore, since bad reviews deduct 10 points.

  • The invariant “students must only be reviewed once per week, up to 4 times per session” is violated.

Impact

  • Score manipulation: A malicious or buggy teacher can give multiple bad reviews, tanking a student’s score below the cutOffScore, preventing them from graduating.

  • Bypass core logic: The system assumes a fixed number of reviews per student per session. This bug breaks that invariant.

  • Potential griefing attack: Repeated bad reviews could be used to block a student from progressing indefinitely.


Tools Used

  • Manual code review

  • forge test suite

POC

Here is the foundry test:

function test_reviewCountFlaw() public {
// Step 1: Dan enrolls
vm.startPrank(dan);
usdc.approve(address(levelOneProxy), schoolFees);
levelOneProxy.enroll();
vm.stopPrank();
assertEq(levelOneProxy.isStudent(dan), true);
assertEq(levelOneProxy.studentScore(dan), 100);
vm.prank(principal);
levelOneProxy.addTeacher(alice);
vm.warp(block.timestamp + 1 weeks);
// Step 2: Alice gives Dan a bad review every week, more than 4 times
for(uint i = 0; i<10; i++) {
vm.warp(block.timestamp + 1 weeks);
vm.prank(alice);
levelOneProxy.giveReview(dan, false);
}
// Step 3: Final assertion - studentScore drops below graduation threshold
assertEq(levelOneProxy.studentScore(dan), 0);
}
  • This test demonstrates a critical flaw: since reviewCount is never incremented,

  • teachers can repeatedly call giveReview every week, indefinitely penalizing the student.

Recommendations

Increment reviewCount[_student] inside the giveReview() function:

reviewCount[_student]++;


Updates

Lead Judging Commences

yeahchibyke Lead Judge 3 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity
yeahchibyke Lead Judge 3 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity

Support

FAQs

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