How it works
Three contracts, a reactive subscription, and a handler that runs inside the block that triggered it. No keeper in the money path.
On this page
Three contracts#
- BallastVault — custody. Holds collateral in the user’s name, records the policy, and reserves against a purchase. 0x9BC43B97…
- HedgeEngine — the trader of record. Subscribes to window events, sizes cover, and places the order in its own name. 0xFE725050…
- SpotExposureSource — measurement. Reads what an account actually holds on the venue, so cover is never sized against a self-declared number. 0x83923535…
Most of this site needs no chain read#
Every engine’s history is captured as JSON and committed to the repository, so the history it wrote is part of the site rather than something the site fetches. That is not a caching trick — it is a property worth stating.
Positions, totals, the cumulative chart, every refusal and its reason, the block ranges and the transaction hashes are all read from that file. Only three figures on the entire site are genuinely live: the vault balance, the engine’s counters, and the spot price used to measure exposure.
The same-block path#
The engine holds a reactive subscription on MarketCreated from dreamDEX’s binary module. When a window opens, Somnia’s reactivity precompile invokes the handler as a synthetic transaction inside the same block as the trigger.
What the trigger transaction is matters, because its summary page does not show a market being created. dreamDEX creates markets from inside a reactive callback of its own, so the trigger below is dreamDEX’s callback and MarketCreated is emitted by BinaryMarketsModule inside it, at log index 75. Ballast’s handler then runs in the same block, on the market that event created — two reactive systems chained inside one block. Open the Logs tab; the summary shows onEvent and two collateral transfers instead.
| Transaction | Block | What it is |
|---|---|---|
| 0x0434d3649993a201… | 476941284 | dreamDEX’s own reactive callback. MarketCreated for market 0x…010253 is log 75 inside it — the transaction creates two markets. |
| 0x79bf978b79eed282… | 476941284 | Ballast’s handler, on retired engine 0xB095Aacf… — the one live on 1 September. Its CallbackRan names that same market. |
Same block. Zero blocks of latency, with no keeper in the money path. This is the part of the design that only works on this chain.
The two are tied together by the subscription rather than by sharing a block number: the engine’s own SubscriptionOpened records emitter 0x3ecC694C… and topic0 0xb5ec75cd…, which is exactly the emitter and topic of log 75. Be warned before clicking: BinaryMarketsModule is unverified on the explorer, so that log renders with no event name and no decoded parameters — raw topics and about twenty lines of hex. Match its topic0 against keccak256("MarketCreated(bytes32,address,address,uint256,…)") = 0xb5ec75cd… to confirm it. The callback transaction reads cleanly on its summary page, so that is the one worth opening. On this particular window the handler declined — CoverSkipped … NoLiquidity, a one-sided Down book at creation, and CallbackRan reports covered 0. It shows the handler running and refusing, which is the behaviour this project argues for; it bought nothing.
Why buying is delayed#
A new pool’s order book is empty at creation. Makers first quote somewhere between 5.5 and 10.2 seconds later. Buying in the creation block would mean buying nothing, or buying at the widest print of the window.
So creation enqueues the window and schedules a one-shot tick, which buys later. The retry ladder is bounded at three attempts; if the book has still not become priceable, the window is marked given up rather than left pending. The recorded history gave up on 7,374 windows that way, and each is on chain with its reason.
The engine set#
The vault approves a set of engines rather than one. Approval is additive by design, so a redeploy strands nothing: an older engine can still settle cover it opened before it was replaced.
That is not a theory. A retired engine with zero balance and no subscription settled a cover it had opened before the redeploy, crediting 200.00 tUSDC into the vault while a different, live engine was taking enrolments: 0xdafa9556f7f474c0… — vault 4,677.40 → 4,877.40 tUSDC.
Settlement#
Settlement reads the market’s payout vector and takes one of four branches. The one worth stating: a losing redemption succeeds and pays zero, rather than reverting. A revert would strand the position and require a rescue path; paying zero closes it cleanly and records the outcome.
Settling is permissionless — anyone can close a position, not only its holder — and if the market itself is stuck, poking the oracle and voiding an expired market are permissionless too. Nothing in the settlement path depends on us being around. See Limitations for what remains untested.