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:
Users are unable to repay their full debt due to burning more than was originally minted.
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
.
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.
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.
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.
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.