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.
switchboard-on-demand = "0.11.3"(Solana Rust)@switchboard-xyz/[email protected](EVM off-chain resolution)@switchboard-xyz/[email protected](EVM on-chain interfaces)
Preconditions
OperatorPolicyexists (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)
Create randomness account (one-time) or reuse (
sb.Randomness.create(...)).Commit in the same transaction as the randomized action (
randomness.commitIx(queue)).Wait oracle generation window.
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 withRandomnessAccountData(for exampleseed_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_slotin 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)
Request on-chain with a unique
randomnessId.Resolve off-chain via Crossbar to obtain an encoded settlement payload.
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