LX

LootXX

Provably Fair

Transparency Report

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

1

Fisher-Yates shuffle

The gold standard for unbiased card ordering

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]];
}
2

crypto.randomBytes — the same primitive your wallet uses

OS-level entropy, FIPS 140-2 grade

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.

3

Deterministic replay from seed

Given the seed, anyone can reproduce the full shoe

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.

Commit — before any cards are dealt
The server generates the shuffle seed and computes 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.
Play — cards dealt from the committed shoe
Every card drawn during the hand is pulled from the shoe that was locked in before you saw a single card. The server cannot change the shoe mid-hand without invalidating the hash you already have.
Reveal — seed exposed at settlement
When the hand settles, the API returns the plaintext shuffleSeed alongside the settlement results. You can immediately verify: SHA256(revealed seed) === shuffleHash you received at hand start.
Verify — replay the shuffle in your browser
Paste the seed into our verify tool. It recomputes the full shoe from the seed using the same HMAC-SHA256 Fisher-Yates algorithm and shows you every card in order. You can confirm your dealt cards appear at the expected positions.

FAQ

Why no VRF (Verifiable Random Function)?

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.

Could you pre-compute a bad seed and choose it after I bet?

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.

What if you run millions of seeds and pick the worst one for me?

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.

Does the seed cover one hand or a full shoe?

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.

Where can I see the source code?

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