Hawk High

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

Missing Student Review Count Check in LevelOne Contract

Summary

The graduateAndUpgrade function in the LevelOne contract fails to verify that all students have received exactly 4 reviews before upgrading, violating the invariant that "System upgrade should not occur if any student has not gotten 4 reviews." This logic error allows premature upgrades, risking incorrect student graduations and system instability.

Vulnerability Details

The graduateAndUpgrade function does not check if each student in listOfStudents has a reviewCount of 4, as tracked in the giveReview function. The invariant requires 4 reviews per student before upgrades, but the function proceeds with payouts and upgrades regardless of review counts. This allows the principal to call graduateAndUpgrade early (before 4 weeks) or with incomplete reviews. A malicious principal could exploit this to graduate students with fewer or no reviews, bypassing academic standards. Tests show the function executes with students having 0–2 reviews, violating the invariant.

Testing suite:

// SPDX-License-Identifier: SEE LICENSE IN LICENSE
pragma solidity 0.8.26;
import {Test, console2} from "forge-std/Test.sol";
import {DeployLevelOne} from "../script/DeployLevelOne.s.sol";
import {LevelOne} from "../src/LevelOne.sol";
import {LevelTwo} from "../src/LevelTwo.sol";
import {MockUSDC} from "./mocks/MockUSDC.sol";
contract LevelOneAndGraduateTest is Test {
DeployLevelOne deployBot;
LevelOne levelOneProxy;
LevelTwo levelTwoImplementation;
address proxyAddress;
MockUSDC usdc;
address principal;
uint256 schoolFees;
address alice = makeAddr("first_teacher");
address clara = makeAddr("first_student");
address dan = makeAddr("second_student");
function setUp() public {
deployBot = new DeployLevelOne();
proxyAddress = deployBot.deployLevelOne();
levelOneProxy = LevelOne(proxyAddress);
usdc = deployBot.getUSDC();
principal = deployBot.principal();
schoolFees = deployBot.getSchoolFees();
usdc.mint(clara, schoolFees);
usdc.mint(dan, schoolFees);
}
function test_missingReviewCheck() public {
// Setup: Add teacher, enroll students, start session
vm.prank(principal);
levelOneProxy.addTeacher(alice);
vm.startPrank(clara);
usdc.approve(address(levelOneProxy), schoolFees);
levelOneProxy.enroll();
vm.stopPrank();
vm.startPrank(dan);
usdc.approve(address(levelOneProxy), schoolFees);
levelOneProxy.enroll();
vm.stopPrank();
vm.prank(principal);
levelOneProxy.startSession(70);
// Give Clara 2 reviews, Dan 0 reviews
vm.startPrank(alice);
levelOneProxy.giveReview(clara, true);
vm.warp(block.timestamp + 1 weeks);
levelOneProxy.giveReview(clara, true);
vm.stopPrank();
// Log review counts (requires getter in contract)
console2.log("Clara reviews:", levelOneProxy.getReviewCount(clara)); // 2
console2.log("Dan reviews:", levelOneProxy.getReviewCount(dan)); // 0
// Attempt upgrade
levelTwoImplementation = new LevelTwo();
vm.prank(principal);
levelOneProxy.graduateAndUpgrade(address(levelTwoImplementation), abi.encodeCall(LevelTwo.graduate, ()));
// No revert occurs, proving missing check
}
}

Impact

  • Invariant Violation: Violates the requirement that all students must have 4 reviews before system upgrade, undermining academic evaluation.

  • System Disruption: Premature upgrades may graduate students with incomplete reviews, eroding system reliability.

  • Exploitation Risk: A malicious principal can upgrade early, bypassing reviews, potentially favoring unqualified students.

Tools Used

Foundry and manual code review.

Recommendations

Add a review count check in graduateAndUpgrade:

+ for (uint256 i = 0; i < listOfStudents.length; i++) {
+ require(reviewCount[listOfStudents[i]] == 4, "Student missing reviews");
+ }
Updates

Lead Judging Commences

yeahchibyke Lead Judge 24 days 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.

yeahchibyke Lead Judge 24 days 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.