Summary
The incorrect calculation formula can lead to erroneous wage distribution, thereby causing financial losses.
Vulnerability Details
The vulnerability is located in the graduateAndUpgrade()
function of the LevelOne.sol
file.
function graduateAndUpgrade(address _levelTwo, bytes memory) public onlyPrincipal {
...
uint256 payPerTeacher = (bursary * TEACHER_WAGE) / PRECISION;
uint256 principalPay = (bursary * PRINCIPAL_WAGE) / PRECISION;
...
}
The two calculation logics in the code above actually compute the total salaries of the teachers and the principal. When it comes to the final distribution, the total amount needs to be divided by the number of people.
Proof of Concept
Test Case
function testPayWages() public {
levelTwoImplementation = new LevelTwo();
levelTwoImplementationAddress = address(levelTwoImplementation);
bytes memory data = abi.encodeCall(LevelTwo.graduate, ());
_studentsEnrolled();
address teacher_third = makeAddr("teacher_third");
vm.startPrank(principal);
levelOneProxy.addTeacher(alice);
levelOneProxy.addTeacher(bob);
levelOneProxy.addTeacher(teacher_third);
levelOneProxy.startSession(70);
vm.expectRevert(
abi.encodeWithSignature(
"ERC20InsufficientBalance(address,uint256,uint256)",
levelOneProxy,
9000 ether,
10500 ether)
);
levelOneProxy.graduateAndUpgrade(levelTwoImplementationAddress, data);
vm.stopPrank();
}
Output
Suite result: ok. 1 passed; 0 failed; 0 skipped; finished in 6.30ms (703.29µs CPU time)
Ran 1 test suite in 1.40s (6.30ms CPU time): 1 tests passed, 0 failed, 0 skipped (1 total tests)
Impact
Incorrect salary distribution, leading to financial losses.
Recommendations
The calculated result needs to be divided by the number of people.
function graduateAndUpgrade(address _levelTwo, bytes memory) public onlyPrincipal {
...
uint256 payPerTeacher = (bursary * TEACHER_WAGE) / PRECISION / totalTeachers;
uint256 principalPay = (bursary * PRINCIPAL_WAGE) / PRECISION;
...
}