What a span is
A span is a fully funded contract on one release hour of SOL. A perp is paid on the candle's body, open to close. A span is paid on the candle, from the bottom of the lower wick to the top of the upper wick, past a length set on each ticket. Direction does not enter the payout.
payout = min(40, 10 × max(100 × (high − low) / open − length, 0)) USDC, length in percent. A 2% ticket on a 3% candle pays 10 USDC. Past 6%, it pays the full 40. A 0% ticket is paid on the whole candle.
The length
The seller sets a length on each ticket, from 0% to 5% in steps of 0.25%. The ticket is paid only for the candle past it. A longer length pays less often; the premium is the seller's to set.
The release candle
Each candle belongs to one published US release: CPI, PPI and the jobs report at 08:30 ET, FOMC statements at 14:00 ET, and the US equity open at 09:30 ET on trading days. The candle opens one minute before the release and lasts sixty minutes. Opening it a minute early puts the release's first move inside the candle.
| Release | Opens | Closes |
|---|
Reads
The keeper reads the price every 300 seconds, thirteen times per candle counting the open. A read is accepted only if the DOVES price was published within — seconds after the read's boundary and is at most — seconds old. Anyone can send a read; span runs a public keeper that sends all of them.
The keeper sends each read on the first DOVES price published at or after the boundary. A price inside a read's window waits for the read before it is used as a wick.
A missed read does not move the wicks. Missing data favors the seller. A ticket carrying SPAN protects itself between reads.
SPAN wicks
Thirteen reads draw a candle with its wicks cut at five-minute marks. In the — jobs-report hours of 2026, those reads caught —% of the candle; on — they drew —% of an hour that reached —%.
A buyer can load SPAN into the ticket. The ticket's reader (the public keeper by default, or a key the buyer names) can then send readings between reads. A reading is accepted only if it stretches a wick by at least the buyer's smallest step. A reading that raises the payout burns a fixed amount of SPAN from the ticket. A reading below the length is recorded without a burn: a later wick on the other side can carry the candle past the length, and the earlier one is part of it. Unused SPAN is returned when the candle closes. Nobody else can burn a ticket's SPAN. The reader is the public keeper by default. To record your own wicks, choose your key and run the public keeper with it. Once the recorded candle is 4% past the ticket's length, no reading is accepted and nothing burns: the payout is already 40.
Payout and settlement
The seller deposits 40 USDC minus the premium when opening a ticket. The buyer pays the premium. — seconds after the candle closes, anyone can settle: the buyer receives the payout, the seller receives the rest of the 40. If the open read was missed, the candle is void and both sides get back what they put in.
| Candle (example) | Length | Buyer | Seller |
|---|
—
—
Tickets
| Instruction | Who | What it does |
|---|---|---|
open_candle | anyone | creates the candle the first time a ticket is opened on it |
open_ticket | seller | deposits 40 − premium and sets the length |
buy | buyer | pays the premium until — seconds before the candle opens |
load_span | buyer | loads SPAN, sets the smallest step and the reader |
read | anyone | records a five-minute read from DOVES |
mark | the ticket's reader | records a reading that stretches a wick by at least the smallest step; burns SPAN when it raises the payout |
settle | anyone | after close, splits the 40 USDC |
withdraw | seller | takes back an unsold ticket at any time |
—
Price
Prices come from Jupiter's DOVES oracle account for SOL, the same price Jupiter perps fill against. Reading it costs nothing.
// DOVES SOL/USD account, read on chain
price u64 at byte 168 // 8 decimals
publish_time i64 at byte 177 // unix seconds
—
Trust assumptions
- The admin can point span at another DOVES account for SOL. Open candles read the new account from their next read. The admin can change the read window, age limit and buy cutoff for candles opened later; an open candle keeps its own.
- A ticket's payout is capped at 40 USDC because the 40 USDC is already in the ticket. Nothing is borrowed.
- The public keeper pays at most — SOL a day to create receiving token accounts at settlement. Past that, a ticket waits, and anyone can settle it with their own key.
Data on this site
The candles here not marked on chain are replays: the DOVES SOL price of each 2026 release hour, rebuilt from the oracle account's own Solana transactions. The reads follow the program's rule. They were computed by this code:
// Read j (j = 0..12) is due at boundary b = t0 + 300 j. It takes the account as it stands once
// Clock reaches b, from the first value published at or after b. It holds only if that value
// was published in [b, b + W], is at most A seconds old at Clock, and read 0 holds.
function reads(S: State[], t0: number): (State | null)[] {
const out: (State | null)[] = [];
for (let j = 0; j <= 12; j++) {
const b = t0 + 300 * j;
let k = S.findIndex((s) => s.publish >= b);
while (k >= 0 && k < S.length && S[k].clock < b) k++;
const s = k >= 0 && k < S.length ? S[k] : null;
const held = s !== null && b <= s.publish && s.publish <= b + W && s.clock - s.publish <= A;
out.push(held && (j === 0 || out[0] !== null) ? s : null);
}
return out;
}
replay.ts · reads() · W = 20, A = 20
Each minute is drawn from its DOVES prices: open, low, high, close for a minute that closed up; open, high, low, close for one that closed down. That order inside the minute is a drawing. The wicks and every number on this site come from the recorded prices alone.