Core Contracts

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

Debt Accounting Mismatch: LendingPool Uses Pre-calculated Scale While DebtToken Includes Balance Increase

Summary :

The LendingPool's borrow function uses a pre-calculated scaledAmount for user debt tracking while DebtToken mints a different amount that includes balance increase, creating a critical accounting mismatch in the protocol's debt tracking system.

Vulnerability Details :

the issue exist in the borrow function as follow :

// Pre-calculates scaled amount before mint
uint256 scaledAmount = amount.rayDiv(reserve.usageIndex);
// Calls mint but ignores amountToMint
(bool isFirstMint, uint256 amountMinted, uint256 newTotalSupply) =
IDebtToken(reserve.reserveDebtTokenAddress).mint(
msg.sender,
msg.sender,
amount,
reserve.usageIndex
);
// Uses pre-calculated amount instead of actual minted amount
user.scaledDebtBalance += scaledAmount;
reserve.totalUsage = newTotalSupply;

while In DebtToken.mint():

uint256 amountScaled = amount.rayDiv(index);
uint256 balanceIncrease = scaledBalance.rayMul(index) -
scaledBalance.rayMul(_userState[onBehalfOf].index);
uint256 amountToMint = amount + balanceIncrease;
_mint(onBehalfOf, amountToMint.toUint128());
return (scaledBalance == 0, amountToMint, totalSupply());
  1. Calculates initial scaled amount:

uint256 amountScaled = amount.rayDiv(index);

Calculates additional balance increase:

uint256 balanceIncrease = scaledBalance.rayMul(index) - scaledBalance.rayMul(_userState[onBehalfOf].index);
uint256 amountToMint = amount + balanceIncrease;

Returns:

return (scaledBalance == 0, amountToMint, totalSupply());

While in LendingPool.borrow():

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

Updates user debt with pre-calculated amount:

user.scaledDebtBalance += scaledAmount;

So for example :

  1. User borrows 100 tokens with index 1e27

    • LendingPool calculates scaledAmount = 100

    • User has previous balance with interest = 10

    • DebtToken mints 110 tokens (100 + 10)

    • LendingPool records only 100 as scaledDebtBalance

  2. Interest Accrual:

    • Index increases to 1.1e27

    • Recorded debt shows 110 (100 * 1.1)

    • Actual debt is 121 (110 * 1.1)

    • 11 token difference untracked

Impact :

  • User's scaledDebtBalance is lower than actual minted tokens and this Gap increases with each interest accrual.

Recommendations :

Update LendingPool's borrow function to use DebtToken's returned values.

Updates

Lead Judging Commences

inallhonesty Lead Judge 7 months ago
Submission Judgement Published
Validated
Assigned finding tags:

LendingPool::borrow tracks debt as user.scaledDebtBalance += scaledAmount while DebtToken mints amount+interest, leading to accounting mismatch and preventing full debt repayment

Support

FAQs

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

Give us feedback!