Core Contracts

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

The protocol unduly inflates user’s debt alway leading to overpayments

Target

contracts/core/tokens/DebtToken.sol

Summary

According to the specification comments, the borrowing and lending mechanism of the protocol aligns with Aave’s implementation, scaling deposit token balances by liquidity index and borrow balances by usage index, however the debt token minting logic deviates from aave’s implementation causing the DebtToken contract to mint more than expected thereby increasing the user’s debt token balance leading to overpayment.

Vulnerability Details

Within Aave, debt tokens minted are only scaled by the reserve index which sets the exchange rate between the tokens and its underlying asset, during debt token minting and burning, if the new index results to an increase in the user’s balance, the new increment is emitted within a mint event.

function _mintScaled(
address caller,
address onBehalfOf,
uint256 amount,
uint256 index
) internal returns (bool) {
uint256 amountScaled = amount.rayDiv(index);
require(amountScaled != 0, Errors.INVALID_MINT_AMOUNT);
uint256 scaledBalance = super.balanceOf(onBehalfOf);
uint256 balanceIncrease = scaledBalance.rayMul(index) -
scaledBalance.rayMul(_userState[onBehalfOf].additionalData);
_userState[onBehalfOf].additionalData = index.toUint128();
_mint(onBehalfOf, amountScaled.toUint128());
uint256 amountToMint = amount + balanceIncrease;
emit Transfer(address(0), onBehalfOf, amountToMint);
emit Mint(caller, onBehalfOf, amountToMint, balanceIncrease, index);
return (scaledBalance == 0);
}

Aave's implementation of scaled token mint function, logic used by both Atoken and debtTokens

However, within the RAAC Debt token contract, if there’s an increase in the debt token balance of a user between the last stored and current index, the increment is added to the amount to be minted to the user, this unduly increases the user’s debt causing the user to be overcharged during repayments

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());
emit Transfer(address(0), onBehalfOf, amountToMint);
emit Mint(user, onBehalfOf, amountToMint, balanceIncrease, index);
return (scaledBalance == 0, amountToMint, totalSupply());
}

DebtToken.mint

Impact

This implementation is wrong as not only does it deviates from Aave’s implementation, it also leads to loss of funds for borrowers, ideally the usage index should should set the exchange rate between the debt token and it’s underlying asset

Tools Used

Manual Review

Recommendations

Refactor the debt token minting logic to only emit balance increments between indices and not add them to the amount to be minted.

Updates

Lead Judging Commences

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

Give us feedback!