Overview
Randomness is fundamental for lotteries, games, NFT minting, and random selection. However, generating truly unpredictable and manipulation-resistant randomness on a deterministic blockchain is one of the hardest problems in smart contract development. FHEVM introduces encrypted on-chain randomness: random values that are encrypted at creation time — nobody can see the random value, not even the block producer or the contract itself. This makes front-running and manipulation mathematically impossible.The Problem with On-Chain Randomness
Why Is Randomness Hard on Blockchain?
Blockchains are deterministic state machines. Every node must compute the same result for the same input. This conflicts with randomness — if everyone can compute the same “random” value, it is not random at all.Common (Broken) Approaches
block.timestamp
block.timestamp
- Block producers can adjust
block.timestampwithin allowed bounds (~15 seconds) - The value is known before the transaction is mined
- Anyone watching the mempool can predict the outcome
block.prevrandao
block.prevrandao
- Validators know
prevrandaobefore they propose the block - They can choose to include or exclude transactions based on the outcome
- MEV bots can front-run transactions that depend on it
blockhash
blockhash
- The blockhash is known to all participants before the next block
- Block producers can withhold blocks if the hash produces an unfavorable result
Chainlink VRF vs FHE Randomness
| Feature | Chainlink VRF | FHE Randomness |
|---|---|---|
| Randomness quality | Cryptographically secure | Cryptographically secure |
| Latency | 2+ blocks (async callback) | Same transaction (synchronous) |
| Cost | LINK token + gas | Gas only |
| Privacy | Random value is public | Random value is encrypted |
| Front-running | Value visible in callback tx | Value never visible |
| External dependency | Chainlink oracle network | Built into the chain |
Critical difference: Chainlink VRF generates a random value that becomes public when delivered. FHE randomness generates a random value that remains encrypted — it can be used in computations without ever being revealed.
FHE-Based Randomness
How It Works
- The FHE coprocessor generates a cryptographically secure random value
- The value is immediately encrypted under the network’s FHE public key
- The encrypted ciphertext is returned to your contract
- Nobody can see the plaintext value
Why It Is Manipulation-Proof
Block Producers
Cannot see the random value because it is encrypted
Validators
Cannot include/exclude transactions based on outcome — the outcome is hidden
MEV Bots
Cannot front-run because the value is never exposed in mempool
The Contract
Cannot read the value — it can only perform encrypted operations on it
Available Random Functions
| Function | Return Type | Range | Description |
|---|---|---|---|
FHE.randEbool() | ebool | true/false | Encrypted random boolean |
FHE.randEuint8() | euint8 | 0 – 255 | Encrypted random 8-bit integer |
FHE.randEuint16() | euint16 | 0 – 65,535 | Encrypted random 16-bit integer |
FHE.randEuint32() | euint32 | 0 – 4,294,967,295 | Encrypted random 32-bit integer |
FHE.randEuint64() | euint64 | 0 – 18.4 quintillion | Encrypted random 64-bit integer |
FHE.randEuint128() | euint128 | 0 – 2^128 - 1 | Encrypted random 128-bit integer |
FHE.randEuint256() | euint256 | 0 – 2^256 - 1 | Encrypted random 256-bit integer |
Basic Usage
RandomDemo.sol
Random in Range
Raw random values span the full range of their type. In most applications, you need a value within a specific range.Using FHE.rem() to Bound Values
RandomDemo.sol
Common Patterns
Dice Roll (1–6)
Card Draw (0–51)
Random Percentage (0–99)
Bounded Random (Power-of-2 Ranges)
For ranges that are powers of 2, fhEVM provides more efficient overloaded functions:Practical Example: Encrypted Lottery
EncryptedLottery.sol
Why This Is Secure
| Attack Vector | Protection |
|---|---|
| Owner sees random before committing | Random is encrypted — owner cannot see it |
| Owner redraws until favorable | drawn flag prevents redrawing |
| Player front-runs the draw | Random is generated in the draw tx, not predictable |
| Miner/validator manipulation | Encrypted value is hidden from block producers |
Use Cases
Lottery and Raffle
Select winners fairly without any party knowing the outcome until reveal
Gaming: Dice and Cards
Generate game outcomes that cannot be predicted or manipulated
NFT Trait Randomization
Assign random traits at mint time without revealing until owner chooses
Random Selection
Pick a random participant from a group without revealing who is selected
Dice and Cards
NFT Trait Randomization
Gas Optimization Tips
Use the Smallest Type
Use FHE.randEbool() for Binary Decisions
Common Pitfalls
Pitfall 1: Forgetting ACL After Generation
Pitfall 2: Forgetting ACL After Operations
Pitfall 3: Modulo Bias with Small Source Types
Combining Randomness with Other Patterns
Random + Conditional Logic
Random + Decryption
Summary
| Concept | Details |
|---|---|
| Synchronous | Random values available in the same transaction |
| Encrypted | Nobody can see the value until explicitly decrypted |
| Manipulation-proof | Block producers, validators, MEV bots cannot exploit |
| ACL required | Always call FHE.allowThis() and FHE.allow() after generation |
| Use smallest type | euint8 for small ranges, euint64 only when needed |
FHE.rem(value, max) | Bound random to range [0, max) |
| Modulo bias | Negligible when source type is much larger than the range |
- FHE randomness is the strongest on-chain randomness — values are encrypted at creation
- Use
FHE.rem()to bound values to a specific range - Always set ACL permissions on generated random values
- Choose the smallest type that fits your use case for gas efficiency
- Operations on random values produce new ciphertexts — set ACL on the final result
Next Module
Integrate FHEVM into your frontend application