Crypto gambling sites using "provably fair" seed pairing systems can, without a doubt, rig outcomes which still pass verification.
freebitco.in CLICK HERE TO VERIFY YOUR ROLLS This game is provably fair. What that means is that there is no way the site can cheat you by picking a number that is in our favour.
duckdice.io Dice Fairness We do not want you to just believe our word when it comes to security. Instead, we are going to explain how we guarantee the fairness of each roll.
I've been researching the mechanics behind "provably fair" systems used by sites like freebitco.in and duckdice.io. There's no doubt of the validity of the (HMAC + seed + nonce) hashes being verified for consistency. What I could find are many explanations of what 'verified' means, and the mathematics behind conjuring a number between 0 and 10000.
There are many promises made of not tampering with seeds after the roll, giving the impression the server commits to a seed before the client submits theirs.
When sites only reveal the server seed hash for the next round after the client sends their seed for the current round, the submitted client seed can be used to generate rolls of unfavorable outcome.
Consider the flow of playing a round on freebitco.in:
A player opens the page to play a new round. The server seed hash is presented along with nonce, the user is able to choose their seed if they wish. By default it is left unchanged after being generated.
After choosing the odds/multiplier, player smashes HI or LO to deliver a payload containing their variables:
It's at this point, one would assume the server, prior to playing this round, had already prepared the next server-seed it will use for the next roll.
However, between receiving the client seed and sending the results of the current roll; the server has the opportunity to cycle through any number of potential server seeds. Coupled with the client's seed, and the next nonce, the server can pre-compute rolls to select a known outcome for the next roll.
With the result of the current roll being delivered to the user, along with the next server seed hash giving the illusion of unbiased selection, all the server must do now is to assume the user will stay on the path of least resistance.
The end-user has a predictable behavior pattern, and at least in the case of "Provably Fair" gambling, it becomes a vector of potential exploit.
Compared to jamming one of two keys and watching your coins evaporate, there is more resistance in: scrolling back to the top of page, clicking on the "PROVABLY FAIR" link to open the dialoge, type in a bunch of nonsense into the text area for the next client seed, close the dialoge, and replay.
None of this means that servers are scamming users. But it does invite the opportunity to any practice which could fly under the radar. Deny big wins only allowing small amounts, to force a loss on a large wager, or to break a new record losing streak.
And they could do it while still providing a "Verified Hash" after every roll.
Because hash verification only proves the server didn’t change the seed after generating the result. It can't validate the conditions of the seed's generation, and says nothing about why or how they picked that seed in the first place.
The "provably fair" model only floats if:
- The server commits to its n+1 seed before knowing the client's.
- Can prove having generated the seed for the next game, after the current roll, before seeing the client seed.
- Users routinely rotates their client seed, after every single roll.
If a "provably fair" system doesn't include any sequencing or legitimate proof of seed commitment, then it’s not provable. It’s just branding.
- Predetermined roll preview before user bets
- Server-side seed selection biased towards player loss
- Auto or manual client seed rotation to break prediction
- Modified Kelly Criterion with tempered wager adjustment
- Recreation of well-known betting odds and payout
- Output includes official verification links
![NOTE] These scripts are meant for exploration, testing, and demonstration of how "provably fair" systems can be manipulated unfairly by the house.
Written in Lua 5.4, and may be backwards compatible but hasn't been tested on earlier versions.
They also tap into /dev/random for entropy, which is not available on Windows machines. I wouldn't know the equivalent, nor if it's available on Mac devices.
The files only run in a terminal, the interactive play.lua uses ascii coloring.
Packaged in this repo are two demonstration scripts. One is a quick, automated version of the interactive "game".
demo.lua
Automated simulation: 10 rounds of "Provably Fixed".
lua demo.lua -s -o
Optional arguments are:
-s: Randomize client seed before every roll (the first seed will always be random regardless)
-o: Randomize odds. If not set, the server will know exactly the range to pick a losing seed
play.lua
Interactive simulation!
Command Line Usage:
- Run the simulation:
lua play.lua - Show this help message:
lua play.lua --help
Run-time Options:
o: change your payout oddss: set a custom client seed stringa: auto-seed random strings before every rollp: play the interactive gameq: (while playing) return to options menuq: quit the program
For the initial launch, you'll see:
$ lua play.lua
Client Seed: PmLkuBckHEZNGuylzS | Random Seed? false | Nonce: 31 | Odds: 2.0 |
Server Seed Hash: 51b8f3bd9f4cbb08f2211380baa18f1807a2bfd60a06ee00b0eb3bfa1a68bad9
Options: (p)lay, (o)dds, (s)eed, (a)uto-seed, (q)uit
>
You have the option to change the odds, your client seed, or enable auto-seed(random).
To start playing, enter p. You will then see:
Client Seed: PmLkuBckHEZNGuylzS | Random Seed? false | Nonce: 31
Server Seed Hash: 51b8f3bd9f4cbb08f2211380baa18f1807a2bfd60a06ee00b0eb3bfa1a68bad9
Bank: 0.00020000 | Odds: 2.00 | Win%: 47.50% | Wager: 0.00002581 | Payout: 0.00002580
To bet: Choose (h)igh or (l)ow, or (q)uit to menu >
The server doesn't know the client seed until after the first bet. Let's bet High by entering h:
To bet: Choose (h)igh or (l)ow, or (q)uit to menu > h
[5250]< 6664 4750
Server Seed: db828ea14c59f9ebc4895c06fea6c4276b8d4f8e8d16ef7c6f7c39638294d7a2
Verification link:
https://s3.amazonaws.com/roll-verifier/verify.html?server_seed=db828ea14c59f9ebc4895c06fea6c4276b8d4f8e8d16ef7c6f7c39638294d7a2&client_seed=PmLkuBckHEZNGuylzS&server_seed_hash=51b8f3bd9f4cbb08f2211380baa18f1807a2bfd60a06ee00b0eb3bfa1a68bad9&nonce=31
Found losing seed in 12 attempts
Number to generate: 4888
Round 2
Client Seed: PmLkuBckHEZNGuylzS | Random Seed? false | Nonce: 32
Server Seed Hash: 3505e377f75dbb3fb98ffdb3e1fffe550536a561508816f66f1e705784fdcada
Bank: 0.00022580 | Odds: 2.00 | Win%: 47.50% | Wager: 0.00002879 | Payout: 0.00002879
To bet: Choose (h)igh or (l)ow, or (q)uit to menu >
Winner! You'll notice the predetermined roll from before betting was incorrect, due to the server not knowing the client seed. This will be the only time we win.
The section [5250]< 6664 4750 shows:
- The "
higher than" range on the left - The "
lower than" range on the right - The middle number is the roll
- The client selection marked with
<, we bet for the roll to be higher than the high range. - The winning selection is marked with square brackets[].
The amount wagered, or staked, is calculated automatically using a modified Kelly Criterion.
You can follow the verification link, the same one provided by freebitco.in.
Following the verify URL, the server announces how many seeds it tried before finding one to generate, along with the client seed and next nonce, an unfavorable outcome for the player.
Below the number of attempts is the next seeded roll, which will result in a loss. Tough luck, check the link, it's all certified verified.
And that’s it. Provably fixed, and verified for fairness.