Core Contracts

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

LendingPool liquidity balance

Summary

The LendingPool contract is checking liquidity at one address (reserve.reserveRTokenAddress - the RToken contract) but actually performing transfers using a different address (address(this) - the LendingPool contract).

Vulnerability Details

  • In _ensureLiquidity, the code checks the balance at reserve.reserveRTokenAddress:

function _ensureLiquidity(uint256 amount) internal {
// if curve vault is not set, do nothing
if (address(curveVault) == address(0)) {
return;
}
// here checking balance of RToken address
uint256 availableLiquidity = IERC20(reserve.reserveAssetAddress).balanceOf(reserve.reserveRTokenAddress);
if (availableLiquidity < amount) {
uint256 requiredAmount = amount - availableLiquidity;
// Withdraw required amount from the Curve vault
_withdrawFromVault(requiredAmount);
}
}
  • Similarly in _rebalanceLiquidity, it checks the balance at reserve.reserveRTokenAddress:

uint256 currentBuffer = IERC20(reserve.reserveAssetAddress).balanceOf(reserve.reserveRTokenAddress);

  • However, in the vault operations, the transfers are happening to/from address(this) (LendingPool):

function _depositIntoVault(uint256 amount) internal {
IERC20(reserve.reserveAssetAddress).approve(address(curveVault), amount);
curveVault.deposit(amount, address(this)); // deposits to LendingPool
totalVaultDeposits += amount;
}
function _withdrawFromVault(uint256 amount) internal {
curveVault.withdraw(amount, address(this), msg.sender, 0, new address[](0)); // withdraws to LendingPool
totalVaultDeposits -= amount;
}

Impact

This is indeed a critical issue because:

  1. The contract is checking liquidity at one address (reserve.reserveRTokenAddress - the RToken contract) but actually performing transfers using a different address (address(this) - the LendingPool contract).

  2. This mismatch means that:

    • The liquidity checks could indicate sufficient funds when there aren't any at the actual transfer location

    • The liquidity checks could indicate insufficient funds when there are actually funds available at the transfer location

    • The rebalancing logic would be operating on incorrect balance information

  3. This could lead to:

    • Failed transfers due to insufficient funds

    • Incorrect rebalancing decisions

    • Potential lockup of funds in either contract

Tools Used

Manual code review

Recommendations

Changing the vault deposit/withdraw operations to use reserve.reserveRTokenAddress as the source/destination

Updates

Lead Judging Commences

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

LendingPool::_depositIntoVault and _withdrawFromVault don't transfer tokens between RToken and LendingPool, breaking Curve vault interactions

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

LendingPool::_depositIntoVault and _withdrawFromVault don't transfer tokens between RToken and LendingPool, breaking Curve vault interactions

Support

FAQs

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