Core Contracts

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

Liquidity providers do not earn any interest

Summary

Liquidity providers in LendingPool do not earn any interest due to a logic error when burning rToken

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 this model is not implemented correctly since liquidity providers receive the lent asset in a 1:1 ratio to their rToken
Let's observe RToken.burn

function burn(
address from,
address receiverOfUnderlying,
uint256 amount,
uint256 index
) external override onlyReservePool returns (uint256, uint256, uint256) {
if (amount == 0) {
return (0, totalSupply(), 0);
}
uint256 userBalance = balanceOf(from);
_userState[from].index = index.toUint128();
if(amount > userBalance){
amount = userBalance;
}
uint256 amountScaled = amount.rayMul(index); // @note correctly multiply the rToken balance by the index
_userState[from].index = index.toUint128(); // however the variable remains unused
@> _burn(from, amount.toUint128()); // input amount is burnt
if (receiverOfUnderlying != address(this)) {
@> IERC20(_assetAddress).safeTransfer(receiverOfUnderlying, amount); // @audit-issue user is sent input amount as well, earning 0 interest
}
return (amount, totalSupply(), amount);
}

We can see that the input amount of rToken is burnt and also sent the same amount in USDC. Let's run a simple example:

  1. LP deposits 100 USDC at index 2, receives 50 rUSDC

  2. LP withdraws 50 rUSDC at index 3, receives 50 USDC when they should've received 150 USDC

  3. LP lost 50 USDC from their own money and 50 USDC unpaid interest

The liquidity provider earned no interest but also lost funds

Impact

Loss of funds, broken core functionality

Mitigation

Use amountScaled in the safeTransfer method instead of amount

Updates

Lead Judging Commences

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

RToken::burn transfers original deposit amount (amount) to users instead of amount plus interest (amountScaled), causing loss of all accrued interest on withdrawals

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

RToken::burn transfers original deposit amount (amount) to users instead of amount plus interest (amountScaled), causing loss of all accrued interest on withdrawals

Support

FAQs

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

Give us feedback!