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 7 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 7 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.

Give us feedback!