How the draw works
Every ticket a player earns during a contest is one entry in the draw — the more tickets, the better the odds. When the contest window closes:
- The server generates a secret random 32-byte seed and locks in its SHA-256 hash — the commitment — before the winning number is computed.
- The winning number is derived from that seed with HMAC-SHA256: the seed is the key, the message is "draw-<contest>:99:0", and the first 4 bytes of the result become a number between 0 and 1.
- That number lands on one player along the line of everyone's cumulative ticket weight — a weighted random draw over every entry.
- After the draw, the seed is revealed and published permanently next to its hash in the public draw record. Each seed is used exactly once.
Company and test accounts are excluded from every draw in code — a rule pinned by automated tests that run before any release.
Verify a past draw right now
This button fetches the public draw record and re-runs both checks in your browser with the standard WebCrypto API — our server isn't involved in the math:
The published draw records
The same values the verifier fetches, stated in plain text for the record. The hash was committed before each draw; the seed was revealed after it. A new record appears here automatically after every draw.
Or do it without our page
A verification that runs on our own site still asks for some trust. So here's the whole thing as a snippet — paste it into any browser console or Node.js, on any machine:
const rec = (await (await fetch('https://b2see-backend.luck-inc.workers.dev/chance/winners')).json()).winners[0];
const f = rec.fairness;
const bytes = h => new Uint8Array(h.match(/../g).map(x => parseInt(x, 16)));
const hex = b => [...new Uint8Array(b)].map(x => x.toString(16).padStart(2, '0')).join('');
// 1) the commitment: SHA-256 of the revealed seed must equal the recorded hash
console.log('commit ok:', hex(await crypto.subtle.digest('SHA-256', bytes(f.server_seed))) === f.server_seed_hash);
// 2) the winning number: HMAC-SHA256(key = seed, msg = `${clientSeed}:${nonce}:0`), first 4 bytes / 2^32
const key = await crypto.subtle.importKey('raw', bytes(f.server_seed), {name:'HMAC', hash:'SHA-256'}, false, ['sign']);
const sig = new Uint8Array(await crypto.subtle.sign('HMAC', key, new TextEncoder().encode(`${f.client_seed}:${f.nonce}:0`)));
console.log('winning number for', rec.name, '=', (((sig[0]<<24)|(sig[1]<<16)|(sig[2]<<8)|sig[3])>>>0) / 2**32);
What this proves — and what it doesn't
It proves the winning number was produced by the published formula from a seed matching its committed hash — not hand-picked. The derivation is deterministic: the same seed can only ever produce the same number.
It doesn't prove the entries themselves, because the full entry ledger contains every player's private balance and is not published. What we publish per draw is the total entry count, the winner's public handle, and the prize — and the exclusion of company accounts from the draw is enforced in code and pinned by tests.
Honest scope beats big claims. If you're auditing us, the winner record carries every draw ever run, and the official rules bind us to all of it.
Fair enough to play?
A contest is running right now — watch ads, play games, earn entries. One winner takes the whole pool.
Download Chance NowNo purchase necessary. Open to U.S. residents 18+. Odds depend on the number of eligible entries. Official rules.