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 10 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.

Give us feedback!