Invariants
Each is enforced on-chain at the instruction named.Solvency
- Gross solvency.
reserved liability + open pool credits ≤ assets, checked insideopen_wager. The pool can pay every open wager’s maximum at once. A net-only rule is not enough: with 200 of assets, a stake of 100 at 3.5× credits 99.50 and reserves 250.50; a net check accepts it, yet the payout owed is 350. - Global exposure. Reserved liability never exceeds κ = 80 % of assets, enforced at open and at every operation that lowers the pool (the strike). Never at settlement, which may not be refused.
- Internal accounting.
total_assetsis never derived from a token balance. Donations and stray transfers move nothing. Each token account holds at least what the ledger says it owes.
Fairness
- Probabilities sum to exactly 1 000 000 000 and none is zero.
- The expected-return check runs in 128-bit integers with no floating point anywhere in the path.
- Bucket selection is exactly uniform: 128-bit words with rejection sampling. (Reducing a 32-bit word modulo 1e9 would carry a 23 % bias.)
- The paytable, the edge, the app fee, the reserved liability and the cap stored at open are the ones used at settlement. Settlement never reads live parameters and never re-checks a cap.
Custody
- No admin instruction can rewrite a liquidity provider’s balance, override a wager’s outcome, or move vault funds outside the user paths (requests, strike, claims, settlement, expiry, payout claims).
- No pause can block
settle_wager,expire_wager,claim_payout,strike_epoch, a claim of a struck request, orrequest_withdraw. - Settlement always succeeds: a beneficiary that cannot receive gets its payout parked in escrow, so one frozen account can never block the pool’s pricing.
Identity
- The app is the signer of
integrator_authority. A program app’s identity is its["fade-integrator"]PDA, which only that program can sign for. Neither the calling program id nor the instructions sysvar is used to identify a caller (the sysvar cannot see inner CPIs). - Every account carrying money or identity is pinned by address, seeds or a stored key against already-trusted state, never accepted by position.
Randomness
- The oracle seed is derived on-chain from entropy that did not exist at open. No instruction accepts a caller-supplied seed or request account, and the wager nonce is the app’s next nonce, never chosen.
settle_wageraccepts the ORAO account only if its address, owner, type, state, stored seed and length all match. A pending request leaves the wager untouched.
Epochs
- Clean strike. An epoch is struck only after its close and once every wager opened before the close has resolved. The strike’s cost is independent of the number of requests and wagers, and it excludes the credits and results of wagers opened after the close.
- Two sides. No wager instruction writes the liquidity side, and no liquidity instruction writes
Poolexcept the strike and the request that opens an epoch.
Token policy
Fade accepts legacy SPL USDC only. Token-2022 is rejected: a transfer hook would hand a third party a guaranteed call into every payout. The flip side is that USDC’s issuer can freeze any USDC account, including the pool’s.Governance
Pause first, then upgrade. Before an upgrade’s timelock starts, the council pauses new wagers, so reserved liability can only shrink while the upgrade waits and liquidity providers can withdraw. The program cannot observe a multisig proposal on-chain, so this ordering is enforced by the council’s procedure and an off-chain watcher, not by the program.
Why the upgrade key exists. Burning it would leave liquidity stranded behind the first bug. It is mitigated (multisig, timelock, pause-first ordering, the never-list above), not eliminated.
On devnet, a single test key holds the council and guardian roles, and parameter changes apply at once. The devnet deployment is a test environment.
The trust that remains
Stated plainly, so nobody has to discover it.- Randomness is oracle-assumed, not proven. The honest claim is publicly verifiable odds, not provable fairness. ORAO’s authorities can stall a request (bounded by forfeiture) and, because their signatures are deterministic, could compute outcomes in advance (bounded by binding the seed to a block that did not exist at open). A malicious upgrade of the ORAO program could write arbitrary randomness after the fact. See Randomness.
- An oracle outage forfeits the wagers in flight. If ORAO stops fulfilling for more than
T_SETTLE, every wager opened in roughly the preceding minute expires, users’ stakes included. The guardian’s pause bounds how many wagers are exposed, not whether they are. - Fade verifies the odds, not the recipient. An app can name any beneficiary. An operator that is its own beneficiary is trusted by its users to credit them.
- A compromised app keeps its access. Whoever takes an app’s key, or its program’s upgrade authority, can open wagers as that app, bounded by the caps, its 20 % ceiling and the funds it controls. The fee destination is fixed in the record.
- Smart contract risk. The program has not completed an external audit.