Hawk High

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

M-01. [M-1] Missing Teacher Payment Validation

Summary

The payment distribution doesn't account for the remaining 60% that should stay in the bursary, and there's no validation of the payment amounts.

Vulnerability Details

  1. The function fails to verify that bursary >= totalPayouts and check if payPerTeacher is fairly distributed.

Exploit Scenario:
If bursary = 99 and TEACHER_WAGE = 35%:
99 * 35 / 100 = 34.65 → Rounds down to 34 (loss of 0.65 per teacher)
Teachers receive less than promised, while excess funds remain stuck.

  1. Improper Bursary Deduction
    The function does not deduct payments from bursary before transfers, risking:
    i. Reentrancy attacks (if usdc.safeTransfer triggers a callback)
    ii. Double-spending (if interrupted mid-execution)
    iii. Incorrect final balance (funds may be over/under-allocated).

  2. Missing Teacher Count Validation
    No check ensures:
    i. listOfTeachers.length > 0 (avoid division by zero)
    ii. Each teacher still exists (they could be removed mid-payment)

Exploit Scenario:
A malicious principal could:
i. Remove a teacher after payment calculation
ii. Cause payPerTeacher to be incorrectly inflated
iii. Drain the bursary via oversized transfers

Impact

  1. Teachers receive incorrect payments due to rounding errors.

  2. bursary accounting fails, allowing excess withdrawals.

  3. If usdc.safeTransfer calls back into the contract, funds could be stolen.

Tools Used

  1. Foundry

  2. VS Code

Recommendations

  1. Secure Payment Calculation

function graduateAndUpgrade(address _levelTwo, bytes memory) public onlyPrincipal {
// ... existing checks ...
uint256 totalTeachers = listOfTeachers.length;
++ uint256 totalTeacherPay = (bursary * TEACHER_WAGE) / PRECISION;
uint256 principalPay = (bursary * PRINCIPAL_WAGE) / PRECISION;
uint256 payPerTeacher = totalTeacherPay / totalTeachers;
// Verify amounts
++ require(totalTeacherPay + principalPay <= bursary, "Insufficient funds");
// Add Validation Checks
++ require(listOfTeachers.length > 0, "No teachers");
++ require(usdc.balanceOf(address(this)) >= totalTeacherPay, "Insufficient USDC");
// Update bursary before payments
++ bursary = bursary - totalTeacherPay - principalPay;
// Make payments
for (uint256 n = 0; n < totalTeachers; n++) {
usdc.safeTransfer(listOfTeachers[n], payPerTeacher);
}
usdc.safeTransfer(principal, principalPay);
_authorizeUpgrade(_levelTwo);
}
Updates

Lead Judging Commences

yeahchibyke Lead Judge about 1 month ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

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