Core Contracts

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

Incorrect Vault Withdrawal Parameters Cause Protocol-Wide DOS

Summary

The LendingPool._withdrawFromVault() function uses incorrect parameters when calling the Curve vault's withdraw function, passing address(this) as receiver and msg.sender as owner. This mismatch causes all vault withdrawals to revert, effectively blocking borrows, withdrawals, and sometimes deposits when the vault is configured.

Vulnerability Details

The issue occurs in the _withdrawFromVault function which is critical for managing liquidity between the lending pool and Curve vault , the function calls the ICurveCrvUSDVault withdraw function and the parameters passed to it are:

function _withdrawFromVault(uint256 amount) internal {
// @audit-issue: Incorrect receiver and owner parameters
curveVault.withdraw(
amount,
address(this), // Should be rToken address
msg.sender, // Should be address(this)
0,
new address[](0)
);
totalVaultDeposits -= amount;
}
  • and as we can see from the ICurveCrvUSDVault interface , the withdraw function has the following parameters:

/**
* @notice Withdraws assets from the vault
* @param assets Amount of assets to withdraw
* @param receiver Address to receive the assets
* @param owner Owner of the shares
* @param maxLoss Maximum acceptable loss in basis points
* @param strategies Optional specific strategies to withdraw from
* @return shares Amount of shares burned
*/
function withdraw(
uint256 assets,
address receiver,
address owner,
uint256 maxLoss,
address[] calldata strategies
) external returns (uint256 shares);

the params passed to the withdraw function call in _withdrawFromVault are wrong , and will lead to a revert.

  1. Incorrect Receiver , as the receiver is set to the LendingPool address , while tokens are sent from the rToken address:

// Current implementation
address receiver = address(this); // LendingPool address
// However, the assets are actually sent from rToken:
// In borrow():
rToken.transfer(msg.sender, amount);
// In withdraw():
rToken.transfer(msg.sender, amount);
  1. Incorrect Owner:

// Current implementation
address owner = msg.sender; // Random user address
// Should be:
address owner = address(this); // LendingPool is the actual owner

This function is called in critical liquidity management flows inside the _insureLiquidity , and _rebalanceLiquidity functions:

function _insureLiquidity(uint256 amount) internal {
if (rToken.balanceOf(address(rToken)) < amount) {
_withdrawFromVault(amount); // Will revert
}
}
function _rebalanceLiquidity() internal {
.....
else if (currentBuffer < desiredBuffer) {
uint256 shortage = desiredBuffer - currentBuffer;
// Withdraw shortage from the Curve vault
_withdrawFromVault(shortage);
}
}
  • the following flows are broken :

// Called in:
1. borrow() --> _insureLiquidity()--> _withdrawFromVault()
2. withdraw() --> _insureLiquidity()--> _withdrawFromVault()
3. deposit() --> _rebalanceLiquidity()--> _withdrawFromVault()

Impact

  • All borrows requiring vault liquidity will revert

  • All withdrawals requiring vault liquidity will revert

  • Deposits may revert during rebalancing

  • Protocol cannot access vault liquidity when needed

Tools Used

  • Manual code review

Recommendations

Fix the parameter order in _withdrawFromVault:

function _withdrawFromVault(uint256 amount) internal {
curveVault.withdraw(
amount,
- address(this),
+ address(rToken), // Correct receiver - where assets should go
- msg.sender,
+ address(this), // Correct owner - LendingPool owns the shares
0,
new address[](0)
);
totalVaultDeposits -= amount;
}
Updates

Lead Judging Commences

inallhonesty Lead Judge 6 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

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

inallhonesty Lead Judge 6 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

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.