Provably Fair
Provably Fair is a transparency system designed to ensure that every outcome on our platform is legitimate and free from manipulation. It uses cryptographic algorithms and independent user input to generate random, verifiable results. After each game, you can confirm that the result was produced using the original seeds and inputs, proving that the game was fair and untampered.
Provide the seeds from the game you want to verify.
We generate a random number per lootbox opening and map it to the 100,000 probability scale.
Each lootbox opening generates one random number per round and maps it to a 100,000-point probability scale. The reward is picked by mapping the slot’s random number onto the lootbox’s item probability ranges and selecting the item whose range contains it.
Battles generate a sequence of numbers for every slot across all rounds, plus one extra number used for tie resolution.
Upgrader rolls generate a single random double and compare it directly to your win chance. A roll between the range given is a win.
TypeScript
These are the helper functions used to derive deterministic results.
const HMAC_DESCRIPTOR = 'sha256'
const BYTES_PER_NUMBER = 4
const NUMBERS_PER_HMAC = 8
const UINT32_MAX_PLUS_ONE = 4294967296
export const toIntWithMaxValue = (random: number, maxValue: number): number => {
return Math.floor(random * maxValue)
}
export const generateHmacSha256Numbers = (
secretKey: string,
message: string,
count: number
): number[] => {
if (count <= 0) {
throw new Error('count must be > 0')
}
const results: number[] = []
let round = 0
while (results.length < count) {
const messageWithRound = `${message}:${round}`
const hash = hmacSha256(secretKey, messageWithRound)
for (let i = 0; i < NUMBERS_PER_HMAC && results.length < count; i++) {
const offset = i * BYTES_PER_NUMBER
let value = 0
for (let j = 0; j < BYTES_PER_NUMBER; j++) {
value = ((value << 8) | (hash[offset + j] & 0xff)) >>> 0
}
results.push(value / UINT32_MAX_PLUS_ONE)
}
round++
}
return results
}
const hmacSha256 = (key: string, data: string): Buffer => {
return createHmac(HMAC_DESCRIPTOR, Buffer.from(key, 'utf8'))
.update(data, 'utf8')
.digest()
}