Open sherlock-admin opened 1 year ago
See the Recommendation
section above for the root of the issue.
Fixed: https://github.com/equilibria-xyz/perennial-mono/pull/204 - this updates totalCollateral
to reflect the amount after fees have been paid
Emmanuel
high
Accounts will not be liquidated when they are meant to.
Summary
In the case that the totalMaintenance*liquidationFee is higher than the account's totalCollateral, liquidators are paid the totalCollateral. I think one of the reasons for this is to avoid the case where liquidating an account would attempt to debit fees that is greater than the collateral balance The problem is that, the value of totalCollateral used as fee is slightly higher value than the current collateral balance, which means that in such cases, attempts to liquidate the account would revert due to underflow errors.
Vulnerability Detail
Here is the
liquidate
function:fee=min(totalCollateral,collateralForFee*liquidationFee)
But the PROBLEM is, the value of totalCollateral is fetched before callingproduct.closeAll
, andproduct.closeAll
debits the closePosition fee from the collateral balance. So there is an attempt to debittotalCollateral
, when the current collateral balance of the account istotalCollateral
-closePositionFees This allows the following:product.closeAll
closes the position and debits a makerFee of 10USDC_products[product].debitAccount(account,fee)
attempts to subtract 500 from 490 which would revert due to underflowNOTE: This would happen when the market token's price increases by (1/liquidationFee)x. In the above example, price of ETH increased by 6x (from 1000USD to 6000USD) which is greater than 5(1/20%)
Impact
A User's position will not be liquidated even when his collateral balance falls WELL below the required maintenance. I believe this is of HIGH impact because this scenario is very likely to happen, and when it does, the protocol will be greatly affected because a lot of users will be trading abnormally high leveraged positions without getting liquidated.
Code Snippet
https://github.com/sherlock-audit/2023-05-perennial/blob/main/perennial-mono/packages/perennial/contracts/collateral/Collateral.sol#L118 https://github.com/sherlock-audit/2023-05-perennial/blob/main/perennial-mono/packages/perennial/contracts/collateral/Collateral.sol#L123 https://github.com/sherlock-audit/2023-05-perennial/blob/main/perennial-mono/packages/perennial/contracts/collateral/Collateral.sol#L129-L132
Tool used
Manual Review
Recommendation
totalCollateral
that would be paid to liquidator should be refetched afterproduct.closeAll
is called to get the current collateral balance after closePositionFees have been debited.