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

Fees could get truncated due to unnecessary precision loss

Summary

The _calculateInterest() function of the Lender.sol contract can lead to inaccuracies in calculating the accrued fees on a loan. This is due to the fact that while calculating the accrued fees, not enough measures are taken to ensure that maximum precision is kept.

Vulnerability Details

Take a look at the _calculateInterest()

/// @notice calculates interest accrued on a loan
/// @param l the loan to calculate for
/// @return interest the interest accrued
/// @return fees the fees accrued
function _calculateInterest(
Loan memory l
) internal view returns (uint256 interest, uint256 fees) {
uint256 timeElapsed = block.timestamp - l.startTimestamp;
interest = (l.interestRate * l.debt * timeElapsed) / 10000 / 365 days;
fees = (lenderFee * interest) / 10000;
interest -= fees;
}

The function currently calculates the accrued interest on a loan as follows:

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

It then computes the accrued fees based on the calculated interest:

fees = (lenderFee * interest) / 10000;

The precision loss occurs when the fees is calculated due to the "division operation" before multiplication, which can lead to a loss of accuracy.
Do note that that the fees could alternatively be calculated as this

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

Essentially putting all multiplications before the divisions.

Impact

Inaccurate accrued fees could be registered, which is not best for beedle

Tools Used

Manual Audit

Recommend Mitigation

Modify the computation to perform multiplication operations before division. This can be achieved by directly calculating fees using l.interestRate, l.debt, timeElapsed, and lenderFee. Here's the idea of the suggested change:

/// @notice calculates interest accrued on a loan
/// @param l the loan to calculate for
/// @return interest the interest accrued
/// @return fees the fees accrued
function _calculateInterest(
Loan memory l
) internal view returns (uint256 interest, uint256 fees) {
uint256 timeElapsed = block.timestamp - l.startTimestamp;
interest = (l.interestRate * l.debt * timeElapsed) / 10000 / 365 days;
- fees = (lenderFee * interest) / 10000;
+ fees = (lenderFee *l.interestRate * l.debt * timeElapsed) / 100000000 / 365 days;
interest -= fees;
}

Additional Notes

There are multiple instances of the call to _calculateInterest() around 5 in the Lender.sol contract, which just exarcebates the issue and shows how little instances of the precision loss could sum up to a significant brick.

Support

FAQs

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