Core Contracts

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

`mint` function in DebtToken contract systematically mints too many debt tokens, leading to loss of funds for all borrowers.

Summary

mint function in DebtToken contract is defined as follows:

function mint(address user, address onBehalfOf, uint256 amount, uint256 index)
external
override
onlyReservePool
returns (bool, uint256, uint256)
{
if (user == address(0) || onBehalfOf == address(0)) revert InvalidAddress();
if (amount == 0) {
return (false, 0, totalSupply());
}
uint256 amountScaled = amount.rayDiv(index);
if (amountScaled == 0) revert InvalidAmount();
uint256 scaledBalance = balanceOf(onBehalfOf);
bool isFirstMint = scaledBalance == 0;
uint256 balanceIncrease = 0;
if (_userState[onBehalfOf].index != 0 && _userState[onBehalfOf].index < index) {
balanceIncrease = scaledBalance.rayMul(index) - scaledBalance.rayMul(_userState[onBehalfOf].index);
}
_userState[onBehalfOf].index = index.toUint128();
// @audit HIGH: only amountToMint should be minted, leads to systematic minting of too many debt tokens for borrowers
uint256 amountToMint = amount + balanceIncrease;
_mint(onBehalfOf, amountToMint.toUint128());
emit Transfer(address(0), onBehalfOf, amountToMint);
emit Mint(user, onBehalfOf, amountToMint, balanceIncrease, index);
return (scaledBalance == 0, amountToMint, totalSupply());
}

We can see that _mint internal function will mint amountToMint tokens. This is problematic because amountToMint is computed like this:

uint256 amountToMint = amount + balanceIncrease;

This is incorrect to add the balance increase to the amount to mint. Only amountScaled should be passed to _mint(scaling to effective debt token by dividing by the usage index).


When looking at AAVE implementation of aToken (ScaledBalanceTokenBase contract), we clearly see that only the amount is minted, and balanceIncrease, representing the increase of token balance between current index and last registered index for the user, is only used for event emission.

All this means the amount of debt tokens minted is way too high, given that amount is not scaled down as it should (divided by index) and we add also balanceIncrease.

Impact

The impact of this issue is high, as it leads to systematic minting of too many debt tokens for all users that borrow against their collateral.

Tools Used

Manual review.

Recommendations

Make sure to mint the right amount of debt token when users borrow through the lending pool:

function mint(address user, address onBehalfOf, uint256 amount, uint256 index)
external
override
onlyReservePool
returns (bool, uint256, uint256)
{
...
uint256 amountScaled = amount.rayDiv(index);
if (amountScaled == 0) revert InvalidAmount();
...
_mint(onBehalfOf, amountScaled);
...
}
Updates

Lead Judging Commences

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

DebtToken::mint miscalculates debt by applying interest twice, inflating borrow amounts and risking premature liquidations

Support

FAQs

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