← Integrations Docs

Provably Fair — Platform Overview

How all eight Swivel original games decide their outcomes, what a player can independently check, and where we currently fall short of the claim.

In one paragraph

"Provably fair" means a player can mathematically confirm we didn't rig their result — not because we say so, but because they can recompute it themselves. Swivel runs two different systems to do this: one for multiplayer games (Crash, When Moon Bro, Chart) and a separate one for single-player games (Roulette, Dice, Limbo, Hi-Lo, Wheel of Fortune). The multiplayer system is built on the right foundations but is weakened by how we rotate seeds in practice. The single-player system produces genuinely fair, deterministic results, but a player currently has no way to independently prove that — the information needed to check it is never published. This document explains both, and what we'd change.

Contents
  1. What "provably fair" promises
  2. Two systems, eight games
  3. Single-player: how an outcome is made
  4. Outcome formulas, game by game
  5. Worked example: a real roulette spin
  6. Multiplayer: the hash chain
  7. Where we fall short today
  8. Proposed improvements
  9. Answering a player or partner
  10. Further reading

1 · What "provably fair" promises

The promise is not "our random numbers are good quality". It's stronger: the result was fixed before you bet, and you can prove it afterwards without trusting us. Every implementation of it follows the same three beats:

🔒

1. Commit

Before any bet, we publish a fingerprint of a secret value. The fingerprint reveals nothing about the secret, but it locks us in — we can't change the secret later without the fingerprint changing.

🎲

2. Play

Each result is computed from that secret, combined with a value the player controls and a counter. Same inputs always produce the same result — no randomness at the moment of the bet.

🔓

3. Reveal & verify

Once the secret is retired, we publish it. Anyone can then fingerprint it themselves, confirm it matches step 1, and re-run every result from it.

Remove step 3 and the whole thing collapses into "trust us" — which is exactly the failure mode described in §7. Our public game rulebooks make the full promise to players, so the bar we're measured against is the three-step version.

2 · Two systems, eight games

Which system applies depends on whether a game resolves one player's bet instantly, or resolves one shared round for everyone at once.

Single-player system Multiplayer system
Games Roulette, Dice, Limbo, Hi-Lo, Wheel of Fortune Crash, When Moon Bro, Chart
Where randomness comes from A seed pair unique to each player — our server seed plus their client seed — and a bet counter that increases with every bet A long chain of hashes generated in advance and shared by everyone; each round consumes exactly one link
Can the player influence it? Yes — they choose their own client seed at any time No, and by design: the shared seed comes from a future public event nobody controls
What's published in advance An encrypted copy of the server seed A public seeding post committing to the chain's first hash, plus the future block whose hash becomes the shared seed
Is the secret ever revealed? No No — the chain's origin value is discarded at generation
Can a player verify a result today? Not independently Partly — the chain proves itself, but rotations break it
Verification tool in product None A "Check" link per round, hosted externally

3 · Single-player: how an outcome is made Roulette · Dice · Limbo · Hi-Lo · WoF

Each player permanently holds two seed pairs: the active pair producing their results right now, and a future pair already generated and committed, waiting for them to switch. Both are visible in the game's Fairness panel.

Ingredient What it is Who sets it
Server seed A random secret we generate. The player sees only an encrypted form of it. Swivel
Client seed A short text value, 5–64 characters. Randomly generated for the player, who can replace it with anything they like. Player
Nonce A counter, starting at zero, that increases by one with every bet — so two identical bets never produce the same result. Automatic

On every bet, these three are combined into a single 64-character value using HMAC-SHA256 — a standard keyed hash. The same three inputs always produce exactly the same value, and changing any one of them by a single character changes the whole thing unpredictably. That value is then mapped onto the game's outcome (a roulette pocket, a dice number, a card) by the formulas in §4.

Server seed secret, ours Client seed player's choice Nonce bet counter HMAC-SHA256 deterministic, one-way Result value 64 hex characters Outcome §4 formula
Fig. 1 — One bet. The result value is shown to the player in their bet history; the server seed behind it is not.

What happens when a player changes their seed

Changing the client seed retires the current pair, promotes the pre-committed future pair (with the player's new client seed attached), resets the bet counter to zero, and generates a fresh future pair. The retired pair is marked as revealed in our database — but, as covered in §7, nothing is actually revealed to the player at that point.

FUTURE committed, not yet in use ACTIVE producing results now USED one record per bet REVEALED retired on seed change seed change bet placed each bet creates the next active record (counter +1) seed change a new future pair is generated
Fig. 2 — A seed pair's life. Retired pairs are terminal: they never return to active use.

4 · Outcome formulas, game by game

Both systems end the same way: a 64-character hash is produced, a few characters are read off the front of it as a number, and that number is scaled onto whatever the game needs — a pocket, a card, a multiplier. None of this is secret in any meaningful sense; the security comes from the hash, not from hiding the arithmetic.

Single-player games seed = HMAC(server seed, client seed + nonce)

Game Characters read How it becomes a result
Roulette first 5 Scaled to 0–36 (European wheel, single zero). The payout multiplier is then derived from which bets won and the configured house edge.
Dice first 5 Scaled to 0–100, then compared against the player's target and direction.
Limbo first 13 Uses the same curve as Crash (below) to roll a multiplier. The player wins if their target sits below the rolled value.
Hi-Lo 5 per card Scaled to 0–51, then split into rank and suit. Because each card reads a different slice, one hash deals a whole sequence.
Wheel of Fortune first 5 Scaled to the number of wheel segments configured for that wheel.

Multiplayer games seed = HMAC(shared client seed, round hash)

Game Characters read How it becomes a result
Crash
and When Moon Bro — same engine
first 13 Converted to a fraction, then run through a curve that produces mostly low multipliers and occasionally very high ones. A proportion of rounds are forced to instant 1.00× — and that proportion is the house edge.
Chart two slices of 5 The first slice sets how far the price moves, the second sets the boundary for the next round. Direction (long / short / unchanged) falls out of comparing the new price to the old one.
Where the house edge lives

Never in the randomness — always in the payout or the mapping afterwards. The edge in force at the time is stored on every round and every bet, so a historical result stays reproducible even after the configuration changes.

5 · Worked example: a real roulette spin

Taking an actual spin — client seed xinUbdR5uI, spin number 520, reported result value beginning 85ce5…, landing on 19 at 1.97×:

Combined input
xinUbdR5uI-520
Result value
85ce57bbfb5840d7904af185812b3f1f332dcd585cbe6caea7c9018711c297c8
First 5 characters
85ce5
Read as a number
548069
Scaled to the wheel
548069 × 37 ÷ 1048576 = 19.339…
Rounded down
19 — matches the recorded result ✓

The 1.97× multiplier is not part of this check. Once the pocket is fixed at 19, the payout follows deterministically from which bets the player placed and the house edge — there is no second random step.

What this example does and doesn't prove

It proves the number wasn't invented: the result value genuinely maps to pocket 19. It does not prove that the result value itself came from the server seed committed to the player before they started betting — that link is exactly what we can't currently demonstrate. See §7.

6 · Multiplayer: the hash chain Crash · WMB · Chart

Multiplayer games don't generate anything at bet time. Millions of hashes are produced in advance, each one the hash of the previous, and rounds consume them one at a time — but in reverse order, so the chain is played from its end back towards its beginning.

Generated forwards, months in advance → hash #1 last round played hash #2 · · · hash #4,999,999 round 2 hash #5,000,000 round 1 — published ← Consumed backwards, one per round hashing any round's value gives you the previous round's value
Fig. 3 — Because the chain is built forwards and played backwards, revealing a round's hash also proves it was fixed before every round that came before it.

This is a genuinely strong construction. To produce a round's hash, we'd have to reverse SHA-256 against a value already published — which is not feasible. Every round's hash is broadcast live and shown in the Hash Info panel, so a player who records one hash can check every later round against it indefinitely. Each round also deep-links to a "Check" page that recomputes the result.

The shared client seed is set by a seeding event: we publish the chain's first hash together with the number of a future, not-yet-produced public blockchain block, whose hash then becomes the seed. Nobody — including us — can know that value in advance, which is what stops the chain from being generated to our advantage.

Deeper detail

The Multi-Player Hash Guide covers the chain end to end — generation, ordering, the seeding ceremony procedure, and the operational issues summarised below.

7 · Where we fall short today

Measured against the three-step promise in §1, both systems complete steps 1 and 2 and neither completes step 3. The details differ.

Single-player Multiplayer
Commit Partial — what we show the player before they bet is an encrypted copy of the server seed, not a one-way fingerprint. Encryption can only be undone by us, so it doesn't let anyone else confirm anything. Yes — the chain commits to itself, and the seeding post commits to its starting point publicly.
Play Yes — fully deterministic, no re-rolls, the consumed record is locked to the bet. Yes — one chain link per round, consumed in order.
Reveal No — the server seed is never disclosed to anyone outside the platform, at any point in the seed's life. No — the value the chain was built from is discarded during generation, so there is nothing left to reveal.
Published method No — the formulas aren't documented for players anywhere. Partial — a Check tool exists, hosted on a third-party sandbox we don't own or control.

The chain-break problem

This is the issue most likely to be raised by an informed player, and it affects both systems: as soon as a seed is rotated or a new chain is generated, the history before that point becomes permanently unverifiable.

Multiplayer — rotation happens mid-chain

We don't wait for a chain to be used up before running a new seeding event. The shared seed is switched while millions of committed hashes remain unused, so a block of rounds ends up committed under one seed but replayed under another. Anyone who kept the original seeding post and tries to verify across that boundary gets a mismatch — not because anything was manipulated, but because the published inputs no longer describe the rounds that were played. The three multiplayer games also burn through hashes at different rates, so they are never exhausted at the same time and there is no clean moment to rotate.

Multiplayer — an old chain can never be proven complete

Even setting rotation aside, proving a whole chain was honest requires revealing the value it was generated from, so anyone can regenerate all five million hashes and confirm not a single one was skipped or cherry-picked. That value is created during generation, used once, and discarded — it does not exist anywhere afterwards. So a retired chain can be spot-checked link by link, but never validated end to end.

Single-player — the same break, once per player

Every time a player changes their client seed, their previous seed pair is retired and its entire betting history becomes permanently uncheckable: the server seed behind it is never published, and the bet counter restarts at zero so old bets can't even be located by position. A player who has changed their seed ten times has ten blocks of history, none of which can be verified — and the retired records are already flagged as "revealed" internally, which makes the missing step look like an oversight rather than a design choice.

No verification path for staff either

When support is asked "can you check this round for me?", there is no tool for it. Answering requires an engineer querying the database by hand. This is the practical cost of the gaps above, and it's the reason this document exists.

To be clear about what this is and isn't

None of the above says results are unfair, manipulated, or wrong. The outcomes are deterministic, the arithmetic is sound, and every input is stored. What's missing is the ability for someone outside the platform to confirm that independently — which is the specific thing the phrase "provably fair" promises. That's a documentation, product and process gap rather than a defect in how games are played.

8 · Proposed improvements

Grouped by what they unlock. Nothing here changes how any game plays or what it pays.

Make single-player results verifiable

  1. Publish a one-way fingerprint of the server seed instead of an encrypted copy. This is the single change that turns the pre-bet commitment into something a player can actually check later. Small change, and everything else depends on it.
  2. Reveal the server seed once a seed pair is retired. The retired state already exists and is set correctly — it's simply never surfaced. Publishing it at that point is what completes the three-step promise.
  3. Return the client seed and bet counter alongside each bet in history. Without them a player cannot tell which seed pair and which position a past bet belonged to, so old bets stay unverifiable even after a reveal.
  4. Document the formulas publicly. They contain no secrets and hiding them buys nothing, while their absence makes the fairness claim impossible for a player to act on.

Fix the chain-break problem

  1. Persist a per-chain secret and publish its fingerprint before the chain's first round. Then, when the chain is retired, reveal it so the entire chain can be regenerated and checked end to end. This is the direct fix for a retired chain being unprovable.
  2. Rotate the shared seed only at a chain boundary. Never replay hashes committed under one seed using a different one. Practically this means per-game chains that can be retired independently, rather than one global rotation across three games that consume at different speeds.
  3. Publish seeding commitments somewhere permanent and findable. A commitment posted where it can later be edited or deleted, and that players have no reliable way to find, does not carry the weight we need it to carry — particularly in a compliance conversation.
  4. Treat retired chains and retired seed pairs as an archive, not as deleted history. Keep the published commitments, revealed secrets and boundary dates available indefinitely, so "verify my bets from March" has an answer long after the seed has changed.

Give players and staff somewhere to go

  1. One verifier we own, covering all eight games. The current multiplayer Check link points at an externally hosted sandbox we don't control, don't version and can't audit — and the same link is used for games that calculate results differently, which is worth confirming on its own. A first-party page removes an external dependency that today props up a compliance-facing claim. The existing one-click-from-the-round experience is good and should be kept.
  2. Add the same Check link to single-player games. The Fairness panel already shows the seeds and counter, then stops. Once the items above land, this is a link.
  3. Build an internal verification view for support and compliance. Paste a bet or round reference, see the inputs, the calculation, the resulting outcome and a clear match/mismatch against what was recorded. Every input is already stored, so this is a read-only view rather than new machinery — and it turns a multi-day engineering request into a self-service answer.
On "can we get a game replay?"

This request comes up regularly and reflects a misunderstanding worth correcting gently: for these games there is no gameplay to replay. A round is a single number produced by a calculation, not a sequence of events. The right answer is to show the calculation — which is exactly what the internal verification view above would provide, and why it's the highest-value item on this list for day-to-day operations.

Also raised, tracked separately

A small number of defence-in-depth items around database constraints and stored-data handling were noted during this review. They carry no player-facing impact and are being handled directly with the backend team rather than documented here.

Suggested order

Priority Item Why first
1 Internal verification view Immediate operational relief, depends on nothing else
2 Single-player fingerprint + reveal + bet data One piece of work; unlocks every other single-player item
3 Per-chain secret + boundary-aligned rotation Closes the multiplayer chain-break problem at its root
4 First-party verifier + published formulas Removes the external dependency and makes the claim actionable
5 Permanent, findable commitments + archive Makes the guarantee hold up months later, not just live

9 · Answering a player or partner

Until the improvements land, this is roughly where the honest line sits. Anything beyond it should go to the backend team rather than being improvised.

Safe to say

Results are generated before the bet resolves, from inputs that are fixed in advance and stored. The player's own client seed contributes to every single-player result, and they can change it at any time. Multiplayer rounds publish their hash, and each round links to a page that recomputes the result.

⚠️

Say carefully

For single-player games we can confirm and show the calculation internally, but we don't yet publish everything a player would need to repeat it themselves. That's a known gap with work planned — not a refusal, and not a statement about whether the result was correct.

🚫

Don't claim

That a player can independently verify single-player results today, that a round can be "replayed" as gameplay, or that a chain can be validated end to end across a seed rotation. None of those are true right now.

➡️

Escalate when

A player, partner or regulator asks for verification of specific rounds or bets, or points at a chain mismatch across a rotation boundary. These need engineering, and the mismatch may be the known boundary issue rather than anything wrong with the result.

10 · Further reading

Topic Where
Multiplayer chain — generation, ordering, seeding ceremony, known problems Multi-Player Hash Guide
Single-player seed pairs, per-bet consumption, outcome formulas Backend — shared single-player hash and RNG modules
Multiplayer round engines and result derivation Backend — engine game services (Crash, When Moon Bro, Chart)
Player-facing Fairness panel and Hash Info panel Web frontend — originals game modules