Hawk High

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

Failure to Check `sessionEnd` in `graduateAndUpgrade` Function

Summary

The graduateAndUpgrade function in LevelOne.sol does not verify whether the school session has ended (block.timestamp >= sessionEnd), allowing the principal to upgrade the system before the 4-week session is complete, violating the project's invariant.

Vulnerability Details

According to the project invariants, the system upgrade cannot take place unless the school's sessionEnd timestamp has been reached (i.e., after 4 weeks). However, the graduateAndUpgrade function lacks a check for block.timestamp >= sessionEnd. This allows the principal to call the function at any time during the session, triggering an early upgrade and distributing wages prematurely.

Relevant code in graduateAndUpgrade:

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

No condition ensures that block.timestamp >= sessionEnd, violating the invariant.

Impact

  • Impact: High
    An early upgrade severely disrupts protocol functionality by allowing the system to transition to LevelTwo before students complete their 4 weekly reviews. This can result in unfair graduation outcomes, premature wage distribution, and violation of the project's core logic. While no direct fund loss occurs, the protocol's integrity and fairness are significantly compromised.

  • Likelihood: Medium
    Exploitation requires the principal to intentionally or mistakenly call graduateAndUpgrade early. While this is not guaranteed, it is feasible, especially if the principal's account is compromised or the function is called in error.

  • Manual code analysis

Recommendations

Add a check to ensure the session has ended before allowing the upgrade. Suggested code modification:

function graduateAndUpgrade(address _levelTwo, bytes memory) public onlyPrincipal {
if (_levelTwo == address(0)) {
revert HH__ZeroAddress();
}
require(block.timestamp >= sessionEnd, "Session has not ended");
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);
}

This ensures the upgrade adheres to the 4-week session invariant.

Updates

Lead Judging Commences

yeahchibyke Lead Judge 6 months ago
Submission Judgement Published
Validated
Assigned finding tags:

can graduate without session end

`graduateAndUpgrade()` can be called successfully even when the school session has not ended

Support

FAQs

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