WSU Alumni

Giveaway draw details and verification inputs for independent reproduction.

Published inputs

Entries count
63
Total weight
749
Entries hash (SHA-256)
958d4782fdcdc177210ffe575ae5a7093311689bc622653606b1058e76d0fdef
Beacon source
https://drand.cloudflare.com/public/latest
Beacon round
6178217
Beacon value
ac5caa1a23ff68c47710e3df9ec83e6c5fa9cb81fb033312827b901eb3cd227a
Seed
e04ec5505634dd2d095a3591f8184cc58d1567acfd91eca600a6a65e82b9cdbb
Drawn at (UTC)
2026-06-06T20:25:45.416Z
Winner entry id(s)
313aab76-b05e-4899-a263-9af1f8338b96

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 = "958d4782fdcdc177210ffe575ae5a7093311689bc622653606b1058e76d0fdef";
const beaconValue = "ac5caa1a23ff68c47710e3df9ec83e6c5fa9cb81fb033312827b901eb3cd227a";
const publishedWinners = ["313aab76-b05e-4899-a263-9af1f8338b96"];

// 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