There is a missing case in the check of the function Position.isIncreasing()
, allowing traders to bypass the restriction and increase their position size.
Basically, the issue is that the check does not consider the case where sizeDelta.abs() > self.size.abs()
(trade size delta is larger than position size).
In the Zaros protocol, the owner can enable or disable a market using the function updatePerpMarketStatus()
. They can also enable or disable settlement using the function updateSettlementConfiguration()
. When settlement is disabled, traders are not allowed to increase the position size. However, traders are still allowed to decrease the position size to avoid liquidation.
As a result, the contract needs to check if the position size is increasing when settling a trade through the Position.isIncreasing()
function.
However, this check lacks the case where the trade delta size is larger than the current position size.
Consider the scenario:
Alice has a LONG position self.size = X
(X > 0). She wants to increase this position to Y
(Y > X > 0). But currently settlement is disabled, Alice should not be able to increase her LONG position.
However, she can still do it by first decreasing her position with sizeDelta = -X - minTradeSize
. Because self.size > 0
and sizeDelta < 0
, this order is allowed. Now, the new position has self.size = -minTradeSize
.
Then she can increase her position with sizeDelta = minTradeSize + Y
. Because self.size < 0
and sizeDelta > 0
, this order is again allowed (bypassing the isIncreasing()
check). Now, Alice has this new position with self.size = Y
while settlement and the market are paused.
PoC (modified from test_WhenThePositionIsBeingDecreasedOrClosed()
)
The check isIncreasing()
is used in two places, each with different impacts:
Order is created and filled. When settlement is paused, traders are still able to trade. This could be the case where a vulnerability is detected in the protocol and the owner disables it to fix the issue.
Checking initial margin. Maintenance margin is used when isIncreasing = false
. Because the maintenance margin is always less than the initial margin, traders could open/increase a position and only check for the maintenance margin instead of the initial margin. This will make the position liquidatable right after it is created, adding risk to the protocol.
Manual Review
Consider adding a check to ensure that sizeDelta.abs() <= self.size.abs()
if self.size != 0
.
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.