Crash Fairness

Our Crash is a provably fair game, which means players from all over the world can manually and individually verify the fairness of each match that is hosted by our reliable system.

Technical Details

Crash's fairness is guaranteed by using a long chain of hashed values that provide a fair distribution of random outcomes. This chain is calculated before any game is initiated and starts with 32 bytes of cryptographically secure pseudorandom numbers, followed by the hash of the previous value. Along with this chain, a 32-byte public salt is also added to ensure that the initial value of the hash chain was not chosen in favor of the house.

The result for each match is determined by feeding the following variables into a SHA256 HMAC hashing algorithm:

  1. Public Salt is a hex string of 32 bytes of the chosen value. The public salt of the current chain is
  2. Secret is the current hash value of the hash chain.
1async function hmacSHA256(keyString, messageString) {
2	const enc = new TextEncoder("utf-8");
3	const key = await window.crypto.subtle.importKey(  
4    "raw",
5    enc.encode(keyString),
6    {
7        name: "HMAC",
8        hash: {name: "SHA-256"}
9    },
10    false,
11    ["sign", "verify"]
12  );
13  const sign = await window.crypto.subtle.sign(
14        "HMAC",
15        key,
16        enc.encode(messageString)
17  );
18  const bytes = new Uint8Array(sign);
19  return Array.prototype.map.call(bytes, x => ('00' + x.toString(16)).slice(-2)).join("");
20}
21
22
23async function calculateMultiplier(hashValue, salt, leverage) {
24  const randomResult = (await hmacSHA256(hashValue, salt)).toLowerCase();
25
26  if (leverage > 0) {
27    const houseLeverage = Math.ceil(100 / leverage);
28    const extraCharacters = randomResult.length % 4;
29    const startIndex = extraCharacters > 0 ? extraCharacters - 4 : 0;
30    let remainder = 0;
31    for (let i = startIndex; i < randomResult.length; i += 4) {
32      const chunk = parseInt(randomResult.substring(i, i + 4), 16);
33      remainder = ((remainder << 16) + chunk) % houseLeverage;
34    }
35
36    if (remainder === 0) {
37      return 1;
38    }
39  }
40
41  const randomValue = parseInt(randomResult.substring(0, 52 / 4), 16);
42  const maxValue = Math.pow(2, 52);
43  return Math.floor(((maxValue - (randomValue / 50)) / (maxValue - randomValue)) * 100) / 100;
44}
45
46const secret = "ddcf544330c1fc826cb36e93866e1e3ec292d60e1242ce6ef5468376cc8541ad";
47const publicSalt = "56c49d1fe912f52855afc1240febed3ac58b944c2022c1bb64edfdf848c3df4d";
48const leverage = 5;
49calculateMultiplier(secret, publicSalt, leverage).then(
50	(multiplier) => console.log(multiplier)
51);

Recent Rounds

Game IDMatch IDDateSecretDurationMultiplier