# Order's creator can update tokenOut to arbitrary token

updateOrder lets an order creator swap tokenOut to any token, so they can front-run fillOrder and force the executor to pay out a high-value token.

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

**Target:** MarginTradingHook.updateOrder / fillOrder
**Root cause:** updateOrder writes order.tokenOut without re-validating it against marginPos.baseAsset/quoteAsset, unlike order creation which enforces that constraint.
**Steps:**
1. Create an order with tokenOut = baseAsset or quoteAsset (passes creation check).
2. Executor approves the hook to spend multiple tokens and prepares to call fillOrder.
3. Creator front-runs fillOrder with `updateOrder(_posId,_orderId,_triggerPrice,_highValueToken,_limitPrice,_collAmt)`.
4. fillOrder executes using the new high-value tokenOut, transferring that token from the executor.
**How found:** Code reading: noticed creation enforces tokenOut == baseAsset||quoteAsset but updateOrder omits the same check, then reasoned about front-running the executor's fill.
**Exploitation:** Order creator watches the mempool for the executor's fillOrder, front-runs with updateOrder setting tokenOut to a high-value token the hook is approved for, and the executor's fill transfers the expensive token instead of the intended one.
**Insight:** When a create function validates a field against position assets, check every mutator (update/setters) re-applies the same invariant; asymmetric validation between create and update is a recurring access/logic gap.
