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 over 1 year 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!