Free 30-min Web3 Consultation
Book Consultation
Smart Contract Security Audits
View Audit Services
Custom DeFi Protocol Development
Explore DeFi
Full-Stack Web3 dApp Development
View App Services
Free 30-min Web3 Consultation
Book Consultation
Smart Contract Security Audits
View Audit Services
Custom DeFi Protocol Development
Explore DeFi
Full-Stack Web3 dApp Development
View App Services
Free 30-min Web3 Consultation
Book Consultation
Smart Contract Security Audits
View Audit Services
Custom DeFi Protocol Development
Explore DeFi
Full-Stack Web3 dApp Development
View App Services
Free 30-min Web3 Consultation
Book Consultation
Smart Contract Security Audits
View Audit Services
Custom DeFi Protocol Development
Explore DeFi
Full-Stack Web3 dApp Development
View App Services
LABS
Guides

How to Design a Smart Contract-Based Randomization Module

A technical guide for developers building a secure, transparent, and regulator-compliant patient allocation system for clinical trials using blockchain.
Chainscore © 2026
introduction
INTRODUCTION

How to Design a Smart Contract-Based Randomization Module

A guide to implementing secure, verifiable, and unpredictable random number generation on-chain.

On-chain randomization is a critical component for many decentralized applications, from NFT minting and gaming to fair lotteries and protocol governance. Unlike traditional systems, smart contracts operate in a deterministic environment where every node must reach the same state. This makes generating a truly unpredictable number, a random number generator (RNG), one of the most challenging tasks in Web3 development. A poorly designed RNG can lead to predictable outcomes, enabling exploits and undermining user trust.

The core challenge is the blockchain oracle problem. Data from within a transaction's execution context—like block.timestamp, blockhash, or block.difficulty—is publicly visible to miners/validators and can be manipulated, making it an insecure source of entropy. A robust design must therefore separate the randomness generation from the randomness consumption, often by combining an on-chain commitment with an off-chain source or a decentralized oracle network like Chainlink VRF.

This guide outlines the architectural patterns for building secure randomization. We will cover the request-and-fulfill model used by verifiable randomness functions (VRF), the use of commit-reveal schemes for multi-party applications, and the trade-offs of RANDAO and VRF approaches. Each method balances security, cost, latency, and decentralization differently, and the correct choice depends heavily on your application's specific requirements and threat model.

We will implement a practical example using a hybrid approach. The contract will request randomness from a VRF oracle, receive a verifiable random number and cryptographic proof, and then use that number to power a function—like randomly assigning traits to an NFT. The code will demonstrate how to handle asynchronous callbacks, verify the oracle's response on-chain, and ensure the result is both provably fair and tamper-proof for all participants.

prerequisites
PREREQUISITES

How to Design a Smart Contract-Based Randomization Module

Before building a secure random number generator (RNG) on-chain, you must understand the core concepts and inherent challenges of blockchain-based randomness.

Blockchain's deterministic nature is its greatest strength and the primary obstacle to generating randomness. Every node must reach the same state, meaning a traditional Math.random() function is impossible. On-chain randomness must be provably fair and tamper-resistant. This requires external entropy sources, often called oracles, or cryptographic techniques like Verifiable Random Functions (VRFs). Understanding this fundamental constraint is the first step in designing a robust system.

You'll need proficiency in a smart contract language like Solidity or Vyper, and familiarity with development tools such as Hardhat or Foundry. Knowledge of core cryptographic concepts—including hashing (keccak256), digital signatures, and public-key cryptography—is essential. For testing, you should be comfortable writing unit and fuzz tests to simulate malicious actors and edge cases. A basic grasp of gas optimization is also important, as complex cryptographic operations can be expensive.

The security model is paramount. You must identify and mitigate key threats: predictability (can a user guess the outcome?), manipulability (can a miner/validator influence the result?), and withholding (can a participant refuse to reveal a result?). Common pitfalls include using blockhash, block.timestamp, or block.difficulty as sole entropy sources, as these are manipulable by miners. A secure design separates the randomness request from the randomness fulfillment to prevent front-running.

Several established solutions provide frameworks to build upon. Chainlink VRF is a widely audited oracle service that delivers cryptographically secure randomness. Commit-Reveal schemes, where a user submits a hashed commitment and later reveals the pre-image, are a classic on-chain pattern for fair draws. RANDAO and VRF-based designs used by protocols like dYdX and Avalanche offer alternative architectural blueprints. Study these to understand the trade-offs between decentralization, cost, and latency.

Finally, define your application's specific requirements. What is the cost tolerance per random request? What is the acceptable latency between request and fulfillment? How many participants need to be included in the randomness generation? Is the use case for a high-value NFT mint, a gaming loot box, or a decentralized lottery? The answers will dictate whether you integrate an oracle, implement a complex multi-party scheme, or use a simpler, more cost-effective solution for lower-stakes scenarios.

key-concepts
SMART CONTRACT DEVELOPMENT

Core Concepts for Randomization

Designing a secure and reliable randomization module requires understanding core cryptographic primitives and blockchain-specific constraints. This guide covers the essential building blocks.

01

Commit-Reveal Schemes

A foundational pattern for generating verifiably fair randomness on-chain. The process involves two phases:

  • Commit: A user or contract submits a hash of their secret random number and a public seed.
  • Reveal: After a delay, the original values are revealed. The final random number is derived from all revealed secrets. This prevents last-second manipulation, as the committer cannot change their secret after the hash is submitted. Used in early applications like lotteries and games.
03

RANDAO & VDFs

A decentralized randomness beacon built into Ethereum. RANDAO works by having participants submit hashes of random numbers in a round, with the final output being the XOR of all revealed values.

  • The main vulnerability is a last-revealer attack, where the final participant can withhold their reveal to influence the outcome.
  • Verifiable Delay Functions (VDFs) are proposed as a solution. A VDF imposes a mandatory time delay on the output computation, making it impossible for the last participant to compute and exploit the result in time. Ethereum's RANDAO/VDF combination aims to be a canonical source of blockchain randomness.
04

Block Hash as a (Weak) Source

Using blockhash(block.number - 1) is a common but insecure method for randomness.

  • Vulnerability: Miners/validators have limited influence over the block hash. They can discard blocks that contain unfavorable outcomes, a practice known as miner extractable value (MEV).
  • This method is only suitable for low-value, non-adversarial contexts. For any application involving economic value, a more robust solution like a VRF or commit-reveal is required.
05

Randomness Request Lifecycle

A secure module must manage the end-to-end flow. A typical VRF-based lifecycle includes:

  1. Request: Contract calls the oracle with a seed and pays the fee.
  2. Fulfillment: Oracle generates randomness off-chain and submits the result with a proof in a subsequent transaction.
  3. Verification & Consumption: Your contract's callback function verifies the proof using the oracle's public key, then uses the random number.
  • You must account for callback gas limits and implement failure handling for edge cases.
06

Entropy and Seed Design

The quality of randomness depends on a strong, unpredictable seed. Best practices include:

  • Combining multiple sources: keccak256(abi.encodePacked(vrfOutput, block.timestamp, msg.sender)).
  • Using globally unique request IDs provided by oracles to prevent replay attacks.
  • Avoiding seeds that a user can predict or control, which can lead to precomputation attacks. The seed should incorporate on-chain state that is finalized at the time of the request.
architecture-overview
SYSTEM ARCHITECTURE OVERVIEW

How to Design a Smart Contract-Based Randomization Module

A guide to architecting secure and verifiable on-chain randomness for applications like gaming, lotteries, and NFT minting.

On-chain randomness is a critical component for many decentralized applications, but generating it securely is a significant challenge. A naive approach using blockhash or block.timestamp is insecure and easily manipulated by miners or validators. A robust randomization module must be provably fair, tamper-resistant, and decentralized. This guide outlines the architectural patterns for building such a system, focusing on the trade-offs between using external oracles like Chainlink VRF and implementing commit-reveal schemes directly on-chain.

The most secure and widely adopted approach is to integrate a Verifiable Random Function (VRF) oracle. Services like Chainlink VRF provide cryptographically secure randomness that is generated off-chain and delivered on-chain with a proof. The consumer contract requests randomness by paying a fee and providing a seed. The oracle responds with a random number and a cryptographic proof, which the contract verifies before accepting the result. This architecture delegates security and liveness to a decentralized oracle network, making it ideal for high-value applications.

For applications requiring lower cost or more control, a commit-reveal scheme can be implemented on-chain. In this pattern, one or more participants submit a hash of their secret random seed (the commit phase). After a delay, they reveal the original seed. The final random number is derived from combining all revealed seeds. This prevents last-revealer manipulation but introduces complexity, requires multiple honest participants, and has higher latency. It's suitable for multi-party games or decentralized governance lotteries.

When designing the module, key considerations include randomness liveness (ensuring a result is always provided), cost predictability (especially with oracles), and user experience (request-completion latency). Your contract must manage state for pending requests, implement a callback function for oracle responses, and include fail-safes. For Chainlink VRF, you must fund your contract with LINK tokens and ensure it can handle the callback's gas costs, which may require patterns like gas station networks.

Always implement access control so only authorized contracts or roles can request randomness. Use the generated random number to derive outcomes within the same transaction when possible to prevent MEV attacks. For example, to pick a winner from a list, calculate winnerIndex = randomNumber % participants.length. Document the source of randomness and its security guarantees for users. A well-architected module is a reusable, audited component that can be securely integrated across your dApp ecosystem.

implementation-steps
IMPLEMENTATION GUIDE

How to Design a Smart Contract-Based Randomization Module

This guide outlines the key steps and considerations for implementing a secure and verifiable random number generator (RNG) on-chain, a critical component for applications like gaming, lotteries, and NFT minting.

The first step is selecting a randomness source. On-chain sources like blockhash or block.timestamp are predictable and should be avoided for high-value applications. Instead, use a commit-reveal scheme or an oracle. In a commit-reveal pattern, a user or contract first submits a hash of their secret number (commit). Later, they reveal the number, and the contract verifies it against the hash to generate the final random output. This prevents front-running but requires two transactions.

For production systems, integrating a verifiable random function (VRF) oracle is the gold standard. Services like Chainlink VRF provide cryptographically secure randomness that is proven to be tamper-proof. Your contract requests randomness by calling the oracle's function, which returns a random number and a cryptographic proof. Your contract's fulfillRandomWords callback function then receives and uses this verified number. This approach shifts the complexity and security guarantees to a specialized, audited provider.

Your contract's core logic must manage the randomness lifecycle. Define a state variable, like requestId, to track pending oracle requests. Emit an event when a request is made so off-chain systems can listen for it. Implement access control—often with the onlyOwner modifier—to restrict who can trigger a randomness request or fulfill it, preventing unauthorized calls to the callback. Store the generated random seed securely for use in your application logic.

Handling the Random Result

Once you have a secure random number (a uint256 seed), you need to derive usable outputs. For selecting a winner from a list, calculate winnerIndex = randomSeed % numberOfParticipants. For weighted distributions or rarity tables in NFTs, you might use cumulative probability arrays. Always perform these derivations inside the secure callback function to prevent manipulation. Avoid storing the raw seed longer than necessary to minimize state bloat.

Thorough testing is non-negotiable. Use a development framework like Foundry or Hardhat to simulate the entire flow, including oracle responses. Write tests for: the successful request-fulfillment cycle, edge cases (like modulo bias), access control failures, and contract state updates. Consider the economic costs: each VRF request consumes LINK tokens and gas, so design your logic to batch operations or request randomness efficiently to keep user costs manageable.

Finally, prioritize security audits and transparency. Have your randomization module audited by a reputable firm. Clearly document the source of randomness in your project's documentation and user interface—users should know if you're using Chainlink VRF or another verifiable system. For transparency, you can emit the final random seed in an event, allowing anyone to independently verify the fairness of the outcome using the oracle's published proof.

PROTOCOL ANALYSIS

On-Chain VRF Provider Comparison

Comparison of major on-chain VRF solutions for smart contract integration, focusing on security, cost, and performance.

FeatureChainlink VRFAPI3 QRNGWitnet Randomness

Verification Method

Verifiable Random Function (VRF)

Quantum Random Number Generator (QRNG)

Commit-Reveal with Proof-of-Work

Provably Fair

On-Chain Proof

Gas Cost per Request

$10-50

$2-10

$1-5

Average Fulfillment Time

1-2 minutes

< 1 sec

5-10 minutes

Supported Chains

EVM, Solana

EVM

EVM, Solana, Polkadot

Subscription Model

Direct Funding Required

Decentralized Oracle Network

security-considerations
SECURITY AND ANTI-MANIPULATION MEASURES

How to Design a Smart Contract-Based Randomization Module

Designing a secure random number generator (RNG) for on-chain applications requires mitigating predictable inputs and adversarial manipulation. This guide covers core principles and implementation patterns.

On-chain randomness is a critical component for applications like NFT minting, gaming outcomes, and fair lotteries. The fundamental challenge is that blockchains are deterministic systems; every node must agree on the state, making traditional random number generation impossible. A naive approach using blockhash or block.timestamp is highly insecure, as these values are predictable and can be influenced by miners or validators. A secure RNG module must combine on-chain and off-chain data sources to create a verifiably random and unpredictable result that cannot be gamed by users or network participants.

The most robust pattern is the Commit-Reveal scheme, which separates the generation of randomness from its use. In the first phase, a trusted oracle (like Chainlink VRF) or a participant submits a commitment—typically the hash of a secret seed. Later, in the reveal phase, the original seed is disclosed. The final random number is derived from this revealed seed combined with other public, but initially unknown, data like a future blockhash. This ensures the result was fixed at the time of commitment but could not be known or altered before the reveal. For multi-party systems, consider a multi-party commit-reveal where several participants each submit a seed, increasing security through decentralization.

For many applications, integrating a verifiable random function (VRF) from a decentralized oracle network like Chainlink is the recommended practice. Services like Chainlink VRF provide cryptographically secure randomness that is proven to be tamper-proof. The smart contract requests randomness, the oracle network generates it off-chain along with a cryptographic proof, and then delivers it on-chain where the proof is verified before the number is used. This shifts the security burden to a battle-tested, decentralized system. Always ensure your contract does not proceed with critical logic until the VRF response is received and verified to prevent race conditions.

When designing the module, incorporate anti-manipulation safeguards directly into the contract logic. Key measures include: imposing a time delay between the reveal and the use of the random number to prevent last-revealer advantage, using multiple entropy sources (e.g., combining a VRF output with a user-provided nonce hashed with block.difficulty), and implementing access controls so only designated functions can request or finalize randomness. For high-value systems, consider adding a dispute period where users can challenge a result if they suspect manipulation, potentially triggering a slashing mechanism for malicious actors.

Thorough testing is non-negotiable. Use forked mainnet environments in your tests (e.g., with Foundry or Hardhat) to simulate real-world conditions. Write tests that simulate adversarial behavior: a miner manipulating block.timestamp, a user trying to revert transactions upon seeing an unfavorable result, or an oracle provider acting maliciously. Fuzz testing the randomness function with random inputs can help uncover edge cases. Always audit the final design, as subtle flaws—like using block.number which increments predictably—can completely compromise the system's fairness.

The choice between a self-built commit-reveal system and an oracle service like Chainlink VRF depends on your application's value, complexity, and trust model. For most production DeFi or NFT projects, the security and reliability of a decentralized oracle outweigh the cost. The final contract should emit clear events for randomness requests and fulfillment, allow for upgradeability in case of flaws, and have a well-documented process for handling edge cases like oracle failure. Remember, in blockchain, transparency and verifiability are more critical than mere unpredictability.

SMART CONTRACT RANDOMNESS

Frequently Asked Questions

Common technical questions and solutions for implementing secure, verifiable randomness in smart contracts.

Using block.timestamp or blockhash for on-chain randomness is fundamentally insecure because the values are predictable and can be influenced by miners/validators.

  • Predictability: A miner can choose to include or exclude a transaction based on the resulting block.timestamp, which changes predictably.
  • Manipulation: For a transaction in block N, the blockhash of block N is 0x0. The blockhash of block N-1 is known. A miner can therefore see the outcome of a randomness-dependent transaction before deciding to mine it.
  • Example Vulnerability: A lottery contract using uint256 random = uint256(keccak256(abi.encodePacked(block.timestamp, blockhash(block.number - 1)))); is trivial for a miner to game.

Solution: Use a commit-reveal scheme or a verifiable random function (VRF) from a trusted oracle like Chainlink.

conclusion
IMPLEMENTATION SUMMARY

Conclusion and Next Steps

You have built a secure, verifiable random number generator (RNG) for on-chain applications. This guide covered the core principles, from basic entropy to advanced commit-reveal schemes.

The implemented Randomizer contract demonstrates a production-ready commit-reveal scheme. By separating the request for randomness from its fulfillment, it prevents front-running and manipulation. The use of a uint256 nonce ensures request uniqueness, while the keccak256 hash of the reveal data provides cryptographic proof that the result was predetermined and not altered after the fact. This pattern is fundamental for any application requiring fair, unpredictable outcomes, such as NFT minting, gaming mechanics, or decentralized lotteries.

For further development, consider these enhancements to increase security and utility. Integrate a cryptoeconomic security model by requiring a staked bond from the revealer that is slashed for malicious behavior. Implement a fallback oracle like Chainlink VRF to guarantee liveness if your primary revealer fails. To reduce gas costs for users, explore signature-based reveals where the provider signs the random number off-chain, allowing the requester to submit the proof. Always conduct a formal audit before deploying any RNG module to mainnet.

To test your module thoroughly, write comprehensive unit tests using Foundry or Hardhat. Simulate edge cases: a revealer submitting an incorrect pre-image, a user attempting to reveal the same request twice, and contract pausing functionality. Measure gas costs for critical functions to optimize for user experience. Review real-world implementations like Art Blocks' use of hashed metadata for generative art or Loot's deterministic derivation for inspiration on applying on-chain randomness.

The next step is integration. Your Randomizer can be used as a standalone library or inherited by a main application contract. For a gaming dApp, your game contract would call requestRandomness, then use the fulfilled random seed to determine loot drops or battle outcomes. Remember that on-chain randomness is a public good—design your system assuming all data is visible and actors are rational. Continue your research with resources like the Ethereum Foundation's blog on RNG and the OpenZeppelin libraries for secure contract patterns.

How to Design a Smart Contract Randomization Module | ChainScore Guides