You don't have to trust us.
A pack-opening product has an obvious way to cheat: wait until it knows how much you spent, then decide what you pulled. Nothing on the surface of the app would show it. So the draw is built to make that impossible rather than to promise it doesn't happen.
How a pull is fixed in advance
- 01The server commits
Before you open anything, the server generates a secret seed and shows you only its SHA-256 hash. That hash is the commitment, and it cannot change later without changing the hash.
- 02You contribute randomness
Your browser generates a client seed and sends it with the request. Because the server can't predict it, it can't pick a server seed that produces a bad outcome for you.
- 03The draw is derived, not chosen
Cards come from HMAC-SHA256(serverSeed, clientSeed:nonce), read four bytes at a time. There is no randomness left for the server to influence.
- 04The seed is revealed
After the pack opens, the server publishes the server seed and rotates to a fresh one. You can hash it and confirm it matches the commitment you were given.
Replaying it yourself
Every opening screen has a Verify this pull panel with the four values you need. Feed them back through the same HMAC and you get the same cards, in the same order.
# reproduce the byte stream a pull was drawn from
python3 - <<'EOF'
import hmac, hashlib
server_seed = "<from the verify panel>"
client_seed = "<from the verify panel>"
nonce = 0
block = hmac.new(server_seed.encode(),
f"{client_seed}:{nonce}:0".encode(),
hashlib.sha256).digest()
# each draw consumes 4 bytes, big-endian, divided by 2^32
print([int.from_bytes(block[i:i+4], "big") / 2**32
for i in range(0, 32, 4)])
EOFThe first float picks a tier inside the first slot, the second picks a card within that tier, and so on down the slot list published on each pack page.
Anchoring on Solana
Every roll and every pack opening can be written to the chain. The transaction carries a digest of the outcome: sha256("RIPL1" ‖ serverSeedHash ‖ clientSeed ‖ nonce ‖ outcome), carried in a Memo instruction. Nothing moves and no program is involved. The prefix RIPL1 is readable as-is in the explorer.
What that proves: at that slot, this exact result existed in this exact form, and it has not been rewritten since. Anyone can recompute the digest from the four values above and find it in the transaction.
What it does not prove: that the server committed before the roll. That guarantee lives in the commit-reveal above, where the draw is fixed before anything reaches your screen. Putting it on-chain too would mean publishing the commitment before each open, which needs a contract and a second transaction. That is the next step, not this one.
What this does not cover
Provable fairness proves the draw wasn't rigged. It says nothing about whether a pack is a good purchase. The expected value of every pack is published, and for most packs the median outcome is well below the price, because a handful of large pulls carry the average. That is how the printed product works too, and it is worth understanding before spending.