Appearance
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)Request. Your transaction creates a request account. It freezes an input
alpha = H(requester ‖ seed ‖ slot ‖ slothash ‖ key_epoch)— theslothashis 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.Fulfill (permissionless). A prover evaluates the VRF on
alphawith 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.Read. The 64-byte VRF output
betais stored in the request account. Your program or app shapes it into an outcome with the rejection-sampledscalehelpers (never a bare% n— see Verifying outcomes).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
| Role | Who | What they do |
|---|---|---|
| Requester | Your wallet (web) or your program's PDA (CPI) | The identity bound into alpha; the only signer that can close the request |
| Payer | The human wallet funding the transaction | Pays rent + fee; must hold a one-time on-chain Terms acknowledgment |
| Prover | A bonded operator with a registered VRF key | Delivers proofs, earns 100% of fees, loses bond on silence |
| comp_dest | An account the requester controls | Receives 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 resolution —
fulfillandslashcan never be blocked by an admin, a pause flag, or a prover. These are protocol invariants, not policies.
Where to go next
- Build a web app → Quickstart: Web
- Build a Solana program → Quickstart: Anchor
- Understand the guarantees → Security model
- Understand the costs → Economics