Hawk High

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

Incorrect Teacher Payment Calculation Breaks Invariant

Summary

The LevelOne::graduateAndUpgrade() function miscalculates teacher compensation by allocating 35% of the bursary to each teacher, rather than splitting 35% among all teachers. This violates a critical protocol invariant and results in excessive fund distribution, potentially depleting the bursary.

Vulnerability Details

The intent of the protocol is to allocate:

  • 35% of the total bursary to all teachers combined

  • 5% to the principal

However, the current implementation distributes 35% to each teacher:

uint256 payPerTeacher = (bursary * TEACHER_WAGE) / PRECISION;

This means:

  • With 2 teachers: they receive 35% + 35% = 70% of bursary

  • With 3 teachers: 105% — exceeding available funds

  • And so on.

This breaks the invariant and drains the bursary.

Impact

Can lead to:

  • Bursary depletion

  • Principal underpayment

  • Protocol imbalance

  • Causes overpayment to each teachers

Proof of Concept (PoC Test)

function test_wrongPayPerTeacher() public {
uint256 bursary = 1000; // Mocked bursary amount
uint256 totalTeachers = 2;
// Simulate current (broken) logic
uint256 payPerTeacher = (bursary * levelOneProxy.TEACHER_WAGE()) / levelOneProxy.PRECISION();
for (uint256 n = 0; n < totalTeachers; n++) {
bursary = bursary - payPerTeacher;
}
console2.log("Bursary: ",bursary); // should be 650 but it's 300 due to wrong payPerTeacher calculation.
// bursary should be 650 as only 35% of bursary is paid to teachers
assertLe(bursary, 650); // Breaking of invariant - teachers share of 35% of bursary
}

Tools Used

  • Manual Code Review

  • Custom test written in Foundry

Recommendations

Update the teacher payment calculation to divide the allocated 35% evenly among all teachers:

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 totalTeacherShare = (bursary * TEACHER_WAGE) / PRECISION;
+ uint256 payPerTeacher = totalTeacherShare / totalTeachers;
uint256 principalPay = (bursary * PRINCIPAL_WAGE) / PRECISION;
_authorizeUpgrade(_levelTwo);
for (uint256 n = 0; n < totalTeachers; n++) {
usdc.safeTransfer(listOfTeachers[n], payPerTeacher);
}
usdc.safeTransfer(principal, principalPay);
}
Updates

Lead Judging Commences

yeahchibyke Lead Judge 7 months ago
Submission Judgement Published
Validated
Assigned finding tags:

incorrect teacher pay calculation

`payPerTeacher` in `graduateAndUpgrade()` is incorrectly calculated.

Support

FAQs

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

Give us feedback!