Core Contracts

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

`DebtToken::burn` Incorrect Debt Token Burning Amount Allows Users to Repay Less Than Required

Summary

The DebtToken::burn function burns the unscaled amount when it should be burning the scaled amount allowing users to repay less than they should when interest has accrued on their debt.

Vulnerability Details

[](https://github.com/Cyfrin/2025-02-raac/blob/89ccb062e2b175374d40d824263a4c0b601bcb7f/contracts/core/tokens/DebtToken.sol#L206)

[](https://github.com/Cyfrin/2025-02-raac/blob/89ccb062e2b175374d40d824263a4c0b601bcb7f/contracts/core/pools/LendingPool/LendingPool.sol#L375)

Inside DebtToken::burn when we call _burn we pass in the amount from the parameter, and this value is the unscaled version which does not account for any interest that has accrued, which in return when calling LendingPool::repay to pay off their debt, they won't suffer from any of the interest.

uint256 amountScaled = amount.rayDiv(index);
if (amountScaled == 0) revert InvalidAmount();
// should be amountScaled from above
@> _burn(from, amount.toUint128());
emit Burn(from, amountScaled, index);

You can also see the event is expecting amountScaled to be burned.

Example:
User borrows 100 tokens (index = 1e27)
After interest accrues (index = 2e27), debt is worth 200 tokens
User tries to repay 50 tokens
Should burn 25 debt tokens (50/2 due to index doubling)
But burns 50 tokens instead, getting 2x value for their repayment

Impact

Users can repay their debt without properly accounting for accrued interest, allowing them to pay significantly less than they should. This leads to protocol value loss as interest payments are effectively discounted.

Tools Used

Foundry

Recommendations

Inside DebtToken::burn fix the call to _burn to pass in amountScaled like so:

function burn(
address from,
uint256 amount,
uint256 index
) external override onlyReservePool returns (uint256, uint256, uint256, uint256) {
....
if(amount > userBalance){
amount = userBalance;
}
uint256 amountScaled = amount.rayDiv(index);
if (amountScaled == 0) revert InvalidAmount();
- _burn(from, amount.toUint128());
+ _burn(from, amountScaled.toUint128());
}
Updates

Lead Judging Commences

inallhonesty Lead Judge about 2 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 about 2 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.