Core Contracts

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

Burn of debt tokens by users through `transfer` ERC20 function is not prevented, major risk of impossibility to repay debt with collateral stuck.

Summary

As currently designed, transfer and transferfrom functions are not overridden and exposed normally in DebtToken contract.

On the other hand, _update function has been overridden as follows:

function _update(address from, address to, uint256 amount) internal virtual override {
if (from != address(0) && to != address(0)) {
revert TransfersNotAllowed(); // Only allow minting and burning
}
uint256 scaledAmount = amount.rayDiv(ILendingPool(_reservePool).getNormalizedDebt());
super._update(from, to, scaledAmount);
emit Transfer(from, to, amount);
}

The check added makes sure no transfer from a non zero address to a non zero address is possible. The purpose of this check is to make sure debt tokens are non-transferrable.

Users should not be allowed to transfer such tokens, neither should be to burn them. Only the lending pool should be able to burn debt tokens when repaying debt.

Nevertheless, any user is still able to call transfer function, sending its own debt token to the 0 address. This is equivalent to burning and should not be allowed.

Vulnerability Details

The problem arises because any user could accidentally, or because of a scam, burn his own debt token, making it impossible to repay debt because attempts to burn debt token will fail.

Impact

The impact of this vulnerability is high, given that allowing direct burning of debt tokens can lead to impossibility to repay debt and collateral stuck, with potentially collateral liquidated if house price stays stable once debt has increased enough.

Tools Used

Manual review.

Recommendations

One potential fix for this issue would be to modify the _update function to make sure burning is only allowed when the caller is the lending pool:

function _update(address from, address to, uint256 amount) internal virtual override {
if (from != address(0) && to != address(0)) {
revert TransfersNotAllowed();
}
// For burning (to = address(0)), only allow if called by the protocol
if (to == address(0) && msg.sender != _reservePool) {
revert();
}
uint256 scaledAmount = amount.rayDiv(ILendingPool(_reservePool).getNormalizedDebt());
super._update(from, to, scaledAmount);
emit Transfer(from, to, amount);
}

Another solution (AAVE approach) would be to override all ERC20 functions needed (transfer, transferFrom, approve etc) and make them revert by default.

Updates

Lead Judging Commences

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

DebtToken permits burning via transfer to address(0), breaking protocol accounting and making debt repayment impossible, permanently locking collateral

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

DebtToken permits burning via transfer to address(0), breaking protocol accounting and making debt repayment impossible, permanently locking collateral

Support

FAQs

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