The _repay function in the LendingPool contract applies debt scaling incorrectly by using the rayDiv function twice during the repayment calculation. Additionally, a locally computed scaledAmount is calculated but never used. These issues can result in borrowers repaying only the principal without covering the accrued interest.
Double Debt Scaling
The function first retrieves the user's total debt:
It then scales this debt by applying:
This operation is intended to adjust the debt based on the reserve’s current usage index.
Next, after capping the repayment amount:
the function applies the scaling a second time:
Issue: This second scaling erroneously divides by the usageIndex again, resulting in an incorrect (and lower) repayment value.
Unused Computed scaledAmount:
The scaledAmount computed by the second call to rayDiv is not utilized in any subsequent logic. Instead, the repayment continues using values returned by the DebtToken.burn function:
Since scaledAmount is discarded, the intended correction for scaling is never applied.
Underpayment of Interest:
The misinterpretation of scaling, combined with the reliance on the return value from the burn function, leads to a situation where the repayment amount does not account for accrued interest.
As a result, borrowers could repay only the principal amount, bypassing the interest component. This undermines the intended financial mechanics of the protocol.
Underpayment of Interest:
Borrowers might repay only the principal without covering the accrued interest, distorting the debt repayment process.
Inaccurate Debt Accounting:
The protocol’s internal accounting will fail to accurately capture the full debt obligation, potentially leading to an overstated debt balance and flawed interest rate calculations.
Exploitation Risk:
Malicious users could exploit this flaw to minimize their repayment, paying less than their true debt obligation over time, which could erode the protocol’s revenue and stability.
Scenario Setup:
A borrower takes out a loan, providing NFT collateral.
Over time, interest accrues, increasing the effective debt.
Repayment Attempt:
The borrower initiates a repayment transaction with an amount that exceeds their scaled debt.
The _repay function computes the scaled debt (userScaledDebt) and then determines actualRepayAmount.
Double Scaling and Ignored Value:
The function incorrectly applies rayDiv a second time on actualRepayAmount, producing scaledAmount.
However, scaledAmount is never used in the subsequent transfer or debt token burn operation.
Outcome:
The repayment relies on the unscaled value returned from the burn function.
The borrower effectively repays only the principal, leaving accrued interest unpaid.
This results in a persistent overstatement of debt and incorrect interest accruals.
Manual review
Remove the Second Scaling:
Eliminate the redundant scaling operation:
This ensures that the repayment amount is correctly computed only once.
Integrate the Correct Scaled Value:
If additional scaling is required, ensure that the correctly computed value is used throughout the repayment logic.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.