Core Contracts

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

`LendingPool::_withdrawFromVault` does not check the actual total deposit done into the vault, potentially withdrawing where there are no balance to withdraw

Summary

Lending pool have the ability to rebalance the liquidity if there are excess or shortage from the desired buffer.

but the logic _withdrawFromVaultdoes not check the value totalVaultDeposits, making the function potentially withdrawing non-existent balance from the vault.

Vulnerability Details

LendingPool.sol#L772-L793

the function _rebalanceLiquidityonly calculate the current buffer and the desired buffer and check the discrepancy between them. if there are so many borrower then it is possible the currentBuffer is lower than the desired buffer. making this function always withdraw from the curve vault on each call.

function _rebalanceLiquidity() internal {
// if curve vault is not set, do nothing
if (address(curveVault) == address(0)) {
return;
}
uint256 totalDeposits = reserve.totalLiquidity; // Total liquidity in the system
uint256 desiredBuffer = totalDeposits.percentMul(liquidityBufferRatio);
uint256 currentBuffer = IERC20(reserve.reserveAssetAddress).balanceOf(reserve.reserveRTokenAddress);
if (currentBuffer > desiredBuffer) {
uint256 excess = currentBuffer - desiredBuffer;
// Deposit excess into the Curve vault
_depositIntoVault(excess);
} else if (currentBuffer < desiredBuffer) {
@> uint256 shortage = desiredBuffer - currentBuffer;
// Withdraw shortage from the Curve vault
_withdrawFromVault(shortage);
}
emit LiquidityRebalanced(currentBuffer, totalVaultDeposits);
}

the problem arise when the shortage amount that would be withdrawed is greater than what the actual deposit left in the curve vault.

because there are no check of the contract balance inside the vault, the function call always assume the contract have enough balance to withdraw, which is not.

LendingPool.sol#L809-L812

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

Impact

the function would revert after so many withdraw from vault done, because the amount withdrawed is greater than the current contract balance inside the curve vault. this would lead to DoS the LendingPool deposit, withdraw and repay function.

Tools Used

manual review

Recommendations

use the totalVaultDepositsto track and check if the withdrawing amount is enough before doing the curveVault.withdraw, so when it is not enough it is handled by return without throwing error. or better, it should be adjusted to whatever contract balance left in the curve vault.

Updates

Lead Judging Commences

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