Skip to Content
OopsIWon

Randomness Design

How winners are chosen and how you can verify it.

The draw is the heart of the raffle. This page explains the design goals, the source of randomness, how a random seed becomes a list of winners, and a worked example you can reproduce yourself.

Confirm the source before relying on this page

The randomness provider and the exact selection algorithm for each round are announced on OopsIWon.xyz and in the round's published draw transaction. The reference algorithm and example below show the method. Check that a round's published algorithm matches before you treat the example as a proof for that round.

Design goals

GoalWhat it means
UnpredictableNobody can know the result before the seed exists.
UnbiasableNeither the team, validators nor entrants can steer the seed.
Committed firstThe entry list is frozen before the seed is revealed.
VerifiableAnyone can recompute winners from public data.
EqualEvery entry has the same chance, regardless of purchase time or wallet.

Randomness source

Solana programs cannot safely use on-chain values such as slot or blockhash as randomness, because block producers can influence them. A raffle needs a dedicated randomness service whose output comes with a proof the program can check.

OptionHow it worksTrade-offs
Switchboard VRF / On-Demand randomnessOracle produces randomness with a verifiable proof, using a TEE-backed commit-reveal flow on Solana.Native to Solana, proof checked on-chain. Depends on the oracle network.
Pyth EntropyCommit-reveal between the requester and a provider, then combined into a seed.Simple model. Depends on provider honesty and liveness.
Other / multi-sourceFor example, combining several providers or a public beacon.Stronger against a single failure, more moving parts.

Source used by OopsIWon: to be published per round (the round announcement names the provider and links the randomness account).

The draw, step by step

Freeze the entry list

When the window closes, the program records the total number of entries N and the supply S. Entries are numbered 0 … N−1 in purchase order. No more entries can be added.

Request randomness

The program (or the keeper) requests a random seed after the list is frozen, so the seed cannot be chosen to favour known entries.

Receive and verify the seed

The randomness provider returns a 32-byte seed with a proof. The program verifies the proof on-chain and stores the seed in the raffle account.

Derive winners

Every entry gets a score derived from the seed. The S entries with the lowest scores win. Anyone can recompute this.

Settle

Winners mint, and all other entries are refunded. See Fund Flow.

Reference selection algorithm

score(i) = SHA-256( seed || u64_little_endian(i) )     for i in 0 .. N-1
winners  = the S entries with the smallest score(i)    (compared as bytes)

Properties:

  • Order independent: each entry's score depends only on the seed and its index.
  • Exactly S winners (or all entries, if N ≤ S).
  • No wallet bias: a wallet with k entries just holds k independent indices.
  • Ties are astronomically unlikely with a 256-bit hash, and broken by the lower index.

Worked example

Ten entries, three NFTs. The seed here is an arbitrary fixed value for demonstration.

supply S = 3
entries  N = 10

Alice  bought 2 entries  → indices 0, 1
Bob    bought 3 entries  → indices 2, 3, 4
Carol  bought 5 entries  → indices 5, 6, 7, 8, 9

seed = 00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff

First 8 bytes of SHA-256(seed || u64le(i)) for each index (hex):

Entry iOwnerScore (first 8 bytes)Rank
0Alice3c4856d9370e3d863rd → wins
1Aliceb5a7fbd3703b3e569th
2Bob8cf284af4df16b3f5th
3Bobb036d36db54f33488th
4Bob480f70eead8433544th
5Carol04141e87beca78d61st → wins
6Carola3b3315d070a29e66th
7Carola48f2c06765be9c17th
8Carold209c6a76bbadbad10th
9Carol28820453eb7621252nd → wins

Only the three lowest scores matter: entries ranked 1st to 3rd win.

Winning entries: 5, 9, 0.

WalletEntriesWinsRefunded entries
Alice21 (entry 0)1
Bob303
Carol52 (entries 5, 9)3

Verify it yourself

For a real round, replace seed, N and S with the on-chain values and compare your list with the published results.

Where to find the real values

Open the raffle account and the draw transaction linked from the round page on a Solana explorer.
Read the stored seed, total entries (N) and supply (S).
Run the script above with those numbers.
Compare with the Raffle Results page. They must match exactly.

See also Verify the Draw.

On this page