Skip to content

What is VRAND?

VRAND is a verifiable randomness protocol on Solana. It gives applications random values that come with a cryptographic proof — so a user, an auditor, or another program can check that the value was generated fairly, rather than taking anyone's word for it.

The problem it solves

On-chain applications cannot roll dice privately:

  • Math.random() (or any server-side RNG) is invisible to users and freely manipulable by whoever operates the code.
  • Blockhashes, slots, and timestamps are influenced or predictable by validators — they look random and are not.
  • A plain oracle that posts "random" numbers must be trusted twice: once not to lie, and once not to go conveniently silent.

A VRF (verifiable random function) solves the lying half: it is a keyed function where every input has exactly one valid output, and that output comes with a proof anyone can verify against the public key. The holder of the key can refuse to answer — but cannot answer falsely.

VRAND solves the silence half too, with staking: provers post a SOL bond, and a request can reserve part of that bond as its at-risk amount. If the prover misses its delivery window, anyone can trigger a slash that pays the requester exactly that amount. Crypto handles lying; staking handles silence.

The request lifecycle

request ──► PENDING ──► fulfill ──► FULFILLED   (beta = your outcome)

                 └────► slash  ──► SLASHED      (you were compensated)
  1. Request. Your transaction creates a request account. It freezes an input alpha = H(requester ‖ seed ‖ slot ‖ slothash ‖ key_epoch) — the slothash is the bank hash of the previous slot, a value nobody could have known before the request landed. This is what makes outcomes non-precomputable and non-re-rollable: the input is committed before the output can exist.

  2. Fulfill (permissionless). A prover evaluates the VRF on alpha with its registered key and submits an 80-byte proof. The on-chain verifier (native curve syscalls, ~39k CU median) checks it; only a valid proof can land, and it may land from anyone — prover replicas, cranks, even your own app. Fulfillment can never be paused, not even by the admin.

  3. Read. The 64-byte VRF output beta is stored in the request account. Your program or app shapes it into an outcome with the rejection-sampled scale helpers (never a bare % n — see Verifying outcomes).

  4. Or: slash. If the window (a network parameter, snapshotted per request) passes with no proof, anyone can slash: the request's at-risk amount moves from the prover's bond to the compensation account you named, and the request becomes terminal.

Finally, close returns the request account's rent (and any unspent fee escrow) to the payer. Closing is only possible in terminal states.

Roles

RoleWhoWhat they do
RequesterYour wallet (web) or your program's PDA (CPI)The identity bound into alpha; the only signer that can close the request
PayerThe human wallet funding the transactionPays rent + fee; must hold a one-time on-chain Terms acknowledgment
ProverA bonded operator with a registered VRF keyDelivers proofs, earns 100% of fees, loses bond on silence
comp_destAn account the requester controlsReceives slash compensation

The two properties everything rests on

  • Uniqueness — one input, exactly one possible output. The suite (VRAND-R255-TAI, an ECVRF over ristretto255) is specified, frozen-vector tested, and cross-checked byte-exactly against reference implementations.
  • Permissionless resolutionfulfill and slash can never be blocked by an admin, a pause flag, or a prover. These are protocol invariants, not policies.

Where to go next

Apache-2.0. Live on Solana devnet.