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): 0x44fa4e6f2742468ce62a087967ad4c50b2039925a3dacb4d780e38fa38b6c767

clientSeed: 0xf4abbde65c29c1ed86b7e3182e52a1969c1a16284de6cfb1d7119b3eb8268267

chain entropy: not yet, arrives with the draw

serverSeedHash (commitment): 0x580c5e02d169c8ae0849905f4e232d04df8d6d9a3b15a17e5ef350b9ebec543d

clientSeed: 0x0548c0fc55c822168c7aea12c10a2a28bcef66d4fa851359384915442aa7ce15

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: 0xf5cb4e9f9f64b0477398be4b5e0bf6d526ef817d693b73e5ca3816da52bfcd2a

clientSeed: 0x5788ae8b568bba9f00b4e0f291ae5f969d36fc736992b6e4336e170b7368a715

serverSeed (revealed): 0xb0cd34f6ff1556b7e14ef9e29991d5c28773c63c1358298303086a7563c6fede

chainBlockhash (revealed): GMzuefYHTcrdSJNYxoNjom17TaAX2MgUHeqJyc8WVt22

chainSlot: 458570796

Rapid Firecancelled

serverSeedHash: 0x381c4498f3045049e62e7a3a71f7af56d0561166d9b54c19b7bee921d32fe236

clientSeed: 0xd56d0e2df7e8f944dc94249a08a7361e2c756759c4f7ee5a8e233909862ba09f

serverSeed (revealed): 0xa755a6ce102e6ac2261063d9a554ea5b2780ddef218c217545a485f16db0b915

chainBlockhash (revealed): 8b7T6EMyt1ihezyjT5q5pKNjL5JqNdGhQqdNHQ44SZ75

chainSlot: 458569407

Rapid Firecancelled

serverSeedHash: 0xa8147e1f6154980d90f61f5c524867d7e01844e72a782f3ffa3f742d06a6d416

clientSeed: 0x07135b0dc43f45ffabf56f9102359e9de4996f6bd41b50904364c713cf567736

serverSeed (revealed): 0xf0268c74c83a7557f0cd3a650b44df4c8140d3dd8491ef330fe861fca30c6fab

chainBlockhash (revealed): EtcwjkoUXQruDZiVcX7uuxDg95Kc717Zx2HpSPNN9W1M

chainSlot: 458568010

Rapid Firecancelled

serverSeedHash: 0x459c7f048c6231c7a77d4bfb83b9679e268ef479a6988bcdcef8c5a771d168ee

clientSeed: 0x8d410bd1fe7f90c0b5d55e57706e5c076d02979c7b8420a98067244f2fb51208

serverSeed (revealed): 0x4478093725b0de6b34f66b75be9560f4ca64db1f1e5dff4136b16c1b396a3319

chainBlockhash (revealed): CCc3vZeVEMfrHTQwdwmNxFUW224jSf5qK8M9TBVJYNR

chainSlot: 458566626

Rapid Firecancelled

serverSeedHash: 0xe3dd0e79a91bfb75c21e2e4f702ecc2cac8a182e0cdd32d3ebc824a2c3353097

clientSeed: 0x50a8572571fff579c43f788b1bf68e251afbc56b246fd09b1b43c0a5538eb7cf

serverSeed (revealed): 0x8b586f823c44f9e27ff897f22388b1a916ea92c8857f2930ad525d4cc8f3ff0c

chainBlockhash (revealed): E4bhEwUd5A6ZmdfGCvEbeTDXgGqh19yJKT3WX1PoSLi4

chainSlot: 458565234

Rapid Firecancelled

serverSeedHash: 0x84e5ab814c14fdc064a8dbc8891d59db8656254ef7b30818d9e20a89def0085c

clientSeed: 0x96dbc6296be09deb72ef9a26ecf8bc643b7d5ea5852a30db8cc4e483f503d939

serverSeed (revealed): 0x1bb50aa0445e641d6b864348ea9fb1ccd106af9291186da344722cb3cd5d4b1f

chainBlockhash (revealed): 7iMW6yJwGfRc5NKWJRZnCxXmvv6Eje8sCa1H8RqLw1AS

chainSlot: 458563879

Rapid Firecancelled

serverSeedHash: 0x689b84e4b7b835bf3bd3cd49a99aad3ae415991c7225b353392795339ca12576

clientSeed: 0xf9b3f27fe2e2a8b9dfb12f5b7f16ada2c00ff82c25349dec1e9f1905377fb5d0

serverSeed (revealed): 0x93ae4a6f092ece5e742a45bfd01cace06c9c776de84ba5e6efc8deda701732f2

chainBlockhash (revealed): CndHK35HWxrP5k9vXJtjMAr6qrqiKdCk4zbtFHMHcKDn

chainSlot: 458562496

Rapid Firecancelled

serverSeedHash: 0xb33e9f0dba42e737fd7776884ba8dabb8328fd15c47c652cf3043f0b95799246

clientSeed: 0x199e3eb2cc9b18104480f06fdf4d72ef496b7cc0059bd6d0d34cef7fe3c1deb3

serverSeed (revealed): 0x4a0cdd9ce0f6f8f51fc18d0a46c45eab8d2c5bb53a4ba7ed903d558170fb9e57

chainBlockhash (revealed): 97aFi3DCMV2tEFm469wfko49Vzw8abY3kPb6FQGgWxJf

chainSlot: 458561116

serverSeedHash: 0xa32ba74698f8cf87c8c3971a5f0c402934d59b5114bf67944501bc856da33632

clientSeed: 0x136587334e463662598c556ed71fe12492b13868b31b2dde4af97d4b413df5a4

serverSeed (revealed): 0xf80f7d62edaf352aee0c77a9447f1377592aaf9e156e753ca2b518ec4c6825d5

chainBlockhash (revealed): DRRcNxcbkQ5qUo1nVAtEELEcnSmxfeLQNjY6kdMNwCWr

chainSlot: 458559726

Rapid Firecancelled

serverSeedHash: 0x9c62215d6ba1e23bb9028fddf8422cb79d95cdb0661650b901e7f300599cd79f

clientSeed: 0xcc0c0108700a97baecbd1fa9010a18cd5788854e0d3d4164c37327a9239b01de

serverSeed (revealed): 0xb8e20de7923b7fb4adf7de712c2789f58c83ce360c994e82c2d71aba96207aec

chainBlockhash (revealed): HZPGCyzT2DSP8Zds6MC4EW1zKXYHGaF436tA2NqQfXV9

chainSlot: 458559727

Rapid Firecancelled

serverSeedHash: 0xe4ba4a20a6b96dd7ed865925dbe1e0c568ce595333bf34f61d19adedf7d75728

clientSeed: 0x645b8feb7a1d97bbb020be68fdbc2ed5113abd8e150115619abb618b8a7a83e4

serverSeed (revealed): 0x4f9e0a29f6b108d02aee9b9a3006d5f211486cc88cd727c0ed8084f56534c599

chainBlockhash (revealed): GWMyw8fgnsDk85rBmioTr7jHmTv6GJF8aRP1mPiAA4ma

chainSlot: 458558352

Rapid Firecancelled

serverSeedHash: 0xf2275e5b4554640a9242419e596fd3d802c6d9c1f34d2a4e8339fd3d240157b7

clientSeed: 0x7962a339a72ec3c994939e16a8991ddd152b6d7147fb7d5cd080813ae422a703

serverSeed (revealed): 0xb756460f6a31489ddb9385f3b67efdb0dd2a8d0970d807cd4963739b99b701c0

chainBlockhash (revealed): FnZwCGB27CvpJhE8HRdSbiAtbavFyVmvdN1WS6rv7mE

chainSlot: 458556978

Verifier