Integrate a consumer contract
A consumer is a deployed smart contract that requests a number and accepts the hub’s callback. The downloadable ExampleConsumer stores one result per sequence.
Get the interfaces
Section titled “Get the interfaces”Download the current reference files, keeping the directory structure:
- interfaces/IRandomnessHub.sol
- interfaces/IEntropyV2Compatible.sol
- interfaces/IEntropyConsumer.sol
- example/ExampleConsumer.sol
The example uses Solidity 0.8.30 and imports interfaces from ../interfaces/. Deploy it with the hub proxy address from your environment’s deployment record.
Quote inside the consumer
Section titled “Quote inside the consumer”The example quotes and forwards the exact fee in the same consumer call:
uint128 fee = hub.getFeeV2(address(hub), gasLimit);if (msg.value != fee) revert WrongFee(fee, msg.value);
sequenceNumber = hub.requestV2{value: fee}( address(hub), userContribution, gasLimit);getFeeV2 uses its caller’s tariff. From this code, the caller is the consumer. For a frontend quote, use quote(consumerAddress, gasLimit) instead of quoting for the user’s externally owned account.
A quote read earlier can become stale if configuration changes before inclusion. Re-read and retry a fee mismatch instead of forwarding an arbitrary overpayment.
Record the sequence
Section titled “Record the sequence”Immediately associate the returned sequence with the action that requested it. The example stores the requester and a separate requested flag.
draws[sequenceNumber] = Draw({ requester: msg.sender, requested: true, stored: false, random: bytes32(0)});The hub cannot fulfill in the request block. Fix the application’s outcome-affecting parameters in this requesting transaction.
Authenticate and handle the callback
Section titled “Authenticate and handle the callback”Inherit IEntropyConsumer. Its external _entropyCallback checks that msg.sender equals the address returned by getEntropy() before dispatching to your internal handler.
function getEntropy() internal view override returns (address) { return address(hub);}
function entropyCallback( uint64 sequenceNumber, address provider, bytes32 random) internal override { if (provider != address(hub)) revert WrongProvider(provider); _store(sequenceNumber, random, true);}Process a known sequence once. The example uses stored as its completion flag and returns without changing the result if the same sequence is presented again. Zero is a valid result.
Keep the callback small: store the value and emit an event. Separating expensive application work from delivery makes the callback gas requirement easier to bound.
Recover after a failed callback
Section titled “Recover after a failed callback”The hub stores a result before calling the consumer. If the callback fails, the example’s public recover(sequence) checks ownership and status before copying that result:
IRandomnessHub.Request memory r = hub.requestOf(sequenceNumber);if ( r.consumer != address(this) || r.status != IRandomnessHub.Status.Fulfilled) revert NotFulfilled(sequenceNumber);
_store(sequenceNumber, hub.randomOf(sequenceNumber), false);Recovery reads the existing number. It does not request a new result or grant permission to deliver randomness to the hub.
Before using your integration
Section titled “Before using your integration”Exercise a successful callback, a reverting callback followed by recovery, repeated recovery, an unknown sequence, and a result equal to zero. Measure the callback on the actual target execution environment and test the hub’s pending limits and expiry boundary.
The reference example holds no application stakes and specifies no application settlement policy. Add those rules in the consuming application with the result-visibility constraints in mind.
The secure integration guide covers binding results to fixed round state, application-specific derivation, timeout handling and the tradeoffs of additional entropy.
