Hawk High

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

Incorrect Teacher Compensation Calculation Leads to Excessive Payouts

Summary

The graduateAndUpgrade function incorrectly allocates the entire 35% teacher wage budget to each individual teacher, rather than dividing it evenly among all teachers. This results in a substantial overpayment that violates the intended distribution logic, potentially causing the contract to disburse more funds than are available or budgeted.

Vulnerability Details

The graduateAndUpgrade function is designed to distribute a fixed percentage of the bursary to teachers and the principal. However, there is a critical miscalculation in how teacher compensation is determined. The TEACHER_WAGE constant represent of 35% of the total schoolFees is used to compute the payPerTeacher without dividing the total teacher share by the number of teachers.

As a result, each teacher receives 35% of the bursary, rather than dividing the 35% equally among all teachers. This causes the total payout to teachers to exceed the intended budget, leading to an overpayment and a potential depletion of contract funds.

POC

This code demonstrates that each teacher receives 35% of the total funds, instead of receiving an individual share from the 35% allocated to all teachers.

function test_wrong_calculation() public schoolInSession {
levelTwoImplementation = new LevelTwo();
levelTwoImplementationAddress = address(levelTwoImplementation);
bytes memory data = abi.encodeCall(LevelTwo.graduate, ());
console2.log("Teacher Alice USDC Amount (Before)", usdc.balanceOf(alice));
console2.log("Teacher Alice USDC Amount (Before)", usdc.balanceOf(bob));
vm.prank(principal);
levelOneProxy.graduateAndUpgrade(levelTwoImplementationAddress, data);
console2.log("Teacher Alice USDC Amount (after)", usdc.balanceOf(alice));
console2.log("Teacher Alice USDC Amount (after)", usdc.balanceOf(bob));
LevelTwo levelTwoProxy = LevelTwo(proxyAddress);
}

Impact

If multiple teachers are present, the contract may attempt to transfer more funds than it holds, potentially causing transaction failures due to insufficient balance.

Tools Used

Manual Review

Recommendations

The payPerTeacher calculation should be modified so that the total 35% portion of the bursary is first calculated, and then evenly divided among all teachers in the list. Here's an example implementation of the corrected logic:

function graduateAndUpgrade(address _levelTwo, bytes memory) public onlyPrincipal {
if (_levelTwo == address(0)) {
revert HH__ZeroAddress();
}
uint256 totalTeachers = listOfTeachers.length;
if (totalTeachers == 0) {
revert("No teachers available for payment");
}
//calculate the total teacher pay (35%)
uint256 totalTeacherPay = (bursary * TEACHER_WAGE) / PRECISION;
//calculate how much per teacher can get the funds.
uint256 payPerTeacher = totalTeacherPay / 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 3 months ago
Submission Judgement Published
Validated
Assigned finding tags:

incorrect teacher pay calculation

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

yeahchibyke Lead Judge 3 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.