Provably fair

Every result on RollFTW can be checked by you. Here is exactly how results are made, with the code for every game.

Manage seeds
01
Server seed

RollFTW creates a random server seed and shows you its SHA-256 hash before you bet. The seed itself stays secret until you rotate it.

02
Client seed

Your own seed. Change it any time in your profile, so RollFTW can never know a result in advance.

03
Nonce

Counts your bets on the current seed pair. It goes up by 1 with every bet, so no two results are the same.

04
Result

Every number comes from its own HMAC-SHA256 of the three values and a counter, drawn through chance.js. Each game maps them to its outcome.

Single player games

Use your active seed pair and nonce. You see the server seed hash before betting. When you rotate to the next seed, the old server seed is revealed so you can check every bet you made with it.

Mines Towers Dice Plinko Blackjack Upgrader Cases
Multiplayer games

One result for everyone, so there is no personal client seed. The server seed hash is shown before the round. The client seed is the hash of a public EOS block mined after betting closes, which nobody can predict, not even RollFTW.

Crash Roll Dice Duels Battles
From seeds to numbers

All games share this helper. The same seeds always give the same numbers, so you can run the code yourself with Node.js.

fairness.js
1const crypto = require('crypto');
2const Chance = require('chance'); // npm install chance@1.1.13
3
4// chance.js draws all numbers of a result, each one comes from its own HMAC-SHA256
5// of the seeds and a counter (0, 1, 2, …), the server seed is the key
6// Single player: getChance(serverSeed, clientSeed, nonce)
7// Multiplayer: getChance(serverSeed, eosBlockId, round)
8function getChance(serverSeed, clientSeed, nonce) {
9 let cursor = 0;
10 return new Chance(() => {
11 const hash = crypto.createHmac('sha256', serverSeed).update(`${clientSeed}:${nonce}:${cursor++}`).digest();
12 return hash.readUIntBE(0, 6) / 2 ** 48;
13 });
14}
15
16// The revealed server seed must match the hash you saw before betting
17const hash = crypto.createHash('sha256').update(serverSeed).digest('hex');
Game by game
mines.js
1// Mines: shuffle the tiles, size is the grid edge (5 to 8)
2const chance = getChance(serverSeed, clientSeed, nonce);
3const tiles = chance.shuffle(Array.from({ length: size * size }, (_, i) => i));
4
5// The first tiles hold the mines (0 = top left, row by row)
6const mineTiles = tiles.slice(0, mines).sort((a, b) => a - b);