20,000 USDC
View results
Submission Details
Severity: low
Valid

Precision loss errors in _calculateInterest function

Summary

Precision loss errors in _calculateInterest function in the Lender contract.

Vulnerability Details

The division is performed before multiplication in the _calculateInterest function. Check this part (the calculation of fees):

interest = (l.interestRate * l.debt * timeElapsed) / 10000 / 365 days;
fees = (lenderFee * interest) / 10000;

It should rather be calculated like this:

uint256 fees2 = (l.interestRate * l.debt * timeElapsed * lenderFee) /
10000 /
365 days /
10000;

The following POC was made (Fuzz-testing):

function testFuzzRoundingError(uint256 principle) public {
vm.assume(principle >= 10 ** 9); //Assume USDC
vm.assume(principle < 10 ** 12);
uint256 rate = 1200;
uint256 time = 365 days;
uint256 feePercent = 2400;
//simplified verison of _calculateInterest()
uint256 interest = (rate * principle * time) / 10000 / 365 days;
uint256 fees1 = (interest * feePercent) / 10000;
uint256 fees2 = (rate * principle * time * feePercent) /
10000 /
365 days /
10000;
assertTrue(fees1 == fees2);
}

The above assertion failed. fees2 was always greater than or equal to fees1.

Impact

Because of rounding errors, the protocol would miss out on potential fees.

Tools Used

Manual review, fuzz-testing.

Recommendations

Use this calculation instead:

uint256 fees2 = (l.interestRate * l.debt * timeElapsed * lenderFee) /
10000 /
365 days /
10000;

Support

FAQs

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