Hawk High

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

Permanent Session Lock from inSession Never Reset

Summary

The LevelOne::startSession function sets the inSession flag to true to indicate the start of a school term. However, no function in either LevelOne or LevelTwo resets inSession to false, even after graduation. As a result, once a session starts, the contract remains stuck in an "active session" state, permanently preventing future sessions or student enrollments.


Vulnerability Details

function startSession(uint256 _cutOffScore) public onlyPrincipal notYetInSession {
sessionEnd = block.timestamp + 4 weeks;
inSession = true;
cutOffScore = _cutOffScore;
emit SchoolInSession(block.timestamp, sessionEnd);
}
// @audit-issue `inSession` is never set back to false, locking the contract in a permanent session
// @> No logic in LevelOne or LevelTwo resets `inSession`

Issue Explanation

  1. One-Way State Transition
    Once inSession is set to true, it remains true indefinitely unless explicitly reset.

  2. No Session Reset Logic
    Neither graduateAndUpgrade in LevelOne nor graduate() in LevelTwo resets this flag, leaving the contract stuck in "session in progress".

  3. Enrollment and Session Initiation Blocked
    The notYetInSession modifier prevents startSession from being called again, blocking future school terms and new student enrollments.


Impact

  • Denial of Functionality: Only one session can ever occur.

  • Enrollment Frozen: No new students can enroll in future terms.

  • Protocol Halt: The core lifecycle of the school system is broken after a single use.


Tools Used

  • Manual Code Review


Recommendations

Option A – Reset inSession in LevelTwo::graduate()

If the graduation and reward logic is now handled in LevelTwo, the proper place to reset inSession is at the end of the graduate() function:

function graduate() public reinitializer(2) onlyPrincipal {
// Graduation logic with score filtering and fund distribution...
inSession = false; // @fix reset session status
sessionEnd = 0;
bursary = 0; // optional: clear remaining funds if unused
}

Option B – Reset inSession in LevelOne::graduateAndUpgrade()

If the graduation logic still resides in LevelOne, you can reset the session flag at the end of graduateAndUpgrade:

function graduateAndUpgrade(address _levelTwo, bytes memory) public onlyPrincipal {
// Existing distribution and upgrade logic...
bursary = 0;
inSession = false; // @fix allow future sessions
}

Option C – Add a Separate endSession() Admin Function

If you want to keep session control flexible, consider exposing a dedicated function:

function endSession() public onlyPrincipal {
require(inSession, "Session is not active");
inSession = false;
sessionEnd = block.timestamp;
}

Updates

Lead Judging Commences

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

session state not updated

`inSession` not updated after during upgrade

Support

FAQs

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