Randomness
The randomness-solidity library provides a minimal, plug-and-play interface for requesting secure, verifiable randomness from the dcipher network. It is ideal for evm-compatible smart contracts that require unpredictable randomness, such as raffles, games, randomized NFT drops, or fair selections.
The core of this library is a base contract, RandomnessReceiverBase, which abstracts away all low-level request/response logic using a threshold signature scheme from the dcipher network. Developers simply inherit from it and override a callback to use the random result.
π This Quickstart Walks You Through:
- Setting up a new Hardhat project
- Installing the
randomness-solidity
& writing a basic randomness consumer contract - Deploying it to Base Sepolia with a known
RandomnessSender
- Requesting and consuming randomness
- Interacting with the contract to retrieve the result
π§° Prerequisitesβ
Before you begin, ensure you have the following:
1. Set Up a New Hardhat Projectβ
mkdir my-randomness-app && cd my-randomness-app
npm init -y
npm install --save-dev hardhat
npx hardhat init
When prompted, choose βCreate a TypeScript projectβ and follow the instructions to finish the init process.
π‘ Hardhat provides a full Ethereum development environment and is one of the most widely used frameworks for writing, testing, and deploying smart contracts. Besides Hardhat, you can also choose other popular frameworks to create the smart contract project, such as Foundry.
2. Install the randomness-solidity Libraryβ
To extend the library from randomness-solidity
, we first need to install the library into your project.
npm install randomness-solidity
This package includes the RandomnessReceiverBase
contract and supporting utilities.
3. Create a Randomness Consumer Contractβ
Create a new solidity file under the /contract
folder: /MyRandomConsumer.sol
. This smart contract will inherit RandomnessReceiverBase
and implement the logic to request and consume the randomness.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import { RandomnessReceiverBase } from "randomness-solidity/src/RandomnessReceiverBase.sol";
contract MyRandomConsumer is RandomnessReceiverBase {
uint256 public requestId;
bytes32 public randomValue;
event RandomnessRequested(uint256 indexed requestId);
event RandomnessFulfilled(uint256 indexed requestId, bytes32 randomValue);
constructor(address randomnessSender) RandomnessReceiverBase(randomnessSender) {}
/// @notice Called by user to request randomness
function getRandomness() external {
requestId = requestRandomness();
emit RandomnessRequested(requestId);
}
/// @notice Called by the randomnessSender to fulfill the request
function onRandomnessReceived(uint256 requestID, bytes32 _randomness) internal override {
require(requestId == requestID, "Request ID mismatch");
randomValue = _randomness;
emit RandomnessFulfilled(requestID, _randomness);
// You can add any logic to consume randomness value here.
}
}
π§ Explanation
Code | Purpose |
---|---|
RandomnessReceiverBase | Base contract handles the request/response logic with the randomness provider. |
constructor(address sender) | Requires the deployed RandomnessSender contract address. |
getRandomness() | Initiates the randomness request. |
onRandomnessReceived(...) | Override this function with your project logic consuming randomness. It will be invoked automatically once the random value is received from the dcipher network. |
4. Deploy the Contractβ
We will use Hardhat Ignition to manage smart contract deployments. Letβs create a file ignition/modules/MyRandomConsumer.js
with the following code to deploy MyRandomConsumer
.
import { buildModule } from "@nomicfoundation/hardhat-ignition/modules";
const randomnessSenderAddress = "0xRandomnessSenderAddressOnBase";
const RandomnessModule = buildModule("RandomnessModule", (m) => {
const lock = m.contract("MyRandomConsumer", [randomnessSenderAddress]);
return { lock };
});
export default RandomnessModule;
Then we should the add desired network into hardhat.config.js - in this example we are using Base Sepolia Testnet. Add your private key for the deployer wallet with test token funded. We advise using a .env file to manager your secrets to avoid leaking them.
module.exports = {
solidity: "0.8.28",
networks: {
baseSepolia: {
url: "https://sepolia.base.org/",
chainId: 84532,
accounts: [PRIVATE_KEY]
}
}
}
Deploy using:
npx hardhat ignition deploy ./ignition/modules/MyRandomConsumer.ts --network baseSepolia
Use a network where RandomnessSender is deployed (e.g., Filecoin Calibration, Base, etc.). Check Networks page for deployed addresses.
5. Interact with the Contractβ
Once deployed:
- Call
getRandomness()
on your contract. - The dcipher network monitors the chain for requests, generates the randomness with a threshold signature and calls back to the
RandomnessSender
contract. - The network delivers randomness to
onRandomnessReceived()
.
π§ͺ A. Use Hardhat Consoleβ
npx hardhat console --network <your-network>
const consumerAddress = "0xContractAddressEncodedAsHex";
const MyRandomConsumer = await ethers.getContractFactory("MyRandomConsumer");
const consumer = await MyRandomConsumer.attach(consumerAddress);
// Request randomness
await consumer.getRandomness();
Wait ~1β2 minutes for fulfillment, then:
await consumer.randomValue();
β Example Outputβ
> await consumer.requestRandomness()
// [Tx submitted]
> await consumer.randomValue()
// '0x0000000000000000000000000000000000000000000000000000000000000000'
...wait 1β2 minutes...
> await consumer.randomValue()
'0x9ec2573095983f37e7ed3d3cd73251e6cc6c44567dbcf231675ea22ccef8c898'
π§ͺ B. Use Frontend or Scriptβ
const consumer = new ethers.Contract(consumerAddress, consumerAbi, signer);
await consumer.getRandomness();
π‘ The event emitted in onRandomnessReceived() can also be listened for via frontend code.
π§ Summaryβ
Step | Purpose |
---|---|
inherit RandomnessReceiverBase | Connect your contract to the randomness flow |
Deploy with sender address | Must point to deployed RandomnessSender |
Call getRandomness() | Kicks off a randomness request from randomnessSender |
Override onRandomnessReceived() | Handle the randomness callback when fulfilled. |
By following this quickstart, you've built a simple Solidity project that can securely request and consume verifiable randomness from the dcipher network using the randomness-solidity library. This foundational setup allows you to easily extend your contract logic, whether you're building games, lotteries, randomized NFT minting, or any application that requires verifiable randomness..
For advanced testing, callback simulations, or extending contract logic, refer to the full documentation and source.