Randomness Tutorial
Example Code: The complete working example for this tutorial is available at sb-on-demand-examples/evm/randomness/pancake-stacker
Try It Out
Play Pancake Stacker directly in your browser! Connect your wallet (MetaMask or Phantom), enter the contract address, and start flipping pancakes.
Contract Address (Monad): 0x8A48241ba47298BBCb417834C6A95860D4273B6B
This tutorial walks you through building Pancake Stacker, a simple on-chain game that demonstrates Switchboard's randomness system. You'll learn how to request, resolve, and use verifiable randomness in your EVM smart contracts.
What You'll Build
A game where players flip pancakes onto a stack:
Each flip has a 2/3 chance of landing successfully
Successful flips increase your stack height
A failed flip knocks over your entire stack (resets to 0)
Randomness is generated off-chain by Switchboard oracles and verified on-chain
Mapping to the Randomness Flow
Before diving into code, let's connect this example to the conceptual flow described in the Randomness Overview. The five parties are:
Alice
You (running the script or using the UI)
App
PancakeStacker smart contract
Switchboard Contract
ISwitchboard interface
Crossbar
CrossbarClient from @switchboard-xyz/common
Oracle
Switchboard oracle (generates the randomness)
The two-stage flow maps directly to our two main functions:
Request Randomness →
flipPancake()Resolve Randomness →
catchPancake()
Prerequisites
Foundry installed for Solidity development
Bun or Node.js 18+
Native tokens for gas (e.g., MON for Monad)
Basic understanding of Solidity and ethers.js
Installation
Solidity SDK:
TypeScript SDK (for off-chain randomness resolution):
Forge remappings - Add to
remappings.txt:
The Smart Contract
Imports and State Variables
The contract tracks:
pendingFlips: Maps each user to their pending randomness request IDstackHeight: Maps each user to their current pancake stack countswitchboard: Reference to the Switchboard contract for randomness operations
Events
Events allow the off-chain script (or UI) to track the outcome of each flip.
Requesting Randomness: flipPancake()
This function implements the Request Randomness phase from the overview:
Flow mapping:
Alice calls the App (
flipPancake())App generates a unique
randomnessIdand calls Switchboard Contract (createRandomness)Switchboard Contract assigns an oracle and stores the request
App emits event with the
randomnessIdfor Alice to use later
Resolving Randomness: catchPancake()
This function implements the Resolve Randomness phase:
Flow mapping:
Alice sends the randomness object (obtained from Crossbar) to the App
App asks Switchboard Contract to verify the randomness (
settleRandomness)If valid, App retrieves the value (
getRandomness) and applies game logicApp emits the outcome event
Helper Function: getFlipData()
This view function provides the data needed for off-chain resolution:
The Off-Chain Script
The stack-pancake.ts script demonstrates how to interact with the contract from off-chain. While the example repository also includes a React UI, the script is simpler to understand and follows the exact same flow.
Note: The UI code does the same thing as this script, but with React state management and a visual interface. Understanding this script is sufficient to understand how any client (UI, bot, etc.) interacts with the randomness system.
Setup
Step 1: Check Current Stats
Step 2: Request Randomness (Flip the Pancake)
This triggers the Request Randomness phase on-chain.
Step 3: Get Flip Data
The contract returns:
randomnessId: Unique identifier for this requestoracle: Address of the assigned oraclerollTimestamp: When the randomness was rolledminSettlementDelay: Minimum wait time before settlement
Step 4: Resolve Randomness via Crossbar
This is where Crossbar talks to the Oracle and returns the encoded randomness proof.
Step 5: Settle On-Chain (Catch the Pancake)
Step 6: Parse Events for Outcome
Complete Flow Diagram
Security Considerations
CEI Pattern (Checks-Effects-Interactions)
Notice that catchPancake() clears pendingFlips[msg.sender] before making external calls:
This prevents reentrancy attacks.
Settlement Delay
The minSettlementDelay (set to 1 second in this example) ensures the randomness can't be resolved instantly. This gives the oracle time to generate the randomness after the request is made, preventing manipulation.
Try-Catch for Settlement
The contract gracefully handles settlement failures by catching exceptions and resetting the player's state, rather than leaving them stuck with an unresolvable pending flip.
Running the Example
1. Clone and Install
2. Configure Your Wallet
Security: Never use
export PRIVATE_KEY=...—it appears in shell history. Use Foundry's encrypted keystore instead.
3. Deploy the Contract
4. Run the Script
Create a .env file (add to .gitignore):
Expected Output
Summary
You've now learned how to integrate Switchboard randomness into an EVM smart contract:
Request: Call
switchboard.createRandomness()with a unique IDResolve: Use
CrossbarClient.resolveEVMRandomness()to get the oracle's signed randomnessSettle: Call
switchboard.settleRandomness()to verify andgetRandomness()to retrieve the valueUse: Apply the random value to your game logic
This pattern works for any application requiring verifiable randomness: games, NFT mints, lotteries, and more.
Last updated