Core Contracts

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

Wrong `_mint` input enables theft of funds

Summary

Depositing in LendingPool does not take into consideration the liquidity index and mints rToken at a 1:1 ratio, which then can be redeemed continuously until the pool is drained

Details

The protocol uses liquidity index to track interest accrual in the lending pool, identical to how Curve finance does it. It works the following way:

  1. User provides 100 USDC at index = 2 and receives 100/2 = 50 rUSDC

  2. At index = 3 user has accrued 50% in interest and decides to withdraw

  3. Withdrawal amount = rTokens * index = 50 * 3 = 150 USDC

However, it is implemented incorrectly here due to the user being minted rTokens at a constant 1:1 ratio.

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); // @note divides as it should
if (amountScaled == 0) revert InvalidAmount(); // however it does not use this value at all
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-issue original amount to mint is just passed here
return (isFirstMint, amountToMint, totalSupply(), amountScaled);
}

From the snippet above we see that if a user deposits 100 USDC they will always receive 100 rUSDC, regardless of the index.
Malicious actors can abuse this and perform deposit-withdraw attacks.

  1. Deposit 100 USDC at index 2, receive 100 rUSDC

  2. Withdraw 100 rUSDC at index 2, receive 200 USDC

  3. Repeat steps 1 and 2

Impact

Protocol is drained

Mitigation

Pass amountScaled in _mint instead of amountToMint

Updates

Lead Judging Commences

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

RToken::mint should mint the amountScaled not the amountToMint

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

RToken::mint should mint the amountScaled not the amountToMint

Support

FAQs

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

Give us feedback!