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

clientSeed: 0xbe3c2688f2dd5a6d4157013ab836259f8cc4b6bb675299e94af6a167e79605e0

chain entropy: not yet, arrives with the draw

serverSeedHash (commitment): 0x67d7b18be77b3efc5328a515a1a3c80adcccc81a7946902407662c71f2aceba9

clientSeed: 0x78efe5713ba26029b6dcc251404ce8335acd2c419df572fae8e78fc1eff1d0e4

chain entropy: not yet, arrives with the draw

serverSeedHash (commitment): n/a

clientSeed: 0xc7232ae2d71047eab03ff5d11ac53807851945f1f3754091bbb5f13cee458411

chain entropy: not yet, arrives with the draw

serverSeedHash (commitment): 0xd141a9cdbb4df966a65cb0c74863245d48c910c0b171cf2afd18e7f0c1bc3214

clientSeed: 0x5131b2aa68e920aacc3e9368129b70d342ce7bc6b0dab05039d62e1b63f33b81

chain entropy: not yet, arrives with the draw

Rapid Firecancelled

serverSeedHash: 0x49a273f47db07f2cec0eb250e3ae447e21f8af37e5e3ba299055b8635539f32c

clientSeed: 0xd86f7d5bc922dfdef6746cf0022f2a19ef18a628d731d6f5e529ca69d9488117

serverSeed (revealed): 0x62b27bc69586d5edcc7fd340cdf13a35cb17eec14549ec008844fae76e64d9c1

chainBlockhash (revealed): 4nLoLR93E1sxJNqWpxQ4WAwaANUH9dzAdrbT8P1fQifS

chainSlot: 458020423

Rapid Firecancelled

serverSeedHash: 0xb10ae7897f879554b1cf6b006e8e2dc0c29c5fc786f9db024e6631892a4fd212

clientSeed: 0x58438e95573bbca4e05d67998b5802fcc0c27beb57b13d4ca8a44a53112751d6

serverSeed (revealed): 0x563fad1e68c177441fe342ac00634d78a378adb77aee9991799372e5591e4b30

chainBlockhash (revealed): 6NGjdjH5SgXNtPK4P2vCuXUT8TBJLUmBBcyMieiKpaxF

chainSlot: 458019043

Rapid Firecancelled

serverSeedHash: 0x2ddfa6521e9039600c0934b4cc86bf15ca2450f40361b135f0d81a1c9623f518

clientSeed: 0x555acc6e68f5be5407ed13f987d60c6a5bba8221c1c2b1e6b7a4f84356dfa18e

serverSeed (revealed): 0x96974f0e90399d9b3a49907c761e466e928e4a8bab381baf08a1d0249c2d3449

chainBlockhash (revealed): 4QDd1iGCGTJvvb1EJonpkfPGLuweSK4aMG6uixdXeARV

chainSlot: 458017652

Rapid Firecancelled

serverSeedHash: 0x2001559f61d5bc04503f55730b5fc3b22c62430b2f25b527bf8d49715b3f45df

clientSeed: 0x209f54c5373356ea1592b3adf263081ca27ba683ec9175e85ed6c6683b2e66be

serverSeed (revealed): 0x7d0b12cc8101d41c86d463032377dfe0e7e09d0487b9909f1bfc41a1b8816d26

chainBlockhash (revealed): 9P7i9rsXdMtpuZKWPk7RSEE9LU5GsmUrrTQHzNGM4m2K

chainSlot: 458016277

Rapid Firecancelled

serverSeedHash: 0x8a7970fa4319a3ff0bc8d904a33a43b43c2f343c4a477b66a0cb083caaa4aac5

clientSeed: 0x7e740874ffb7f5a2ee02084e2fefae9e0fefce4b925dedf121d3ad87422db59a

serverSeed (revealed): 0x3ae9996aaacc8cf24bb9e7c4d7d1935f1bd11f4e1f5318a96bb5f1f07cb05219

chainBlockhash (revealed): GVnJsDsRkAV9HN99VAVGU96zPtnR9pUshNVwtLbywAHC

chainSlot: 458014900

Rapid Firecancelled

serverSeedHash: 0x987346a05f90ddf23b92b1f3c43dd01a5091e36aa2c89e954b363f8a63bcd707

clientSeed: 0x2d2083814b2aa284ae21788e97ce416586ac8e394b8b193156b58156e25ea36b

serverSeed (revealed): 0xa9045827907e7a28c291a4c179d2c5110e337e5fba95edddd942e0dcd7fa4833

chainBlockhash (revealed): Fj6nvYUXXotWuuE4EXMxhvjiEZ5WD2Kec6YdAGPWxHyd

chainSlot: 458013524

Rapid Firecancelled

serverSeedHash: 0xa54aaf6c77b568322180d9516936739a6a2f606a0db6cf7f68bd56ab13ad15f3

clientSeed: 0x1d31dc7d692b86f40b73172d2a331a3263cfe43eef3766a4843c0685a819dec4

serverSeed (revealed): 0x243f5f0b3f90663f0afd4253150342f46d091a37c321d834532681f015fe4d79

chainBlockhash (revealed): DaZLgsbwRGNBi4FXLPS52jnQRCBm9vA4As4zumgcfjnn

chainSlot: 458012143

serverSeedHash: 0x71f502bb32569cba6c909d4d97eade6bed7a6182307c9349a636e2705920ded4

clientSeed: 0x77c3cdae831d602b70e58033be6ef1d301ac9d9d912e031cbeceb3544d272c42

serverSeed (revealed): 0x1aed4813bade1ab562a16c32baebd3b99600b1024f1c830c6d6fb02fd19ec0d7

chainBlockhash (revealed): DaZLgsbwRGNBi4FXLPS52jnQRCBm9vA4As4zumgcfjnn

chainSlot: 458012143

Rapid Firecancelled

serverSeedHash: 0x91273e9605ea8bccf96092e4b30e7be30a631794ccbcc0d711df18c6761bfa99

clientSeed: 0xb7597bb7eea49159ea756bb79e5f5ee673c348437781e07d37bb715d427ac68d

serverSeed (revealed): 0xa08fd260642ba50c203ec3900b720fc641f05ae46154ca1f4ec601d34c08d9a9

chainBlockhash (revealed): 8L2P6sRuqKBZLjYwz2T3FD4A42tMLMYovLsPiJ7yfCEV

chainSlot: 458010766

Rapid Firecancelled

serverSeedHash: 0xd80bb84e7d73c92beb4ab7596fb58178a8dcf87775092090d3b9f1cabd6b2f61

clientSeed: 0xb18afa469ac7755979913e1ea26c351f8ea0db99ba64fc7335cfc8f343897a43

serverSeed (revealed): 0x4ddc2322f0fe7a60647848b214c3dae31f9e9b097dd25af4ecd2b88e625dca47

chainBlockhash (revealed): 6d8JpeEezMnbiTrn7RQMMhNPBk2JnL6NuXGFNvWBUyUX

chainSlot: 458009398

Rapid Firecancelled

serverSeedHash: 0x6026a109b6623db2fb94127648abe670ee91a4b696730757a169e703194f813d

clientSeed: 0x3915f6922fb420113b75ddb75df45008ec0ac7ad22e8d2391ac02ccd110850ad

serverSeed (revealed): 0x7916343706673d934776b7d0eddaf812d90bd54c6088629931ab9f847a978273

chainBlockhash (revealed): JAF3uNx46VjLTLSReaHjjMHPNcXzvRzSVj5NBF2Zcvj5

chainSlot: 458008008

Rapid Firecancelled

serverSeedHash: 0xd1cf1021388d91feab58238b6583009dfeca20e79f1618a5b6806145196ee186

clientSeed: 0x7f4f714111917bd59cfe3ec41e1b0e5b9ed0c820e8aba67159d46d8af9214c7f

serverSeed (revealed): 0x730f60ebbebdfeeee20c49395891b6e9264654c4c418dc4109da067786850dfe

chainBlockhash (revealed): 7hx3r5teabEWfPo1F46xAFqEkdrwxgJaWFgg3FUJTL12

chainSlot: 458006633

Verifier