Memoraloo

Don't trust us. Verify us.

Verify this draw.

Tom Brady New England Patriots Autographed Nike Navy Color Rush Elite Jersey with SB 36 38 39 49 51 53 Champs InscriptionCommitment publishedStatus seed sealed until drawBack to competition ↗
  1. The commitment

    Published before any entry was sold

    We generated a secret server seed and published its SHA-256 hash the moment this competition opened. Changing the seed afterwards would break the hash — publicly and permanently.

    SHA-256 commitment
    385fe9fcec1d48013802ff11b56e9ddfacd109f0837bb1f4824b9017fc562d45
  2. The public entrant list & client seed

    Snapshotted and published at the draw

    Ticket numbers are allocated at random within the fixed pool of 100,000 — which numbers you hold never changes your odds (tickets held ÷ tickets sold). The draw selects a position among valid sold tickets, so an unsold number can never win. The full ticket list is public: ticket numbers (JSON) — live until the draw snapshots it (refunded entries drop out, per the terms).

    The client seed is the SHA-256 of slug:entryCount:listHash:closesAt where listHash is the SHA-256 of that exact ticket list — the outcome is bound to the published entrant set, and the seed behind it was committed before a single ticket was sold.

  3. The result

    Awaiting draw

    This competition has not been drawn yet. The server seed stays sealed until the draw — it will be revealed here, next to the commitment above, so the two can be checked against each other.

  4. Recompute it yourself

    Any machine, ~5 lines

    Run this in Node.js with the revealed values — it must print the published hash and the same winning entry:

    const { createHash, createHmac } = require("crypto");
    const sha256 = (s) => createHash("sha256").update(s).digest("hex");
    
    // numbers = the published list at /api/verify/<slug>/numbers
    const sorted = [...numbers].sort((a, b) => a - b);
    const entryCount = sorted.length;
    
    // 1. Check the commitment and the ticket-list hash
    console.log(sha256(serverSeed));          // must equal the published hash
    const listHash = sha256(sorted.join(",")); // must equal the published one
    const clientSeed = sha256(`${slug}:${entryCount}:${listHash}:${closesAt}`);
    
    // 2. Recompute the winning position
    const key = ["DRAW", slug, serverSeed, clientSeed, entryCount].join("-");
    const hmac = createHmac("sha256", key).digest("hex");
    const value = parseInt(hmac.slice(0, 13), 16);
    const position = Math.floor((value / 2 ** 52) * entryCount) + 1;
    
    // 3. The winner is the position-th ticket, ascending
    console.log("Winning ticket:", sorted[position - 1]);