The contract incorrectly calculates each teacher’s wage in the graduateAndUpgrade() function by applying the full 35% share to each individual teacher, rather than splitting that 35% pool evenly among all teachers.
This results in massive overpayment — potentially draining the entire bursary.
uint256 payPerTeacher = (bursary * TEACHER_WAGE) / PRECISION;
for (uint256 n = 0; n < totalTeachers; n++) {
usdc.safeTransfer(listOfTeachers[n], payPerTeacher);
}
Bursary = 1000 USDC
TEACHER_WAGE = 35
Calculated payPerTeacher = 1000 * 35 / 100 = 350 USDC
With 3 teachers, each teacher gets 350 USDC → total payout = 1050 USDC — exceeding the bursary.
This is a multiplication bug where the total pool wasn’t divided among recipients.
Overpayment or bursary drained.
The contract pays out more than intended, violating the invariant that only 35% of the bursary goes to teachers.
Student funds depleted
The leftover 60% meant for bursary carryover is compromised.
Repeated upgrades could leave the system with zero funds, permanently harming school operations.
Manual code inspection
Solidity calculation verification
Percentage + loop payout logic review
AI for organizing the writing
Percentage + loop payout logic review
Replace:
uint256 payPerTeacher = (bursary * TEACHER_WAGE) / PRECISION;
With
uint256 totalTeacherPool = (bursary * TEACHER_WAGE) / PRECISION;
uint256 payPerTeacher = totalTeacherPool / totalTeachers;
This ensures:
The total 35% is correctly shared among all teachers.
Prevents overpayment.
Protects contract funds.
`payPerTeacher` in `graduateAndUpgrade()` is incorrectly calculated.
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.