abadi
The markets expire every window. The liquidity doesn't.
Somnia × DreamDEX Event Contracts Hackathon · Shannon testnet
Every position dies on a timer.
DreamDEX runs six window tiers on two assets — sixty seconds through twenty-four hours. Twelve series live at once, each expiring and respawning on schedule.
Liquidity has to be re-placed every window, on every series, forever. Nobody does that by hand — and the book shows it: a flat 2.9% spread on every market regardless of tenor, volatility, or moneyness. That is the signature of one naive quoter, not a competitive book.
Does up win more often than the market prices it to?
| Tier | n | Up won | z vs fair coin |
|---|---|---|---|
| 60s | 500 | 49.6% | −0.18 |
| 300s | 500 | 48.6% | −0.63 |
| 900s | 500 | 48.2% | −0.80 |
| 1h | 500 | 51.0% | +0.45 |
| 4h | 364 | 51.9% | +0.73 |
| 24h | 58 | 58.6% | +1.31 |
| pooled | 2,422 | 49.96% | −0.04 |
No. Four hundredths of a standard error from a coin flip, across every settled market on the venue.
With a coin flip and a 3% spread, only one side of the trade is positive.
taker crosses the spread −1.45% per contract maker collects the spread +1.45% per fill
Our first design was a directional vault that took liquidity every window. On the 900-second tier at 10% deployment:
after 1 day ( 96 rolls) 87.0% of deposit after 7 days (672 rolls) 37.7%
Zero fees don't save it — the spread is the cost. We cut that product on the evidence and built the other side of the trade instead.
Quote both sides holding nothing.
DreamDEX keeps one book with a fill path most venues don't have: two opposite-side buyers cross with no seller at all, and the pool mints a fresh up/down pair from their combined collateral.
BUY_YES @ p escrows p per contract
BUY_NO @ p + s escrows 1−(p+s) price is always YES-side
───────
pair cost 1 − sBoth legs fill and the vault holds a complete set — worth exactly 1 at settlement whichever side wins. The spread is captured with zero directional exposure, and no inventory was ever required.
We quoted inside, and the market tightened.
theirs 0.742 / 0.772 spread 0.030 ours 0.744 / 0.770 spread 0.026 inside the book, read back: 0.744 × 100 ← abadi 0.769 × 200 0.742 × 200 0.770 × 100 ← abadi 0.733 × 330 0.779 × 330 spread after 0.030 → 0.025 the incumbent responded
Abadi's bid became the best bid on the market. One vault quoting inside made prices better for everyone else trading it — the ecosystem claim as a screenshot, not an assertion.
paid 97.40
holds 100 up + 100 down
worth at settlement 100.00
either way
──────
locked in +2.60Both legs were buys. Neither could fill against a seller, because none was involved.
directional exposure
The number a market maker is judged on. The 2.60 isn't a bet that paid — it's the spread, collected.
The key that steers the quotes can't move a token.
BinaryPool has no operator gate. The DreamDEX team confirmed the only shape that works today is a contract that owns its own orders — which is what Abadi is.
| Actor | Can | Cannot |
|---|---|---|
operator | quote, cancel | move any token |
governor | set operator, risk params; sweepNative the vault's ~32.8 STT wake-up reserve | touch depositor collateral |
| depositor | deposit, withdraw | steer quotes |
settle() is permissionless — proceeds go to the vault, never the caller, and a settled market leaves the live list so redemption has to be pulled. flatten() is operator-only while a market still trades, because cancelling a live quote destroys the spread; open to anyone once it can't.
Four assumptions died on contact with the chain.
- Prices scale to the collateral's decimals, not 1e18 — and a wrong scale reverts as
PostOnlyWouldCross, sending you to look at spreads instead of units. - The spot
placeOrderABI exists on binary pools and always fails. It compiles, type-checks, and reverts at runtime. - Reactivity fails identically for two unrelated reasons — a 32 STT floor and a missing ERC-165 — both with empty revert data.
- Docs list two window tiers. There are six. A headroom rule tuned for the documented ones silently stops trading the fast tiers.
- Redemption pulls through the module, not the pool — and nothing says so until the one call that turns tokens back into money. Cost us a stranded position.
- Cancelling an order that already filled reverts. So cleanup breaks on exactly the position that needs cleaning up.
- The explorer’s verifier lists
osakaand cannot verify it. Same nine-line probe: cancun passes, osaka fails. - A reactivity callback that runs out of gas vanishes — no event, no error, subscription spent. And the callback’s topic is the fired millisecond, not the scheduled one.
All reported back with reproduction steps, alongside what genuinely worked: the Gotchas page, unpruned history, and a dev channel that answered a hard question in under an hour.
One vault. Full lifecycle. Honest about the rest.
| Run against the venue | |
|---|---|
| Quoting inside the book, top of book | ✓ |
| Both legs filled into a complete set | ✓ |
settle() — redeemed 100.00 on a 97.60 basis | ✓ |
flatten() — merged early, 671s before expiry | ✓ |
| 149 tests, five stateful invariants | ✓ |
| Keeper-free wake-up — the chain settled a window for us | ✓ |
A handful of fills proves the mechanism, not the edge. Adverse selection is the real risk a maker carries, and we met it twice in one afternoon — a leg taken while the market walked away from the other. NAV marks that leg at zero, so the loss lands on us and not on whoever deposits next. Measuring the frequency needs many quotes across many windows. The bot and the ledger exist so that number grows without anyone having to trust it.
The markets expire. The liquidity doesn't.
One quoter, one spread, every window.
tier created traded spread at the touch
60s 2,880 4% 0.0270 one address
300s 1,128 40% 0.0260 one address
900s 186 70% 0.0260 one address ← abadi
────────────────────────────────────────
one day 4,312 73% never tradedEvery tier carries the same book: a flat ~2.6% spread, and in 172 of 172 windows measured, a single address holding both sides of the touch — a different one each window. What changes between tiers is takers, not makers.
So the 60-second tier is 67% of the venue Abadi has never quoted, and the only thing resting in it is that one quoter at its fixed spread — the same thing Abadi already measurably tightens elsewhere. Two absolute numbers were what held it shut: the bot refused any tier under 900s, and demanded 600 seconds of life left, which is longer than a 60-second window ever has. Both are relative to the window now, and MIN_TIER=60 TIERS=60 reaches it — verified against the live venue, two windows with 58 seconds left. It stays off: whether quoting it earns is unmeasured, and arming it multiplies a 1.15 STT/day gas burn by the fourteen-fold jump in windows. Market creation stays out on measurement: two addresses made every one of the last 3,000 markets.