User is able to revert a position being closed
Description
Both long and short pools make use of the common BaseWasabiPool::_payCloseAmounts
function to transfer the fees and the payout when closing or liquidating a position.
The function takes an _unwrapWETH
argument that determines whether the transfer should be made as WETH or ETH. If an ETH transfer is requested, the function will use PerpUtils.payETH
to transfer the required fees and payout amounts to, respectively, the fee-collector address and the user address.
Since reverts are not caught, there is the possibility to prevent a position from being closed or liquidated. If the recipient of the transfer is a smart contract, it is possible for it to revert, either directly or for example by consuming all the available gas.
Impact
This issue allows a malicious user to prevent liquidating a position under the following two conditions:
The payout is requested in ETH (
_unwrapETH
is true).The position is undercollateralized but not insolvent (the payout is still greater than zero after fees are deducted).
The latter condition is required because the user address is called only if the value to transfer is greater than zero. Because of this, an attacker cannot prevent liquidation indefinitely, but they can prevent it until their position is insolvent.
Recommendations
The possibility to consume all the gas can be addressed by limiting the amount of gas forwarded by PerpUtils.payEth
.
However, this does not completely address the issue, as the recipient smart contract could immediately execute a revert. One possibility would be to consider forbidding usage of Wasabi Perps through smart contracts or, somewhat less constraining, forbidding the recipient of the payout to be a smart contract. This is achievable by checking that extcodesize == 0
for the recipient of the payout. If restricting the recipient of the payout to being an EOA is not acceptable, we recommend supporting only WETH for payouts. Alternatively, it could be possible to ignore reverts originated by the transfer, but this could allow benign smart contract recipients to lose their payout if they reverted for any reason while receiving it.
Remediation
Wasabi informed us that currently liquidations happen without unwrapping WETH. They opted to not make changes to the smart contracts at this time, and proposed a potential off-chain mitigation in case they wanted to liquidate a position while unwrapping WETH: a failed liquidation could be detected and retried without unwrapping WETH.