Cohort Order Book: an O(1) fully on-chain limit order book via generational fungible liquidity
Cohort Order Book: an O(1) fully on-chain limit order book via generational fungible liquidity Draft for Ethereum Magicians. Looking for critique, especially on the one-sided-add justification in §4 and the FIFO concerns in §6. TL;DR A fully on-chain limit order book where orders at each price point are fungibilized into time-ordered “cohorts.” Fills touch ≤2 cohorts per price point → O(1) (no per-order loop), partial fills are exact, and cancellation is just “withdraw your own position.” The design’s real justification isn’t gas — it’s that it’s the clean way to accept one-sided liquidity adds to a partially-filled price level , which pro-rata AMMs cannot do without either two-sided adds or subtle rebasing math. The cost is a coarse, tunable batch-FIFO . I want to pressure-test whether that price is acceptable — and whether this is worth building at all. 1. Motivation On-chain order books are gas-hostile: filling loops over resting orders, O(n) in the number of orders. That’s why on-chain trading converged on AMMs , which fungibilize liquidity per price level (O(1) fills) — but in doing so give up clean limit-order semantics. The specific semantic that breaks is one-sided adds to a partially-filled level (§4). This post proposes a structure that keeps O(1) fills and clean one-sided adds, and is honest that the price is a coarse FIFO. 2. Core idea — cohorts At each price point (tick), resting liquidity lives in cohorts — fungible batches (one fungible token per cohort). At most two are live at any time: Staging — where new orders land; not yet being filled. Open — the batch currently being filled; frozen (no new orders join it). 3. Mechanism Place → mint a share of the current staging cohort. Promote → on the first fill at this price, staging is frozen → open , and a fresh staging opens. Fill → consume open , tracked by a single fill fraction ( filled / frozen total ). Settle → when open is fully consumed it settles (redeemable), and the next staging promotes. Because only one open + one staging are ever live, a fill touches ≤2 cohorts per price point → O(1) (settled cohorts just await redemption, O(1) per LP). A trade sweeping multiple ticks is O(ticks crossed), same as any tick-based AMM. Freeze-on-fill is what gives exact partial-fill accounting: each cohort has a single clean fill fraction, and new orders never inherit someone else’s partial fill. Worked example (one tick): Alice 100 + Bob 50 → Staging C1=150. Fill 90 → C1 freezes (60% filled), new Staging C2. Carol 30 → C2=30. Fill 60 → C1 fully settles. Fill 20 → C2 promotes, consumed 67%. 4. Why generations at all? — the one-sided-add problem This is the actual justification, and it’s easy to miss. A limit order is one-sided (you post a single token at a price). In a pro-rata AMM (Uniswap V3 range order), once a tick is partially crossed (price inside the range), you can only add liquidity in the current two-token ratio — you cannot cleanly top up one-sided. In practice, V3 range-order users open a new position per add during a partial fill — i.e. they manually create generations. You can pool one-sided adds with a per-LP accumulator, but consuming fills rebase the remaining one-sided balance while accruing the counter-asset — a rebasing-token-plus-rewards accounting that is doable but subtle and error-prone. Cohorts automate the “new position per add” workaround: freeze the partially-filled batch, route fresh one-sided liquidity to a clean 0%-filled batch. That’s the real value. The same structure that enables this — draining the open batch before promoting the next — is also what imposes a batch-FIFO ordering across cohorts. That’s the main tradeoff, discussed in §6. 5. Prior art (this is not novel in isolation) Ambient (CrocSwap) “knockout liquidity” is essentially this: on-chain limit orders as concentrated liquidity that fully converts when crossed, using pivots/epochs — which are cohorts by another name — precisely to handle one-sided adds + partial fills. This post is largely a generalization/formalization of that pattern as a standalone order book. Trader Joe Liquidity Book — fungible per-bin liquidity (the recurring, two-sided endpoint). Uniswap V3/V4 range orders + feeGrowth — the pro-rata accumulator alternative in production. If there’s prior art that handles one-sided adds more cleanly, I’d love pointers. 6. Known concerns / where I expect pushback Being upfront, because these are real: FIFO on-chain is arguably not real FIFO. Intra-block ordering is set by builders (MEV), so “time priority” is partly auctioned, not earned. The promotion boundary (“first fill freezes the cohort”) is itself a potential griefing/MEV surface (dust-fill to freeze a rival cohort; snipe into staging before a known large fill). Mitigation: coarsen cohorts (promote on a volume/time threshold, not every first fill) so it’s pro-rata within large batches and FIFO only at rare boundaries — but does that fully address it? Front-of-queue adverse selection. The oldest cohort fills first, i.e. gets picked off first by toxic flow. “Priority” may be a poisoned chalice. Fresh-liquidity discouragement. Back cohorts fill last, so why add depth right before a move? Pro-rata welcomes liquidity anytime. Capital + adverse selection. A one-shot resting order earns nothing while waiting and is a free option to takers (the classic reason on-chain order books lost to AMMs). This is independent of the cohort structure. Is one-sided limit UX even worth building given off-chain intents (CoW/1inch/UniswapX: gasless, no lockup, free cancel) and AMM range orders already serve most limit-order demand? 7. Discussion questions Does keeping O(1) fills + clean one-sided adds necessarily force batch-FIFO, or is there a pro-rata construction that avoids it? Does coarsening cohorts (threshold-based promotion) reduce the FIFO/MEV concerns to de minimis, or just move them? Is there a cleaner accounting for one-sided adds under a pro-rata accumulator that I’m underrating (rebase index done right)? Given Ambient already ships the pattern — is there value in a standalone, generalized order-book form, or is “limit orders as a layer inside an AMM” the only version worth having? For a term-structure / maturity-bucketed market, a far-dated limit is a composite of per-period orders that must fill atomically — does the cohort model extend, or does that push you back to intent/solver execution? Thanks in advance for tearing into it. 1 post - 1 participant Read full topic
DeFi Intel is an entity-graph aggregator: we curate, tag and link crypto news to a typed knowledge graph of protocols, tokens, people and incidents. We do not republish the full article body. Use the link above to read the original report at Ethereum_magicians.
Want the full article?
Continue reading on Ethereum_magicians →