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

How to Integrate Verifiable Randomness

A technical guide for developers to implement secure, on-chain verifiable randomness using major oracle protocols. Includes code examples and protocol comparisons.
Chainscore © 2026
introduction
PRACTICAL GUIDE

How to Integrate Verifiable Randomness

A technical tutorial for developers to implement cryptographically secure random number generation in smart contracts using Chainlink VRF.

Verifiable Randomness Functions (VRFs) provide a solution to the blockchain oracle problem for randomness. Unlike pseudo-random number generators (PRNGs) like blockhash or block.timestamp, which are predictable and manipulable by miners/validators, a VRF generates a random number and a cryptographic proof. This proof allows anyone to verify that the number was generated correctly without knowing the secret key, ensuring the result is provably fair and tamper-proof. This is critical for applications like NFT minting, gaming, and decentralized lotteries where trust in randomness is non-negotiable.

Chainlink VRF is the most widely adopted solution for on-chain verifiable randomness. The process involves a two-transaction model. First, your smart contract requests randomness by calling the VRF Coordinator and paying LINK tokens. An off-chain oracle node generates the random number and proof, then submits it back to your contract in a second transaction. Your contract must implement a fulfillRandomWords callback function to receive and use the generated number. This asynchronous design ensures the randomness is generated off-chain but verified and delivered on-chain with cryptographic guarantees.

To integrate Chainlink VRF, start by importing the VRFConsumerBaseV2 contract and initializing it with the coordinator and LINK token addresses for your chosen network (e.g., Ethereum Sepolia). You'll need a subscription ID from the Chainlink VRF Subscription Manager, which manages LINK balances for multiple requests. Your request function must call coordinator.requestRandomWords, passing the keyHash (gas lane), subscription ID, request confirmations (typically 3), callback gas limit, and the number of random words needed. Always fund your subscription with LINK before making requests.

Here is a minimal implementation for a contract that requests a single random number:

solidity
import "@chainlink/contracts/src/v0.8/VRFConsumerBaseV2.sol";
import "@chainlink/contracts/src/v0.8/interfaces/VRFCoordinatorV2Interface.sol";

contract RandomNFT is VRFConsumerBaseV2 {
    VRFCoordinatorV2Interface COORDINATOR;
    uint64 s_subscriptionId;
    bytes32 s_keyHash;
    uint256 public randomResult;

    constructor(uint64 subscriptionId, address vrfCoordinator, bytes32 keyHash)
        VRFConsumerBaseV2(vrfCoordinator) {
        COORDINATOR = VRFCoordinatorV2Interface(vrfCoordinator);
        s_subscriptionId = subscriptionId;
        s_keyHash = keyHash;
    }

    function requestRandomNFT() external {
        COORDINATOR.requestRandomWords(
            s_keyHash,
            s_subscriptionId,
            3, // requestConfirmations
            100000, // callbackGasLimit
            1 // numWords
        );
    }

    function fulfillRandomWords(uint256, uint256[] memory randomWords) internal override {
        randomResult = randomWords[0];
        // Use randomness to mint NFT or determine outcome
    }
}

When the oracle fulfills the request, your fulfillRandomWords function is executed. The random number is provided as a uint256 within the randomWords array. This is where your core application logic should reside, such as assigning traits to an NFT, selecting a winner, or shuffling items. It's crucial to ensure this function is gas-efficient and has no external calls that could fail, as it's called by the VRF coordinator. For multiple random values, request numWords > 1; each word is an independent 256-bit random number. Always test thoroughly on a testnet like Sepolia before mainnet deployment.

Beyond basic integration, consider security and design patterns. Use the Commit-Reveal scheme for applications where the random outcome should be hidden until a later reveal phase. Protect your fulfillRandomWords function with access control (e.g., onlyVRFCoordinator) even though the base contract provides some protection. Be mindful of the callback gas limit; complex logic may require increasing it via the subscription manager. For cost-effective frequent requests, explore VRF Direct Funding or batch processing. Alternatives like randcast on Arbitrum or Witnet offer different trust models and should be evaluated based on your application's specific latency, cost, and decentralization requirements.

prerequisites
GETTING STARTED

Prerequisites and Setup

This guide outlines the core requirements and initial steps for integrating verifiable randomness into your Web3 application, focusing on practical implementation.

Integrating verifiable randomness (VRF) requires a foundational understanding of blockchain development and smart contract security. You should be comfortable with Solidity or Vyper for on-chain logic, and have experience with a Web3 library like ethers.js or web3.js for off-chain interaction. A basic grasp of cryptographic concepts such as public-key cryptography and hash functions is also essential, as VRF relies on these principles to generate and prove randomness. Ensure your development environment includes Node.js (v18+ recommended) and a package manager like npm or yarn.

The primary prerequisite is access to a VRF service provider. Leading options include Chainlink VRF, which is the most widely adopted on networks like Ethereum, Polygon, and Avalanche, and Witnet, a decentralized oracle network offering randomness. For applications on specific Layer 2s or alt-L1s, check for native solutions; for example, Pyth provides randomness on Solana and Sui. You will need to obtain testnet tokens for the network you're building on (e.g., Sepolia ETH, Mumbai MATIC) to pay for gas and, in most models, to fund requests for randomness.

Begin by setting up your project. For a typical Hardhat project, initialize your workspace and install necessary dependencies: npm init -y, followed by npm install --save-dev hardhat @nomicfoundation/hardhat-toolbox. Then, install the provider's SDK, such as @chainlink/contracts for Chainlink. Configure your hardhat.config.js with the appropriate network RPC URLs and your wallet's private key (stored securely in a .env file using dotenv). This setup allows you to compile, test, and deploy contracts that will interact with the VRF system.

Your smart contract must be designed to request randomness and handle the callback. This involves importing the provider's interface (e.g., VRFConsumerBaseV2 for Chainlink VRF v2), storing the returned requestId, and implementing a fulfillRandomWords function that contains your application logic using the generated random number. A critical security practice is to validate that the callback originates from the authorized VRF coordinator contract using msg.sender checks to prevent malicious injections.

Before deploying to a testnet, thoroughly test the integration locally or on a forked network. Simulate the full request-fulfillment cycle to ensure your contract correctly emits the request event, handles the callback, and updates its state as expected. Use the provider's testnet subscription manager (like the Chainlink VRF Subscription Manager) to create a subscription and fund it with testnet LINK. This end-to-end dry run is crucial for catching logic errors without incurring real costs.

Finally, plan for production. Understand the cost model: most providers charge a premium in their native token per randomness request. Ensure your application's backend or a dedicated keeper service can reliably fund requests and handle potential fulfillment delays. Consider implementing fail-safes, such as request expiration logic, to manage edge cases. With the environment configured, contracts written and tested, and a funded subscription, you are ready to deploy and integrate verifiable randomness into your dApp.

key-concepts
DEVELOPER INTEGRATION

Core Concepts of Verifiable Randomness

Verifiable Random Functions (VRFs) generate random numbers that are publicly verifiable, enabling trustless applications in DeFi, gaming, and NFTs. This guide covers the core cryptographic concepts and practical integration steps.

05

Implementing a Basic VRF Client

Here's a minimal Solidity example for a VRF consumer contract using Chainlink VRF v2.

solidity
import "@chainlink/contracts/src/v0.8/VRFV2WrapperConsumerBase.sol";

contract Lottery is VRFV2WrapperConsumerBase {
    uint256 public randomResult;
    uint32 callbackGasLimit = 100000;
    uint16 requestConfirmations = 3;
    uint32 numWords = 1;

    constructor() VRFV2WrapperConsumerBase(LINK_ADDRESS, VRF_WRAPPER_ADDRESS) {}

    function requestRandomWinner() external returns (uint256 requestId) {
        requestId = requestRandomness(callbackGasLimit, requestConfirmations, numWords);
    }

    function fulfillRandomWords(uint256 _requestId, uint256[] memory _randomWords) internal override {
        randomResult = _randomWords[0];
        // Use randomness, e.g., select a winner
    }
}

Key security practice: Never use blockhash or block.timestamp alone for critical randomness.

06

Security Considerations & Best Practices

Integrating verifiable randomness introduces specific attack vectors. Follow these practices to secure your application.

Common Risks:

  • Oracle Manipulation: A malicious oracle could withhold the response. Mitigate by using a decentralized network with sufficient node count.
  • Transaction Ordering (Front-running): An adversary could see your request and act before fulfillment. Use commit-reveal schemes or VRF's inherent properties.
  • Seed Predictability: Ensure your request seed includes msg.sender, blockhash, and a user-supplied nonce to prevent pre-computation.

Best Practices:

  • Always verify the VRF proof on-chain if the oracle provides it.
  • Design your application logic to be resilient if the randomness request fails or is delayed.
  • For high-value applications, consider using multiple randomness sources or a multi-round process.
PROVIDER OVERVIEW

VRF Protocol Comparison: Chainlink, API3, Witnet

A technical comparison of leading verifiable randomness providers for on-chain integration, covering architecture, cost, and performance.

Feature / MetricChainlink VRFAPI3 QRNGWitnet Randomness

Architecture Model

Decentralized Oracle Network

Decentralized API (dAPI)

Decentralized Oracle Protocol

Randomness Source

On-chain VRF + Off-chain Oracle

Quantum Random Number Generator (ANU)

On-chain VRF + Committee Consensus

Verification Method

On-chain cryptographic proof

dAPI response with attestation

On-chain proof with Witnet's consensus

Average Fulfillment Time

< 20 seconds

< 5 seconds

< 60 seconds

Cost Model (Est.)

0.1 - 2 LINK + gas

Gas costs only

WIT reward + gas

On-Chain Finality

Immediate upon fulfillment

Immediate upon fulfillment

After Witnet epoch (~5 min)

Supported Chains

EVM, Solana, more (15+)

EVM chains

EVM, Solana, Algorand, Polkadot

Developer Integration

Subscription or Direct Funding

Direct dAPI call

Post a data request to Witnet

implementation-api3
IMPLEMENTATION

How to Integrate Verifiable Randomness with API3 QRNG

A step-by-step guide to integrating API3's Quantum-Resistant Random Number Generator (QRNG) into your smart contracts for secure, verifiable on-chain randomness.

API3 QRNG provides a decentralized source of verifiable randomness by leveraging quantum processes from first-party oracles. Unlike traditional RNGs that rely on potentially manipulable on-chain data, QRNG uses quantum vacuum fluctuations measured by API3's Airnode operators. This randomness is delivered on-chain via a request-response mechanism, where a smart contract makes a request and an off-chain Airnode fulfills it, posting the random value back to the contract. The process is provably fair and tamper-resistant, making it suitable for high-stakes applications like NFT minting, gaming, and lotteries.

To begin, you'll need a smart contract that inherits from RrpRequesterV0. This interface, provided by the API3 QRNG package, handles the cross-chain communication. Your contract must define a makeRequestUint256() function to initiate a randomness request, specifying the Airnode address, endpoint ID, and sponsor wallet. The key parameters are the airnode (the specific provider's address), endpointId (identifying the QRNG service), and your contract's own address as the sponsor. The request is funded by the sponsor wallet, which must be topped up with the chain's native token.

Once the request is made, the off-chain Airnode generates a random number using its quantum source and calls back to your contract's fulfillUint256() function. You must implement this function to receive the random value, typically storing it in a state variable and triggering your application logic. A critical security practice is to validate that the callback originates from the expected Airnode by checking the msg.sender within the fulfill function. This prevents malicious actors from injecting false randomness.

For developers, the easiest integration path is using the pre-deployed QrngExample contract or the @api3/airnode-protocol NPM package. You can find example contracts for chains like Ethereum, Polygon, and Avalanche in the API3 QRNG GitHub repository. A typical workflow involves: 1) Installing the package, 2) Deploying a requester contract, 3) Funding a sponsor wallet, and 4) Calling makeRequestUint256() from your dApp's frontend or a script. The random number is usually available within a few blocks.

Consider gas costs and request timing in your design. Each request involves two transactions: your initial request and the Airnode's fulfillment. On high-throughput chains, you may use a request-and-fulfill-in-one pattern via AirnodeRrpV0.sol's makeFullRequest() to reduce latency. For batch operations, you can request multiple random values in a single call. Always test your integration on a testnet like Sepolia or Mumbai first, using testnet Airnode addresses and endpoint IDs provided in the documentation.

API3 QRNG is ideal for any application requiring trust-minimized randomness. Common use cases include generative NFT trait assignment, fair winner selection in decentralized games, and randomized governance tasks. By using a first-party, quantum-backed oracle, you eliminate the need to trust a centralized RNG provider or vulnerable on-chain entropy sources. The entire process is transparent and verifiable on the blockchain, providing users with cryptographic assurance of fairness—a fundamental requirement for the next generation of Web3 applications.

VERIFIABLE RANDOMNESS

Common Implementation Mistakes and Security Pitfalls

Integrating verifiable randomness (VRF) into smart contracts is critical for fairness in applications like gaming and NFTs, but common errors can compromise security and functionality. This guide addresses frequent developer questions and pitfalls.

A failed request often stems from insufficient LINK token allowance or balance for the VRF subscription. The consumer contract must be approved to spend LINK on your behalf and the subscription must be funded.

Common checks:

  • Verify the consumer contract address is an approved consumer on the Chainlink VRF subscription.
  • Ensure the subscription has a sufficient LINK balance for the request's gas lane and callback gas limit.
  • Confirm the keyHash (gas lane) and subscriptionId passed to requestRandomWords are correct for your network (e.g., Sepolia vs Mainnet).
  • The requesting account (msg.sender) must be the subscription's owner or an authorized consumer.
solidity
// Example of a correct request call on Ethereum Sepolia
requestId = COORDINATOR.requestRandomWords(
    keyHash, // e.g., 0x... for 500 gwei lane
    SUBSCRIPTION_ID,
    requestConfirmations,
    callbackGasLimit,
    numWords
);
use-cases
INTEGRATION GUIDE

Practical Use Cases for Verifiable Randomness

Verifiable Random Functions (VRFs) provide cryptographically secure randomness for on-chain applications. This guide covers key implementation patterns across gaming, DeFi, and NFTs.

VRF INTEGRATION

Frequently Asked Questions (FAQ)

Common questions and troubleshooting for developers integrating verifiable randomness into smart contracts and applications.

A Verifiable Random Function (VRF) is a cryptographic primitive that produces a random number and a cryptographic proof. The proof allows anyone to verify that the number was generated correctly, without bias or manipulation, using the prover's public key. This is fundamentally different from using blockhash or block.timestamp.

Key Differences:

  • Blockhash/Timestamp: These are publicly known, predictable values. A miner or validator can influence them, making them insecure for applications like lotteries or NFT minting.
  • VRF: The random number is generated off-chain (e.g., by an oracle) and is unknown until the proof is published on-chain. The proof links the number to the specific request, ensuring it was not retroactively chosen. This provides cryptographic guarantees of fairness and unpredictability.
conclusion
IMPLEMENTATION GUIDE

Conclusion and Next Steps

You have explored the core concepts of verifiable randomness in Web3. This section outlines practical steps for integration and advanced applications.

To integrate a verifiable randomness function (VRF) like Chainlink VRF, start by defining your smart contract's requirements. Determine the necessary randomness for your application—whether it's for minting NFTs, selecting winners in a raffle, or shuffling items in a game. You must then request randomness by calling the VRF coordinator contract, providing a seed and paying the requisite LINK fee. The oracle network will generate a random number and a cryptographic proof, delivering it back to your contract via a callback function like fulfillRandomWords. Always ensure your contract can handle the asynchronous nature of this request-response pattern.

For on-chain verification, you can use a commit-reveal scheme with a verifiable delay function (VDF). Implement a two-phase process where a value is first committed (hashed) and later revealed after a predetermined delay. This prevents front-running by making the final outcome unpredictable until the reveal phase completes. Libraries like randao or protocols using Ethereum's beacon chain randomness (RANDAO) offer alternative models. When choosing a solution, evaluate the trade-offs between cost (gas fees for on-chain VDFs), speed (oracle network latency), and the level of cryptographic guarantee required for your use case.

Advanced applications of verifiable randomness extend beyond simple number generation. Consider using it for:

  • Procedural generation of in-game maps or asset traits in a verifiable way.
  • Fair ordering of transactions in a mempool to mitigate MEV.
  • Randomized governance mechanisms, such as selecting committee members.
  • Zero-knowledge proof systems that require trusted randomness for security. Implementing these requires careful smart contract design to ensure the randomness is consumed correctly and cannot be manipulated by any party, including the contract owner.

Your next steps should involve testing extensively on a testnet. Use Sepolia or Goerli to simulate VRF requests without spending real funds. Review the Chainlink VRF documentation for the latest contract addresses and best practices. For on-chain alternatives, study the Ethereum Beacon Chain specs on RANDAO. Remember, the security of your application hinges on correctly implementing the randomness consumption logic and understanding the trust assumptions of your chosen provider.