Core Contracts

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

Incorrect Liquidity Withdrawal Target in _ensureLiquidity() Function

Summary

The _ensureLiquidity() function in LendingPool.sol is responsible for ensuring that enough liquidity is available when a user borrows or withdraws funds. When liquidity is insufficient, it calls _withdrawFromVault() to retrieve funds from the CurveVault(part of the user deposits are send there). The issue arises because the withdrawn funds are sent to the LendingPool.sol contract instead of RToken.sol, which is responsible for transferring funds to users.

Vulnerability Details

The function _ensureLiquidity() checks if there is enough liquidity in the RToken contract before processing a withdrawal:

uint256 availableLiquidity = IERC20(reserve.reserveAssetAddress).balanceOf(reserve.reserveRTokenAddress)

If there is insufficient liquidity, it calculates the shortfall:

uint256 requiredAmount = amount - availableLiquidity;

Then, _withdrawFromVault(requiredAmount); is called to withdraw the missing funds from CurveVault.

The _withdrawFromVault() function sends the funds to LendingPool.sol instead of RToken.sol, meaning the borrowed funds do not reach users.

Incorrect Behavior Flow

  1. User requests a withdrawal_ensureLiquidity(amount) is called.

  2. Liquidity check fails_withdrawFromVault(requiredAmount) is executed.

  3. Funds are sent to LendingPool.sol instead of RToken.sol.

  4. Withdrawal fails because RToken.sol does not receive the necessary funds.

Impact

Transaction failures: Users will experience reverts when trying to withdraw or borrow if the RToken.sol contract does not have sufficient funds.

Potential fund mismanagement: Funds sitting in LendingPool.sol instead of RToken.sol can cause accounting mismatches.

Tools Used

manual review

Recommendations

Modify _withdrawFromVault() to send funds directly to RToken.sol:

Original function:
function _withdrawFromVault(uint256 amount) internal {
curveVault.withdraw(amount, address(this), msg.sender, 0, new address[](0));
totalVaultDeposits -= amount;
}
Corrected function:
function _withdrawFromVault(uint256 amount) internal {
curveVault.withdraw(amount, reserve.reserveRTokenAddress, reserve.reserveRTokenAddress, 0, new address[](0));
totalVaultDeposits -= amount;
}
Updates

Lead Judging Commences

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

LendingPool::_withdrawFromVault incorrectly uses msg.sender instead of address(this) as the owner parameter, causing vault withdrawals to fail

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

LendingPool::_withdrawFromVault incorrectly uses msg.sender instead of address(this) as the owner parameter, causing vault withdrawals to fail

Support

FAQs

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