Docs / Protocol

The price book and the fill rule(15)

RedStone publishes packages on a 10-second grid: every timestamp is a multiple of 10,000 ms. Paper100 fills every request at a grid point the trader could not have seen when sending it.

The fill rule

[ Fig. 1 ] FILL TIMESTAMP (MS)
fillTs = (floor((requestTime + fillDelay) × 1000 / 10000) + 1) × 10000
fillDelay = 2 s by default (Config.fill_delay_s, admin-set between 0 and 10 s)

requestTime is the Solana clock time of your request, in seconds. The program adds a short fill delay, 2 seconds by default, so that a request sent in the last moments of an interval never fills at a price already being published. The fill is the first grid point strictly after that time. There is exactly one valid price per request, so nobody, the keeper and you included, can choose between prices. The trade page counts down to the exact fill_ts_ms stored in your request.

Request clock timeFills at the grid price of (2 s delay)
14:02:0314:02:10
14:02:0714:02:10
14:02:0814:02:20
14:02:1014:02:20

The price book

Verifying three signatures costs about 75,000 compute units, so each verified price is stored once and reused by every request and liquidation at that grid point. Each market has a PriceBook account (seeds ["book", market_id]): a ring of 64 entries {ts_ms, price}, where an entry lives in slot (ts_ms / 10000) % 64.

  • post_price(market_id, proof): anyone. Verifies the proof (signers, threshold, median, Pyth band) and writes the price into its slot if the slot is empty or holds an older timestamp.
  • execute(): anyone. Reads the entry whose timestamp equals the request's fillTs, then opens or settles the position.
  • execute_with_proof(proof): anyone. The fallback when the entry has already been overwritten (the ring covers 640 seconds, about ten minutes). It verifies the proof inline.
  • liquidate(): reads the newest entry, which must be at most 60 seconds old and newer than the position's open.

Who executes

A keeper run by the protocol watches requests, fetches the packages for each fillTs about 1.5 seconds after it, posts the price and executes, usually two seconds after the grid point. It has no special rights. If it is late, you can execute your own request from the trade page with the same packages, fetched from RedStone's historical endpoint.

When a price never comes

If the packages for a request's fillTs never existed, anyone can cancel the request after requestTTL (3,600 s). An open is refunded; a close is dropped and the position stays open. Before the TTL nobody can cancel, so a cancel is never an option on the price.