> ## Documentation Index
> Fetch the complete documentation index at: https://docs.fade.finance/llms.txt
> Use this file to discover all available pages before exploring further.

# Randomness

> ORAO VRF, a seed bound to a block that did not exist at open, and what a withheld draw means.

## Why an oracle

When the user signs their own wager, block-derived randomness is unsafe: the user can simulate a transaction and only submit the ones that win, and a block producer knows its own block hash with certainty. A verifiable random function (VRF) served by an oracle is the arrangement both sides can accept. Fade uses **ORAO VRF** (`VRFzZoJdhFWL8rkvu87LpKM3RbcVezpMEc6X5GVDr7y`).

ORAO is a push oracle: once a request exists, its authorities write the fulfilment, each contributing an Ed25519 signature over the seed, stored publicly. On mainnet the quorum is 3 of 3 authorities. ORAO's fee and treasury are read from its on-chain network state at request time, never set by Fade.

## Request after entropy

ORAO's key holders can compute the outcome of any seed before it is requested, because Ed25519 signatures are deterministic. If the seed were known when the wager opened, a key holder colluding with a user could open only the wagers that win. Fade closes this by deriving the seed from entropy that does not exist yet when the wager opens:

<Steps>
  <Step title="Open at slot t">
    `open_wager` admits the wager and stores the paytable. No oracle call is made.
  </Step>

  <Step title="Request from t + 2">
    `request_randomness` (permissionless, from `t + 2` until `t + T_SETTLE`) takes `s*`, the smallest slot in `SlotHashes` greater than `t` (skipped slots are simply absent), and its hash `h*`, and derives:

    ```
    seed = SHA256("FADE/ORAO-SEED/v1" ‖ program_id ‖ wager ‖ t ‖ s* ‖ h*)
    ```

    with `t` and `s*` as little-endian `u64`. The wager's `vrf_payer` PDA pays ORAO to create the request for that seed. The seed, `s*`, `h*` and the request address are stored in the wager.
  </Step>

  <Step title="Fulfil">
    ORAO's authorities write a 64-byte random value `R` into the request account.
  </Step>

  <Step title="Settle">
    `settle_wager` checks the request's address, owner, type, state and seed, and derives the outcome:

    ```
    w_i = SHA256("FADE/OUTCOME/v1" ‖ program_id ‖ wager ‖ seed ‖ R ‖ i)
    ```

    `i` is a single byte, starting at 0. Each 32-byte `w_i` gives two candidate words, bytes 0 to 15 then 16 to 31, each read as a little-endian `u128`. A word below `LIMIT = (2^128 − 1) − ((2^128 − 1) mod 1e9)` gives `x = word mod 1e9`, exactly uniform in `[0, 1e9)`; a word at or above `LIMIT` is rejected and the next candidate is tried, for at most 8 hashes. A rejection has a probability of about 2.3 × 10⁻³⁰; rejecting all 16 candidates would fail with `DrawFailed`. The bucket drawn is the first index `k` with `x < p_0 + … + p_k`.
  </Step>
</Steps>

To bias an outcome, an attacker now needs ORAO's key holders **and** the leader of slot `s*` (to grind or skip that block) **and** the user. Mixing `h*` in at settlement instead would not work: if ORAO fulfilled at or before `s*`, that slot's leader would already know `R`.

Settlement never reads `SlotHashes`, so it has no 512-slot cliff, and it has no deadline: a wager fulfilled late can still be settled.

## A withheld draw

Any single ORAO authority can stall a request by not signing. If the randomness is not fulfilled by `open_slot + T_SETTLE` (150 slots, about a minute), anyone may call `expire_wager`, and **the pool keeps the stake's pool credit**. It is never returned.

That rule is what makes withholding worthless. If an unfulfilled wager were returned, a user colluding with a key holder could let every losing draw expire and keep every winner: a free option. Under forfeiture, suppressing losing draws and revealing only winners produces exactly the same payoff distribution as honest play.

Forfeiture does not stop a key holder who also holds pool shares from withholding a user's winning draw to save the pool the payout. The per-wager cap bounds each such event, and an isolated expiry among fulfilled requests, which a genuine outage does not produce, is the signature to watch for.

A genuine outage longer than `T_SETTLE` forfeits every wager in flight. The guardian pausing new wagers when the oracle stalls bounds how many wagers that reaches.

## Verify a draw yourself

Everything needed is public:

1. **The paytable**: in the `open_wager` instruction data of the open transaction (decode with `getOpenWagerInstructionDataDecoder()`), and in the wager account while it is open.
2. **`t`, `s*`, the seed and the request**: the wager account while open, or the `WagerOpened` (`open_slot`) and `RandomnessRequested` (`seed`, `request`, `entropy_slot`) events.
3. **`R`**: the ORAO request account. ORAO has no close instruction, so it remains readable after settlement.
4. Recompute `w_i`, apply the rejection sampling and the cumulative mapping above, and compare the bucket with the `bucket` in `WagerSettled`.

## Limits

* **Verifiable odds, not provable fairness.** The guarantee rests on ORAO's authorities not colluding with the leader of `s*` and a user, and on the ORAO program not being maliciously upgraded. A malicious upgrade could write arbitrary randomness after the fact; its upgrade authority is a single key. Verifying the authorities' Ed25519 signatures over the seed inside the settle transaction is the planned hardening.
* **One provider.** Fade depends on ORAO's availability. An outage forfeits in-flight wagers as described above.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.