Core Contracts

Regnum Aurum Acquisition Corp
HardhatReal World AssetsNFT
77,280 USDC
View results
Submission Details
Severity: high
Invalid

Double scaling in `_repay` function and unused `scaledAmount` in `LendingPool.sol`

Summary

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.

Vulnerability Details

  1. Double Debt Scaling

    • The function first retrieves the user's total debt:

      uint256 userDebt = IDebtToken(reserve.reserveDebtTokenAddress).balanceOf(onBehalfOf);
    • It then scales this debt by applying:

      uint256 userScaledDebt = userDebt.rayDiv(reserve.usageIndex);

      This operation is intended to adjust the debt based on the reserve’s current usage index.

    • Next, after capping the repayment amount:

      uint256 actualRepayAmount = (amount > userScaledDebt) ? userScaledDebt : amount;

      the function applies the scaling a second time:

      uint256 scaledAmount = actualRepayAmount.rayDiv(reserve.usageIndex);

      Issue: This second scaling erroneously divides by the usageIndex again, resulting in an incorrect (and lower) repayment value.

  2. 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:

      (uint256 amountScaled, uint256 newTotalSupply, uint256 amountBurned, uint256 balanceIncrease) =
      IDebtToken(reserve.reserveDebtTokenAddress).burn(onBehalfOf, amount, reserve.usageIndex);
    • Since scaledAmount is discarded, the intended correction for scaling is never applied.

  3. 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.

Impact

  • 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.

Proof-of-Concept (POC) Example

  1. Scenario Setup:

    • A borrower takes out a loan, providing NFT collateral.

    • Over time, interest accrues, increasing the effective debt.

  2. 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.

  3. 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.

  4. 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.

Tools Used

Manual review

Recommendations

  1. Remove the Second Scaling:

    • Eliminate the redundant scaling operation:

      // Remove this line:
      uint256 scaledAmount = actualRepayAmount.rayDiv(reserve.usageIndex);
    • This ensures that the repayment amount is correctly computed only once.

  2. Integrate the Correct Scaled Value:

    • If additional scaling is required, ensure that the correctly computed value is used throughout the repayment logic.

Updates

Lead Judging Commences

inallhonesty Lead Judge 10 months ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement
Assigned finding tags:

LendingPool::_repay double scales the debt

inallhonesty Lead Judge 10 months ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement
Assigned finding tags:

LendingPool::_repay double scales the debt

Support

FAQs

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

Give us feedback!