How Fairness Works in Poker
The hardest problem in on-chain poker is dealing cards fairly. If the deck is on-chain, anyone can read it. If it's off-chain, you have to trust the dealer. FALKEN solves this with a commit-reveal entropy system combined with delayed salt revelation — nobody can see or manipulate the cards during play, and anyone can verify fairness after the fact.
The Problem
In physical poker, a dealer shuffles a deck and you trust they're not cheating. On a blockchain, there's no trusted dealer — smart contract storage is public, and any on-chain randomness can be predicted or front-run.
The naive approach (put the deck on-chain) fails immediately: anyone can call a view function, compute the deck, and see all hands before betting.
FALKEN's Solution: Dual-Entropy Commit-Reveal
Both players contribute randomness. Neither can control the outcome alone. Here's the full flow:
Step 1: Entropy Commit
Each player generates a random 32-byte salt and submits its hash on-chain:
commitHash = keccak256("FALKEN_POKER_V5_ENTROPY", matchId, round, playerAddress, salt)
The contract stores the hash but not the salt. At this point:
- Each player knows their own salt
- Nobody knows the other player's salt
- Nobody can compute the deck
Step 2: Private Salt Submission
Players send their actual salts to the referee (off-chain, not on-chain). The referee verifies each salt matches its committed hash, then calls submitPrivateEntropy() on the contract.
This is the critical security property: salts are NOT written to public contract storage during the game. The contract stores them in a way that they're only readable at showdown. During betting, no one — not even someone reading raw contract storage — can derive the deck.
Step 3: Deterministic Deck Generation
The referee combines both salts to compute a seed:
seed = keccak256("FALKEN_POKER_V5", contractAddress, matchId, round, sortedSalts)
This seed is run through a Fisher-Yates shuffle to produce a deterministic 52-card deck. The same inputs always produce the same deck — this is what makes post-game verification possible.
Step 4: Dealing
The referee uses the FISE JavaScript's dealCards() method to allocate cards from the shuffled deck based on the variant:
| Variant | Cards Per Player | Community Cards |
|---|---|---|
| 5-Card Draw | 5 | 0 |
| Texas Hold'em | 2 | 5 (flop/turn/river) |
| Omaha | 4 | 5 |
| 7-Card Stud | 3 down + 4 up | 0 |
The referee publishes a hand receipt on-chain — a commitment to what was dealt, without revealing the actual cards.
Step 5: Play
Betting rounds proceed normally. During play:
- Each player only knows their own cards (sent privately by the referee)
- The referee knows all cards (same as a physical dealer)
- No on-chain observer can derive the deck (salts aren't in public storage)
Step 6: Showdown
At showdown, salts are revealed on-chain. Now anyone can:
- Take both salts
- Compute the seed
- Shuffle the deck
- Verify every card dealt matches what the referee claimed
If the referee lied about any card, the fraud is provable and the evidence is permanent on-chain.
What Can't Go Wrong
| Attack | Why It Fails |
|---|---|
| Player predicts the deck | They'd need the opponent's salt before it's revealed. The commit phase prevents this — changing your salt after seeing the opponent's would break the hash. |
| Player front-runs with a chosen salt | Salts are committed (hashed) before either is revealed. You can't adapt your salt to manipulate the deck after seeing the opponent's commitment. |
| Referee manipulates the deck | The deck derivation is deterministic from the salts. Post-showdown, anyone can re-derive the deck and prove the referee dealt correctly or didn't. |
| On-chain observer reads the deck | Salts are not stored in public contract storage until showdown. There's nothing to read during the game. |
| Referee colludes with a player | The referee can see all cards (like a physical dealer), but cannot change them. Hand receipts are committed on-chain before betting starts. Any discrepancy is provable. |
The Trust Model
The referee is a trusted dealer, not a trusted arbiter. Here's the distinction:
- Trusted dealer — sees the cards, but can't change them (hand receipts lock the deal)
- Trusted arbiter — decides the outcome with no verification (this is NOT what FALKEN does)
The referee's power is limited to:
- Seeing cards during the game (necessary to deal)
- Submitting settlement results
It cannot:
- Change the deck (deterministic from salts)
- Change the salts (locked by commit hashes)
- Withhold settlement indefinitely (timeouts exist)
Any misbehavior is detectable post-match by replaying the salts through the shuffle algorithm. The path to removing even this minimal trust is decentralized referees — a network where multiple nodes verify each other.
Verification
After a match, anyone can verify the deal was fair:
- Read both revealed salts from the contract
- Compute
seed = keccak256("FALKEN_POKER_V5", contract, matchId, round, sortedSalts) - Run Fisher-Yates shuffle with the seed
- Check that dealt cards match the shuffled deck positions
This requires zero trust and zero special tools — just the public contract data and the open-source shuffle algorithm.