Hawk High

First Flight #39
Beginner FriendlySolidity
100 EXP
View results
Submission Details
Impact: high
Likelihood: high
Invalid

Improper Wage Calculation Causes DoS When Teacher Count >= 3

Summary

The graduateAndUpgrade() function attempts to pay each teacher a fixed percentage (35%) of the bursary, without adjusting for the number of teachers. This creates a logic flaw: once the number of teachers reaches 3 or more, the total amount paid out exceeds 100% of the bursary, leading to an insufficient balance and a transaction revert. Since this function is responsible for upgrading the system, the protocol enters a denial-of-service (DoS) state, where no future upgrades can occur.

Vulnerability Details

Current logic in graduateAndUpgrade() function:

uint256 payPerTeacher = (bursary * TEACHER_WAGE) / PRECISION;
...
for (uint256 n = 0; n < totalTeachers; n++) {
usdc.safeTransfer(listOfTeachers[n], payPerTeacher);
}

If TEACHER_WAGE = 35%:

  • For 1 teacher → pays 35% of the bursary ✅ (plus 5% to principal → 40%)

  • For 2 teachers → pays 70% of the bursary ✅ (plus 5% to principal → 75%)

  • For 3 teachers → pays 105% of the bursary ❌ (plus 5% to principal → 110%)

Because there's no check on listOfTeachers.length, the system does not guarantee that the number of teachers remains within a safe range. Once the loop attempts to transfer more tokens than are available, it will revert, causing the transaction to fail entirely.

This also violates the invariant:

"60% should reflect in the bursary after upgrade."

Impact

Once the number of teachers exceeds 2, the protocol will:

  • Denial-of-Service: graduateAndUpgrade() becomes uncallable.

  • Protocol Upgrade Blocked: The system cannot transition to the next version.

  • Teacher/Principal Payouts Fail: No one receives payment once the condition is triggered.

  • Invariant Violation: 60% of the bursary meant to remain in the contract gets disrupted.

Tools Used

  • Manual Code Review

Recommendations

There are two viable solutions:

Option 1: Restrict Teacher Count
(It is not recommended; it only ensures the upgrade transaction won't revert, but it still breaks the system invariant.)

  • In addTeacher() function:

    require(listOfTeachers.length < 3, "Maximum 2 teachers allowed"); // add this

  • In startSession() function:

    require(listOfTeachers.length > 0 && listOfTeachers.length <= 2, "Invalid teacher count"); // add this

Option 2 (Preferred): Correct the Payment Logic

  • Ensure that the 35% share is split among all teachers:

    require(totalTeachers > 0, "No teachers to pay");
    uint256 payPerTeacher = (bursary * TEACHER_WAGE) / PRECISION / totalTeachers;

  • This aligns directly with the protocol invariant and removes the hard cap on teacher count, offering greater flexibility.


Updates

Lead Judging Commences

yeahchibyke Lead Judge 4 months ago
Submission Judgement Published
Invalidated
Reason: Lack of quality

Support

FAQs

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