Verified Random Number Generator (vRNG)
ApeChain's vRNG is powered by Supra dVRF, a distributed and cryptographically verifiable randomness service. It enables smart contracts to request tamper-proof random numbers on-chain — suitable for NFT minting, gaming, lotteries, and any use case where provable fairness matters.
Contract addresses for ApeChain Mainnet and Testnet are listed on the Supra dVRF Available Networks ↗ (opens in a new tab) page.
Dev Guides
- Getting Started ↗ (opens in a new tab).
- Create your Subscription ↗ (opens in a new tab)
- Gas Configurations ↗ (opens in a new tab)
- Deposit & Withdraw Funds ↗ (opens in a new tab)
- Request Random Numbers ↗ (opens in a new tab)
Advanced Example (with Custom Seed)
This example demonstrates requesting multiple random numbers with a custom client seed for additional entropy, and mapping results back to individual users.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface ISupraRouter {
function generateRequest(
string memory _functionSig,
uint8 _rngCount,
uint256 _numConfirmations,
uint256 _clientSeed, // Optional: provide your own seed for extra entropy
address _clientWalletAddress
) external returns(uint256);
}
contract Interaction {
address supraAddr;
constructor(address supraSC) {
// Pass the ApeChain Mainnet Router address:
// 0xf4966137dE4638Baa280ea35265B3AFEc5332df3
supraAddr = supraSC;
}
mapping(uint256 => string) result;
mapping(string => uint256[]) rngForUser;
function exampleRequest(uint8 rngCount, string memory username) external {
// Number of block confirmations before randomness is generated.
// You can customize this value to meet your needs. Minimum: 1, Maximum: 20.
uint256 numConfirmations = 1;
uint256 nonce = ISupraRouter(supraAddr).generateRequest(
"exampleCallback(uint256,uint256[])", // Must match callback signature exactly
rngCount,
numConfirmations,
123, // Custom client seed — replace with your own value (e.g. timestamp, UUID)
msg.sender // Must be your whitelisted wallet address
);
// Map the nonce to the username so the callback knows who to assign results to
result[nonce] = username;
}
// Supra Router calls this automatically once randomness is ready
function exampleCallback(uint256 nonce, uint256[] calldata rngList) external {
// Security: only the Supra Router is allowed to call this function
require(msg.sender == supraAddr, "only supra router can call this function");
uint256[] memory x = new uint256[](rngList.length);
rngForUser[result[nonce]] = x;
for(uint8 i = 0; i < rngList.length; i++) {
// Example: normalise each result to a value between 0–99
rngForUser[result[nonce]][i] = rngList[i] % 100;
}
}
// View the random results assigned to a username
function viewUserName(string memory username) external view returns (uint256[] memory) {
return rngForUser[username];
}
}