This repository has been archived by the owner on Feb 18, 2024. It is now read-only.
panprog - Bad debt (shortfall) liquidation leaves liquidated user in a negative collateral balance which can cause bank run and loss of funds for the last users to withdraw #72
Labels
Has Duplicates
A valid issue with 1+ other issues describing the same vulnerability
Medium
A valid Medium severity issue
Reward
A payout will be made for this issue
Sponsor Confirmed
The sponsor acknowledged this issue is valid
Won't Fix
The sponsor confirmed this issue will not be fixed
panprog
high
Bad debt (shortfall) liquidation leaves liquidated user in a negative collateral balance which can cause bank run and loss of funds for the last users to withdraw
Summary
Bad debt liquidation leaves liquidated user with a negative collateral. However, there is absolutely no incentive for anyone to repay this bad debt. This means that most of the time the account with negative balance will simply be abandoned. This means that this negative balance (bad debt) is taken from the other users, however it is not socialized, meaning that the first users to withdraw will be able to do so, but the last users will be unable to withdraw because protocol won't have enough funds. This means that any large bad debt in the market can trigger a bank run with the last users to withdraw losing their funds.
Vulnerability Detail
Consider the following scenario:
Since all users know about this feature, after bad debt they will race to be the first to withdraw, triggering a bank run.
Impact
After ANY bad debt, the protocol collateral for all non-negative users will be higher than protocol funds available, which can cause a bank run and a loss of funds for the users who are the last to withdraw.
Even if someone covers the shortfall for the user with negative collateral, this doesn't guarantee absence of bank run:
Proof of concept
The scenario above is demonstrated in the test, add this to test/unit/market/Market.test.ts:
Console output for the code:
After initial total deposit of $1010, in the end liquidated user will just abandon his account, and remaining user accounts have $550+$550=$1100 but only $1000 funds in the protocol to withdraw.
Code Snippet
When account is liquidated, its collateral becomes negative, but is allowed when protected and the collateral is never reset to 0:
https://github.com/sherlock-audit/2023-07-perennial/blob/main/perennial-v2/packages/perennial/contracts/Market.sol#L497
However, user with negative collateral will simply abandond the account and shortfall will make it impossible to withdraw for the last users in case of bank run.
Tool used
Manual Review
Recommendation
There should be no negative collateral accounts with 0-position and no incentive to cover shortfall. When liquidated, if account is left with negative collateral, the bad debt should be added to the opposite position pnl (long position bad debt should be socialized between short position holders) or maybe to makers pnl only (socialized between makers). The account will have to be left with collateral = 0.
Implementation details for such solution can be tricky due to settlement in the future (pnl is not known at the time of liquidation initiation). Possibly a 2nd step of bad debt liquidation should be added: a keeper will call the user account to socialize bad debt and get some reward for this. Although this is not the best solution, because users who close their positions before the keeper socializes the bad debt, will be able to avoid this social loss. One of the solutions for this will be to introduce delayed withdrawals and delayed socialization (like withdrawals are allowed only after 5 oracle versions and socialization is applied to all positions opened before socialization and still active or closed within 5 last oracle versions), but it will make protocol much more complicated.
The text was updated successfully, but these errors were encountered: