The withdraw function allows users to withdraw reserve assets from the protocol, the function checks if there are enough reserve assets in the protocol by calling _ensureLiquidity, if the reserve asset balance is not up to the amount required, it attempts to withdraw the amount needed from curve vault by calling _withdrawFromVault. However, Curve vault withdrawal parameters are incorrectly configured.
This misconfiguration could lead to users being unable to withdraw funds.
The withdraw
above is called by the user to withdraw amount
of reserve assets by burning Rtokens
. The function calls _ensureLiquidity
which checks the available liquidity in Rtokens
contract. If there's insufficient liquidity, it attempts to withdraw from curve.
The main issue is in _withdrawFromVault
;
According to Curve documentation:
Incorrect Receiver Address
Current: address(this)
(the protocol contract)
Expected: reserve.reserveRTokenAddress
(the RToken contract)
Impact: Tokens are being withdrawn to the protocol contract instead of the RToken contract where they should be available for user withdrawals
Incorrect Owner Address
Current: msg.sender
(the user requesting withdrawal)
Expected: address(this)
(the protocol contract)
Impact: Incorrect permission structure as the protocol contract is the one who deposits into the vault and owns the shares to be burnt.
Also, The implementation includes two additional parameters (uint256 maxLoss
and
address[] calldata strategies
) that aren't part of the Curve vault interface. This suggests possible confusion with a different vault implementation.
The transactions will fail when users attempt to withdraw reserve assets and the protocol doesn't have enough liquidity and attempts to withdraw from the vault.
Manual
The fix below should be implemented
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.