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

Precision loss when calculating the protocol interest

Summary

The calculation of the fees (protocolInterest) in the Lender::_calculateInterest() suffers from a rounding down issue, resulting in a small precision loss that can be improved.

Vulnerability Details

Division before multiplication can lead to rounding down issue since Solidity has no fixed-point numbers. Consider the calculation of the fees (protocolInterest) in the _calculateInterest(), the function does the division (by the remainder part: "/ 10000 / 365 days") before the multiplication (by lenderFee). Hence, the computed result can suffer from the rounding down issue, resulting in a small precision loss, especially in a loan token with small decimals.

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;
}
  • Division (by the remainder part: "/ 10000 / 365 days") before multiplication: https://github.com/Cyfrin/2023-07-beedle/blob/658e046bda8b010a5b82d2d85e824f3823602d27/src/Lender.sol#L724

  • Multiplication (by lenderFee) after division: https://github.com/Cyfrin/2023-07-beedle/blob/658e046bda8b010a5b82d2d85e824f3823602d27/src/Lender.sol#L725

Impact

The computed fees (protocolInterest) returned by the _calculateInterest() can suffer from the rounding down issue, resulting in a small precision loss, especially when a loan token has small decimals (e.g., GUSD (Gemini dollar) has 2 decimals).

Tools Used

Manual Review

Recommendations

I recommend improving the formula for calculating the fees by taking multiplications before divisions to prevent truncation, as shown below.

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 = (l.interestRate * l.debt * timeElapsed * lenderFee) / 10000 / 365 days / 10000;
interest -= fees;
}

Support

FAQs

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