Hawk High

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

Core invariants not enforced before authorizing contract upgrade

Description

The graduateAndUpgrade() function in LevelOne.sol fails to enforce several protocol-critical invariants before authorizing a system upgrade. This omission introduces significant risks of protocol corruption, misaligned payment logic, and broken progression rules.

The function unconditionally calls _authorizeUpgrade() and proceeds with fund distribution — all without verifying:

  • if the school session has ended (i.e., sessionEnd is reached),

  • whether each student received the required 4 weekly reviews,

  • whether each student has met the cutOffScore to graduate,

  • and if payments occur after a valid time period (i.e., every 4 weeks).

These checks are foundational to the protocol’s integrity and were explicitly documented as invariants.

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); // ❌ Upgrade authorized without checking any invariant
for (uint256 n = 0; n < totalTeachers; n++) {
usdc.safeTransfer(listOfTeachers[n], payPerTeacher); // ❌ Incorrect pay logic (see below)
}
usdc.safeTransfer(principal, principalPay);
}

Impact

This results in:

Time-based session integrity loss: upgrades can be triggered at any time, even during an active session. The sessionEnd is declared but never used to enforce session completion.
Invalid graduation: students may be upgraded without completing the required reviews or meeting the cutOffScore, completely bypassing the educational logic.
Upgrade misuse: Upgrades should be a reward mechanism after a validated session. Without these guards, malicious or negligent principals can skip progression logic and steal funds.


Recommended Mitigations

  • Require that block.timestamp >= sessionEnd before allowing upgrade.

  • Validate that all students have exactly 4 reviews.

  • Enforce cutOffScore for all students before graduation.

  • Emit an Upgraded(address) event to track the upgrade.


Severity: High

Component Reason
Impact: High Funds can be misused; logic broken.
Likelihood: High All checks are currently missing; easily exploitable by the principal.
Confidence: High Code review and invariants documentation confirm the issues.

Tools Used

  • Manual Review

Updates

Lead Judging Commences

yeahchibyke Lead Judge
28 days ago
yeahchibyke Lead Judge 18 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.

can graduate without session end

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

no event

Event not emitted

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

can graduate without session end

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

no event

Event not emitted

Support

FAQs

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