Request lifecycle
A request is identified by its hub, chain, and uint64 sequence number. Sequence numbers begin at 1 and increase for accepted requests.
States
Section titled “States”| 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 ↘ ExpiredcallbackFailed is a separate field. A failed consumer callback leaves the request Fulfilled, with its result available from randomOf(sequence).
Acceptance
Section titled “Acceptance”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
Section titled “Delivery”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.
Expiry
Section titled “Expiry”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.
Read the result correctly
Section titled “Read the result correctly”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.
