Core Contracts

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

`mint` function in RToken contract doesn't return the correct expected values, leading to emission of ReserveLibrary `Deposit` event and LendingPool `Deposit` event with incorrect values.

Summary

The mint function in RToken contract is defined as follows:

function mint(address caller, address onBehalfOf, uint256 amountToMint, uint256 index)
external
override
onlyReservePool
returns (bool, uint256, uint256, uint256)
{
if (amountToMint == 0) {
// @audit: info, should return false, 0, totalSupply(), 0
return (false, 0, 0, 0);
}
uint256 amountScaled = amountToMint.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();
_mint(onBehalfOf, amountToMint.toUint128());
emit Mint(caller, onBehalfOf, amountToMint, index);
return (isFirstMint, amountToMint, totalSupply(), amountScaled);
}

As per the function documentation, return values should be :

* @return A tuple containing:
* - bool: True if this is the first mint for the recipient, false otherwise
* - uint256: The amount of scaled tokens minted
* - uint256: The new total supply after minting
* - uint256: The amount of underlying tokens minted

The problem is that the second return value, which should be the amount of scaled tokens minted (i.e., the amount of RTokens minted), is actually the amount in underlying assets (amountToMint). Also, the fourth should be the amount in underlying assets but the scaled amount in RToken unit is returned.

This means:

return (isFirstMint, amountToMint, totalSupply(), amountScaled); in mint function should be :

return (isFirstMint, amountScaled, totalSupply(), amountToMint);

Consequences of this are wrong data during Deposit event emission in deposit function in ReserveLibrary:

// `deposit` function in ReserveLibrary :
// Mint RToken to the depositor (scaling handled inside RToken)
(bool isFirstMint, uint256 amountScaled, uint256 newTotalSupply, uint256 amountUnderlying) = IRToken(
reserve.reserveRTokenAddress
).mint(
address(this), // caller
depositor, // onBehalfOf
amount, // amount
reserve.liquidityIndex // index
);
amountMinted = amountScaled;
// Update the total liquidity and interest rates
updateInterestRatesAndLiquidity(reserve, rateData, amount, 0);
emit Deposit(depositor, amount, amountMinted);
return amountMinted;

We can see that amountScaled return value (which is actually the amount in underlying asset as we saw previously) is used to set amountMinted. Then, when emitting Deposit event, we pass amount (underlying asset) and amountMinted (underlying asset). Both are actually the same value.

Also, amountMinted is returned from deposit function in ReserveLibrary, but this is incorrect as amountScaled should be returned (see documentation, deposit should return "amountMinted: The amount of RTokens minted.").

This means the deposit function in LendingPool will also emit a wrong Deposit event (note that the double Deposit event emission is another issue):

function deposit(uint256 amount) external nonReentrant whenNotPaused onlyValidAmount(amount) {
// Update the reserve state before the deposit
ReserveLibrary.updateReserveState(reserve, rateData);
// Perform the deposit through ReserveLibrary
uint256 mintedAmount = ReserveLibrary.deposit(reserve, rateData, amount, msg.sender);
// Rebalance liquidity after deposit
_rebalanceLiquidity();
emit Deposit(msg.sender, amount, mintedAmount);
}

Impact

The impact is medium as it leads to incorrect event emission with wrong data, i.e., the amount of RToken minted (scaled amount) is never passed to events. This might break front-end integration.

Tools Used

Manual review.

Recommendations

Make sure to correctly return the amount in underlying asset or in RToken minted. RToken should return:

return (isFirstMint, amountScaled, totalSupply(), amountToMint);
Updates

Lead Judging Commences

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

RToken::mint doesn't return data in the right order, making the protocol emit wrong events

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

RToken::mint doesn't return data in the right order, making the protocol emit wrong events

Support

FAQs

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