Skip to main content
Chance uses commit–reveal with an epoch-bound server seed. Every payout derives from entropy the contract itself verified — either against the revealed seed or via a Groth16 proof. There is no operator-attested settle path.

How an epoch works

1

Commit

The pool opens an epoch by publishing commitment = PoseidonT2([serverSeed]) on-chain. Many bets share one epoch commitment; the seed itself stays secret.
2

Play

Each bet binds your clientSeed and its unique betId under the open epoch. The outcome is already fixed: entropy = PoseidonT4([serverSeed, clientSeed, betId]). The house cannot pick your entropy without breaking the commitment; you contribute clientSeed, so it cannot precompute a forced loss either.
3

Settle early with a proof (optional)

While the epoch is still open, anyone can call settleWithProof(betId, entropy, proof) with a Groth16 proof that the entropy is consistent with the committed seed — without revealing the seed. The API computes and delivers these proofs in realtime (see Results & proofs).
4

Close, then reveal

advanceEpoch(nextCommitment) closes the epoch (no seed in that transaction) and opens the next. Afterwards, anyone holding the seed can call settleWithSeed(betId, serverSeed) — the contract checks PoseidonT2([seed]) against the commitment, publishes the seed, and settles. Remaining bets settle with settleBet / settleBets.
5

Verify

With the revealed seed public, anyone can recompute every outcome in the epoch (see below).

Verify a bet yourself

After the epoch’s EpochRevealed event publishes serverSeed:
  1. Check the commitment: computeCommitment(serverSeed) (a public view on ChancePool) must equal the commitment from the epoch’s EpochOpened event.
  2. Recompute the entropy: computeEntropy(serverSeed, clientSeed, betId) — also a public view — must produce the entropy the bet settled with.
  3. Re-derive the payout: map entropy to the outcome with the mode formula (Strike / Range / Ladder) and compare against the BetSettled event’s payout.
The Poseidon hashes match circomlib / poseidon-lite, so the same math runs in JavaScript verifiers and inside the ZK circuit.

The refund safety net

Every bet carries a deadline of placedAt + revealTimeout (default 1 hour): If the server seed is ever lost, the operator’s only power is closing the compromised epoch (forceAdvanceEpoch) so bets refund — it can never choose an outcome.
The public API delivers results and proofs, but never the server seed while an epoch is open. Treat any result shown before an on-chain settle as display-only; the paid truth is always the contract settle.