Quickstart
Integrate RandProof into your contracts in four steps: no token purchase, no staking, no minimum commitment.
Integration follows the same four steps regardless of which RandProof product you use.
1. Choose the Product
Match your need to a Layer 1 product:
| Need | Product |
|---|---|
| Verifiable randomness | RandProofRNG |
| Triggered execution / upkeep | RandProofAutomation or Sentinel |
| Off-chain computation / AI inference | RandProofCompute or Forge |
| External data | RandProof Oracle |
| Sybil-resistance signals | RandProof Identity |
| Continuous monitoring | RandProof Audit |
| Reserve attestation | RandProof Custody Proof |
2. Call the Contract
Integrate the relevant Layer 1 interface directly from your client contract. Where a RandProof product is built as a compatible replacement for an existing dependency, such as RandProofAutomation's Chainlink-compatible interface, integration can be a direct address swap with no logic changes required.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
interface IKeeperCoordinator {
// Request a PoFR event. Returns eventId.
// Fee must be >= MIN_FEE. Rate limited: 1 request per 10 blocks per address.
function requestRandomness(bytes32 userSeed) external payable returns (bytes32 eventId);
// 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 memory aggregatedBLSSig,
address[] memory signers,
uint256 fulfillBlock,
uint256 fulfillTimestamp
);
}A minimal consumer requests randomness and receives the fulfilled seed via callback:
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 the 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;
}
// 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;
// ... settle the draw
}
}The full interface, including fulfill, submitEntropy, submitFraudProof, and getEntropyInputs, is documented in Client Contract Integration.
3. Pay Per Use
Fees are paid in USDC at the point of use via the x402 micropayment rail. There is no protocol token required to integrate, no staking requirement on the client side, and no minimum commitment beyond the fee for the specific call being made.
4. Consume the Result
A request returns either an on-chain value directly (randomness, an oracle reading) or a certificate referencing an off-chain result (a PoIF fidelity certificate, a PoRC provenance certificate, an identity attestation). Where ERC-8004 integration applies, you can additionally check a counterparty's or keeper's attestation history in the Validation Registry before relying on a given result.
What Integration Does Not Require
- No RandProof token purchase or holding requirement to integrate any product as a client.
- No migration of existing contract logic beyond the specific function calls being replaced, for products offered as compatible drop-in replacements.
- No relationship with BIT5050 or any other existing production deployment, every Layer 1 product is designed to be integrated independently.