Back to Dice

DiceXo

Provably Fair

Every dice roll on DiceXo is produced by a formula, not by a decision. Before you bet, the site publishes a fingerprint — a SHA-256 hash — of a secret number called the server seed. Your rolls are then computed from that secret, a client seed you can set yourself, and a counter that goes up by one with every bet. When you rotate your seeds, the secret is revealed, and because its fingerprint was published first, you can check that the secret was not swapped along the way and re-compute every roll it produced — on your own machine, with one line of code, using nothing of ours. This page explains how that works, walks you through checking one of your own bets, gives you the exact algorithm so the maths is reproducible, and is honest about what the check does and does not prove.

Last updated: 21 September 2026

The problem it solves

You cannot see our dice. When a roll comes up just short of your target, there is no way to tell by looking whether the number was generated honestly or chosen after we saw your bet. "Trust us" is not an answer, and neither is a certificate on a footer.

Commit–reveal fixes that with ordering. We lock in the secret before you bet and hand you proof that we locked it in; later we show you the secret. If the secret we reveal does not match the proof we gave you earlier, we have been caught. If it does match, then the server seed behind those rolls was fixed before you ever placed a bet.

The four ingredients

NameWhat it isWho controls it
Server seed 32 random bytes, shown as 64 hexadecimal characters. Kept secret while it is in use. Us — but we are locked into it in advance.
Server seed hash The SHA-256 hash of the server seed. Shown to you before you bet. A hash cannot be worked backwards into the seed, and no other seed will produce the same hash. Published by us, held by you. This is the commitment.
Client seed A short piece of text mixed into every roll. You get a random 16-character one by default and can replace it with anything you like. You, if you set it.
Nonce A counter. It starts at 0 for a fresh seed pair and goes up by one with each bet, so no two bets use the same input. Nobody — it just counts.

A server seed and a client seed together are a "seed pair". Your first pair is created the moment your account is created, so a commitment exists before your very first bet. Open Fairness (the shield button in the header, or Provably Fair in your account menu) to see the current hash, your client seed, and the next nonce.

Why the hash has to come first

This is the whole trick, so it is worth being slow about it. SHA-256 turns any input into a 64-character fingerprint. You cannot run it backwards, and finding a second input with the same fingerprint is not something anyone can do. So when we show you a hash, we have tied ourselves to exactly one server seed without telling you what it is.

Later, we reveal the seed. You hash it yourself. If it matches the hash you were given before you bet, then that was the seed all along — we had no way to swap it for a friendlier one after seeing your bets. That is the entire guarantee, and it only works if you keep your own copy of the hash before you play. Copy it, screenshot it, paste it in a note to yourself. A hash we show you afterwards proves nothing at all.

How a roll is calculated

Here is the exact algorithm, the same one that runs on the server and inside the verifier page:

  1. Build the message: the client seed, a colon, and the nonce. For client seed my-lucky-seed on your first bet, the message is my-lucky-seed:0.
  2. Compute HMAC-SHA256 of that message, using the server seed as the key. The key is the 64 hexadecimal characters treated as ordinary text, not decoded into bytes — this trips people up when they write their own checker. The result is a 64-character hex digest.
  3. Cut the digest into eight chunks of 8 hex characters. Each chunk is a 4-byte number between 0 and 4,294,967,295.
  4. Take the first chunk whose value is below 4,294,960,000, and skip any chunk at or above it.
  5. The roll is that value modulo 10,000, displayed with two decimals: 0.00 to 99.99.

Step 4 is not decoration. 4,294,960,000 is 232 rounded down to a whole multiple of 10,000. Taking a remainder without that cut would make the lowest 7,296 results very slightly more likely than the rest, which is exactly the sort of quiet bias a house could hide behind. Discarding the top 7,296 values out of 4.29 billion (about 0.00017% of digests) makes all 10,000 outcomes exactly equally likely. In the vanishingly unlikely case that all eight chunks are too high — roughly a 1 in 1046 event — the message is hashed again with :r1 appended, then :r2, and so on.

A worked example you can re-run right now

These are real values from a real seed pair. Every number below can be reproduced on your own machine in a few seconds.

That bet was "roll under 49.00", so 40.41 was a win, paid at 2.020408×.

How the roll decides win or lose

You pick a win chance between 1.00% and 98.00% and a direction:

Either way the count of winning numbers is exactly your stated chance, with no rounding in our favour at the edges. The bet row records your stake, chance, target, direction, the roll and the result, so you can check the decision followed the number as well as checking the number itself.

The payout, and the 1% house edge

Your payout multiplier is 99 divided by your win chance in percent. In the code the stake is multiplied by 9,900 and divided by the chance expressed in hundredths of a percent, then rounded down to whole coin units.

Win chanceDiceXo paysA zero-edge game would pay
98.00% (the maximum)1.010204×1.020408×
49.00%2.020408×2.040816×
10.00%9.90×10.00×
1.00% (the minimum)99.00×100.00×

In every row the payout is exactly 99% of the break-even payout. That 1% gap is the house edge, and it is the entire business model — there is no rake, no commission and no fee on top of it. The rounding-down of the payout to whole coin units keeps the fractional remainder with the house too, which on ordinary stakes is a rounding error but is not nothing, so it is worth stating.

What "99% RTP" actually means

Return to player of 99% is a statement about long-run averages, not a promise about your session. For every 100 units you stake, 99 come back on average, across an enormous number of bets. Three things follow, and all three matter:

Verify one of your own bets, step by step

1. Take control of the client seed

Open Fairness. Type your own client seed into the client seed box and press rotate ↻. Use something you will recognise — 1 to 32 characters, using letters, digits, underscore, dot, colon or hyphen. (Anything outside those rules is silently replaced with a random 16-character seed, so check the box shows what you typed.) Now write down two things: your client seed and the server seed hash shown above it. This is the moment the commitment becomes yours.

2. Place some bets

The nonce starts at 0 and goes up by one per bet, so your first bet on this pair is nonce 0, your second is nonce 1, and so on.

3. Reveal the server seed

Go back to Fairness and press rotate ↻ again. Rotating retires the pair you just played on, reveals its server seed, commits a brand-new hashed seed for your next bets, and resets the nonce to 0. The revealed pair then appears in the list at the bottom of the Fairness panel, labelled with its client seed and how many bets were made on it. Until you rotate, the server seed stays hidden — that is necessary, because a seed you could read in advance would let you compute every future roll before betting.

4. Check the bet in the app

Open the My Bets tab and click the bet you want to check. The dialog shows the stake, target and roll, the profit, the server seed hash, the revealed server seed and the HMAC message. Your browser then recomputes the roll locally and reports either "✓ Verified in your browser — seed matches its pre-committed hash and HMAC reproduces …" or a mismatch. Compare the hash in that dialog against the one you wrote down in step 1, and the client seed in the message against the one you chose.

5. Check it again in the verifier page

The dialog has a link that opens /verify.html with the server seed, client seed, nonce and committed hash filled in, and computes straight away. You can also open it directly and paste values in by hand: Server seed (revealed), Expected server seed hash, Client seed / bot ID, Nonce, then Compute roll. It prints the SHA-256 of the seed you pasted, a match-or-mismatch line against the committed hash, the exact HMAC message, the full digest, and the roll.

That page runs entirely in your browser using the built-in WebCrypto library and makes no request back to us — you can disconnect from the network after it loads and it still works. Be clear-eyed about it though: we host it. It is a convenience, not an outside opinion. Which is why the next section exists.

Do it without using anything of ours

The algorithm is standard HMAC-SHA256 and standard SHA-256. Any language, any tool, any machine will give the same answer. Substitute your own values for the placeholders below; these commands work as-is in a terminal.

Check the commitment — hash the revealed server seed and compare with the hash you saved before betting:

printf '%s' 'SERVER_SEED' | shasum -a 256

(On Linux, sha256sum instead of shasum -a 256.)

Get the digest for one bet, with openssl:

printf '%s' 'CLIENT_SEED:NONCE' | openssl dgst -sha256 -hmac 'SERVER_SEED'

Then take the first 8 characters of that digest, convert them from hexadecimal to a decimal number, confirm it is below 4,294,960,000, take the remainder when divided by 10,000, and divide by 100. That is your roll.

Or do the whole thing in one line of Python:

python3 -c "import hmac,hashlib;s='SERVER_SEED';m='CLIENT_SEED:NONCE';d=hmac.new(s.encode(),m.encode(),hashlib.sha256).hexdigest();print(d);print(next(int(d[i:i+8],16)%10000 for i in range(0,64,8) if int(d[i:i+8],16)<4294960000)/100)"

Run it on the worked example above and it prints 7fc5b7a9ddc078b1… and 40.41. If your own bet gives you the roll the site recorded, and the hash check passes, that bet is confirmed — by you, not by us.

What a verified bet actually proves

What it does not prove

This is the part most fairness pages leave out, and it is the part worth reading twice.

Small print that affects verification

One more thing, so you do not read the feed as something it is not: the live bet feed and the profiles behind those names include activity generated by the site rather than placed by people. Those rows open the same verify dialog and they do recompute correctly — which proves the arithmetic, not that a person placed the bet. Your own bets, your own balance and your own history are real.

If a bet does not verify

If the hash does not match the revealed seed, or the recomputed roll is not the roll we recorded, that is a serious result and we want to hear about it. Send the bet number, the server seed hash, the revealed server seed, the client seed, the nonce and the roll you calculated — all of which appear in the verify dialog — to support@dicexo.com. It is read by the operator, and a bet that does not verify is the one message on this site worth answering first. Keep your own copy of those values; they are what makes the claim checkable by anyone, including people who do not have to take our word for it.