When the liquidity is withdrawn from the Curve vault the Receiver address is LendingPool instead of being rToken address
The LendingPool has a feature that rebalances liquidity, when the excess tokens are deposited into the curve vault and the shortage is withdrawn from the curve vault.
But originally, LendingPool don't stock those funds in LendingPool contract, but in rToken address
We can see for example when assets are deposited into curve vault, the assets are transferred directly from the RToken contract (reserve.reserveRTokenAddress) to the curve vault, not from the LendingPool contract itself. The RToken contract holds the actual reserve assets and handles the transfers, while the LendingPool contract manages the lending logic and accounting.
When a user deposit, withdraw, borrow, or repay, they always interact with rToken address
The problem is when shortened tokens are withdrawn from curve vault, they are transferred to LendingPool and not rToken address
as we can see in ICurveCRVUSDCVault interface, receiver is address(this) (lending pool here) instead of rToken address
These withdrawn funds become locked in the LendingPool contract since there's no mechanism to transfer them to rToken
When users try to withdraw/borrow after a vault withdrawal, the transaction will fail because rToken won't have the expected funds
This breaks the core accounting system since rToken's balance won't match the protocol's tracked liquidity
Manual review
Put the receiver as a rToken address instead of address(this) in _withdrawFromVault
function
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.