Severity: High
Traders can create order with sizeDelta of -positon.size * 2 + x. The order would flip the direction but will also have new position size greater than old size i.e trade has resulted in increase of the position size. The Position::isIncreasing function incorrectly returns false for such a sizeDelta.
The Position::isIncreasing is used to
disallow increasing orders in disabled markets and disabled settlement type.
determine the margin requirement: trader have to satisfy initial margin requirement if increasing otherwise only the maintenance margin.
Because of the incorrect implementation of the isIncreasing function, traders can create increasing orders in disabled markets, with disabled settlement types. More importantly, traders can trade by only satisfying maintenance margin requirement.
Note the trader can keep their position direction on the market when increasing the position size:
Increasing the trade using this vulnerability would flip the trader's position for e.g from long to short.
Trader can create another order which will bring the position to original direction e.g back from short to long
The offline orders allow traders to perform this without any market risk in between the two orders.
Definition of the isIncreasing function: Position.sol#L166-L172
The Position::isIncreasing function determines whether sizeDelta is increasing the position or not based on the direction instead of the sizes of old and new positions. As a result, the isIncreasing function would return false even for orders which increase the overall size of the position if sizeDelta moves it in the opposite direction.
The SettlementBranch::_fillOrder allows for sizeDelta that flips the direction of position.
The _fillOrder function uses the isIncreasing function before filling the order:
Use of the isIncreasing function to check for enabled markets in the _fillOrder function: SettlementBranch.sol#L369-L380
The Zaros protocol intends to prevent existing positions from being increased when market and settlement is disabled. The isIncreasing function is used to determine if existing position is being increased.
Similarly, the Zaros protocol allows for decreasing orders to only satisfy the maintenance margin. But the increasing orders must satisfy the initial margin requirement.
Use of isIncreasing to determine the margin requirement to use: SettlementBranch.sol#L416-L430
Because of incorrect implementation of the isIncreasing function
Traders can trade, both increase and decrease positions, in disabled markets and disabled settlement types
Traders can increase position size with only maintenance margin.
Example:
Initial Position Size = 100 BTC; Long on BTC
Trader wants to increase size to 120 BTC; Long on BTC
Trader have margin balance less than initial margin requirement
Protocol disallows increasing the size if margin balance is less than initial margin requirement. Creating an order with sizeDelta = +20 will fail.
Trader can use this issue and create two offline orders:
Order1 sizeDelta = -110
Order2 sizeDelta =+130
Position after Order1: size = -10 BTC; Short on BTC
Position after filling Order2: size = 120 BTC; Long on BTC
Multiple offline orders are filled in a single transaction. As a result, trader is not subjected to market risk in between Order1 and Order2.
Traders can trade, both increase and decrease positions, in disabled markets and disabled settlement types
Traders can increase position size with only maintenance margin.
Manual Review
Update the isIncreasing function to account for the value of sizeDelta along with direction to determine if the order is increasing the position.
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.