Native, Secure, and Fast — Built Into the Sui Protocol
Move Threshold CryptographyLive Demo
Use ← → arrow keys or click to navigate
Blockchains are deterministic state machines — every node must independently arrive at the exact same state after processing the same transactions. This fundamental property makes generating unpredictable randomness impossible natively on most chains.
All nodes run the same code with the same inputs. If you use block.timestamp or blockhash, every node sees the same value. An attacker can pre-compute outcomes before submitting a transaction.
Gaming (loot drops, matchmaking), NFT trait distribution, governance lotteries, DeFi randomized airdrops, on-chain raffles — all require fair, unpredictable, and verifiable outcomes.
Front-running: MEV bots see your randomness call and act first.
Test-and-abort: Simulate outcomes off-chain, only commit if favorable.
Gas manipulation: Influence transaction ordering to bias results.
Developers have tried many workarounds. Most introduce centralization, cost, or security trade-offs.
| Approach | How It Works | Why It Fails |
|---|---|---|
| Block Hash / Timestamp | Use blockhash or timestamp as a seed | Miners/validators can manipulate block contents and timing. Fully predictable. |
| Oracle Services (Chainlink VRF) | Off-chain oracle generates randomness and delivers it on-chain | Requires trusting the oracle operator. Adds latency and cost per request. |
| Commit-Reveal Schemes | Users commit hashes, then reveal seeds later | Complex UX, requires multiple rounds, users can refuse to reveal. |
| RANDAO | Validators commit to random values that get combined | Last revealer can bias the outcome by choosing to reveal or abort. |
Sui embeds randomness directly into the validator protocol. At every epoch, validators run a Distributed Key Generation (DKG) ceremony to create a shared secret that no single validator knows. This secret powers a continuous randomness beacon.
At each epoch boundary, validators collaboratively generate a BLS12-381 key pair. The private key is never assembled in one place — each validator holds only a key share. A threshold of shares (e.g., 2/3 of validators) is required to produce a valid signature.
During the epoch, validators use their shares to sign a deterministic message (e.g., the round number). The aggregated signature is random, unpredictable, and verifiable by anyone using the public key. Because it's threshold-based, no single validator can bias it.
The beacon runs parallel to consensus — it does not block transaction execution. New randomness rounds are produced continuously, and Move contracts can consume fresh values within the same epoch. This means low latency without sacrificing security.
1. Validators agree on a new committee.
2. Each validator generates a private key share using verifiable secret sharing (VSS).
3. The public key is published on-chain for verification.
4. If a validator is offline, the threshold still holds as long as enough honest validators participate.
1. Each validator signs the current round number with their share.
2. Signatures are aggregated into a single BLS threshold signature.
3. The signature is hashed to produce a randomness output.
4. Any client can verify the output against the public key — no trust needed.
Sui exposes randomness through a shared Random object that lives at a well-known address. Your contract borrows it, creates a generator, and draws values. The compiler enforces safety rules automatically.
generate_u8() / u16 / u32 / u64 / u128 / u256()generate_u64_in_range(min, max)generate_bytes(n) — raw byte vectorshuffle(vector<T>) — Fisher-Yates shuffle
Randomness-dependent functions must be entry — not public. This prevents attackers from calling them programmatically inside a PTB to test outcomes and abort if unfavorable. The compiler enforces this at build time.
Sui's randomness is not just a number generator — it is a defense system designed to neutralize the most common on-chain randomness exploits.
| Attack Vector | How It Works | Sui's Defense |
|---|---|---|
| Front-Running MEV | Attacker sees your randomness transaction in the mempool and inserts their own transaction before it to steal the outcome. | Randomness is unpredictable at transaction submission time. Even if an attacker sees your tx, they cannot compute the outcome before it executes. The beacon output depends on validator aggregation that happens at execution. |
| Test-and-Abort | Attacker writes a PTB that calls a randomness function, checks the result, and aborts if unfavorable. They retry until they win. | Move compiler rejects public functions that depend on randomness. Only entry functions can consume it. Entry functions cannot be called programmatically within a PTB for conditional abort — the compiler enforces this. |
| Gas Manipulation | Attacker manipulates gas price or transaction ordering to land in a specific block where they predicted the randomness. | Built-in restrictions prevent attackers from gaming gas budgets to influence randomness outcomes. The beacon runs independently of transaction ordering. |
| Single Validator Bias | A malicious validator tries to influence the randomness by withholding or manipulating their signature share. | Threshold cryptography ensures no single validator can influence the output. A minimum quorum (e.g., 2/3 of stake) is required to produce a valid signature. A minority of malicious validators cannot bias the result. |
Keep randomness-dependent code in its own entry function. Do not mix it with state reads that could leak information. The outcome should be committed atomically.
Never expose a public function that returns a random value and then lets the caller decide what to do. The compiler blocks this, but design matters too.
Once randomness is consumed, write the result to on-chain state immediately. Do not hold it in a temporary variable across multiple transactions where it could be observed.
Always create a fresh RandomGenerator for each randomness operation. Reusing a generator across multiple independent decisions can leak correlation information.
Loot boxes: Random item drops with verifiable rarity.
Matchmaking: Shuffle player queues fairly.
Card games: Shuffle decks without client trust.
Procedural worlds: Seed terrain generation on-chain.
Blind mints: Reveal traits after purchase.
Rarity distribution: Weighted trait tables.
Randomized art: Compose layers from a seed.
Airdrops: Fair selection from a whitelist.
Lottery pools: Winner selection without oracle fees.
Randomized drops: Surprise token distributions.
Committee selection: Random validator sub-sampling.
DAO voting: Tie-breaking without bias.
Traditional solutions require oracles (cost + trust), commit-reveal (bad UX), or block hashes (exploitable). Sui provides sub-second latency, zero extra cost, and protocol-level security — making randomness viable for high-frequency use cases like real-time gaming.
Testing randomness is tricky because the output is non-deterministic. Sui Move provides test-only helpers to inject controlled randomness for reproducible tests.
1. Use random::create_for_testing() for deterministic seeds.
2. Test boundary conditions (empty lists, single participants).
3. Test that public functions with randomness fail to compile.
4. Use #[expected_failure] for abort paths.
For large-scale validation, run your contract thousands of times in tests and verify distribution properties (e.g., chi-squared test on rarity outcomes). This catches biased generators.
entry functions only.new_generator() → generate_*() / shuffle(). Security depends on proper design patterns: isolate, commit, don't expose intermediate state.random::create_for_testing() for reproducible unit tests, and validate statistical fairness for production contracts.