One Last Time

Giveaway draw details and verification inputs for independent reproduction.

Published inputs

Entries count
1
Total weight
Entries hash (SHA-256)
549e10e5a3482ddf5259a0003c1e27004030f46c4024d6eaa072329cb2470f0b
Beacon source
https://drand.cloudflare.com/public/latest
Beacon round
5409056
Beacon value
cad3f625f7b47554eb6b070d8754d7db3c2b1af2e22ed6be4d75192b93a8b5e3
Seed
2cd40d75980fd3227f0551c5deac546942b5a61d40d112d345d87a4ad0a38c67
Drawn at (UTC)
2025-09-12T18:45:23.817Z
Winner entry id(s)
1efd8604-3512-4476-80f0-d7e8bfbefb63

Verification algorithm

Deterministic weighted selection using HMAC-SHA256 seeded randomness from SHA256(entries_hash + '|' + beacon_value). Each entry has a weight based on their total giveaway entries earned. Selection uses cumulative weight distribution to ensure fair proportional chances.

Verify this draw (Node.js)

Copy and run with Node 18+. Download the entries array separately to avoid cluttering this view.

Download as entries.json and place in same folder as verification script
// Node 18+
const crypto = require('crypto');

function sha256Hex(input) {
  return crypto.createHash('sha256').update(input).digest('hex');
}

function deterministicWeightedSelection(weightedEntries, seedHex, winnersCount) {
  const winningEntryIds = [];
  const usedEntries = new Set();
  const seedBytes = Buffer.from(seedHex, 'hex');
  
  for (let i = 0; i < winnersCount && usedEntries.size < weightedEntries.length; i++) {
    // Create a new seed for each selection to avoid patterns
    const selectionSeed = sha256Hex(seedBytes.toString('hex') + i.toString());
    const selectionSeedBytes = Buffer.from(selectionSeed, 'hex');
    
    // Generate deterministic random number (0-1) from seed
    const randomBytes = selectionSeedBytes.slice(0, 8);
    const randomValue = randomBytes.readBigUInt64BE(0);
    const maxBigInt = BigInt('0xFFFFFFFFFFFFFFFF');
    const normalizedRandom = Number(randomValue) / Number(maxBigInt);
    
    // Calculate cumulative weights for available entries
    const availableEntries = weightedEntries.filter(e => !usedEntries.has(e.uuid));
    const availableTotalWeight = availableEntries.reduce((sum, e) => sum + e.weight, 0);
    
    let targetWeight = normalizedRandom * availableTotalWeight;
    let cumulativeWeight = 0;
    
    for (const entry of availableEntries) {
      cumulativeWeight += entry.weight;
      if (targetWeight <= cumulativeWeight) {
        winningEntryIds.push(entry.uuid);
        usedEntries.add(entry.uuid);
        break;
      }
    }
  }
  
  return winningEntryIds;
}

// Load entries from downloaded file
const fs = require('fs');
const entries = JSON.parse(fs.readFileSync('entries.json', 'utf8'));

// Published inputs
const publishedEntriesHash = "549e10e5a3482ddf5259a0003c1e27004030f46c4024d6eaa072329cb2470f0b";
const beaconValue = "cad3f625f7b47554eb6b070d8754d7db3c2b1af2e22ed6be4d75192b93a8b5e3";
const publishedWinners = ["1efd8604-3512-4476-80f0-d7e8bfbefb63"];

// 1) Verify entries hash
const entriesHash = sha256Hex(JSON.stringify(entries));
if (entriesHash !== publishedEntriesHash) {
  console.error('Entries hash mismatch:', { entriesHash, publishedEntriesHash });
  process.exit(1);
}

// 2) Derive seed
const seed = sha256Hex(publishedEntriesHash + '|' + beaconValue);

// 3) Perform weighted selection and compare winners
const winners = deterministicWeightedSelection(entries, seed, publishedWinners.length);
console.log({ winners });
console.log('Matches published:', JSON.stringify(winners) === JSON.stringify(publishedWinners));

Note: We publish opaque entry IDs only. No user handles or PII are exposed.

Back to giveaways