How It Works
The hash chain, the domain-separated draw, and a precise account of what is and isn't proven
Provable fairness on 155.io rests on three ideas: a pre-committed hash chain of seeds, a commit-then-reveal flow per round, and a domain-separated draw that turns a seed into an outcome the same way in every language. Everything a verifier needs is published; nothing about the algorithm is secret.
The pre-committed hash chain
Before any round is played, the platform generates a chain of random seeds where each seed is the hash of the next:
seed[i] = SHA-256(seed[i+1])The first seed — the root — is published up front. Round j uses seed[j], and because hashing is one-way, a revealed seed[j] can be hashed forward j times to reproduce the published root, but the root reveals nothing about any future seed.
This is what makes the outcomes un-grindable: seeds are fixed in advance and consumed strictly in order, so we cannot generate a batch of seeds, peek at the outcomes each would produce, and pick a favourable one. Every consumed seed ends up either as a played round or a published "burn" — the chain stays contiguous and auditable.
One chain per game, per environment
Each game keeps its own independent chain. A round's reveal names the exact chain root and index it came from, so verification is always unambiguous.
Commit, then reveal
At round open — the commitment
The round publishes serverSeedHash = SHA-256(serverSeed). The seed itself stays secret. Because the seed alone determines the outcome, publishing its fingerprint locks the outcome in before a single bet is placed.
Betting closes
The result is already fixed by the committed seed — nothing about the outcome can change once betting is closed.
At settlement — the reveal
The round publishes the server seed, the chain root + index, and the game-specific result values. Anyone can now recompute the outcome and confirm the seed hashes back to the root.
From seed to outcome
Every draw is a domain-separated value derived from the seed:
draw = HMAC-SHA256(key = server seed, message = ":<label>:<index>") // first 13 hex digits
r = draw / 2^52 // a uniform number in [0, 1)The label names which decision is being made (crash, outcome, order, …), so revealing one draw never leaks another, and every draw is provably uniform and unpredictable given a committed seed. From there each game family maps r to its result:
| Family | Mapping |
|---|---|
| Crash | r → the crash multiplier via the published house-edge curve. |
| Counting (CCTV) | r → the winning market, drawn against the published probabilities; the boundaries are then placed around the camera-measured count. |
| Classic | r → the winner (a weighted pick for the weighted games) or the full finishing order (a uniform pick over the possible orderings for the podium games). |
The exact formulas, cross-language test vectors, and reference code all live in the open-source verifier repository.
What is (and isn't) proven
Provable fairness makes a precise guarantee. It's worth being exact about its edges.
It proves — cryptographically, per round:
- The outcome was fixed by a seed committed before betting closed, and reproduces exactly from that seed.
- The seed is a genuine, in-order link in a chain whose root was published in advance.
- For weighted games, the draw used the published probabilities. A "40% option" occupies 40% of the draw space and, because the draw is provably uniform, hits 40% of the time — verifiably per round (we can't rig the rounds the money is on) and statistically over many rounds (collect the reveals and the frequencies converge).
It does not, by itself, prove:
- The payout side of RTP. Return-to-player is probability × payout. Provable fairness rigorously covers the probability; the payout multiplier is a separate published figure in the odds table — an auditable number, but not one derived from the seed. So "is the RTP really 90%?" resolves to "is the probability what's published?" (proven and enforced here) × "does it pay what the table says?" (read off the payouts).
- That a published number matches an advertisement. The cryptography proves the game used the odds it published in the reveal. Confirming those match what the board advertised is a quick comparison a player makes — and the game shows the same odds it bets against.
In short
Provable fairness turns "trust our odds" into "the odds are cryptographically enforced every round and independently checkable." That is the hard, valuable half of fairness — the payout side is a published number that anyone can read.
Independent and open
- The verifier is open source (marbles-io/155-fairness-verifier) and runs entirely client-side — host your own copy if you prefer.
- It ships golden test vectors that lock the algorithm across every implementation (the engines, the widget, and the verifier), so a mismatch anywhere fails the build.
- Nothing about verification depends on 155.io being online or honest at check time — a saved reveal verifies offline, forever.