The LendingPool contract interacts with a Curve vault to manage deposits. The vault operations are critical for core functionalities like deposits, withdrawals and borrowing, which all rely on the _rebalanceLiquidity() function that in turn calls _withdrawFromVault().
The _withdrawFromVault() function incorrectly passes msg.sender as the owner parameter when calling curveVault.withdraw(). However, the vault shares are owned by the LendingPool contract itself (address(this)), not by the user interacting with the pool.
This creates a mismatch between the actual owner of the shares (LendingPool) and the claimed owner (msg.sender) in the withdrawal call, which will cause the transaction to revert due to insufficient share balance and missing token approvals.
Since _withdrawFromVault() is called by _rebalanceLiquidity(), which is in turn used by core functions like deposit(), withdraw(), and borrow(), this issue affects these main functions when rebalancing is needed.
High. When triggered, the issue causes core contract functionality (deposits, withdrawals, borrowing) to be completely unusable as transactions will revert. This represents a complete failure of the contract's main purpose in scenarios requiring rebalancing.
Medium. This issue will manifest when currentBuffer < desiredBuffer, requiring the pool to withdraw funds from the vault to rebalance liquidity. While this is a common scenario in normal operations, it's not guaranteed to occur on every transaction.
User calls deposit() function with some amount
deposit() calls _rebalanceLiquidity()
If currentBuffer < desiredBuffer, _rebalanceLiquidity() determines some amount needs to be withdrawn from the vault and calls _withdrawFromVault()
_withdrawFromVault() attempts to withdraw using the user's address as owner
The transaction reverts because:
The user doesn't own any vault shares (they are owned by the LendingPool)
The user hasn't approved the LendingPool to spend their vault shares (which they don't have anyway)
The owner parameter in the vault withdrawal should be set to address(this) since the LendingPool contract is the actual owner of the shares. Update the _withdrawFromVault() function as follows:
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.