Automatic & Live Draws Free postal entry — equal chance Provably fair · 18+ · UK only
Open Verification

Draw Verification

WHACK AN ORK

Provably fair — cryptographic Draw complete

Draw complete — independently verifiable

This draw used a cryptographic commitment scheme. The draw secret was generated before ticket sales began, its sha256 hash (the commitment hash) was published, and the secret was only revealed after the draw. This proves the winner selection could not have been influenced by ticket sales.

Draw Result

Winner
Morris
Winning ticket
#1342
Entries in pool
444 (all entrants)
Winner index
235 (0-based)
Draw executed
24 Sep 2026, 8:31 PM
Entropy source
secrets.SystemRandom (instant-win positions at setup)
Fairness mechanism
SHA-256 commit-reveal — selection by sha256(legion-draw-v1:draw:draw_secret:pool_hash:drand_randomness:counter) rejection sampling

How This Result Was Produced

7 steps, each one checkable against the values published below. Nothing here depends on trusting us — every input is shown.

Verify commitment was published before the draw

This sha256 hash was published when the competition was created. It proves the draw_secret could not have been changed after tickets were sold.

ec937576a15bca51ebe3ba7eb32f5714a88f4fe434d54541ee8c10f4d86cbb2e

Verify the pool-freeze commitment was published before the beacon round

sha256 of the exact UTF-8 string 'legion-draw-v1:pool_freeze:' + pool_hash + ':' + drand_chain_hash + ':' + str(round_number) — colon-separated, no spaces, no trailing newline. Published before the targeted round resolved, it pins both the entry pool and the round while the round's randomness was still unknowable. Rebuild it from this page's published values with the command below.

c576b5a73d5a6ddadfaad2836ef7abaeb115bb0e55351b7147325b5bd51b9c64
python3 -c "import hashlib; print(hashlib.sha256('legion-draw-v1:pool_freeze:7c7fe622cf8917a5c59b5c80a70401d3da854ae57b2257cfb0af54429223f171:52db9ba70e0cc0f6eaf7803dd07447a1f5477735fd3f661792ba94600c84e971:32491622'.encode()).hexdigest())"

Verify draw_secret matches commitment_hash

The draw_secret is revealed below. sha256(draw_secret) is shown — it must equal the commitment_hash in step 1.

draw_secret (input)

43796fea7e72d983a256fd6f6c0c078e27352d449d245b40dc8f5e09659b93bc

sha256(draw_secret) must equal step 1

ec937576a15bca51ebe3ba7eb32f5714a88f4fe434d54541ee8c10f4d86cbb2e

Verify the entry pool hash

sha256 of every ticket number in the draw pool, in ascending numeric order, joined with commas and no spaces.

7c7fe622cf8917a5c59b5c80a70401d3da854ae57b2257cfb0af54429223f171

Verify the drand beacon randomness

Round 32491622 of the public drand randomness beacon (chain 52db9ba70e0cc0f6eaf7803dd07447a1f5477735fd3f661792ba94600c84e971). This value is published independently by multiple operators and could not have been known when the pool above was frozen. Check it yourself: fetch https://api.drand.sh/52db9ba70e0cc0f6eaf7803dd07447a1f5477735fd3f661792ba94600c84e971/public/32491622, hex-decode the response's 'signature' field into raw bytes, then compute sha256 of those bytes — it must match the value shown here. (Hashing the ASCII hex text of the signature instead of the decoded bytes gives a different, wrong answer.) The command below does exactly that.

36246fc10684e2c77b7f4170687f9454392edddf7da02820ef019388e4c5e28b
python3 -c "import hashlib, json, urllib.request; r = json.load(urllib.request.urlopen('https://api.drand.sh/52db9ba70e0cc0f6eaf7803dd07447a1f5477735fd3f661792ba94600c84e971/public/32491622')); print(hashlib.sha256(bytes.fromhex(r['signature'])).hexdigest())"

Verify the beacon's BLS signature

Before accepting the randomness above, the platform checked drand's BLS12-381 signature for this round against this chain public key — a relay can withhold a round but cannot forge one without drand's private key. Fetch the round's 'signature' field from the URL above and verify e(H(round_bytes), public_key) == e(signature, G2_generator) yourself with any BLS12-381 library; source: https://drand.love/developer/http-api/.

83cf0f2896adee7eb8b5f01fcad3912212c437e0073e911fb90022d3e760183c8c4b450b6a0a6c3ac6a5776a2d1064510d1fec758c921cc22b0e17e63aaf4bcb5ed66304de9cf809bd274ca73bab4af5a6e9c76a4bc09e76eae8991ef5ece45a

Reproduce the winner selection (rejection sampling)

Starting at counter=0, compute sha256(f'legion-draw-v1:draw:{draw_secret}:{pool_hash}:{drand_randomness}:{counter}') as a 256-bit integer. Let limit be the largest multiple of N below 2^256. If the value is >= limit, increment counter and retry. Otherwise winner_index = value mod N.

counter=0, winner_index=235

Check It Yourself

Run every check in your own browser. It recomputes the hashes and the winner selection locally from the values published on this page, and fetches the drand round directly from the public relays — nothing is sent to our servers, so a pass cannot depend on trusting us.

  1. Confirm sha256(draw_secret) equals the commitment hash in step 1.
  2. Confirm the sha256 of the entry pool below equals the pool hash in step 3. Hash the text exactly as shown — ticket numbers in ascending numeric order, separated by commas, with no spaces and no trailing newline.

    Entry pool — ticket numbers in ascending numeric order

    6,10,16,19,20,23,24,26,37,39,44,49,50,53,71,74,79,105,106,109,110,112,120,121,123,141,142,148,169,171,174,176,178,179,183,186,189,193,205,213,215,216,218,220,222,239,242,245,256,257,264,267,268,270,283,286,299,304,306,309,315,316,320,325,326,330,334,336,338,339,349,354,356,360,361,380,386,388,397,400,402,407,421,427,429,432,433,434,441,463,466,468,475,506,509,510,522,523,527,530,545,548,558,577,589,590,592,593,597,607,612,619,632,637,638,652,658,667,668,669,677,680,681,682,683,692,697,698,705,706,709,719,729,733,734,742,747,748,751,753,754,756,758,762,768,771,772,780,784,788,800,801,817,818,829,832,841,844,848,856,865,873,885,889,892,893,919,921,929,931,932,935,940,941,952,960,964,965,967,977,978,983,988,989,992,994,995,998,1005,1021,1024,1036,1038,1048,1049,1052,1055,1060,1066,1071,1073,1083,1087,1093,1096,1100,1116,1119,1126,1128,1130,1139,1140,1143,1145,1158,1160,1161,1178,1199,1201,1212,1218,1233,1235,1252,1256,1259,1297,1301,1302,1303,1309,1311,1316,1342,1344,1347,1353,1357,1359,1360,1363,1364,1368,1369,1373,1386,1387,1397,1400,1403,1407,1413,1423,1427,1428,1429,1430,1432,1440,1443,1455,1462,1463,1472,1475,1477,1486,1487,1500,1501,1511,1516,1524,1527,1536,1547,1551,1553,1557,1558,1562,1569,1583,1589,1591,1598,1601,1603,1606,1619,1626,1633,1634,1636,1644,1645,1647,1650,1666,1681,1690,1703,1705,1713,1714,1726,1733,1740,1741,1747,1748,1751,1754,1770,1776,1783,1785,1791,1798,1804,1805,1809,1814,1817,1827,1830,1831,1838,1840,1844,1848,1856,1858,1861,1862,1866,1867,1869,1877,1879,1883,1884,1889,1897,1906,1909,1910,1914,1916,1918,1929,1930,1935,1937,1947,1952,1955,1962,1970,1979,1988,1989,1995,2004,2005,2006,2009,2021,2033,2034,2040,2044,2051,2054,2063,2064,2078,2086,2100,2122,2131,2151,2154,2158,2163,2171,2172,2173,2177,2183,2185,2191,2195,2201,2208,2224,2236,2250,2253,2255,2260,2270,2281,2287,2288,2289,2290,2298,2300,2302,2305,2306,2315,2332,2339,2344,2345,2346,2348,2356,2363,2367,2369,2386,2394,2399,2404,2407,2422,2423,2431,2432,2442,2443,2450,2455,2457,2472,2477,2487,2488,2496
  3. Run the pre-filled command below to reproduce the beacon-seeded rejection-sampling winner index (counter=?, expected winner_index=235). This folds in the drand beacon randomness from the step above alongside the draw secret and pool hash, so the winner could not have been known until that round resolved.
    python3 - <<'PY'
    import hashlib
    draw_secret = '43796fea7e72d983a256fd6f6c0c078e27352d449d245b40dc8f5e09659b93bc'
    pool_hash = '7c7fe622cf8917a5c59b5c80a70401d3da854ae57b2257cfb0af54429223f171'
    beacon_randomness = '36246fc10684e2c77b7f4170687f9454392edddf7da02820ef019388e4c5e28b'
    total_entries = 444
    counter = 0
    limit = (1 << 256) - ((1 << 256) % total_entries)
    while True:
        seed = hashlib.sha256(f'legion-draw-v1:draw:{draw_secret}:{pool_hash}:{beacon_randomness}:{counter}'.encode()).digest()
        candidate = int.from_bytes(seed[:32], 'big')
        if candidate < limit:
            print(f'counter={counter} winner_index={candidate % total_entries}')
            break
        counter += 1
    PY

Full Entry List

All sold tickets with entry method (no personal names). This competition had no engagement question, so the file carries no answer column. Download it to cross-reference ticket numbers against the draw pool; the "In Main Draw" column marks which rows formed it.

Download entry list CSV

Independent Timestamp Proof

Each commitment hash is anchored to the Bitcoin blockchain via OpenTimestamps. A confirmed proof establishes the hash existed before the Bitcoin block that attests it — checkable without trusting our records. Save the commitment hash to a file and check the proof with the free ots tool: printf '%s' 'COMMITMENT_HASH' > commitment.txt && ots verify -f commitment.txt proof.ots

Draw commitment — anchored in Bitcoin 11 Sep 2026 02:04 UTC

ec937576a15bca51ebe3ba7eb32f5714a88f4fe434d54541ee8c10f4d86cbb2e Download OTS proof

Instant win commitment — anchored in Bitcoin 11 Sep 2026 02:04 UTC

55ffe78c68122df479b6518eda7fadf6b9987b9e134df97a121f3feadbdac57e Download OTS proof

Pool freeze commitment — anchored in Bitcoin 24 Sep 2026 23:05 UTC

c576b5a73d5a6ddadfaad2836ef7abaeb115bb0e55351b7147325b5bd51b9c64

What this proof does and does not show: Bitcoin confirmation takes hours, while the targeted drand round resolves seconds after the pool freeze — so a confirmed proof here demonstrates the pool-freeze commitment existed before its attesting block, not that the freeze happened before the drand round. The freeze-before-round ordering rests on the commitment having been published before the round resolved (step 2 above) and on our audit records.

Download OTS proof