Core Contracts

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

Incorrect return value handling in `RToken::mint` -`ReserveLibrary::Deposit` flow

Summary

The RToken::mint function returns amountToMint (unscaled value) in its second return parameter while the ReserveLibrary::deposit function processing this value assuming it's amountScaled. This mismatch creates an accounting inconsistency since the system internally works with scaled values to handle interest-bearing tokens correctly.

Vulnerability Details

function mint(
address caller,
address onBehalfOf,
uint256 amountToMint,
uint256 index
) external override onlyReservePool returns (bool, uint256, uint256, uint256) {
... omitted code
_mint(onBehalfOf, amountToMint.toUint128());
emit Mint(caller, onBehalfOf, amountToMint, index);
@> return (isFirstMint, amountToMint, totalSupply(), amountScaled);
}
function deposit(ReserveData storage reserve,ReserveRateData storage rateData,uint256 amount,address depositor) internal returns (uint256 amountMinted) {
...omitted code
// 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;
}

Impact

The RToken::mint function returns amountToMint (unscaled value) in its second return parameter while the ReserveLibrary::deposit function processing this value assuming it's amountScaled. This value is assigned to a variable and returned to Lendingpool::deposit. This leads to incorrect accounting of user shares in the protocol.

Tools Used

Manual review

Recommendations

Modify the parameters order as:

function deposit(ReserveData storage reserve,ReserveRateData storage rateData,uint256 amount,address depositor) internal returns (uint256 amountMinted) {
...omitted code
// Mint RToken to the depositor (scaling handled inside RToken)
- (bool isFirstMint, uint256 amountScaled, uint256 newTotalSupply, uint256 amountUnderlying) = IRToken(reserve.reserveRTokenAddress).mint(
+ (bool isFirstMint, uint256 amountUnderlying, uint256 newTotalSupply, uint256 amountScaled) = 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;
}
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.