As per docs :
Primary Margin Call Method
In the Primary Margin Call Method, when an account is below 200% and is flagged for liquidation, a liquidation timer of 10 hours begins on the account to give a window of opportunity to the flagged shorter to fix their CR and stop the liquidation countdown.
To halt the liquidation timer and remove the flag, the shorter must reach the target maintenance margin CR (200%) again by either the price moving favorably or by adding additional collateral.
Basically the flag is expected to be reset by the price moving favorably.
This behaviour is not followed by the protocol.
Imagine the following flow of events:
#1. A short is flagged by a flagger
as its cRatio < 4
#2. Shorter
now has 10 hours. If cRatio is still < 4 after 10 hours, flagger
has a 2 hour window to liquidate the short.
#3. Assume that the price moves in favour of the shorter
and at the 8th hour, cRatio > 4 is achieved. The shorter
himself did not take any action to do this. He just bet on the market & the price movement to save him. Or you can imagine that in the time he was arranging funds to fund the short, the market moved favourably and hence he did not need to do any action.
#4. 10 hours pass. Obviously, flagger
won't be able to liquidate now as cRatio > 4.
#5. The flag should also have been reset at the 8th hour. This is necessary so that in case cRatio again dips below 4 in the future, one has to flag the short again and wait for 10 hours before attempting liquidation.
However, the flag is not reset by the protocol in the above scenario.
Since the flag never got reset, if the price moves unfavourably again such that cRatio < 4, then -
between 10-12 hour window, flagger
can liquidate the short immediately, with no waiting period.
between 12-16 hour window, anyone can liquidate the short immediately, with no waiting period.
Let's now imagine that:
#1. 16 hours pass. As sepcified in the docs flag should be reset, forcing margin-callers to re-flag the short:
Since the flag never got reset, if the price ever moves unfavourably after the 16 hour window such that cRatio < 4, then -
anyone can liquidate the short immediately, with no waiting period.
Create a file inside test/
folder by the name of FlagNotResetOnPriceMovement.t.sol
and paste the following code. It has 3 tests along with a few helper functions:
Test-1: Run forge test --mt test_01_flagDoesNotResetOnFavorablePriceMovement -vv
to verify that the flag is never reset.
Output:
Test-2: Run forge test --mt test_02_ImmediateLiquidationPossibleOnUnfavorablePriceMovement -vv
to verify the aforementioned Impact-1
.
The test passes, but should have failed as per protocol specifications.
Test-3: Run forge test --mt test_03_flagNotResetAfter16Hours -vv
to verify the aforementioned Impact-2
.
The test passes, but should have failed as per protocol specifications.
Manual review, foundry.
Whenever a short is flagged, its price movement needs to be tracked so that its flag can be correctly reset whenever it crosses a healthy cRatio back again. This might need altogether additional new functions to be implemented. An idea: Users can be incentivized to reset a short's flag when the right conditions are met (just like they are incentivized to flag a short).
Another approach could be that at every liquidation or flagging attempt of a short, the code not only checks whether the short is already flagged, but also the timestamp of the flagging. If it is beyond 16 hours, flag resets. This approach however, will only address Impact-2
.
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.