How to Create a Spin-the-Wheel Smart Contract on Sui Blockchain Using Move | by Ryan Adhitama Putra | January 2025
2 mins read

How to Create a Spin-the-Wheel Smart Contract on Sui Blockchain Using Move | by Ryan Adhitama Putra | January 2025


Stackademic

In this tutorial, we will learn how to create a “Spin the Wheel” gaming smart contract using the Move programming language on the Sui blockchain. Players spin a wheel with customizable segments and win multipliers. The outcome is determined randomly and an event records the outcome of the player’s turn.

This game allows players to:

  • Set the number of segments on the wheel (4 to 20).
  • Assign payout multipliers to each segment.
  • Spin the wheel and receive a multiplier based on the segment you landed on.

You will implement the following:

  1. A Move smart contract for game logic.
  2. A rotation mechanism based on chance.
  3. Events to record spin results.

Before you start coding, make sure you have the following setup:

  • About CLIs: Mandatory for contract deployment. Install your CLI.
  • Code editor: A good editor like VS Code or IntelliJ with the Move plugin.

Run the following command to create a new Sui Move project:

sui move new spinwheel

This will create a directory named spinwheel with the following structure:

spinwheel/
├── Move.lock
├── Move.toml
├── sources/
│ └── spinwheel.move
└── tests/
└── spinwheel_tests.move

Go to the project directory

cd spinwheel

Replace the contents of sources/spinwheel.move with your module code (explained in the following steps).

module spinwheel::spinwheel;

THE spinwheel::spinwheel The module defines a smart contract for a Spin The Wheel game built on the Sui blockchain using the Move programming language.

use sui::{
random::Random,
event,
};
  • random::Random: Provides functionality for generating random numbers.
  • event: Used to emit events that record game results for transparency.
public struct SpinResult has copy, drop, store {
player: address,
spin_result: u64, // The segment number landed on
multiplier: u64, // Payout multiplier for the segment
}
  • player: The address of the player who spun the wheel.
  • spin_result: The number of the segment where the wheel stopped.
  • multiplier: The payout multiplier for the landed segment.
const INVALID_SEGMENTS: u64 = 1;
const MIN_SEGMENTS: u8 = 4; // Minimum number of segments on the wheel
const MAX_SEGMENTS: u8 = 20; // Maximum number of segments on the wheel
  • INVALID_SEGMENTS: Error code used when the number of segments is invalid.
  • MIN_SEGMENTS: Minimum authorized number of segments (4).
  • MAX_SEGMENTS: Maximum authorized number of segments (20).
entry fun spin(
num_segments: u8,
multipliers: vector<u64>,
random: &Random,
ctx: &mut TxContext
) {
// Validate the number of segments
assert!(num_segments >= MIN_SEGMENTS && num_segments <= MAX_SEGMENTS, INVALID_SEGMENTS);

// Ensure multipliers length matches the number of segments
assert!(vector::length(&multipliers) == num_segments as u64, 1);

// Generate the spin result (random segment index)
let spin_result = generate_spin_result(num_segments, random, ctx);

// Determine the multiplier for the segment landed on
let multiplier = multipliers[spin_result as u64];

// Emit the result as an event
let player = ctx.sender();
event::emit(SpinResult {
player,
spin_result,
multiplier,
});
}

  • Valid that num_segments is within the permitted range (4–20).
  • Check that the multipliers the vector has the correct length to match the number of segments.
  • Generates a random spin result and determines the corresponding multiplier.
  • Issues a SpinResult event with game details.
fun generate_spin_result(num_segments: u8, random: &Random, ctx: &mut TxContext): u64 {
let mut gen = random.new_generator(ctx);
let random_number = gen.generate_u64();
let segment = random_number % (num_segments as u64); // Cast num_segments to u64

segment
}

  • Uses chance to generate a number between 0 And num_segments - 1.
  • Ensures compatibility by casting num_segments of the same type as the random number (u64).
module spinwheel::spinwheel;

use sui::{
random::Random,
event,
};

/// Struct to store the result of a spin
public struct SpinResult has copy, drop, store {
player: address,
spin_result: u64, // The segment number landed on
multiplier: u64, // Payout multiplier for the segment
}

// === Constants ===
const INVALID_SEGMENTS: u64 = 1;
const MIN_SEGMENTS: u8 = 4; // Minimum number of segments on the wheel
const MAX_SEGMENTS: u8 = 20; // Maximum number of segments on the wheel

// === Public-Mutative Functions ===

/// Spin the wheel and calculate the result
entry fun spin(
num_segments: u8,
multipliers: vector<u64>,
random: &Random,
ctx: &mut TxContext
) {
// Validate the number of segments
assert!(num_segments >= MIN_SEGMENTS && num_segments <= MAX_SEGMENTS, INVALID_SEGMENTS);

// Ensure multipliers length matches the number of segments
assert!(vector::length(&multipliers) == num_segments as u64, 1);

// Generate the spin result (random segment index)
let spin_result = generate_spin_result(num_segments, random, ctx);

// Determine the multiplier for the segment landed on
let multiplier = multipliers[spin_result as u64];

// Emit the result as an event
let player = ctx.sender();
event::emit(SpinResult {
player,
spin_result,
multiplier,
});
}

// === Private Functions ===

/// Generate a random spin result (segment index between 0 and `num_segments - 1`)
fun generate_spin_result(num_segments: u8, random: &Random, ctx: &mut TxContext): u64 {
let mut gen = random.new_generator(ctx);

// Generate a random number and calculate the segment index
let random_number = gen.generate_u64();
let segment = random_number % (num_segments as u64); // Cast num_segments to u64

segment
}

Follow these steps to deploy your spinwheel module:

Compile the contract
Navigate to the project directory and run:

sui move build

Publish the contract
Use the Sui CLI to publish the module:

sui client publish --gas-budget 100000000

Package deployed

Call him spin work with the following command:

sui client call \
--package <PackageId> \
--module spinwheel \
--function spin \
--args <num_segments> '[<multiplier1>, <multiplier2>, ...]' <Random_ObjectId> \
--gas-budget 10000000
  • Replace <PackageId> with the ID of your deployed spinwheel module.
  • Replace <num_segments> with the number of segments (4–20).
  • Replace the multiplier table with values ​​corresponding to the number of segments.
  • Replace <Random_ObjectId> with the identifier of Random object in your environment.

Example

sui client call \
--package '0x42f79866f445dcef3d65439b9f87442beebabf0f7032a74553daa1d74024b901' \
--module spinwheel \
--function spin \
--args 6 '[0,1,2,1,3,0]' '0x0000000000000000000000000000000000000000000000000000000000000008' \
--gas-budget 10000000

Before leaving:



Grpahic Designer