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
| Name | What it is | Who 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:
- Build the message: the client seed, a colon, and the nonce. For client seed
my-lucky-seedon your first bet, the message ismy-lucky-seed:0. - Compute
HMAC-SHA256of 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. - Cut the digest into eight chunks of 8 hex characters. Each chunk is a 4-byte number between 0 and 4,294,967,295.
- Take the first chunk whose value is below 4,294,960,000, and skip any chunk at or above it.
- The roll is that value modulo 10,000, displayed with two decimals:
0.00to99.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.
- Committed hash, published before betting:
dbbcbc86c4983944cd23e5f569ed535ab8bdbbde9708adcba5f5b8fd4dca13ca - Server seed, revealed on rotation:
6e94ee5c403c8b62adb7480f555de6d911d4b23b1a41332396dabc09b66a721d - Client seed
my-lucky-seed, nonce0→ messagemy-lucky-seed:0 - HMAC-SHA256 digest:
7fc5b7a9ddc078b15af9796055d75ba5ae9a86df571f17a5cb50f9ca3566a4d1 - First chunk
7fc5b7a9= 2,143,664,041, which is below 4,294,960,000, so it is accepted - 2,143,664,041 modulo 10,000 = 4,041 → roll 40.41
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:
- Roll under. Your target is your chance. Pick 49.00% and you win on any roll below 49.00 — that is the 4,900 outcomes from 0.00 to 48.99, out of 10,000.
- Roll over. Your target is 99.99 minus your chance. Pick 49.00% and the target is 50.99; you win on any roll above it — 51.00 to 99.99, again exactly 4,900 outcomes.
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 chance | DiceXo pays | A 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:
- The edge applies to everything you stake, not to what you deposit. Bet $1 a thousand times and you have staked $1,000, with an expected loss of about $10 — even though you may never have had more than a few dollars in play.
- Over a short session, luck completely swamps the edge. Winning or losing a lot in an evening tells you nothing about whether the game is honest.
- The expectation is negative on every single bet, at every chance setting, in both directions. There is no combination of chance, direction or staking pattern that changes it. A verifiable game is still a game you are expected to lose money on over time.
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
- The server seed behind your bets was fixed before you placed them. The published hash pins it, and no other seed produces that hash.
- Given that seed and the recorded message, the roll is forced. There is no room in the formula for a decision — not about your stake, not about your chosen chance, not about whether you were up or down.
- Therefore the server seed could not have been chosen after the fact to suit the result.
What it does not prove
This is the part most fairness pages leave out, and it is the part worth reading twice.
- It does not make the game a good deal. Provably fair means "the roll was not tampered with after the commitment". It says nothing about whether the odds or payouts are generous. A game with a 30% house edge could be verified exactly as cleanly as this one. Ours is 1%, and you can confirm that yourself from the payout table above, but the cryptography is not what tells you so — the arithmetic is.
- It only pins our half of the message. The commitment covers the server seed. The client seed is the other half of the input, and nothing published in advance pins it. If a bet ever showed a client seed you did not choose, the check would still "pass" while proving nothing, because the input was free to be anything. This is why step 1 matters: set your own client seed, write it down, and check that every bet row shows exactly that string.
- One bet is one bet. A per-bet check can never reveal a bias that only appears across many bets. Every individual roll could recompute perfectly while the overall win rate is quietly off. Only statistics on a decent sample can see that: at a 49.00% chance over 10,000 bets you should get about 4,900 wins, and the ordinary spread is roughly ±50 — a result more than about 150 away from 4,900 would be genuinely surprising and worth asking about. If you want to test that, keep your own log as you play; the app shows only your most recent 35 bets.
- It covers rolls, not money. Verification says nothing about whether a deposit was credited at the right amount, whether a withdrawal was paid, or whether a balance is correct. Those are separate questions with separate answers.
- Nothing on this page is an audit or a certificate. The only evidence offered here is a calculation you can repeat yourself, and the fact that our hash was published before you bet. That evidence is real, and it is also the limit of what we are claiming.
Small print that affects verification
- Win chance runs from 1.00% to 98.00%, so the highest multiplier available is 99.00× and the lowest is about 1.0102×.
- There is a maximum stake and a maximum profit per bet — currently $50,000 and $10,000 in USD value. These are operator settings and the app always shows the values in force.
- Bets are rate-limited to 30 in any 2-second window per account; past that you get "Slow down a moment".
- The My Bets list shows your most recent 35 bets. Older bets are still stored, and a retired seed pair with real bets behind it is never deleted, but there is no way to browse or export older rows in the app — so note down the client seed, nonce and roll of anything you may want to check later.
- The Fairness panel lists your last 10 revealed seed pairs.
- Rotating always resets the nonce to 0. If you rotate without typing a client seed, you are given a random 16-character one.
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.