Overview
Every bet you place uses three inputs to produce a game outcome:
1. Server Seed — A random value generated by Degen, kept secret until you rotate your seed pair
2. Client Seed— A value you can set yourself (or we generate one for you)
3. Nonce — A counter that increments by 1 with every bet you place
These three values are combined using HMAC-SHA512 to produce a hash. The first 4 bytes of that hash are then converted into a random number between 0 and 1. Each game applies its own formula to turn that number into a game result.
Seed Pair Lifecycle
1. When you start playing, a server seed and client seed are generated for you
2. You can see the SHA-256 hash of your server seed at any time — this proves the seed existed before your bet
3. Your nonce starts at 0 and increments by 1 with every bet
4. When you change your client seed, the current server seed is revealed, and a new server seed is activated
5. Once revealed, you can use the server seed to verify every bet you made with that seed pair
Commitment Scheme
Before you bet, we show you the SHA-256 hash of the server seed. This hash is a commitment — it proves we cannot change the server seed after the fact. After you rotate seeds, the server seed is revealed and you can verify that its SHA-256 hash matches what was shown to you.
Random Number Generation
Hash Generation
For most games, we generate a hash using:
HMAC-SHA512(serverSeed, clientSeed:nonce:cursor)
- Key: Server Seed
- Message: `clientSeed:nonce:cursor`
For single-outcome games (Dice, Limbo, Roulette), the cursor is replaced by the game type name:
HMAC-SHA512(serverSeed, clientSeed:nonce:DICE)
HMAC-SHA512(serverSeed, clientSeed:nonce:LIMBO)
HMAC-SHA512(serverSeed, clientSeed:nonce:ROULETTE)
For multi-outcome games (Keno, Mines, Plinko, Blackjack, Baccarat, Casino War, Stacks), a numeric cursor (starting at 0) generates each successive random value:
HMAC-SHA512(serverSeed, clientSeed:nonce:0) → first value
HMAC-SHA512(serverSeed, clientSeed:nonce:1) → second value
HMAC-SHA512(serverSeed, clientSeed:nonce:2) → third value
Bytes to Float Conversion
The 128-character hex hash is converted into a float between 0 and 1 using the first 4 bytes:
float = byte[0] / 256 + byte[1] / 65536 + byte[2] / 16777216 + byte[3] / 4294967296
This produces a value in the range [0, 0.9999999998) — it can never equal exactly 1.0. This is the same algorithm used by Stake.com and other major provably fair casinos.
Game Events
Dice
Dice produces a single result from 0.00 to 100.00.
Inputs: `serverSeed`, `clientSeed`, `nonce`
Event Calculation:
// 1. Generate hash
hash = HMAC-SHA512(serverSeed, clientSeed:nonce:DICE)
// 2. Convert first 4 bytes to float
float = bytesToFloat(hash) // Range: [0, 0.9999999998)
// 3. Calculate dice result
result = Math.floor(float × 10001) / 100
Range: 0.00 to 100.00 (10,001 possible outcomes)
Example:
- float = 0.5050 → result = 50.50
- float = 0.0000 → result = 0.00
- float = 0.9999 → result = 99.99
Limbo
Limbo produces a multiplier of 1.00x or higher.
Inputs: `serverSeed`, `clientSeed`, `nonce`
Event Calculation:
// 1. Generate hash
hash = HMAC-SHA512(serverSeed, clientSeed:nonce:LIMBO)
// 2. Convert first 4 bytes to float [0, 1)
float = bytesToFloat(hash)
// 3. Calculate multiplier with house edge
result = (1 - houseEdge%) / float
// 4. Clamp to valid range
result = clamp(result, 1.00, 1000000)
// 5. Floor to 2 decimal places
result = floor(result * 100) / 100
Range: 1.00x to 1,000,000x
The result is always floored (truncated) to 2 decimal places. For example, a raw result of 2.997x becomes 2.99x. This matches the industry standard used by other provably fair platforms.
The house edge is configurable and may vary. The current house edge can be seen on the game page.
Example (with 1% house edge):
- float = 0.01 → result = 99.00x
- float = 0.50 → result = 1.98x
- float = 0.99 → result = 1.00x
Crash
Crash uses a unique provably fair system based on a pre-generated chain of 10 million seeds verified against a Bitcoin block hash.
How the seed chain works:
1. We generate a random seed for the 10,000,000th game
2. Each previous game's seed is the SHA-256 hash of the next game's seed (seed[N-1] = SHA-256(seed[N]))
3. The terminating hash— SHA-256 of the very first game's seed — is published publicly before any games are played. You can verify the entire chain by hashing forward from any revealed seed
4. A future Bitcoin block hash is announced in advance — once mined, it becomes the client seed for all Crash games
Public Constants:
Terminating Hash: `a8cdd5b9ba3b9910d90e1f7bd7e582407fc9658e8e4410b657aa46de89f6ec9d`
Bitcoin Block: #931850
Bitcoin Block Hash: `000000000000000000015fd8624ab0ba8f4901f22e44edb35426beb4680d6624`
House Edge: 1%
Event Calculation:
// 1. Generate HMAC-SHA256 (not SHA-512)
hash = HMAC-SHA256(serverSeed, bitcoinBlockHash)
// 2. Take first 8 hex characters (32 bits)
hashInt = parseInt(hash[0..7], 16)
// 3. Calculate crash point
crashPoint = max(1.00, (2^32 / (hashInt + 1)) × 0.99)
Range: 1.00x to 1,000,000x
Verification: You can verify any Crash game by:
1. Taking the server seed for a given game
2. Hashing it with SHA-256 — the result should match the server seed of the previous game
3. Computing the crash point using the formula above
This chain structure means we cannot manipulate any individual game's outcome without breaking the entire verifiable chain.
Roulette
Roulette produces a single number on a European wheel (0–36).
Inputs: `serverSeed`, `clientSeed`, `nonce`
Event Calculation:
// 1. Generate hash
hash = HMAC-SHA512(serverSeed, clientSeed:nonce:ROULETTE)
// 2. Convert first 4 bytes to float
float = bytesToFloat(hash)
// 3. Calculate winning number
result = Math.floor(float × 37)
Range: 0 to 36 (37 possible outcomes — European roulette with single zero)
Keno
Keno draws 10 unique numbers from a pool of 40.
Inputs: `serverSeed`, `clientSeed`, `nonce`
Event Calculation:
availableNumbers = [1, 2, 3, ..., 40]
drawnNumbers = []
for cursor = 0 to 9:
// Generate random value for this draw
hash = HMAC-SHA512(serverSeed, clientSeed:nonce:cursor)
float = bytesToFloat(hash)
// Pick from remaining numbers
index = Math.floor(float × availableNumbers.length)
drawnNumbers.push(availableNumbers[index])
availableNumbers.remove(index) // Prevent duplicates
return drawnNumbers.sort()
Each draw uses an incrementing cursor (0–9). After a number is selected, it is removed from the available pool, ensuring all 10 drawn numbers are unique. The final result is sorted in ascending order.
Mines
Mines places mines on a 5×5 grid (25 tiles). You choose how many mines (1–24).
Inputs: `serverSeed`, `clientSeed`, `nonce`, `mineCount`
Event Calculation:
availablePositions = [0, 1, 2, ..., 24]
minePositions = []
for cursor = 0 to (mineCount - 1):
// Generate random value for this mine
hash = HMAC-SHA512(serverSeed, clientSeed:nonce:cursor)
float = bytesToFloat(hash)
// Place mine on remaining position
index = Math.floor(float × availablePositions.length)
minePositions.push(availablePositions[index])
availablePositions.remove(index) // Prevent duplicate placement
return minePositions.sort()
Each mine placement uses an incrementing cursor. Positions are removed after selection to ensure no two mines occupy the same tile. The final result is sorted in ascending order.
Grid Layout: Positions 0–24 map to a 5×5 grid, left to right, top to bottom:
0 1 2 3 4
5 6 7 8 9
10 11 12 13 14
15 16 17 18 19
20 21 22 23 24
Plinko
Plinko drops a ball through a pyramid of pegs. At each peg, the ball goes either left or right. The number of rows (8–16) determines how many decisions are made.
Inputs: `serverSeed`, `clientSeed`, `nonce`, `rows`
Event Calculation:
path = [Math.floor((rows + 1) / 2)] // Start position (middle)
leftSteps = 0
for cursor = 0 to (rows - 1):
// Generate random value for this peg
hash = HMAC-SHA512(serverSeed, clientSeed:nonce:cursor)
float = bytesToFloat(hash)
// Pure 50/50 decision
if float < 0.5:
leftSteps++ // Ball goes left
path.push(leftSteps) // Record position
return path
The total number of left steps determines which bucket the ball lands in (bucket index = leftSteps). The bucket determines the multiplier. Multipliers vary by risk level (Low, Medium, High) and row count.
Blackjack
Blackjack deals cards from an infinite deck (52 possible cards per draw, with replacement).
Inputs: `serverSeed`, `clientSeed`, `nonce`
Event Calculation (per card):
for cursor = 0, 1, 2, ...:
// Generate random value for this card
hash = HMAC-SHA512(serverSeed, clientSeed:nonce:cursor)
float = bytesToFloat(hash)
// Map to card
cardIndex = Math.floor(float × 52) // 0-51
suit = ['Hearts', 'Diamonds', 'Clubs', 'Spades'][Math.floor(cardIndex / 13)]
rank = ['A','2','3','4','5','6','7','8','9','10','J','Q','K'][cardIndex % 13]
Card Dealing Order (interleaved, casino-standard):
- Cursor 0: Player's first card
- Cursor 1: Dealer's first card (face-up)
- Cursor 2: Player's second card
- Cursor 3: Dealer's second card (hole card, face-down until reveal)
- Cursor 4+: Additional cards (hits, splits, etc.)
Card Values: A = 11 (or 1), 2–9 = face value, 10/J/Q/K = 10
Blackjack Switch
Blackjack Switch deals two player hands and one dealer hand from an infinite deck. You may switch the top cards between your two hands before playing.
inputs: `serverSeed`, `clientSeed`, `nonce`
Event Calculation:
Same card generation as Blackjack — `cardIndex = Math.floor(float × 52)`
Card Dealing Order (interleaved, casino-standard):
- Cursor 0: Hand 1, first card
- Cursor 1: Hand 2, first card
- Cursor 2: Dealer, first card (face-up)
- Cursor 3: Hand 1, second card
- Cursor 4: Hand 2, second card
- Cursor 5: Dealer, second card (hole card)
- Cursor 6+: Additional cards (hits, doubles, splits)
Switch Mechanic: After the initial 6-card deal, you may choose to swap the second cards of your two hands (cursor 3 and cursor 4). The first cards and dealer cards are never affected.
Card Values: A = 11 (or 1), 2–9 = face value, 10/J/Q/K = 10
Double Down Madness
Double Down Madness is a blackjack variant where you receive one card and the dealer receives two. You can double down on every hand.
Inputs: `serverSeed`, `clientSeed`, `nonce`
Event Calculation:
Same card generation as Blackjack — `cardIndex = Math.floor(float × 52)`
Card Dealing Order:
- Cursor 0: Player's card
- Cursor 1: Dealer's first card (face-up)
- Cursor 2: Dealer's second card (hole card)
- Cursor 3+: Additional cards (player's double down card, etc.)
Card Values: A = 11 (or 1), 2–9 = face value, 10/J/Q/K = 10
Baccarat
Baccarat deals cards from an infinite deck with the same card generation and deal order as Baccarat Switch, but without the switch mechanic.
Inputs: `serverSeed`, `clientSeed`, `nonce`
Event Calculation:
Same card generation — `cardIndex = Math.floor(float × 52)`
Card Values (Baccarat rules): A = 1, 2–9 = face value, 10/J/Q/K = 0
Deal Order:
- Cursor 0: Player's first card
- Cursor 1: Banker's first card
- Cursor 2: Player's second card
- Cursor 3: Banker's second card
- Cursor 4: Player's third card (if Player draws); or Banker's third card (if only Banker draws)
- Cursor 5: Banker's third card (only when both Player and Banker draw a third card)
Third Card Rules: Same standard Baccarat rules as Baccarat Switch (see below).
Score: Sum of card values mod 10. Highest score wins.
Baccarat Switch
Baccarat Switch deals cards from an infinite deck using the same card generation as Blackjack.
Inputs: `serverSeed`, `clientSeed`, `nonce`
Event Calculation (per card):
for cursor = 0, 1, 2, ...:
hash = HMAC-SHA512(serverSeed, clientSeed:nonce:cursor)
float = bytesToFloat(hash)
cardIndex = Math.floor(float × 52) // 0-51
suit = ['Hearts', 'Diamonds', 'Clubs', 'Spades'][Math.floor(cardIndex / 13)]
rank = ['A','2','3','4','5','6','7','8','9','10','J','Q','K'][cardIndex % 13]
Card Values (Baccarat rules): A = 1, 2–9 = face value, 10/J/Q/K = 0
Deal Order:
- Cursor 0: Player's first card
- Cursor 1: Banker's first card
- Cursor 2: Player's second card (switchable)
- Cursor 3: Banker's second card (switchable)
- Cursor 4: Player's third card (if Player draws); or Banker's third card (if only Banker draws)
- Cursor 5: Banker's third card (only when both Player and Banker draw a third card)
Third Card Rules (standard Baccarat):
- Natural: If Player or Banker has 8 or 9 on initial two cards, no more cards are drawn
- Player draws on 0–5, stands on 6–7
- Banker draws based on their score and the Player's third card value:
- Banker 0–2: Always draws
- Banker 3: Draws unless Player's third card is 8
- Banker 4: Draws if Player's third card is 2–7
- Banker 5: Draws if Player's third card is 4–7
- Banker 6: Draws if Player's third card is 6–7
- Banker 7: Always stands
Switch Mechanic: After the initial 4-card deal, you are shown the face-down cards — Player's second card (cursor 2) and Banker's second card (cursor 3). You may choose to switch these two cards between hands, then the round resolves normally. The first cards of each hand (cursors 0 and 1) are never affected by the switch.
- No switch: Player = [cursor 0, cursor 2], Banker = [cursor 1, cursor 3]
- Switch: Player = [cursor 0, cursor 3], Banker = [cursor 1, cursor 2]
Both outcomes are computed and committed before you make your switch decision, ensuring the result is provably fair regardless of your choice.
Super 6 Rule: When the Banker wins with a final score of exactly 6, the Banker bet pays 1.5x instead of the standard 1.95x.
Side Bets:
- Player Pair (12x): Player's first two cards are the same rank
- Banker Pair (12x): Banker's first two cards are the same rank
- Either Pair (6x): Either hand has a pair
- Perfect Pair (26x): Either hand has a pair of the same rank AND suit
- Switch Win (5x): You switched AND the switch changed the winning outcome
- Natural Switch (15x): You switched AND the switch created a natural (8 or 9) that didn't exist before the switch
Score: Sum of card values mod 10. Highest score wins.
Casino War
Casino War deals cards from an infinite deck using the same card generation method.
Inputs: `serverSeed`, `clientSeed`, `nonce`
Event Calculation:
for cursor = 0, 1, 2, ...:
hash = HMAC-SHA512(serverSeed, clientSeed:nonce:cursor)
float = bytesToFloat(hash)
cardIndex = Math.floor(float × 52)
suit = ['Hearts', 'Diamonds', 'Clubs', 'Spades'][Math.floor(cardIndex / 13)]
rank = ['A','2','3','4','5','6','7','8','9','10','J','Q','K'][cardIndex % 13]
Card Comparison Values: 2 = 2, 3 = 3, ..., 10 = 10, J = 11, Q = 12, K = 13, A = 14 (Ace is highest)
Deal Order:
- Cursor 0: Player's card
- Cursor 1: Dealer's card
- If tied (War):
- Cursor 2: Burn card 1
- Cursor 3: Burn card 2
- Cursor 4: Burn card 3
- Cursor 5: Player's War card
- Cursor 6: Dealer's War card
Higher card wins. On a tie, you can surrender (lose half your bet) or go to War — 3 cards are burned and new cards are dealt. If a second tie occurs during War, you receive a bonus payout.
Stacks
Stacks is a level-climbing game with a pre-determined bust level. At game start, the bust level is fixed by your seed pair — neither you nor the casino can change it. You climb one level at a time and can cash out at any reached level. The bust level is the highest level you can safely reach; attempting another step from that level busts the game.
Inputs: `serverSeed`, `clientSeed`, `nonce`, `difficulty`
Difficulty Settings:
| Difficulty | Death Points | Max Levels |
|------------|-------------:|-----------:|
| Easy | 1 | 19 |
| Medium | 3 | 17 |
| Hard | 5 | 15 |
| Extreme | 10 | 10 |
`TOTAL_POSITIONS = 20`. `maxLevels = TOTAL_POSITIONS − deathPoints` — the bust algorithm guarantees `bustLevel ∈ [0, maxLevels]`, so the player either reaches the top (auto-cashout at `maxLevels`) or busts at some earlier level.
Bust Level Calculation (committed at game start, revealed after the game ends):
bustCandidates = []
for cursor = 0 to (deathPoints - 1):
hash = HMAC-SHA512(serverSeed, clientSeed:nonce:cursor)
float = bytesToFloat(hash)
bustCandidates.push(Math.floor(float × (TOTAL_POSITIONS - cursor)))
bustLevel = min(bustCandidates)
The bust level is the minimum of `deathPoints` scaled random values. Each candidate uses a successively smaller scaling factor (`20, 19, 18, …`), which is mathematically equivalent to drawing `deathPoints` car positions without replacement on a 20-cell track and taking the first (lowest) one the player would walk into. Higher `deathPoints` ⇒ more chances to draw a low bust level ⇒ higher risk.
Landing Position per Step (column the chip lands on, visual-only):
Each attempted step also generates a landing position (0–3 column index) used for animation. The cursor for the step from `currentLevel → currentLevel + 1` is offset past the bust-level cursors:
cursor = deathPoints + currentLevel // currentLevel is 0-based before the step
hash = HMAC-SHA512(serverSeed, clientSeed:nonce:cursor)
float = bytesToFloat(hash)
landingPosition = min(3, Math.floor(float × 4)) // 0-3
Multipliers (house edge baked in, indexed by reached level `1..maxLevels`):
| Difficulty | Multipliers (level 1 → maxLevels) |
|------------|-----------------------------------|
| Easy | 1.03, 1.09, 1.15, 1.23, 1.31, 1.4, 1.51, 1.63, 1.78, 1.96, 2.18, 2.45, 2.8, 3.27, 3.92, 4.9, 6.53, 9.8, 19.6 |
| Medium | 1.15, 1.37, 1.64, 2.0, 2.46, 3.07, 3.91, 5.08, 6.77, 9.31, 13.3, 19.95, 31.92, 55.86, 111.72, 279.3, 1117.2 |
| Hard | 1.31, 1.77, 2.46, 3.48, 5.06, 7.59, 11.81, 19.18, 32.89, 60.29, 120.59, 271.32, 723.52, 2532.32, 15193.92 |
| Extreme | 1.96, 4.14, 9.31, 22.61, 60.29, 180.88, 633.08, 2743.35, 16460.08, 181060.88 |
Step Resolution (server check on every step):
// pre-step level is checked against the pre-committed bust level
isSuccess = (currentLevel !== bustLevel)
if isSuccess:
currentLevel += 1 // step succeeds; player now at new level
if currentLevel >= maxLevels:
auto-cash-out at multipliers[maxLevels - 1]
else:
BUSTED // step from bustLevel always fails
Outcome:
- The player can safely reach (and cash out at) any level `1..min(bustLevel, maxLevels)`. Cashing out at reached level `L` pays `betAmount × multipliers[L − 1]`.
- A step taken while `currentLevel == bustLevel` busts the game and forfeits the bet.
- If `bustLevel >= maxLevels`, the bust is unreachable inside the playable range — the game auto-cashes out at `maxLevels` with the top multiplier.
The bust level is only revealed once the game ends (busted, manually cashed out, or auto-cashed). While the game is active, the next step's outcome is committed but hidden.
Chicken (Chicken Crossing)
Chicken is a one-dimensional crossing game. The chicken walks forward one cell at a time across a 20-cell road; some cells contain cars. The chicken's path, including all car positions, is committed at game start by the seed pair. The chicken survives any step that doesn't land on a car cell, and busts the moment it steps onto one. The player may cash out after any safe step.
Inputs: `serverSeed`, `clientSeed`, `nonce`, `difficulty`
Difficulty Settings:
| Difficulty | Cars (deathPointsCount) | Max Safe Steps |
|------------|------------------------:|---------------:|
| Easy | 1 | 19 |
| Medium | 3 | 17 |
| Hard | 5 | 15 |
| Expert | 10 | 10 |
`GRID_SIZE = 20`. `maxSteps = GRID_SIZE − deathPointsCount` (always reachable in the best case, when all cars are clustered at the end of the road).
Event Calculation (committed at game start, revealed after the game ends):
availablePositions = [0, 1, 2, ..., 19]
carPositions = []
for cursor = 0 to (deathPointsCount - 1):
hash = HMAC-SHA512(serverSeed, clientSeed:nonce:cursor)
float = bytesToFloat(hash)
index = Math.floor(float × availablePositions.length)
carPositions.push(availablePositions[index])
availablePositions.remove(index) // Selection without replacement
return carPositions.sort()
Each car uses an incrementing cursor (0 to `deathPointsCount - 1`). Positions are removed after selection so two cars never share the same cell. The final list is sorted in ascending order. This is the **same Fisher-Yates-style algorithm as Mines**, only on a 20-cell 1D road instead of a 5×5 grid.
Step Resolution (server check on every step):
// pre-step `currentStep` is the cell the chicken is about to enter
position = currentStep // 0 on the first step, 1 on the second, …
if position in carPositions:
BUSTED // chicken walks into a car
else:
currentStep += 1 // safe step; chicken advances
if currentStep >= maxSteps:
auto-cash-out at multipliers[maxSteps - 1]
Outcome:
- The chicken can safely take `1..min(min(carPositions), maxSteps)` steps. Cashing out after `N` safe steps pays `betAmount × multipliers[N − 1]`.
- The bust happens the first time the chicken tries to step onto a car cell, i.e., when `currentStep == min(carPositions)`.
- `min(carPositions)` is the first blocking car — equivalent to Stacks' `bustLevel` for the same seeds.
- If `min(carPositions) >= maxSteps`, the chicken auto-cashes out at `maxSteps` before any car can be reached.
Multipliers (house edge baked in, identical schedule to Stacks):
| Difficulty | Multipliers (step 1 → maxSteps) |
|------------|---------------------------------|
| Easy | 1.03, 1.09, 1.15, 1.23, 1.31, 1.4, 1.51, 1.63, 1.78, 1.96, 2.18, 2.45, 2.8, 3.27, 3.92, 4.9, 6.53, 9.8, 19.6 |
| Medium | 1.15, 1.37, 1.64, 2.0, 2.46, 3.07, 3.91, 5.08, 6.77, 9.31, 13.3, 19.95, 31.92, 55.86, 111.72, 279.3, 1117.2 |
| Hard | 1.31, 1.77, 2.46, 3.48, 5.06, 7.59, 11.81, 19.18, 32.89, 60.29, 120.59, 271.32, 723.52, 2532.32, 15193.92 |
| Expert | 1.96, 4.14, 9.31, 22.61, 60.29, 180.88, 633.08, 2743.35, 16460.08, 181060.88 |
Car positions are only revealed once the game ends (busted, cashed out, or auto-cashed). While the game is active, the chicken sees the road ahead but not where the cars are.
Verification
How to Verify Your Bets
1. Go to the Provably Fair page on Degen
2. Find the bet you want to verify
3. Once your seed pair has been rotated (server seed revealed), all values are visible
4. Use the formulas above — or any third-party HMAC-SHA512 calculator — to independently compute the game result
5. Confirm the result matches what was shown in your game
Step-by-Step Manual Verification (Dice Example)
1. Get your seeds: server seed, client seed, and nonce for the bet
2. Compute the HMAC:
- Algorithm: HMAC-SHA512
- Key: your server seed
- Message: `clientSeed:nonce:DICE`
3. Extract first 4 bytes of the resulting hex hash
4. Convert to float: `byte[0]/256 + byte[1]/65536 + byte[2]/16777216 + byte[3]/4294967296`
5. Apply game formula: `Math.floor(float × 10001) / 100`
6. Compare with the result shown in your bet history
Verify Server Seed Hash
Before rotating your seeds, you can see the **server seed hash** (SHA-256). After rotation, verify:
SHA-256(revealedServerSeed) === previouslyShownHash
This confirms the server seed was not changed between when you saw the hash and when it was revealed.
Technical Summary
| Game | Hash Algorithm | HMAC Message | Conversion | Result Range |
|------|---------------|-------------|------------|-------------|
| Dice | HMAC-SHA512 | `clientSeed:nonce:DICE` | float × 10001 / 100 | 0.00 – 100.00 |
| Limbo | HMAC-SHA512 | `clientSeed:nonce:LIMBO` | (1 - houseEdge%) / float | 1.00x – 1,000,000x |
| Crash | HMAC-SHA256 | `bitcoinBlockHash` | 2³² / (hashInt + 1) × 0.99 | 1.00x – 1,000,000x |
| Roulette | HMAC-SHA512 | `clientSeed:nonce:ROULETTE` | floor(float × 37) | 0 – 36 |
| Keno | HMAC-SHA512 | `clientSeed:nonce:cursor` | Fisher-Yates selection | 10 from 40 |
| Mines | HMAC-SHA512 | `clientSeed:nonce:cursor` | Fisher-Yates selection | Positions on 5×5 |
| Plinko | HMAC-SHA512 | `clientSeed:nonce:cursor` | float < 0.5 (L/R) | Path + bucket |
| Blackjack | HMAC-SHA512 | `clientSeed:nonce:cursor` | floor(float × 52) | Card index 0–51 |
| Blackjack Switch | HMAC-SHA512 | `clientSeed:nonce:cursor` | floor(float × 52) | Card index 0–51 |
| Double Down Madness | HMAC-SHA512 | `clientSeed:nonce:cursor` | floor(float × 52) | Card index 0–51 |
| Baccarat | HMAC-SHA512 | `clientSeed:nonce:cursor` | floor(float × 52) | Card index 0–51 |
| Baccarat Switch | HMAC-SHA512 | `clientSeed:nonce:cursor` | floor(float × 52) | Card index 0–51 |
| Casino War | HMAC-SHA512 | `clientSeed:nonce:cursor` | floor(float × 52) | Card index 0–51 |
| Stacks | HMAC-SHA512 | `clientSeed:nonce:cursor` | min over `deathPoints` of `floor(float × (20 − cursor))` | Bust level 0–19 (pre-committed) |
Card Mapping Reference
For all card-based games (Blackjack, Blackjack Switch, Double Down Madness, Baccarat, Baccarat Switch, Casino War), card index 0–51 maps to:
| Index | Card | Index | Card | Index | Card | Index | Card |
|-------|------|-------|------|-------|------|-------|------|
| 0 | A♥ | 13 | A♦ | 26 | A♣ | 39 | A♠ |
| 1 | 2♥ | 14 | 2♦ | 27 | 2♣ | 40 | 2♠ |
| 2 | 3♥ | 15 | 3♦ | 28 | 3♣ | 41 | 3♠ |
| 3 | 4♥ | 16 | 4♦ | 29 | 4♣ | 42 | 4♠ |
| 4 | 5♥ | 17 | 5♦ | 30 | 5♣ | 43 | 5♠ |
| 5 | 6♥ | 18 | 6♦ | 31 | 6♣ | 44 | 6♠ |
| 6 | 7♥ | 19 | 7♦ | 32 | 7♣ | 45 | 7♠ |
| 7 | 8♥ | 20 | 8♦ | 33 | 8♣ | 46 | 8♠ |
| 8 | 9♥ | 21 | 9♦ | 34 | 9♣ | 47 | 9♠ |
| 9 | 10♥ | 22 | 10♦ | 35 | 10♣ | 48 | 10♠ |
| 10 | J♥ | 23 | J♦ | 36 | J♣ | 49 | J♠ |
| 11 | Q♥ | 24 | Q♦ | 37 | Q♣ | 50 | Q♠ |
| 12 | K♥ | 25 | K♦ | 38 | K♣ | 51 | K♠ |
Formula: `suit = floor(index / 13)` → Hearts(0), Diamonds(1), Clubs(2), Spades(3). `rank = index % 13` → A(0), 2(1), ..., K(12).
All card games use an infinite deck model — each card is drawn independently, so the same card can appear multiple times.
FAQ
Can the casino change the outcome after I bet?
No. The server seed is committed (via its SHA-256 hash) before you bet. Changing the server seed would change the hash, which you can detect.
Why can't I see my server seed right now?
Revealing the server seed while it's active would let you predict future outcomes. It is revealed only after you rotate to a new seed pair.
What is the nonce?
It's a counter that increments with every bet you place under the same seed pair. It ensures each bet produces a unique outcome even with the same server and client seeds.
Can I set my own client seed?
Yes. You can change your client seed at any time from the Provably Fair settings. Changing it also rotates your server seed, revealing the old one.
How is Crash different from other games?
Crash uses a pre-generated chain of 10 million seeds verified against a public Bitcoin block hash. This means all Crash outcomes are predetermined before the first game is played — not even the casino can change them.
What algorithm standard do you use?
Our provably fair system uses HMAC-SHA512 for game outcome generation, offering greater cryptographic strength than SHA-256, and SHA-256 hashing for server seed commitment. Our bytes-to-float normalization is Stake.com-compatible, using the same conversion algorithm used by major provably fair casinos industry-wide.