# Order double-linked list is broken because order.prevOrderId is not persisted

In GTE's CLOB, order.prevOrderId is set on a memory struct and never persisted, breaking the order book's doubly-linked list and enabling DoS when the book fills.

- Payout: Contest reward
- Severity: high
- Program: GTE
- Credited: montecristo
- Disclosed: 2026-02-05
- Write-up quality: 7/10
- Original: https://code4rena.com/reports/2025-07-gte-spot-clob-and-router#h-01
- Library page: https://bugbountylibrary.com/r/c4%3A2025-07-gte-spot-clob-and-router%3AH-01
- Tags: domain:web3 impact:dos kind:contest platform:code4rena sev:high tech:evm tech:solidity technique:source-review vuln:accounting-error vuln:dos

**Target:** Solidity CLOB order book (Book.sol linked-list management)
**Root cause:** addOrderToBook passes the Order as `memory` to _updateLimitPostOrder, so `order.prevOrderId = tailOrder.id` mutates only the memory copy and is never written to `self.orders[order.id]` storage.
**Steps:**
1. Read `addOrderToBook(Book storage self, Order memory order)` at Book.sol L150-154; note order is `memory`.
2. Observe `_updateLimitPostOrder(..., Order memory order)` at L275 sets `order.prevOrderId = tailOrder.id` (L284) on the memory copy only.
3. Confirm storage `self.orders[order.id].prevOrderId` remains null after insertion.
4. On removal (L320-327), `prev = order.prevOrderId` is always null, so `limit.headOrder = next` always executes and `self.orders[prev].nextOrderId` is never updated.
5. Fill the book so limit.tailOrder points to a stale/invalid order, triggering DoS on subsequent add/remove.
**How found:** Code reading of the linked-list update path: noticed the Order parameter was declared `memory` while the function writes to `order.prevOrderId`, implying the write is lost; traced removal logic to confirm prev is always null.
**Exploitation:** Not a direct theft; an attacker (or normal usage) fills the order book so the broken linkage leaves limit.tailOrder invalid, causing order add/remove operations to revert and denying service to the CLOB.
**Insight:** When auditing storage-mutating helpers, check the data-location qualifier (`memory` vs `storage`) of struct parameters — writes to `memory` structs silently no-op, and linked-list invariants (head/tail/prev/next) are a common place this surfaces as DoS.
