Core Contracts

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

Incorrect function calls to curve vault prevent liquidity rebalancing and withdrawals

Summary

The LendingPool contract attempts to interact with a Curve vault through function calls to deposit and withdraw. However, the Curve vault does not implement these functions. Instead, the correct functions for liquidity management are add_liquidity and remove_liquidity. As a result, any attempt to rebalance liquidity or withdraw funds from the Curve vault will fail due to calling non-existent functions. This leads to a denial of service (DoS) for users attempting to withdraw, as the _ensureLiquidity function relies on these failed interactions to replenish liquidity.

Vulnerability Details

Incorrect Function Calls to Curve Vault

The LendingPool contract calls deposit and withdraw when interacting with the Curve vault:

function _depositIntoVault(uint256 amount) internal {
IERC20(reserve.reserveAssetAddress).approve(address(curveVault), amount);
curveVault.deposit(amount, address(this)); // Incorrect function call
totalVaultDeposits += amount;
}
function _withdrawFromVault(uint256 amount) internal {
curveVault.withdraw(amount, address(this), msg.sender, 0, new address ); // Incorrect function call
totalVaultDeposits -= amount;
}

However, the Curve vault does not have deposit or withdraw functions. Instead, it uses:

  • add_liquidity(...) to deposit assets

  • remove_liquidity(...) to withdraw assets

Since the LendingPool contract is calling functions that do not exist, these operations will revert, preventing liquidity management functions from executing correctly.

Impact on _ensureLiquidity

The _ensureLiquidity function depends on _withdrawFromVault to source liquidity when needed:

function _ensureLiquidity(uint256 amount) internal {
uint256 availableLiquidity = IERC20(reserve.reserveAssetAddress).balanceOf(reserve.reserveRTokenAddress);
if (availableLiquidity < amount) {
uint256 requiredAmount = amount - availableLiquidity;
_withdrawFromVault(requiredAmount); // This call will revert
}
}

Since _withdrawFromVault reverts, _ensureLiquidity fails to provide additional liquidity when needed, which directly impacts user withdrawals.

Impact on _rebalanceLiquidity

Similarly, _rebalanceLiquidity attempts to call _depositIntoVault or _withdrawFromVault, both of which will revert:

function _rebalanceLiquidity() internal {
uint256 totalDeposits = reserve.totalLiquidity;
uint256 desiredBuffer = totalDeposits.percentMul(liquidityBufferRatio);
uint256 currentBuffer = IERC20(reserve.reserveAssetAddress).balanceOf(reserve.reserveRTokenAddress);
if (currentBuffer > desiredBuffer) {
uint256 excess = currentBuffer - desiredBuffer;
_depositIntoVault(excess); // Will revert
} else if (currentBuffer < desiredBuffer) {
uint256 shortage = desiredBuffer - currentBuffer;
_withdrawFromVault(shortage); // Will revert
}
}

Since neither _depositIntoVault nor _withdrawFromVault functions work, liquidity cannot be managed, leading to imbalances that could cause further system failures.

Proof-of-Concept (PoC)

  1. Deploy the LendingPool contract with a mocked Curve vault.

  2. Call withdraw(amount) when liquidity is insufficient in the RToken contract.

  3. Observe that _ensureLiquidity attempts to call _withdrawFromVault, which reverts.

  4. Similarly, attempt to trigger _rebalanceLiquidity and observe that calls to _depositIntoVault and _withdrawFromVault revert.

  5. Confirm that users cannot withdraw their funds due to the DoS condition.

Impact

  • User Withdrawals Fail (DoS): Since _ensureLiquidity cannot source additional liquidity, user withdrawals will fail if the reserve does not have enough available funds.

  • Liquidity Rebalancing Fails: The contract is unable to move funds between the buffer and Curve vault, leading to liquidity mismanagement.

  • Protocol Funds Are Locked: If excess liquidity is supposed to be deposited into Curve but cannot be retrieved, it could lead to funds being permanently inaccessible.

  • Contract Reverts Unexpectedly: Any function relying on _depositIntoVault or _withdrawFromVault will fail, potentially affecting broader system functionality.

Tools Used

Manual review

Recommendations

  1. Update Function Calls to Match Curve Vault API:

    • Replace deposit(amount, address(this)) with the correct add_liquidity(...) function.

    • Replace withdraw(amount, address(this), msg.sender, 0, new address ) with the correct remove_liquidity(...) function.

  2. Implement Compatibility Checks:

    • Validate that the contract implements the expected Curve vault interface before attempting function calls.

    • Use try/catch blocks to gracefully handle failures.

Updates

Lead Judging Commences

inallhonesty Lead Judge 6 months ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

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