# fillOrder executor can be front-run by the order creator by changing order's limitPrice_e36, the executor's assets can be stolen

Order creator front-runs fillOrder by raising limitPrice_e36, inflating amtOut and stealing the executor's tokens during order fill.

- Payout: Contest reward
- Severity: high
- Program: INIT Capital
- Credited: said
- Disclosed: 2024-02-22
- Write-up quality: 7/10
- Original: https://github.com/code-423n4/2024-01-init-capital-invitational-findings/issues/22
- Library page: https://bugbountylibrary.com/r/c4%3A2024-01-init-capital-invitational%3AH-03
- Tags: domain:web3 impact:funds-loss kind:contest platform:code4rena sev:high tech:solidity technique:race-window technique:source-review vuln:business-logic vuln:race-condition

**Target:** MarginTradingHook.fillOrder / updateOrder
**Root cause:** fillOrder computes amtOut from the mutable order.limitPrice_e36 at execution time, and the order creator can update limitPrice_e36 via updateOrder before the executor's transaction lands.
**Steps:**
1. Order creator posts an order with a favorable limitPrice_e36 and an executor prepares to call `fillOrder`.
2. Creator front-runs with `updateOrder` setting limitPrice_e36 to an extreme value (higher for long-hold-base / short-hold-quote paths).
3. Executor's `fillOrder` executes `_calculateFillOrderInfo`, which uses the new limitPrice_e36 to compute amtOut.
4. Inflated amtOut is transferred to order.recipient, draining the executor's assets.
**How found:** Code review of _calculateFillOrderInfo showing amtOut depends directly on order.limitPrice_e36, combined with the fact that updateOrder lets the creator mutate that field after the executor commits.
**Exploitation:** Order creator watches the mempool for the executor's fillOrder, submits updateOrder with a manipulated limitPrice_e36 at higher gas, then the executor's fillOrder settles at the skewed price and overpays the recipient.
**Insight:** When an order's price/slippage parameter is read at fill time and remains mutable by the counterparty, treat it as a front-run vector: check whether the executor's fill can be sandwiched by an update to that parameter.
