Arkiv Ideathon · DeFi track · idea sketch

Last Look

A trader can promise you a price, watch you accept it, and then walk away — and by the time you object, the price they broke has already vanished. Make the offer expire on schedule and the receipt outlive it, and refusing stops being free.

Start here

Picture a currency exchange counter at an airport. The board says £1 = $1.25, good for the next 12 seconds. You walk up and say yes. The man behind the counter glances at his screen, sees the rate has just moved, and says: sorry, that one's gone.

If it had moved the other way he would have taken your money without a word. He wins in both directions.

And you cannot even complain, because the price he offered was only on the board for 12 seconds and it is already gone. There is no record of what he promised. It is your word against his.

That counter is a market maker. The board is a quote. Walking up is a trader taking it. And "sorry, that one's gone" happens billions of dollars a day under the name last look — the maker's right to see that you want to trade and only then decide whether to honour the price.

The fix, in one move

Write four kinds of note, and give them deliberately different lifespans. The offer is allowed to die. The evidence that someone accepted it is not.

In plain wordsCalledHow long it livesWho writes it
The price on the boardQuoteexactly as long as it is binding — 12sthe maker
"I accept, at these terms"Hit7 daysthe trader
Honoured it / walked awaySettle7 daysthe maker
"I was at the counter"Heartbeat30 daysthe maker
taker hits t = 20s Quote · firmFor = 12s written by the maker · $creator Hit · expiresIn = disputeWindow (7d) written by the taker · $creator Settle · outcome = 2 REFUSED written by the maker · $creator 0s 12s 20s 7 days Query the book at t = 8s eq(pair,"cow:WETH/USDC") AND eq(side,2) AND lt(priceMinor,…) 1 result — firm for 4 more seconds Everything returned is still binding. Same query at t = 20s 0 results The quote is not filtered out. It is not there. eq($creator,maker) AND eq(outcome,2) …still returns the refusal. The receipt survives.
Green is the offer, and it is short. Blue is the acceptance and the outcome, and they run a full week. That difference in length is the entire idea.

Ask the same question twice

This is the whole product in one screen. You ask the system what is on the board right now.

At 8 seconds

1 offer — firm for 4 more seconds

Anything the system hands you is binding. You never have to check whether a price is stale, because a stale price cannot be returned to you.

At 20 seconds

0 results

The expired offer is not shown to you greyed out. It does not exist any more. Firmness stops being a promise the maker makes and becomes a property of the database.

Now ask a different question — show me the times this maker walked away — and it all comes back. The offer vanished on schedule. The receipt is still sitting there, six days from now, written by the person who was refused.

A maker who sees intent and then declines holds a free option on every quote they publish. Today the refusal leaves no trace, because the quote it broke has already expired.

The four records

EntityLifetimeAttributes
Quote expiresIn = firmFor quoteId · pair "cow:WETH/USDC" · side 1 bid / 2 ask · priceMinor (the range attribute) · priceTier, a log10 band · sizeMinor · firmFor, even, since lifetimes count in 2s blocks · termsHash · $creator = maker
Hit expiresIn = disputeWindow, 7d quoteId · quoteHash, the exact terms the taker saw · makerRef · takenMinor · $creator = taker
Settle expiresIn = disputeWindow quoteId · outcome 1 filled / 2 REFUSED / 3 partial · filledMinor · txRef · $creator = maker
Heartbeat 30d quoteId · $creator = maker. Append-only, so there is no counter to overwrite and nothing to race.

Range-queried attributes are integers; strings match by equality only. Money is carried in minor units, never floats. Every entity carries quoteId because Arkiv has no joins — the client fetches by that key. There is no updateEntity anywhere: it replaces the whole entity and races concurrent writers, which is the wrong primitive for two-party evidence. Only extendEntity, so a re-quote is a change of lifetime rather than a new signed blob.

The four queries it lives on

QuestionPredicate
What is actually on the board?eq(pair,…) AND eq(side,2) AND lt(priceMinor,…)
What am I bound to right now? (maker)eq($creator,me) over live Quotes
Who took my price and must be honoured?eq(makerRef,me) over live Hits
How often does this maker actually fill?count() eq($creator,maker) AND eq(outcome,1) vs eq(outcome,2)

There is no server-side ORDER BY, so sorting after a limit gives you the top of a page rather than the best price. priceTier narrows the filter until the candidates fit one fetch and the client sorts them.

Why it cannot be the venue's database

Fill rate becomes a number anyone can count: honoured against refused, computed from records the maker never wrote alone. Reputation is a query, not a badge, and never one the maker issues about themselves.

The three records are written by different parties in turn — maker, then trader, then maker — and the chain stamps who wrote each one. So neither side can forge the half they did not write, and neither can the venue.

Which is the point. The venue takes a cut of the flow it would be reporting on. Trust us, this maker fills 99% of the time is exactly the claim you should not accept from whoever is being paid for the trade. A venue that can forge a quote can forge the refusal record for it.

What deliberately stays off Arkiv

Matching, routing and settlement: the hot path is untouched. Arkiv holds the offer and the evidence; the venue reads and acts. Funds are never custodied — a Settle records an outcome, nothing more. The signed quote payload stays off-chain behind termsHash. Maker inventory, hedge state and reserves stay off entirely, because anything whose value depends on secrecy cannot live in a publicly queryable store.

Accepted openly: anyone can read the whole live book, competing makers included. For price discovery that is a feature, and it is why the quote is written down and the strategy behind it never is.