A vulnerability exists in the LendingPool.sol
implementation, where Curve Vault
withdrawals are incorrectly handled, leading to unnecessary transaction reverts during deposit()
, borrow()
, and withdraw()
operations. The failure arises due to unchecked vault balances, incorrect coupling of liquidity management, in addition to the absence of partial success mechanisms.
There are three core issues contributing to this flaw:
Flaw 1: Deposits should not fail due to low totalVaultDeposits
.
The current implementation couples _rebalanceLiquidity()
with deposit()
such that even if a user has successfully deposited reserve tokens, the transaction can still revert if totalVaultDeposits < amount
when _withdrawFromVault()
is eventually triggered.
Flaw 2: Borrow and withdraw requests should not fail if _ensureLiquidity()
already passed.
The _ensureLiquidity()
function which can also trigger _withdrawFromVault()
ensures that there is sufficient reserve token liquidity to fulfill a user’s borrow or withdrawal request. However, even when this check passes, the embedded _rebalanceLiquidity()
in withdraw
and borrow()
can still cause the entire transaction to revert like as described in Flaw 1.
Flaw 3: No mechanism for partial success when liquidity cannot be fully ensured.
When the required liquidity cannot be fully ensured (e.g., totalVaultDeposits
is insufficient), the protocol currently reverts the entire transaction instead of supporting partial borrow/withdraw success. As a result, capital efficiency is reduced, as users cannot withdraw or borrow the maximum available amount.
Critical failure of deposit transactions: Deposits are expected to always succeed, but the current design makes them prone to failure, significantly affecting user trust.
Failed borrow and withdraw requests: Users can be prevented from accessing funds even when sufficient liquidity is available.
Missed partial success opportunities: The lack of partial borrowing or withdrawal leaves available capital underutilized.
Manual
Consider implementing the following:
Modify _rebalanceLiquidity()
to skip calling _withdrawFromVault()
if totalVaultDeposits < amount
is detected or simply withdraw whatever is available.
If the liquidity check only partially succeeds, borrow()
and withdraw()
should allow users to access the available portion of funds.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.