Node Operators
Client Contract Integration (For Developers Using RandProof)
If you are building a protocol that consumes RandProof (e.g., a raffle, NFT mint, or DAO tool), integrate the following interface:
If you are building a protocol that consumes RandProof (e.g., a raffle, NFT mint, or DAO tool), integrate the following interface:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
interface IKeeperCoordinator {
// Request a PoFR event. Returns eventId.
// fee must be sent with the call (msg.value or ERC20 approve first)
// Request a PoFR event. Returns eventId.\
// fee must be >= MIN_FEE (spam protection, AV-27 fix)\
// Rate limited: 1 request per 10 blocks per address\
function requestRandomness(bytes32 userSeed) external payable returns (bytes32 eventId);
// Fulfill with verified entropy inputs (called by keepers)
function fulfill(bytes32 eventId, bytes32[15] memory entropyInputs, uint256 entropyBlock, bytes memory aggregatedSig, address[] memory signers) external;
// Submit entropy attestation (Layer 2: multi-keeper attestation)
function submitEntropy(bytes32 eventId, uint8 sourceId, bytes32 value, bytes memory proof) external;
// Submit fraud proof during challenge window (Layer 3)
function submitFraudProof(bytes32 eventId, uint8 sourceId, bytes memory proof) external;
// Get verified entropy inputs for a fulfilled event
function getEntropyInputs(bytes32 eventId) external view returns (bytes32[15] memory);
// Check if an event has been fulfilled
function isFulfilled(bytes32 eventId) external view returns (bool);
// Get the RandProof artifact for a fulfilled event
function getRandProof(bytes32 eventId) external view returns (
bytes32 seed,
bytes aggregatedBLSSig,
address[] memory signers,
uint256 fulfillBlock,
uint256 fulfillTimestamp
);
}
contract MyRaffle is IRandProofConsumer {
IKeeperCoordinator public coordinator;
mapping(bytes32 => uint256) public pendingDraws; // eventId => totalEntrants
constructor(address _coordinator) {
coordinator = IKeeperCoordinator(_coordinator);
}
// Step 1: Request randomness when draw is ready
function requestDraw(uint256 totalEntrants) external payable {
bytes32 userSeed = keccak256(abi.encode(block.number, msg.sender, totalEntrants));
bytes32 eventId = coordinator.requestRandomness{value: msg.value}(userSeed);
pendingDraws[eventId] = totalEntrants;
emit DrawRequested(eventId, totalEntrants);
}
// Step 2: Receive the fulfilled randomness (called by KeeperCoordinator)
function fulfillRandomness(bytes32 eventId, bytes32 seed) external override {
require(msg.sender == address(coordinator), "Only coordinator");
uint256 totalEntrants = pendingDraws[eventId];
require(totalEntrants > 0, "Unknown event");
uint256 winnerIndex = uint256(seed) % totalEntrants;
emit WinnerSelected(eventId, winnerIndex);
delete pendingDraws[eventId];
}
event DrawRequested(bytes32 indexed eventId, uint256 totalEntrants);
event WinnerSelected(bytes32 indexed eventId, uint256 winnerIndex);
}KeeperCoordinator contract addresses (current deployments — 10 chains live):
| Chain | Variant | Fee token | Address |
|---|---|---|---|
| Base Mainnet | V8 | ETH | 0x4D7Ca11c363Ad5ADce9F5C9F48F65c26fdE4D006 |
| Optimism | V8 | ETH | 0x67245111A09692Ee0A964A9C37a7D20A0B506805 |
| Arbitrum One | V8 | ETH | 0xF7e34F900b845e3a2F72fbCE78E6666803D15a82 |
| Avalanche C-Chain | V8A | AVAX | 0xb19Ff6bc924C6BA04424bADe0c0f0F9973af3b69 |
| Polygon | V8 | POL | 0xb19Ff6bc924C6BA04424bADe0c0f0F9973af3b69 |
| Linea | V8 | ETH | 0xBC933FDe13CD109e551edf01BDD28cD8B8B0AFeA |
| BNB Chain | V8 | BNB | 0xb19Ff6bc924C6BA04424bADe0c0f0F9973af3b69 |
| HyperEVM | V8A | HYPE | 0xF2f79eE04C1c303426F0d1543267286460b5321C |
| Robinhood Chain | V8 | ETH | 0xF2f79eE04C1c303426F0d1543267286460b5321C |
| Arc | V8 | USDC | 0xF2f79eE04C1c303426F0d1543267286460b5321C |
⚠ NOTE: KeeperCoordinatorV8 is live on all ten chains; the V8A variant (for chains without the EIP-2537 BLS12-381 precompile — the drand anchor is committee-attested instead of verified on-chain) runs on Avalanche C-Chain and HyperEVM. Arc is the first dollar-denominated deployment, with fees priced in USDC. Always verify contract addresses against the official repository or RandProofScan before use.