Switchboard Randomness Skill

Purpose

Implement verifiable randomness with Switchboard:

  • Solana: commit → generate → reveal (commit-reveal)

  • EVM: request → resolve via Crossbar → settle on-chain

Dependencies

Use exact pins from the SDK Version Matrix.

Preconditions

  • OperatorPolicy exists (approval/spend limits for on-chain calls).

Inputs to Collect

  • chain + network

  • app contract/program identifiers

  • minimum settlement delay requirement

  • binding requirement (what state transition must be gated)

  • replay protections and failure handling requirements

Minimal Example

Solana settle/read (commit-reveal flow):

EVM request + settle:

Solana Playbook (commit/reveal)

  1. Create randomness account (one-time) or reuse (sb.Randomness.create(...)).

  2. Commit in the same transaction as the randomized action (randomness.commitIx(queue)).

  3. Wait oracle generation window.

  4. Reveal and settle in a follow-up transaction (randomness.revealIx()).

Requirements:

  • bind commit to action

  • prevent replay/double-settle

  • retries with exponential backoff

Solana Account and Timing Reference

What the account structure looks like:

  • Switchboard randomness account: created via sb.Randomness.create(...); stores commit/reveal state parsed with RandomnessAccountData (for example seed_slot, revealed bytes).

  • App-owned state/PDA: your program state that binds business logic to randomness (for example storing randomness_account, commit_slot, wager/round state).

What PDA seeds to use:

  • Switchboard randomness account is not documented as an app PDA derivation pattern in this skill; create it using sb.Randomness.create(...).

  • App PDAs are application-specific. Tutorial examples use seeds like [b"playerState", user.key().as_ref()] and [b"stateEscrow"] for app state/escrow.

How oracle assignment works:

  • Assignment is handled by Switchboard during request/commit and validated during reveal/settlement.

  • Integrators should bind commit and reveal to the same randomness account reference (store at commit, verify at settle) and verify expected slot linkage (for example seed_slot == commit_slot in app state).

Generation window duration:

  • Treat timing as a policy decision, not a hard-coded universal duration.

  • For safety-sensitive flows, recommended strict policy is fresh-slot usage (for example seed_slot == clock.slot - 1).

  • For less latency-sensitive flows, you can allow a looser freshness bound if your threat model allows it.

How to check readiness for reveal:

  • On-chain: use RandomnessAccountData::get_value(clock.slot).

    • Commit path guard: if it already returns Ok(_), randomness was already revealed.

    • Settle path guard: require Ok([u8; 32]), otherwise treat as not yet resolved.

  • Client-side: retry randomness.revealIx() with backoff until reveal succeeds.

Compact on-chain pattern:

EVM Playbook (request/resolve/settle)

  1. Request on-chain with a unique randomnessId.

  2. Resolve off-chain via Crossbar to obtain an encoded settlement payload.

  3. Settle on-chain, then read randomness value and execute logic.

Contract requirements:

  • enforce minimum settlement delay

  • CEI pattern (clear state before external calls)

  • validate oracle assignment matches stored assignment

References

  • https://docs.switchboard.xyz/docs-by-chain/solana-svm/randomness

  • https://docs.switchboard.xyz/docs-by-chain/evm/randomness

  • https://docs.switchboard.xyz/tooling/crossbar

Last updated