GmxProxy contract allows multiple concurrent order attempts when it should only permit one at a time. This breaks the assumption that orders are processed sequentially, potentially leading to state inconsistencies and unexpected position management.
The GmxProxy contract acts as a bridge between PerpetualVault and GMX protocol, managing order creation and execution. When an order is pending (tracked by queue.requestKey), the contract should reject new order attempts until the current one completes. However, the code allows new orders to be created while an existing order is in flight.
Think of it like a single-lane bridge that accidentally allows multiple vehicles to enter simultaneously, while each vehicle (order) should wait for the previous one to cross, the gate mechanism is faulty.
We expects that when pendingOrderCount > 0, any attempts to createOrder() or settle() should revert. Looking at GmxProxy.sol, we can see the queue struct.
The contract tracks the current order in queue but lacks proper guards against new orders while queue.requestKey is non-zero. This leads to: createOrder() → queue.requestKey set → another createOrder() allowed → state confusion
The GmxProxy contract serves as a critical bridge between user vaults and GMX's perpetual trading system. When a user wants to open or modify a position, their request flows through this proxy, but there's a catch. The contract assumes orders will be processed one at a time, like cars going through a tunnel. However, there's possiblity that multiple cars can enter the tunnel simultaneously.
When a user initiates an order through PerpetualVault, it calls GmxProxy's createOrder() function. The order details get stored in a queue structure with a unique requestKey. Here's where things get interesting - while the contract tracks this key, it never prevents new orders from being created while one is pending.
Let's walk through a real scenario:
Alice's vault calls createOrder() to open a long ETH position
Before GMX executes Alice's order, Bob's vault calls createOrder()
Now two orders exist simultaneously, but the queue can only track one
This breaks a fundamental assumption of the system that order execution is sequential and atomic. GmxProxy#createOrder
The protocol's whitepaper explicitly describes sequential order processing as a core safety feature, each position change should complete before the next begins.
The GmxProxy contract tracks orders using a simple queue structure: GmxProxy.sol#L38-L40
But crucially, it never enforces queue exclusivity. This oversight creates a race condition where multiple orders can exist simultaneously.
Here's where things get interesting. When a vault initiates a position change through createOrder(), the contract records the order's requestKey but never enforces exclusivity. This creates a scenario where multiple position changes can race through the system simultaneously.
The real-world impact is precise and severe. When multiple orders execute concurrently:
Position sizes can deviate from intended amounts due to race conditions
Share calculations in PerpetualVault become misaligned with actual positions
Users could receive incorrect amounts of collateral during withdrawals
GMX callbacks could process against incorrect order context
Think of it like a banking system allowing multiple simultaneous withdrawals from an ATM, each transaction believes it has the correct account balance, but they're all working from different versions of reality.
Consider enforcing strict order sequencing
There is no real proof, concrete root cause, specific impact, or enough details in those submissions. Examples include: "It could happen" without specifying when, "If this impossible case happens," "Unexpected behavior," etc. Make a Proof of Concept (PoC) using external functions and realistic parameters. Do not test only the internal function where you think you found something.
Order is proceed one by one and requestKey is only used to cancelOrder. I didn’t see any real scenario where it will cause a problem. Flow and gmxLock will prevent that to happen.
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.