Randomness Tutorial

Example Code: The complete working example for this tutorial is available at sb-on-demand-examples/evm/randomness/pancake-stackerarrow-up-right

Try It Out

Play Pancake Stacker directly in your browser! Connect your wallet (MetaMask or Phantom), enter the contract address, and start flipping pancakes.

Play Pancake Stackerarrow-up-right

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:

Conceptual Party
In Pancake Stacker

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 RandomnessflipPancake()

  • Resolve RandomnesscatchPancake()

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

  1. Solidity SDK:

  1. TypeScript SDK (for off-chain randomness resolution):

  1. 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 ID

  • stackHeight: Maps each user to their current pancake stack count

  • switchboard: 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:

  1. Alice calls the App (flipPancake())

  2. App generates a unique randomnessId and calls Switchboard Contract (createRandomness)

  3. Switchboard Contract assigns an oracle and stores the request

  4. App emits event with the randomnessId for Alice to use later

Resolving Randomness: catchPancake()

This function implements the Resolve Randomness phase:

Flow mapping:

  1. Alice sends the randomness object (obtained from Crossbar) to the App

  2. App asks Switchboard Contract to verify the randomness (settleRandomness)

  3. If valid, App retrieves the value (getRandomness) and applies game logic

  4. App 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 request

  • oracle: Address of the assigned oracle

  • rollTimestamp: When the randomness was rolled

  • minSettlementDelay: 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:

  1. Request: Call switchboard.createRandomness() with a unique ID

  2. Resolve: Use CrossbarClient.resolveEVMRandomness() to get the oracle's signed randomness

  3. Settle: Call switchboard.settleRandomness() to verify and getRandomness() to retrieve the value

  4. Use: 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