Skip to content

Request lifecycle

A request is identified by its hub, chain, and uint64 sequence number. Sequence numbers begin at 1 and increase for accepted requests.

Value State Meaning
0 None No accepted request exists at that sequence.
1 Pending Accepted and awaiting delivery or expiry.
2 Fulfilled The hub stored the result and attempted the callback.
3 Expired Closed without a result after the history window.
accepted request → Pending → Fulfilled
↘ Expired

callbackFailed is a separate field. A failed consumer callback leaves the request Fulfilled, with its result available from randomOf(sequence).

requestV2 checks the fee, callback gas, capacity limits, and active lane before allocating an index. A successful call stores its parameters and emits Requested.

A rejected request does not consume a sequence or lane index. A reverted transaction still has its network execution cost.

Delivery must occur strictly after the request block. The authorized relayer submits a link, the hub verifies it, and the result is stored before the callback executes.

If the delivery transaction lacks the hub’s required gas reserve, the whole transaction reverts and the request remains Pending. If the transaction succeeds but the consumer callback reverts, the stored result remains Fulfilled.

At an age of 8191 blocks, a request can still be delivered. At an age greater than 8191, anyone may call expire(sequence) to close a Pending request and free its pending slot.

Expiry is a transaction, not an automatic state transition at a wall-clock deadline. It emits Expired, delivers no number, and invokes no consumer callback. The request fee pays for the delivery attempt and is not refunded on expiry.

The relayer has a keeper that submits expiry transactions. Public cleanup remains possible when the hub is paused.

Check requestOf(sequence).status == Fulfilled before using randomOf(sequence). Zero is a valid random value, so random != 0 is not a fulfillment test.

The application owns any business timeout or settlement policy. RUFF’s expiry closes a randomness request; it does not move assets held by the consumer.