Skip to content

Accounts & layouts

Byte offsets are exported as constants by the zero-dependency vrand-interface crate and pinned by layout tests — the numbers below are documentation of those constants, not a second source of truth.

Request (460 bytes)

One randomness request. PDA: ["request", requester, seed].

FieldOffsetSizeMeaning
discriminator08[125, 172, 150, 161, 162, 115, 39, 71]
requester832identity bound into alpha; only signer that can close
payer4032paid rent + fee; receives them back at close
comp_dest7232receives slash compensation
prover10432the prover PDA this request pins
vrf_pubkey13632the exact key the proof must verify under
key_epoch1688prover key epoch at request time
seed17632your 32-byte seed
alpha20832the frozen VRF input
request_slot2408slot the request landed in
at_risk_lamports2488coverage bought
fee_lamports2568escrowed fee
fulfill_window_slots2648deadline window, snapshotted
state27210 = PENDING, 1 = FULFILLED, 2 = SLASHED
fulfilled_slot2738slot the proof landed
tai_ctr2812hash-to-curve counter; 0xffff = fallback-resolved
proof28380the VRF proof (zeroed until fulfilled)
beta36364the VRF output — only meaningful when state = FULFILLED
bump4271
slothash42832the bank-hash entry alpha commits to (persisted because no RPC serves bank hashes)

Readers must check the account owner is the VRAND program before trusting any offset, and must treat beta as absent unless state == FULFILLED — the SDK accessors enforce both.

Address reuse is intentional

After a resolved request is closed, the same (requester, seed) re-derives the same address and can be created afresh with an independent outcome. Key your application state on outcome data (beta, fulfilled_slot), never on the request address alone.

Network (singleton)

Admin key, pause flag (new requests only — never resolution), and the parameters, each bounded on-chain so no setting can become a shutdown.

Prover

PDA: ["prover", operator].

FieldMeaning
operatorthe operator's wallet — receives fees, controls the bond
vrf_pubkey, key_epochthe registered key (rotation bumps the epoch; in-flight requests stay pinned to the old key)
status0 = ACTIVE, 1 = UNBONDING, 2 = REVOKED — only ACTIVE provers take new requests
bond_lamportstotal bonded SOL (held as PDA lamports)
reserved_lamportscommitted to open requests; invariant bond ≥ reserved
pending_requestsopen-request counter; withdrawal requires 0

Available coverage for a new request = bond − reserved (and per-request at most max_single_at_risk_bps of the bond).

TermsState & Acknowledgment

TermsState (["terms"], singleton) holds the current terms version and SHA-256 hash. Acknowledgment (["ack", wallet], 83 bytes) records a wallet's acceptance of a specific version+hash; request requires the payer's acknowledgment to match the current terms exactly.

Apache-2.0. Live on Solana devnet.