Provably Fair

Every game commits first, then rolls with entropy from the Solana chain. Here is exactly what that does and does not protect you from.

How a round actually runs

  1. Commit. When a lottery round, duel lobby or case battle is created, the server generates a secret serverSeed and publishes keccak256(serverSeed) straight away, next to the public clientSeed. For duels and battles this happens before an opponent even exists, so nobody can pick a seed that targets a known player list. Lottery rounds commit before a single ticket goes on sale.
  2. Close. Entries lock: lottery buys and sells stop at the closing tick, a duel needs both stakes in, a battle needs both players matched. Case battles also freeze a copy of the case's drop table at match, so later case edits cannot touch a battle already running.
  3. Entropy. Only after the inputs are locked does the settlement worker fetch one Solana blockhash and persist it together with its slot. Battles fetch theirs at match because the live per-round reveal starts there. The fetch only accepts a slot strictly newer than the chain tip recorded at commitment, so a game created and matched inside a single slot waits for the chain to move. A blockhash from after the commitment cannot be known at commitment time, which is what breaks seed grinding: the operator can try seeds all it wants, the final input has not happened yet.
  4. Derive and reveal. The outcome is one hash over serverSeed, clientSeed, the chain blockhash and the game id. At settlement everything is revealed: the seed, its published hash, the blockhash and its slot. You can re-run the math yourself in the verifier below and check the blockhash on any Solana explorer against the published slot.

What we can still do, stated plainly

  • The worker that fetches the blockhash is ours. It keeps trying until a value lands in a slot newer than the commitment, and exactly one fetched value is written with the settlement claim, so it cannot be quietly swapped afterwards. Attempts that fail or land too early simply retry, and a compromised or dishonest server could still time or retry that fetch. That is a single point of infrastructure trust, and no purely server-run scheme removes it.
  • Your account, your balance and the payouts live in our database. If the whole stack is compromised, fairness math will not save you. What this design removes is protocol-level steering: grinding seeds, re-rolling after seeing entries, or adding tickets once the draw entropy is known.
  • Rounds settled before this upgrade (visible in the reveal: no chain blockhash) used only the two seeds, and are still verifiable with the legacy formula.

Formulas

Winner-take-all lottery draws:

target(tier, attempt) = uint256(keccak256(serverSeed || clientSeed || [chainBlockhash] || drawId || tier || attempt)) mod totalTickets; winner(tier) = first entrant whose cumulative ticket count exceeds target; the single tier-1 winner takes the whole pot (legacy rounds paid up to 4 tiers; collisions with an earlier tier re-derive with attempt+1). Rounds settled after the chain-entropy upgrade include the 32 raw bytes of the revealed Solana blockhash (base58-decoded) between clientSeed and drawId; legacy rounds verified without it leave that segment out

Duel coin flip:

winnerSide = uint256(keccak256(serverSeed || clientSeed || [chainBlockhash] || lobbyId || 0x01 || 0x00)) mod 2; side 0 = lobby creator, side 1 = opponent (join order); rake = floor(pot * 0.5%). Duels settled after the chain-entropy upgrade include the 32 raw bytes of the revealed Solana blockhash (base58-decoded) between clientSeed and lobbyId; legacy duels verified without it leave that segment out

Case battle drops:

value(round, slot) = uint256(keccak256(serverSeed || clientSeed || [chainBlockhash] || battleId || round || slot)) mod 10000; drop = case dropItem whose cumulative weight range contains value; slot 0 = creator, slot 1 = joiner; winner = higher cumulative drop total; exact tie splits the pot after rake; winner takes the pot minus 5% rake, not the opened items. Battles settled after the chain-entropy upgrade include the 32 raw bytes of the revealed Solana blockhash (base58-decoded) between clientSeed and battleId, and derive against the drop table frozen on the battle at match; legacy battles verified without it leave that segment out and use the case's current drop table

Seed commitments

serverSeedHash (commitment): 0x6f741a180211deb5914d17c9b1acdb2c7cdfe50116f86d91539281b964b26990

clientSeed: 0x41d5bcb99a5a47bcdd2f375bb6857a5aafcd450e9c02b535b203c2a131713a92

chain entropy: not yet, arrives with the draw

serverSeedHash (commitment): 0xc29743a92dede32eeadbdc417acad07c82afb9a64381864cc03f097deb3fce5a

clientSeed: 0x4b91cea767f18076de9f378896ab31e241ac0707bcd13f8cb9b71e6f2e9dfb2c

chain entropy: not yet, arrives with the draw

serverSeedHash (commitment): 0xd449f4dc8f4994cc7c58d5ee3451cc40a65f0076a822926c1139ddd40bea0bb3

clientSeed: 0x784fc8db8aa524dc91467d096b5b9c554b245854bd8a025f940d258928a9b57f

chain entropy: not yet, arrives with the draw

serverSeedHash (commitment): 0x1de14308e3055e32d9036594b402fa7d4b23e064f19f926e2e66b8e23301aa1a

clientSeed: 0x19af35baedda7731037af3be6faf601530cecb36afc236f3791b09e792b82184

chain entropy: not yet, arrives with the draw

Rapid Firecancelled

serverSeedHash: 0x07a4717741e4d4dad585dce4a5fa35aaf256ef80aa794bbc50793fb3c9a49bc9

clientSeed: 0x9841c85c8ea98cf5ee70aa012c8b4372a4fc7c9790287e6deccbcd66ac7854c8

serverSeed (revealed): 0xaa35c2a4e04db6e70799ba9fe8483f404fc999bc6f803a9082496b7d9dcc0aca

chainBlockhash (revealed): 2hZZcHHnfzzwcRDwd4hXdnRJn9CeMkWuYaxXm4pPjykS

chainSlot: 458262227

Rapid Firecancelled

serverSeedHash: 0x43b8f4f6f24ea70820d075a6007b412f8b317c1cb69ee626d854057e0d3653aa

clientSeed: 0x9560daf6f19670f6ab70957ad8ae43af7cf82fb01213c2bf501fd6dbcfe1aba3

serverSeed (revealed): 0x60d117bb36a1cc7dae9972996eaf19c77d5831a459f0e933ba7e65b0b1ba8639

chainBlockhash (revealed): DCFkpHvMjcpjSddwVHnkxHanXBFi1x7m6QTAQjMSXaon

chainSlot: 458260837

serverSeedHash: 0xba1b092c81ba77325fd6789197f21892d9849378949b0a0e05fd92d4f5d0ccdb

clientSeed: 0xfe76ee7a896d491976563aefe95d26d64644e29870884ee049e9c6480c6f721f

serverSeed (revealed): 0x992c8675db482eddaa1c6d71e05dc7488876832712c0d9a1fb1a2d1b8641bedd

chainBlockhash (revealed): HBt9vzJf8UdfKxZRYaL4B4VofGUATUyXXihiVGYzyQAc

chainSlot: 458260836

Rapid Firecancelled

serverSeedHash: 0xcdcb2916a2c318027df47aae21117b2cd1e35fdc96d2c7f4072e3b50834bed5e

clientSeed: 0x6dac17107306b32e8072051ac8bb2c7677719e001efc62d60db814e9fe0c0c8b

serverSeed (revealed): 0xb68f2c4d0148b645151c9fd415bbb36f0e523c4c85deafddae0f0f88430879b7

chainBlockhash (revealed): 2pXbW1CFJTeaYNRPTAs5GSt9h8BjX2un1ZoVSesht2hr

chainSlot: 458259441

Rapid Firecancelled

serverSeedHash: 0xc469e5b7b8677266fa69ca04a70dbd3a8fc79d0b047caaa3a6c4cdf04ef64e02

clientSeed: 0x4bbc58d77e82934543c735db743e444eea792b8a6d70a7c9460c76a23dfca2d6

serverSeed (revealed): 0x9a0103b3c82057f6876cf507887f09971c86fb83de511029a7c0790b802290cb

chainBlockhash (revealed): E6G1sFNp1ZN9kZL759VgRD33syvkLKPyAQKugFX3JiDG

chainSlot: 458258054

Rapid Firecancelled

serverSeedHash: 0xa4f458ca08b18572e0952823eec2d1cc112eb01a830d54c95e98ec5c862a9f31

clientSeed: 0xd45e3701d2480943bec8186abe0e3536d6811fa90ea8db80f90e9fe6607b3d07

serverSeed (revealed): 0x33edd082ee5401055e312263ffb6d3df24671b4c9af36d7e20e08fa91380328b

chainBlockhash (revealed): G7iCtNQ38FXmTaBrgrq8FdGvHAo1UThwqu797N9YsrWZ

chainSlot: 458256665

Rapid Firecancelled

serverSeedHash: 0x3b9ad7c2dc2232d0d4e4f3d8b9a664506a0bc8097381518c66690c42cbaee057

clientSeed: 0xef5cca1a89566c0732751b0364a14e4f8f04b9c503b00ac6041030c3bb6539dd

serverSeed (revealed): 0x3d77a11b6ba8cc5c4556dbacb420d491f9efab128fba86d555b8c21110d2f572

chainBlockhash (revealed): 2d1XQTHwj5QCb5JxQHn2wBPAKzJ4T4KGhLogt5CvxMoh

chainSlot: 458255277

Rapid Firecancelled

serverSeedHash: 0x4ddd8c18ae1348dd9affd8dbcddb5f53985e211f28eaf7c6789252151e899071

clientSeed: 0xa05b3a2e5a5112dee3a4256de8a2faaa5841ac9f392f8d54ec687988af0de80d

serverSeed (revealed): 0xa9d6e4273eb90469ea5b863f9b7b053021400917f765513c03398a0bde623014

chainBlockhash (revealed): EWnsEZ7PbhB3bC8SXZUQtya6tKtqABo6Xxe3UXtVKX7L

chainSlot: 458253911

Rapid Firecancelled

serverSeedHash: 0xc6c777f5bb42f6b090b1e7e738db1072a0b16b7d731ad43497157b7a618e2a84

clientSeed: 0x98517938623091032f1718670d619fa2e01abc0ae8349c688ab5ed2d746dc3a2

serverSeed (revealed): 0xfb2c201f1c0fa6fcfddb433d762578cf9bb2e7c237da4763d0423d1e85fb1af8

chainBlockhash (revealed): AnAEBny5RNrimWJPu31xjGi6pHWfLcQHbgz7V6fRDKLM

chainSlot: 458252526

Rapid Firecancelled

serverSeedHash: 0xc4c8ba0f21540359eb7c31c686110052c7b40cdf6a204e33442d5e8739d7e4e5

clientSeed: 0x29446f94bd40cfa2b18db877ee74a2cf9cd3cd735f9f40969db19c6d43510aee

serverSeed (revealed): 0x4a36ce6a41fbeb1bd7ed4de5aaaf7faf67a8aac31ef57f1b9d05785f65550e24

chainBlockhash (revealed): D8mMqkdpuhLBxz1hKNgzVibL5crFRYck6qYiN3yaFqKL

chainSlot: 458251135

Rapid Firecancelled

serverSeedHash: 0x3b79ffce384d927be0dd7787eb5ee0c0ab2bf77dc9cb7e5cbd62cef2c79e44de

clientSeed: 0xb55b717d666756960839d691bd037f4db5caa958ea04f952b272186e2f780943

serverSeed (revealed): 0xb5cd67453f0f282fc5bff4c260491139a5e22810db76a021e44a6cdd72d0298e

chainBlockhash (revealed): ARvLmPJHZvFwZPxKfeb7p2sLDDufF39iV1eh657T1fWT

chainSlot: 458249769

Rapid Firecancelled

serverSeedHash: 0xe3f1257e6e428d71fb6fd2a8f8cd9e5df67c90875c0fc9146cd4181238ba4f2e

clientSeed: 0x3133364dcfee7c2d1686a4ab095f6ff71a3c2a4261e30fefac164f1c3820886b

serverSeed (revealed): 0x69f2c6ffb0e7d679877392191e1b3fbb3bb29de2b3afd3798bd044e8cf9075f1

chainBlockhash (revealed): Eaznk3JDeM6pZrgfEPZpu87VL1EmSDna69Zef2rtgqge

chainSlot: 458248383

Verifier