Core Contracts

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

EnsureLiquidity is not working correctly

Summary

During the withdraw and borrow operations, the LendingPool attempts to ensure sufficient liquidity by withdrawing funds from the curveVault. However, the current implementation contains a logical flaw that causes the transaction to revert.

function withdraw(uint256 amount) external nonReentrant whenNotPaused onlyValidAmount(amount) {
if (withdrawalsPaused) revert WithdrawalsArePaused();
// Update the reserve state before the withdrawal
ReserveLibrary.updateReserveState(reserve, rateData);
// Ensure sufficient liquidity is available
_ensureLiquidity(amount); // Issue: `amount` is not deducted from available liquidity
// Perform the withdrawal through ReserveLibrary
(uint256 amountWithdrawn, uint256 amountScaled, uint256 amountUnderlying) = ReserveLibrary.withdraw(
reserve, // ReserveData storage
rateData, // ReserveRateData storage
amount, // Amount to withdraw
msg.sender // Recipient
);
// Rebalance liquidity after withdrawal
_rebalanceLiquidity();
emit Withdraw(msg.sender, amountWithdrawn);
}
function _ensureLiquidity(uint256 amount) internal {
// If the Curve vault is not set, do nothing
if (address(curveVault) == address(0)) {
return;
}
uint256 availableLiquidity = IERC20(reserve.reserveAssetAddress).balanceOf(reserve.reserveRTokenAddress);
if (availableLiquidity < amount) {
uint256 requiredAmount = amount - availableLiquidity;
// Withdraw the required amount from the Curve vault
_withdrawFromVault(requiredAmount);
}
}

Vulnerability Details

Scenario

  1. A user attempts to withdraw 100 assets from the LendingPool.

  2. The reserveRTokenAddress only holds 90 assets.

  3. The _ensureLiquidity function withdraws the missing 10 assets from the curveVault and sends them directly to the msg.sender.

  4. The ReserveLibrary.withdraw function then attempts to withdraw 100 assets from the reserveRTokenAddress, which will revert because only 90 assets remain.

Root Cause

The _ensureLiquidity function does not account for the fact that the withdrawn funds from the curveVault are sent directly to the user, rather than being added to the reserveRTokenAddress. As a result, the subsequent withdrawal from reserveRTokenAddress fails due to insufficient balance.


Impact

  • Incorrect Accounting: The logic fails to properly account for the liquidity adjustment, leading to a mismatch between expected and actual balances.

  • Transaction Reverts: The withdrawal operation will always revert when additional liquidity is required from the curveVault, rendering the function unusable in such cases.


Tools Used

Manual review.


Recommendations

Modify the _ensureLiquidity function to ensure the withdrawn funds from the curveVault are added to the reserveRTokenAddress before proceeding with the withdrawal.

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.