Core Contracts

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

Flawed Liquidity Tracking with `totalVaultDeposits` in LendingPool

Summary

The LendingPool contract incorrectly tracks the liquidity deposited into the Curve Vault using the totalVaultDeposits variable, which does not account for rebasing or negative yield adjustments. This results in potential underestimation or overestimation of available liquidity, leading to unexpected reverts or inefficient liquidity management.

Vulnerability Details

The LendingPool contract attempts to track deposits into the Curve Vault with totalVaultDeposits, which is incremented when liquidity is added and decremented when liquidity is withdrawn:

LendingPool.sol#L795-L812

/**
* @notice Internal function to deposit liquidity into the Curve vault
* @param amount The amount to deposit
*/
function _depositIntoVault(uint256 amount) internal {
IERC20(reserve.reserveAssetAddress).approve(address(curveVault), amount);
curveVault.deposit(amount, address(this));
totalVaultDeposits += amount;
}
/**
* @notice Internal function to withdraw liquidity from the Curve vault
* @param amount The amount to withdraw
*/
function _withdrawFromVault(uint256 amount) internal {
curveVault.withdraw(amount, address(this), msg.sender, 0, new address[](0));
totalVaultDeposits -= amount;
}

Inaccurate Accounting Due to Rebasing`

The Curve Vault rebases balances based on yield and potential losses, meaning the actual balance can be higher or lower than totalVaultDeposits.

  • If totalVaultDeposits overestimates available liquidity, withdrawals can fail when attempting to withdraw more than the rebased amount. This incurs DoS to deposit(), withdraw() and borrow() that internally trigger _withdrawFromVault() via _rebalanceLiquidity() or _ensureLiquidity(), provided partial withdrawal from the Curve vault has been implemented as I have reported separately.

  • If totalVaultDeposits underestimates, funds remain idle instead of being used efficiently. The idling funds could have been used to prevent DoS aforementioned.

Impact

  • Essential functions, i.e. deposit(), withdraw() and borrow() run into unneeded revert risk especially when underestimation is entailed.

  • Such reverts deprive interest rate calculations, indirectly incurring cascading effects relating to reserve liquidity and utilization rates. Hence, any miscalculations foster a delay that propagates to borrow rates, liquidity rates, and user interest rewards, destabilizing the protocol’s core mechanics.

Tools Used

Manual

Recommendations

Eliminate totalVaultDeposits, ensuring withdrawals are based on real available liquidity.

LendingPool.sol#L795-L812

function _depositIntoVault(uint256 amount) internal {
IERC20(reserve.reserveAssetAddress).approve(address(curveVault), amount);
curveVault.deposit(amount, address(this));
- totalVaultDeposits += amount;
}
function _withdrawFromVault(uint256 amount) internal {
+ uint256 actualBalance = IERC20(reserve.reserveAssetAddress).balanceOf(address(this));
+ // Ensure we don't attempt to withdraw more than available
+ if (amount > actualBalance) {
+ amount = actualBalance;
+ }
curveVault.withdraw(amount, address(this), msg.sender, 0, new address[](0));
- totalVaultDeposits -= amount;
}
Updates

Lead Judging Commences

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

LendingPool::totalVaultDeposits can underflow when withdrawing yield-inclusive amounts and vault yield isn't factored into interest rate calculations

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

LendingPool::totalVaultDeposits can underflow when withdrawing yield-inclusive amounts and vault yield isn't factored into interest rate calculations

Support

FAQs

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