Provably fair

Every Crash, Dice and Plinko result on Aurion is generated from three inputs: a server seed we commit to before you play, a client seed, and a nonce. You can recompute any result yourself — in this page, in your own browser — and check that we couldn't have changed it.

How it works

  1. Before play, we publish the SHA-256 hash of a secret server seed. The hash proves which seed we'll use without revealing it.
  2. The result is HMAC-SHA256(server seed, client seed : nonce). For Dice and Plinko you can set your own client seed; the nonce counts your bets. Crash rounds use a public random client seed and a round counter.
  3. Afterwards we reveal the server seed. Hash it: it must match the commitment. Recompute the result: it must match what happened.

Verify a result

The exact algorithm

const enc = new TextEncoder()

// HMAC-SHA256(key = serverSeed, message), via the browser's Web Crypto API
async function hmac(key, message) {
  const k = await crypto.subtle.importKey('raw', enc.encode(key), { name: 'HMAC', hash: 'SHA-256' }, false, ['sign'])
  return new Uint8Array(await crypto.subtle.sign('HMAC', k, enc.encode(message)))
}

async function floatStream(serverSeed, clientSeed, nonce, count) {
  const out = []
  for (let cursor = 0; out.length < count; cursor++) {
    const block = await hmac(serverSeed, `${clientSeed}:${nonce}:${cursor}`)
    for (let i = 0; i < 32 && out.length < count; i += 4) {
      out.push(block[i] / 256 + block[i + 1] / 256 ** 2 + block[i + 2] / 256 ** 3 + block[i + 3] / 256 ** 4)
    }
  }
  return out
}

async function diceRoll(serverSeed, clientSeed, nonce) {
  const [f] = await floatStream(serverSeed, clientSeed, nonce, 1)
  return Math.floor(f * 10000)            // 0..9999
}

async function plinkoPath(serverSeed, clientSeed, nonce, rows) {
  const floats = await floatStream(serverSeed, clientSeed, nonce, rows)
  return floats.map((f) => (f < 0.5 ? 1 : -1))   // +1 right, -1 left
}

async function crashPoint(serverSeed, clientSeed, nonce) {   // no cursor
  const digest = await hmac(serverSeed, `${clientSeed}:${nonce}`)
  const hex = Array.from(digest, (b) => b.toString(16).padStart(2, '0')).join('')
  const h = BigInt('0x' + hex.slice(0, 52)) % 2n ** 52n
  const e = 2n ** 52n
  if (h % 33n === 0n) return 1            // instant crash
  const mult = Number((100n * e - h) / (e - h)) / 100   // exact integer floor
  return Math.min(mult, 1000)
}