Core Contracts

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

Debt token should burn scaled amounts

Vulnerability Details

In DebtToken::burn(), the token amount passed to _burn() is a normal token amount, which is incorrect. It must be the scaled amount to properly account for historically accrued debt. This leads to incorrect debt payments, causing users to be unable to repay their actual full debt, as the correct amount should be calculated using rayDiv().

For example, when a user calls LendingPool::borrow(), the borrowed amount should be divided by the index using rayDiv() to adjust for previously accrued interest.

Therefore, when burning debt, the user must burn the scaled amount to maintain consistency in unit calculations.

For interest-bearing tokens tracked using an index-based system—such as DebtToken, which mirrors AAVE’s debt tokens—the burn amount must be divided by the index using rayDiv() to ensure proper unit alignment and maintain coherence in index-based math. These types of tokens are referred to as ScaledBalanceTokens in AAVE, and both aToken and debtToken inherit from the same base contract, named accordingly.

Another explanation of why VariableDebt burning must follow this logic can be found in the AAVE book here.

Additionally, you can verify in the AAVE VariableDebtToken implementation that the burn amount should be the scaled amount:

  • See the relevant contract lines here, which are inherited by VariableDebtToken here.


Impact

Users are unable to repay their full debt due to burning more than was originally minted.

Example: Borrowing and Repaying 1,000 USDC

Step 1: Borrowing 1,000 USDC

Time Scaled Debt Index Actual Debt (Scaled Debt × Index)
Start 1,000 1.0 1,000 USDC

At this point:

  • The scaled debt is 1,000.

  • The index is 1.0, so the actual debt is also 1,000 USDC.

  • The scaled balance is calculated as 1000 / 1 = 1000.

Step 2: Interest Accrues Over Time

After some time, the index increases to 1.1 due to accrued interest.

Time Scaled Debt Index Actual Debt
Later 1,000 1.1 1,100 USDC

Now:

  • The scaled debt remains 1,000.

  • The actual debt increases to 1,100 USDC due to interest accrual.

Step 3: Repaying Debt (Burning Scaled Amounts)

  • When repaying 1,100 USDC, the correct scaled amount must be burned, which was initially divided by the index to avoid carrying forward historical interest.

  • If you attempt to repay 1100 USDC and thus burn 1100 USDC, the system will attempt to subtract 1,100 from 1,000, leading to an underflow and revert.


Recommendations

The DebtToken::burn() function must burn a scaledAmount, similar to the already calculated amount a few lines earlier in the contract.
See the related code section here.

Updates

Lead Judging Commences

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

DebtToken::burn incorrectly burns amount (asset units) instead of amountScaled (token units), breaking token economics and interest-accrual mechanism

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

DebtToken::burn incorrectly burns amount (asset units) instead of amountScaled (token units), breaking token economics and interest-accrual mechanism

Support

FAQs

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