Core Contracts

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

The accrued interest or the accrued rTokens are computed but never minted to the user when he/she deposits reserveAssets

Summary

The user uses the deposit function to deposit crvUsd and in exchange rTokens are minted to the depositor. The amount of rTokens that the user is supposed to get minted varies accordingly depending on the index.

Vulnerability Details

The user uses the deposit function to deposit crvUsd and in exchange rTokens are minted to the depositor. The amount of rTokens that the user is supposed to get minted varies accordingly depending on the index of the user i.e UserState.index and the global liquidity index. This liquidityIndex variiable is updated everytime a function is called in the LendingPool contract whether that function be deposit , withdraw , borrow , repay or any other function that user interacts with in the LendingPool and same goes for the UserState.index is also updated in almost very transaction and it is updated along with the global liquidity index via ReserveLibrary.updateReserveState function and the mint function in the RToken contract. Now when the user deposits reserveAssets i.e crvUsd using the deposit function, he is supposed get minted rtokens and the amount of RTokens that the user should get minted will initially be 1:1 but as the liquidityIndex accrues the rTokens that are to be minted to the user must change. Now these RTokens that should be minted along with the interest accrued are computed here in the mint function of the RToken.sol. However, the issue that arises here is that even though these accrued tokens are computed, they are not minted to the user. instead the RTokens which get minted to the user are minted 1:1 with the deposited amount which is not the intended behaviour because- The deposit-to-rToken ratio is not always 1:1 and can change over time. This ratio is influenced by the liquidity index, which represents the cumulative interest accrued over time. When users deposit assets, they receive rTokens based on the current liquidity index. As interest accrues, the value of each rToken increases, . And as can be seen in the mint function, the balanceIncrease is being calculated depending on the liquidityIndex but when the tokens are minted in the end of the function this balanceIncrease is not being included there and this will lead to the user getting less amount tokens than he is supposed to get.

Also Note that this same vulnerability will also cause problems in the withdraw function too as the user deposits and when they withdraw they are supposed to get back the deposited amount along with the interest accrued on that amount, the user will not get the accrued part because of the reasons given above i.e the balanceIncrease is computed but that amount of rTokens is never minted to the user

Impact

Even though the user is depositing their funds n the protocol to provide with liquidity, in return they are not fully getting the amount of tokens that they are supposed to get. For example- lets assume the user deposits - 100e18 for the first time and his index is updated to 1e27 which is the initial index, then some time passes maybe a few weeks after the same user comes again and deposits 200e18 tokens, this time the liquidityIndex = 1.1e27 and userIndex=1e27 from before, the balance increase is computed as- balanceIncrease =scaledBalance.rayMul(index) -scaledBalance.rayMul(_userState[onBehalfOf].index); scaledBal here will be 100e18 which the user deposited for the first time so- balIncrease = 100e18.ray*(1.1e27) - 100e18.rayMul(1e27) = 10e18 Now 200e18 + balance increase = 210e18 but the user only gets minted amountToMint i.e 200e18

Tools Used

Manual Review

Recommendations

when minting the rTokens instead of only passing amountToMint in the ERC20 _mint function add the balanceIncrease var along with it too like this:-
_mint(onBehalfOf, balanceIncrease + amountToMint.toUint128());

Code Snippets

function deposit(ReserveData storage reserve,ReserveRateData storage rateData,uint256 amount,address depositor) internal returns (uint256 amountMinted) {
if (amount < 1) revert InvalidAmount();
// Update reserve interests
updateReserveInterests(reserve, rateData);
// Transfer asset from caller to the RToken contract
IERC20(reserve.reserveAssetAddress).safeTransferFrom(
msg.sender, // from
reserve.reserveRTokenAddress, // to
amount // amount
);
// 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
);```
function mint(
address caller,
address onBehalfOf,
uint256 amountToMint,
uint256 index
) external override onlyReservePool returns (bool, uint256, uint256, uint256) {
if (amountToMint == 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()); //<-AUDIT- does not include the accrued balanceIncrease computed above
Updates

Lead Judging Commences

inallhonesty Lead Judge 7 months ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement
Assigned finding tags:

RToken::mint calculates balanceIncrease (interest accrued since last interaction) but never mints it, causing users to lose earned interest between deposits

The balanceIncrease is the interest that has already accrued on the user's existing scaledBalance since their last interaction. It's not something you mint as new tokens in the _mint function.

inallhonesty Lead Judge 7 months ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement
Assigned finding tags:

RToken::mint calculates balanceIncrease (interest accrued since last interaction) but never mints it, causing users to lose earned interest between deposits

The balanceIncrease is the interest that has already accrued on the user's existing scaledBalance since their last interaction. It's not something you mint as new tokens in the _mint function.

Support

FAQs

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

Give us feedback!