Hawk High

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

[M-4] Missing Review-Count Increment Breaks Weekly-Review Invariant

Summary

The giveReview function in the LevelOne contract enforces a one-week cooldown between reviews and purports to limit each student to five total reviews, but it never increments the reviewCount mapping. As a result, a teacher can call giveReview indefinitely on the same student—one time per week—completely bypassing the intended four-review cap.

Vulnerability Details

The code checks two conditions before recording a review: that the caller is a teacher and that fewer than five reviews have been given (require(reviewCount[_student] < 5, "Student review count exceeded!!!")), and that at least one week has passed since the last review (require(block.timestamp >= lastReviewTime[_student] + reviewTime, "Reviews can only be given once per week")). However, after passing these checks and adjusting the student’s score and lastReviewTime, the function never increments reviewCount[_student]. Consequently, the five-review limit is never reached and the count check remains perpetually true.

Impact

A malicious or compromised teacher can indefinitely penalize or reward a student beyond the intended limit, potentially manipulating student scores and graduation eligibility. The effect undermines fairness and trust in the system’s academic logic but does not directly steal funds. Exploitation requires only teacher privileges and weekly calls, making it straightforward once a teacher account is available.

Proof Of Concept

The following test proves that we can review a student more than 4 times without reverting:

function test_reviewCountInvariant_broken() public {
_teachersAdded();
_studentsEnrolled();
vm.prank(principal);
levelOneProxy.startSession(50);
for (uint i = 0; i < 10; i++) {
vm.warp(block.timestamp + levelOneProxy.reviewTime());
vm.prank(alice);
levelOneProxy.giveReview(harriet, false);
}
assertTrue(true, "reviewCount never increments; more than 5 reviews allowed");
}

Tools Used

  • Foundry

  • Manual Review

Recommendations

To restore both the weekly-rate and total-count invariants, update giveReview as follows:

  1. Introduce a separate counter for weekly reviews, resetting it when a new week begins.

+ mapping(address => uint256) private weeklyReviewCount;
  1. Increment the total-review counter and enforce the five-review cap.

function giveReview(address _student, bool review) public onlyTeacher {
if (!isStudent[_student]) revert HH__StudentDoesNotExist();
// Reset weekly counter if a full review interval has passed
- require(block.timestamp >= lastReviewTime[_student] + reviewTime, "Reviews can only be given once per week");
+ if (block.timestamp >= lastReviewTime[_student] + reviewTime) {
+ weeklyReviewCount[_student] = 0;
+ }
+ require(weeklyReviewCount[_student] < 1, "Only one review per week");
require(reviewCount[_student] < 5, "Student review count exceeded!!!");
if (!review) {
studentScore[_student] -= 10;
}
// Update timestamps and counters
lastReviewTime[_student] = block.timestamp;
+ weeklyReviewCount[_student] += 1;
+ reviewCount[_student] += 1;
emit ReviewGiven(_student, review, studentScore[_student]);
}
Updates

Lead Judging Commences

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

reviewCount not updated

`reviewCount` for students is not updated after each review session

Support

FAQs

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