How we shuffle the deck
Every card draw at LootXX is governed by a cryptographically strong random number generator. You don't have to trust us — you can verify every shuffle yourself, after the fact, with free tools.
The shuffle algorithm
Fisher-Yates shuffle
We use the Fisher-Yates shuffle algorithm — the same method used by most modern card game engines. It works like a physical riffle: starting from the last card, swap it with any card at a random position (including itself). Repeat moving backwards until every card has been placed exactly once.
The result is a uniformly random permutation: every possible ordering of the 416-card shoe (8 decks × 52 cards) has equal probability. No bias, no hot streaks, no patterns.
// Fisher-Yates — the exact code running on our server for (let i = cards.length - 1; i > 0; i--) { const r = seededRand(seed, counter++); // deterministic from seed const j = Math.floor(r * (i + 1)); [cards[i], cards[j]] = [cards[j], cards[i]]; }
crypto.randomBytes — the same primitive your wallet uses
The shuffle seed is a 32-byte random value produced by Node.js's crypto.randomBytes(32). On Linux this reads directly from /dev/urandom, which is seeded by the operating system's entropy pool: hardware interrupt timing, CPU jitter, and kernel noise accumulated since boot.
This is the same primitive used by every TLS library, every SSH key generator, and — yes — every Solana wallet when it creates your keypair. If it's good enough to protect billions of dollars in on-chain assets, it's good enough to shuffle a deck of cards.
The seed is a Cryptographically Secure Pseudo-Random Number Generator (CSPRNG) output. Predicting it without access to the server's kernel entropy state is computationally infeasible — the search space is 2256.
Deterministic replay from seed
Each swap in the Fisher-Yates algorithm uses a counter-indexed HMAC-SHA256 value: HMAC-SHA256(seed, counter). Counter 0 governs the first swap, counter 1 the second, and so on. This makes the entire shoe order a pure function of the 32-byte seed.
After a hand settles, we reveal the seed. You can reproduce every card in the shoe on your own machine — or use our verify tool to do it in your browser without installing anything.
Commit-reveal scheme
Knowing the shuffle algorithm isn't enough if you have to trust that we didn't swap the deck after you placed your bet. Our commit-reveal scheme makes that manipulation provably impossible.
SHA256(seed). This hash is returned in the /api/blackjack/new-hand response as shuffleHash. The hash is public; the seed stays encrypted on the server.shuffleSeed alongside the settlement results. You can immediately verify: SHA256(revealed seed) === shuffleHash you received at hand start.FAQ
VRFs like Chainlink VRF provide on-chain randomness with cryptographic proofs. They are excellent for high-stakes lottery draws where the entire verification must live on-chain. For a blackjack game with a commit-reveal scheme, VRFs add significant cost (gas + oracle fees) and latency (waiting for an on-chain callback before dealing) without a meaningful fairness advantage. Our CSPRNG is seeded from OS-level entropy that no server operator can predict in advance, and the commit-reveal scheme ensures we cannot change the outcome after you bet. The result is provably fair play at zero extra cost to players. We will reconsider if player feedback shows demand.
No. The seed is committed (hashed and published) in the same API response that confirms your bet was accepted. The shuffleHash field arrives in the new-hand response before you see your cards. Changing the seed after that would change the hash — and your client already has the old hash. Any mismatch is detectable by you.
We commit to the hash before accepting the bet. The nonce / bet amount are sent to us at the same time, so we cannot know your exact bet before committing the seed. Even if we could — cherry-picking from 2256 possible seeds to find one that causes you to lose a specific hand is not computationally feasible. The house edge is already defined by the rules (payout ratios, commission) and doesn't require deck manipulation.
One seed covers one full shoe (8 decks, 416 cards), which serves approximately 75 hands before reshuffling. Every hand within the shoe is deterministic from the same seed. The shuffleHash published at the start of any hand in the shoe can be used to verify the entire shoe's card order, including all prior and subsequent hands dealt from it.
The shuffle logic lives in game.js in the lootxx-blackjack repository. The relevant functions are buildShoeFromSeed, seededRand, and encryptSeed / decryptSeed. The verify tool at /play/fairness/verify is a self-contained browser page — view its source to confirm it uses the same algorithm.
Verify a hand yourself
Paste the shuffle seed and your dealt cards — our browser tool recomputes the shoe and shows you the match in seconds. No installs. No extensions. Pure JavaScript.
Open verify tool