Sports

Games

General

Custom Games - Provably Fair

How It's Used in Custom Games

Every bet in a YEET Original starts from a round seed. The round seed is an HMAC-SHA256 of your client seed and the bet's nonce, keyed with a server seed chosen by YEET. The game then draws every random value it needs for that bet from the round seed. The server seed is shown to you hashed before you play and revealed when you rotate your seed pair, so you can recompute the round seed of any past bet and check that its result was not changed after you bet.

Other verifiers may not match

Verification sites made for other casinos can generate random numbers differently, so checking a YEET bet there can give a different result. Verify YEET bets in the Verify tab of a game's Fairness window, or with the code on this page.

Conversions

A conversion turns the round seed's entropy into a game outcome. The building block is the same in every Original: unbiasedUint picks one of n equally likely positions, and the game checks whether that position wins. A step with s winning positions out of n has a chance of s / n.

This page does not list a conversion for every game. The example below shows the pattern with one game.

Example: Lamb Chop

Lamb Chop has 16 hops, and each hop is one draw from the same round seed. On hop h the lane has totalStart − h positions, of which safeStart − h are safe. A roll below the number of safe positions survives. The first roll that does not ends the round, and the multiplier is read from the paytable for the number of hops cleared.

const LAMB_CHOP_TOTAL_HOPS = 16;

const LAMB_CHOP_LANES = {
  easy: [19, 21],
  medium: [19, 23],
  hard: [19, 25],
  very_hard: [19, 27],
  death_wish: [20, 32],
};

const LAMB_CHOP_PAYTABLE = {
  easy: [
    1.0721, 1.1912, 1.3313, 1.4977, 1.6975, 1.94, 2.2384, 2.6115,
    3.0863, 3.7036, 4.5266, 5.6583, 7.275, 9.7, 13.58, 20.37,
  ],
  medium: [
    1.1742, 1.4351, 1.7728, 2.216, 2.8069, 3.6089, 4.7194, 6.2925,
    8.5807, 12.013, 17.3522, 26.0283, 40.9016, 68.1694, 122.705, 245.41,
  ],
  hard: [
    1.2763, 1.7017, 2.3023, 3.1657, 4.432, 6.3315, 9.2537, 13.8806,
    21.4519, 34.323, 57.2051, 100.1089, 185.9166, 371.8333, 818.0333, 2045.0833,
  ],
  very_hard: [
    1.3784, 1.991, 2.928, 4.392, 6.7344, 10.5826, 17.0951, 28.4918,
    49.2132, 88.5838, 167.325, 334.65, 717.1071, 1673.25, 4350.45, 13051.35,
  ],
  death_wish: [
    1.552, 2.5322, 4.2203, 7.1994, 12.5989, 22.6781, 42.1166, 80.9934,
    161.9869, 338.7, 745.1401, 1738.6604, 4346.651, 11798.0529, 35394.1588, 120340.14,
  ],
};

async function verifyLambChopBet(serverSeed, clientSeed, nonce, volatility) {
  const seed = await deriveGameSeed(serverSeed, clientSeed, nonce);
  const result = await verifyLambChopFromSeed(seed, volatility);
  return { serverSeed, clientSeed, nonce, ...result };
}

async function verifyLambChopFromSeed(seed, volatility) {
  const lane = LAMB_CHOP_LANES[volatility];
  if (!lane) throw new Error(`No lamb-chop lane geometry for risk profile '${volatility}'.`);

  const [safeStart, totalStart] = lane;
  const entropy = new GameEntropy(hexToBytes(seed));
  const hops = [];
  let bustIndex = LAMB_CHOP_TOTAL_HOPS;

  for (let hop = 0; hop < LAMB_CHOP_TOTAL_HOPS; hop++) {
    const safePositions = safeStart - hop;
    const totalPositions = totalStart - hop;
    const roll = await unbiasedUint(entropy, totalPositions);
    const survived = roll < safePositions;

    hops.push({
      hop,
      safePositions,
      totalPositions,
      chance: safePositions / totalPositions,
      roll,
      survived,
    });

    if (!survived) {
      bustIndex = hop;
      break;
    }
  }

  return {
    seed,
    entropyCursor: entropy.cursor,
    volatility,
    hops,
    bustIndex,
    clearedAllHops: bustIndex >= LAMB_CHOP_TOTAL_HOPS,
    maxReachableMultiplier: lambChopMultiplierFor(volatility, bustIndex),
    paytable: LAMB_CHOP_PAYTABLE[volatility],
  };
}

function lambChopMultiplierFor(volatility, hopCount) {
  if (hopCount < 1) return 0;

  const row = LAMB_CHOP_PAYTABLE[volatility];
  if (!row) throw new Error(`No lamb-chop paytable for risk profile '${volatility}'.`);

  const multiplier = row[hopCount - 1];
  if (multiplier === undefined) {
    throw new Error(`No lamb-chop paytable row for ${volatility} at ${hopCount} hop(s).`);
  }

  return multiplier;
}

// Use the revealed server seed (64 hex characters) and the client seed and nonce shown on the bet.
console.log(await verifyLambChopBet(
  'REVEALED_SERVER_SEED',
  'yeetdemo-7f3a91',
  '1842',
  'easy'
));