This report identifies a logical flaw in the graduateAndUpgrade() function of the LevelOne.sol contract. The function, intended to process end-of-session activities such as payouts and contract upgrade authorization, lacks a crucial check to ensure that the school session has actually concluded. The principal can call this function at any time after a session has started, potentially before the defined 4-week duration is complete. This allows for premature payouts and upgrade authorization, contradicting the expected operational lifecycle of a fixed-duration school session and potentially leading to unfair outcomes for participants.
The graduateAndUpgrade() function in LevelOne.sol is responsible for finalizing a school session. Its operations include distributing the bursary to teachers and the principal, and authorizing an upgrade to a new contract implementation (_levelTwo).
The startSession() function sets a sessionEnd timestamp, which is block.timestamp + 4 weeks, and sets inSession = true;. However, the graduateAndUpgrade() function does not verify that the current block.timestamp is greater than or equal to sessionEnd before proceeding with its operations. It also doesn't explicitly check if inSession is true (though onlyPrincipal and other checks might implicitly assume a session context, a direct check for session end is missing).
This omission allows the principal to trigger the end-of-session logic, including financial distributions and upgrade authorization, before the 4-week period has elapsed.
Setup:
The LevelOne.sol contract is initialized.
The principal calls startSession(cutOffScore), which sets inSession = true and sessionEnd = block.timestamp + 4 weeks.
Students enroll, and teachers are added. The bursary accumulates.
Premature Execution:
Before the 4-week duration is over (e.g., after only 1 week, so block.timestamp < sessionEnd), the principal calls graduateAndUpgrade(levelTwoAddress, "").
Outcome:
The graduateAndUpgrade() function executes successfully (assuming no other revert conditions like the payout bug are hit).
Teachers and the principal receive their payouts based on the current bursary.
The _authorizeUpgrade(levelTwoAddress) call succeeds, allowing the proxy to be upgraded.
The session effectively ends prematurely from the perspective of payouts and system evolution.
Violation of Expected Operational Lifecycle: The system allows for the premature conclusion of a fixed-duration school session, which contradicts the intent implied by setting a sessionEnd time.
Potential Unfairness to Participants:
Students might not have the full 4-week period to receive reviews and achieve the cutOffScore if the session is ended early.
Teachers' payouts are based on the bursary at the time of the call. If called early, the bursary might not have reached its full potential (e.g., if enrollments were still trickling in under a specific policy, though enroll is notYetInSession).
Misleading System State: The system can be authorized for an upgrade and payouts can occur based on an incomplete session, which might not align with the expectations of users or the intended design.
Manual Code Review
Implement a check at the beginning of the graduateAndUpgrade() function to ensure that the current block.timestamp is greater than or equal to the sessionEnd timestamp and that a session was indeed active. This will enforce the intended session duration before end-of-session procedures can be initiated.
`graduateAndUpgrade()` can be called successfully even when the school session has not ended
`graduateAndUpgrade()` can be called successfully even when the school session has not ended
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.