Server-authoritative
The browser sends only intents such as “place piece 2 at column 4, row 1”. Board, level, multiplier, payout and balance are computed on the server.
Fair play
Our games keep chance small and make it provable. Here is exactly what is random, how it is generated, and how you can verify it yourself.
What is random
In Puzzle Crash, the single random element is which pieces appear in each hand. Placement, line clears, levels, multipliers and payouts follow fixed, published rules. The piece generator takes only two seeds and the hand number as input — never your balance, your past results or the decisions you make.
Commit – reveal
Before you play, the server draws a secret 32-byte server seed from a cryptographic random generator and shows you its fingerprint: SHA-256(serverSeed). It cannot change the seed afterwards without the fingerprint changing.
A client seed is mixed in, so the server alone does not choose the outcome of the draws.
Hand n is derived from HMAC-SHA256(serverSeed, clientSeed + ":" + n) and the published piece probabilities. Hands are created only when the previous one is finished — future pieces do not exist yet.
When the round ends the server reveals the seed. Anyone can check the fingerprint, recompute every hand and replay every move.
Verify it yourself
After a round, take the revealed server seed and the commitment you were shown at the start. This snippet runs in any modern browser console:
// serverSeed: revealed after the round (64 hex chars)
// commitment: shown to you before the round started
const bytes = (hex) => new Uint8Array(hex.match(/../g).map((b) => parseInt(b, 16)));
const hex = (buf) => [...new Uint8Array(buf)].map((b) => b.toString(16).padStart(2, '0')).join('');
const digest = await crypto.subtle.digest('SHA-256', bytes(serverSeed));
console.log(hex(digest) === commitment ? 'commitment OK' : 'MISMATCH');
// Entropy for hand n (input to the published piece draw):
const key = await crypto.subtle.importKey('raw', bytes(serverSeed), { name: 'HMAC', hash: 'SHA-256' }, false, ['sign']);
const hand0 = hex(await crypto.subtle.sign('HMAC', key, new TextEncoder().encode(clientSeed + ':0')));
The game also re-checks the commitment and every dealt hand automatically in the round history, and the server publishes a full verification report (commitment, dealt hands, replay of every move and the hash chain).
Integrity
The browser sends only intents such as “place piece 2 at column 4, row 1”. Board, level, multiplier, payout and balance are computed on the server.
Cash-outs are protected by locks, version checks and a unique ledger entry — a retried or duplicated request can never pay twice.
Every accepted move is stored with a state hash chained to the previous one. History tables are append-only.
Sessions
Whatever happens, you see a notice explaining it the next time you open the game.
Being straight with you