Verifiable randomness for Robinhood Chain.
HoodRand turns drand’s public randomness beacon into random numbers your contract can use, checked onchain. There’s no secret and no single server to trust: nobody can predict or bias a result, PFWA included. Same interface as Dice and Pyth Entropy.
Read from the contract · no requests yet · refreshed every minute.
How it works
Four steps, each one checkable onchain.
drand signs a new value every 3 seconds
drand’s evmnet beacon is run by the League of Entropy (Cloudflare, Protocol Labs, universities and others). Each round’s BLS signature is its random value.
Locked to a future round
Your contract calls requestV2 with the fee. The request is tied to a round 5 rounds ahead (15 to 18 seconds), whose value doesn’t exist yet.
Anyone submits the signature
Our relayer submits every round with waiting requests. If it’s down, you or anyone else can, with drand’s public signature.
Checked, then delivered
HoodRand checks the signature against drand’s public key with Robinhood Chain’s BN254 pairing precompile, then calls your _entropyCallback with keccak256(sha256(signature), yourRandom, sequence).
Not answered within a day? refundRequest returns your fee.
Integrate in 30 lines
No sign-up and no API key. Already built for Dice or Pyth Entropy? Point it at HoodRand’s address and you’re done.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
interface IHoodRand {
function getFeeV2(address provider, uint32 gasLimit) external view returns (uint128);
function requestV2(address provider, bytes32 userRandomNumber, uint32 gasLimit)
external payable returns (uint64 sequence);
}
contract MyGame {
IHoodRand constant HOODRAND = IHoodRand(0xbE5105faf1Cb76733876959d5802448d066D734F);
uint32 constant CALLBACK_GAS = 100_000;
mapping(uint64 => address) public rollOf;
event Rolled(address indexed player, uint256 face);
function roll() external payable {
uint128 fee = HOODRAND.getFeeV2(address(HOODRAND), CALLBACK_GAS);
require(msg.value == fee, "send exactly the fee");
bytes32 userRandom = keccak256(abi.encode(msg.sender, block.number));
uint64 seq = HOODRAND.requestV2{value: fee}(address(HOODRAND), userRandom, CALLBACK_GAS);
rollOf[seq] = msg.sender;
}
// HoodRand calls this about 15 seconds later. Don't revert in it.
function _entropyCallback(uint64 seq, address, bytes32 randomNumber) external {
require(msg.sender == address(HOODRAND), "only HoodRand");
emit Rolled(rollOf[seq], uint256(randomNumber) % 6 + 1);
delete rollOf[seq];
}
}
- Pass HoodRand’s own address as
provider. It’s ignored: HoodRand is its own provider. - Send exactly
getFeeV2(…).gasLimitis your callback’s gas, up to 1,000,000. - Check
msg.senderin the callback, and don’t revert in it: a reverting callback still counts as answered.
Answer a round yourself
# 1. drand's signature for the round your request waits on
curl https://api.drand.sh/v2/beacons/evmnet/rounds/<round>
# 2. submit it: HoodRand checks it and answers every request on that round
cast send 0xbE5105faf1Cb76733876959d5802448d066D734F "reveal(uint64,bytes,uint256)" \
<round> 0x<signature> 25 --rpc-url https://rpc.mainnet.chain.robinhood.com
Pay per number, over x402
For agents and apps without a contract. One HTTP call and 0.10 USDG on Robinhood Chain gets a verifiable random number back in about 20 seconds: no ETH, no gas, no sign-up. Our relayer makes the HoodRand request for you, so the number is checked onchain like any other.
# Priors agents: one tool call
pay_url("https://www.pfwa.fun/api/hoodrand/x402?seed=my-game-42")
# Any x402 client: allow USDG on eip155:4663 in its spend controls, then
GET https://www.pfwa.fun/api/hoodrand/x402?seed=my-game-42
→ 402, with the price in the PAYMENT-REQUIRED header
→ sign the USDG transfer it asks for, send it again with PAYMENT-SIGNATURE
→ 200 {
"status": "answered",
"randomNumber": "0x…",
"sequence": 12, "round": 21903110,
"userRandom": "0x…", // keccak256(seed, payer, payment nonce)
"drandSignature": "0x…",
"requestTx": "0x…", "revealTx": "0x…"
}
# Check any answer later, free
GET https://www.pfwa.fun/api/hoodrand/result?sequence=12
- Payment. x402 v2
exactoneip155:4663: a signed USDG transfer (EIP-3009) for 0.10 USDG, settled onchain only if the number is delivered. Each payment buys one number. - Your input.
?seed=(up to 256 characters) is mixed into the request with your address and the payment’s nonce, so no two requests share an input. - Verify it.
randomNumber = keccak256(abi.encode(sha256(drandSignature), userRandom, sequence)), withdrandSignaturedrand evmnet’s signature forround, the same one HoodRand checked inrevealTx. - Slow round? Past about 50 seconds you get
"status": "pending"and aresultUrlto read the number from once it lands.
Use ours, or read the source
Call the live contract
0.00002 ETH a request from a contract, or 0.10 USDG a number over x402. Answered by our relayer within seconds of its round. Nothing to run.
Everything is public
The contract, its tests against real drand signatures, and the relayer’s logic. Source under the Business Source License 1.1, MIT from Oct 28, 2028.
Contract
| HoodRand | 0xbE5105faf1Cb76733876959d5802448d066D734F |
| Chain | Robinhood Chain · chain id 4663 |
| Deployed | block 100,426,050 · Oct 28, 2026 |
| Owner | 0x4209…1EEF (PFWA’s admin wallet) |
| Interface | requestV2, getFeeV2, refundRequest · callback _entropyCallback(uint64, address, bytes32) |
| Answer it | reveal(round, signature, maxAnswers), answer(round, maxAnswers) · anyone can call |
drand evmnet
| Chain hash | 04f1e9062b8a81f848fded9c12306733282b2727ecced50032187751166ec8c3 |
| Genesis · period | 1727521075 · 3 seconds |
| Scheme | bls-bn254-unchained-on-g1 |
| Info | api.drand.sh/v2/beacons/evmnet/info |
What you’re trusting
- Not PFWA. The owner can set the fee (capped at 0.0002 ETH), withdraw fees of answered requests and hand over ownership. Nothing touches a result.
- drand’s League of Entropy, to not collude past its threshold. That’s the assumption behind every drand beacon.
- Robinhood Chain’s sequencer, which sets block timestamps. The 5-round delay is the margin against a timestamp running behind real time.
- Unaudited code. The BLS library comes from randa-mu’s bls-solidity, which its authors call experimental; HoodRand hasn’t been audited yet. Checking a round costs about 228k gas.