Core Contracts

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

Incorrect `amountToMint` calculation in DebtToken::mint()

Summary

Incorrect amountToMint calculation in DebtToken::mint()

Vulnerability Details

In DebtToken::mint(), we will mint debt token for the borrowers. In the mint() function, we will calculate the borrow interest from last borrow timestamp to current block.timestamp and mint the debt token for these borrow interest. This is incorrect. We should not mint any extra debt tokens for these borrow interest. Because the debt token is the normalized token.

Although we mint more debt token for the borrower, this will not have the impact for the borrower's position's health status. Because we will use user.scaledDebtBalance to record the normalization debt in lending pool.

The actual impact here is that we mint more debt token than expected. And we will use the debt token's totalSupply to record the reserve.totalUsage. And we will use reserve.totalUsage to record the asset utilization. This will cause that the asset utilization is higher than expected, because we have one higher total debt than expected.

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();
uint256 amountToMint = amount + balanceIncrease;
_mint(onBehalfOf, amountToMint.toUint128());
return (scaledBalance == 0, amountToMint, totalSupply());
}
function getUserDebt(address userAddress) public view returns (uint256) {
UserData storage user = userData[userAddress];
return user.scaledDebtBalance.rayMul(reserve.usageIndex);
}
function borrow(uint256 amount) external nonReentrant whenNotPaused onlyValidAmount(amount) {
(bool isFirstMint, uint256 amountMinted, uint256 newTotalSupply) = IDebtToken(reserve.reserveDebtTokenAddress).mint(msg.sender, msg.sender, amount, reserve.usageIndex);
reserve.totalUsage = newTotalSupply; // total debt amount.
}

Impact

The utilization may be higher than expected. Borrowers need to pay more interest than expected.

Tools Used

Manual

Recommendations

Do not mint the debt token for the accrued borrow intereset.

Updates

Lead Judging Commences

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