Provable fairness
Every draw can be recomputed from published data. You do not have to trust that the operator picked fairly, because the operator commits to the outcome before knowing it and reveals the proof afterwards.
The problem being solved
A draw needs randomness the operator cannot control. Two naive approaches both fail. If the operator alone supplies the randomness, they can pick a winner and claim it was random. If a public value like a blockhash alone supplies it, the operator can wait, see the value, and decide whether to run the round at all.
Commit and reveal closes both holes by splitting the randomness in two.
The scheme
- Commit. Before the round opens, the keeper derives a secret
serverSeedand publishes onlysha256(serverSeed). It is now locked in. It cannot change the seed later, because no other seed produces the same hash. - Wait. The round runs. Anyone can read the commitment on the live round.
- Reveal the client half. At draw time the keeper fetches a recent Solana blockhash as the
clientSeed. That value did not exist when the commitment was published, so the outcome could not have been known in advance. - Derive. Both random choices come from the seed pair.
- Reveal the server half. On settlement
serverSeedis published, and anyone can check the whole chain.
The derivations
stockIndex = sha256(serverSeed:clientSeed:"stock:0") mod eligibleStocks
winningTicket = sha256(serverSeed:clientSeed:"ticket:0") mod totalTicketsThe distinct labels mean the two draws are independent: knowing which stock came up tells you nothing about who won.
Both use rejection sampling rather than a raw modulo. A raw modulo of a 256-bit value into a range that does not divide 2256 evenly gives low values a fractionally higher chance. The bias is tiny but real, and avoidable, so it is avoided. See Odds and ticketing for the loop.
Verifying a round yourself
Open any settled round from the history. It publishes:
- the commitment hash, written when the round opened
- the revealed server seed
- the client seed, which is the blockhash used
- the winning ticket and the total ticket count
- the full entrant snapshot with every wallet's ticket range
Three checks:
sha256(serverSeed)equals the published commitment. This proves the seed was fixed before entries existed.- Re-running the ticket derivation reproduces the published winning ticket. This proves the number was not chosen.
- The winning ticket falls inside the winner's published range. This proves the right wallet was paid.
The round page performs all three in your browser and shows the result, but the point is that it does not need to be believed. Every input is published, so you can recompute them with any SHA-256 implementation.
What is and is not verifiable
The winner selection is fully reproducible from stored data. That is the part that decides who gets paid, and it is the part that is airtight.
The stock selection is verifiable in method but not replayable exactly. The candidate list depends on live routing depth at draw time, and market conditions from that moment cannot be reconstructed later. The keeper logs the candidate set it used. This is disclosed rather than glossed over, because a fairness claim that overstates itself is worse than one that does not.
Note the asymmetry in trust. The keeper is trusted to execute honestly, since it holds the keys that buy and send. It is not trusted to pick winners, which is the part this scheme removes from its control.
The fairness page walks through the same scheme in the context of a live round.