In the LendingPool contract, the _ensureLiquidity
function withdraws funds from the Curve vault to the wrong address (LendingPool) instead of the RToken address, causing a mismatch between accounting and actual balances, potentially leading to protocol fund loss.
The issue stems from the _ensureLiquidity
function in the LendingPool contract. This function is responsible for ensuring sufficient liquidity is available for withdrawals or borrowing by pulling funds from the Curve vault when needed. However, there's a critical flaw in how the withdrawal destination is handled.
Let's look at the vulnerable code:
The issue propagates through the _withdrawFromVault
function:
The key problems are:
The vault withdrawal sends funds to address(this)
(LendingPool) instead of reserve.reserveRTokenAddress
The protocol's accounting assumes all reserve assets are held in the RToken contract
This creates a discrepancy between where funds are actually held vs. where the protocol thinks they are
This issue is particularly severe because:
The ReserveLibrary's functions like deposit()
and withdraw()
operate under the assumption that all reserve assets are managed through the RToken contract
Balance checks and liquidity calculations look at the RToken's balance
Interest calculations and rate updates depend on accurate liquidity tracking
User A deposits 100 crvUSD into the protocol
Protocol deposits 80 crvUSD into Curve vault (20% buffer)
User B attempts to withdraw 90 crvUSD
_ensureLiquidity
detects insufficient funds and withdraws 70 crvUSD from vault
Funds go to LendingPool instead of RToken
RToken balance check fails as it only has 20 crvUSD
Transaction reverts despite protocol having sufficient funds
Protocol funds become stuck in the LendingPool contract
Users cannot withdraw their funds even when the protocol has sufficient liquidity
Accounting system becomes unreliable
Interest calculations become inaccurate
High severity as it affects core protocol functionality and user funds
Manual code review
Modify _withdrawFromVault
to send funds to the RToken contract:
Add balance reconciliation functions to handle any stuck funds
Add proper validation to ensure funds are always in the correct contract
Add events to track vault withdrawals and their destinations
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.