Core Contracts

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

Incorrect Handling of Vault Withdrawal Return Value Leading to Liquidity Accounting Errors

Summary

The LendingPool contract integrates with a Curve crvUSD Vault to manage liquidity. During the withdrawal process, the contract incorrectly subtracts a fixed withdrawal amount from the internal tracking variable (totalVaultDeposits) instead of using the actual number of vault shares burned. This discrepancy in accounting can lead to liquidity mismatches over time, potentially impacting the accurate tracking of deposited funds.

Vulnerability Details

In the _withdrawFromVault function, the contract invokes the vault's withdraw method with a fixed withdrawal amount and immediately subtracts that amount from totalVaultDeposits:

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

However, the vault's withdraw method returns the actual amount of shares (or tokens) that were burned during the withdrawal. This value may differ from the nominal amount requested due to factors such as share conversion rates, rounding errors, or other internal vault calculations. Not capturing this return value leads to incorrect subtraction from totalVaultDeposits, causing an inaccurate reflection of the actual vault liquidity.

The correct integration—as demonstrated in the reference implementation from Curve's VaultV3—requires capturing the returned value from the withdraw call and using it to update totalVaultDeposits accordingly:

function _depositIntoVault(uint256 amount) internal {
IERC20(reserve.reserveAssetAddress).approve(address(curveVault), amount); // asset is crveVault
uint256 sharesMint = curveVault.deposit(amount, address(this));
totalVaultDeposits += sharesMint;
}
function _withdrawFromVault(uint256 amount) internal {
uint256 sharesBurnt = curveVault.withdraw(amount, address(this), msg.sender, 0, new address[](0));
totalVaultDeposits -= sharesBurnt;
}

Impact

Incorrect updating of totalVaultDeposits can result in an inaccurate representation of the actual liquidity held in the vault.

Tools Used

Manual Code Review

Recommendation

Modify the _withdrawFromVault function to capture and utilize the actual number of shares burned by the vault. This ensures that totalVaultDeposits accurately reflects the current liquidity. For example:

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

Lead Judging Commences

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

Give us feedback!