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

Wrong Amount of Loan Interest is Calculated

Summary

The vulnerability involves miscalculating interest rates in a lending protocol's codebase. The code mistakenly treats the interestRate meant for per-second calculations as if it's per-year. This results in underestimated interest due to incorrect division by 365 days. The impact is illustrated with a $10,000 loan for a year: correct interest should be $31,536,000, but the flawed code yields $1. Precision loss also arises from omitting 6 hours in a year. Additionally, using 3 decimals for interest rates compounds precision issues. Corrective actions involve adjusting calculations based on intended time units.

Vulnerability Details

In the Structs.sol#L48 the interestRate variable is defined. The comment mentions its explanation below:

/// @notice the interest rate of the loan per second (in debt tokens)

Then, the interestRate variable is used in the _calculateInterest() function in Lender.sol#L720-L727 as 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;
interest -= fees;
}

We can see that for calculating the interest, the interestRate which shows the interest rate of the loan per second is divided by 365 days. Since the interestRate variable is multiplied by timeElapsed which is in seconds and divided by 365 days, means that the interestRate variable is considered to show the interest Rate per 365 days.

We know that the interestRate shows the interest rate of a loan per second. Also, we know that 365 days have 31,536,000 seconds. So, the interest rate per 365 days should be 31,536,000 times more than the interest rate per second. However, in the given code, both interest rate per second and interest rate per 365 days, are used interchangeably.

Also, note that 1 year is equal to 365 days and 6 hours. A lack of 6 hours in the computation can lead to precision loss.

The final note regarding calculating the interest is that 3 decimals is way small and can lead to precision loss easily.

Impact

This can lead to a huge underestimation of the interest on a loan. Consider the interest rate per second is . Consider three decimals considered for interestRate, this value should be equal to one. Consider there is a loan with the value of $10,000, which has been given to the borrower for 365 days. Hence, the total interest is:

We can see the interest of this loan must be $31,536,000 for 365 days. However, the implementation calculates the interest like below:

A huge difference can be observed here.

Regarding the second case, consider that 1 year is 365 days and 6 hours. Consider we are calculating the interest using the implementation but with the correct period for a year. In this case, the interest would be:

Since the result should be an integer, we can see adding the exact time of a year can make the interest zero instead of one.

Tools Used

Manual Review, Foundry

Recommendations

In case of using the interest variable for showing interest per second; change the Lender.sol#L724 to the following:

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

In case of using the interest variable for showing interest per year; change the Lender.sol#L724 to the following:

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

Support

FAQs

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