Zum Hauptinhalt springen
All posts
TransparencyRaffleFairnessSecurity

How Transparent Raffles Work: The Winbase Approach Explained

Winbase Team·31 May 2026·8 min read

What makes an online raffle truly fair?

Many online giveaways claim to be fair — but can they prove it? At Winbase, the answer is a clear yes. Every draw on our platform is fully reproducible and verifiable by anyone. No operator, no creator, and no secret algorithm stands between you and the result.

The process: From entry to draw

1. Participation phase

While a raffle is active, users can enter. All participants are publicly visible with timestamps, in chronological order. There are no hidden participants.

2. Freezing the participant list

Once a raffle ends, the participant list is frozen. No changes are possible afterwards — neither by Winbase nor by the creator.

As a cryptographic proof of integrity, Winbase immediately computes a participant list hash: SHA-256 of all participant IDs in draw order (sorted by registration timestamp). This hash is published in the public draw proof. If even a single participant were added, removed, or reordered after this point, the hash would change completely — visible to anyone who checks.

3. External entropy: What is a Bitcoin block hash?

The critical random value does not come from Winbase — it comes from the Bitcoin network. Every Bitcoin block contains a cryptographic hash: a 64-character hexadecimal number computed from the entire block contents. This hash is:

  • Public: Anyone can look it up on blockchain explorers like blockstream.info
  • Unpredictable: No miner and no company can compute the hash of a future block in advance
  • Outside Winbase's control: The Bitcoin network is decentralized and independent

At draw time, Winbase uses only the first Bitcoin block whose timestamp falls after the raffle's end time. Because that block was only mined after the raffle closed, its hash was not yet public when the last participant joined — ruling out any advance knowledge of the entropy value. Which block is used is fully determined before the draw, with no room for Winbase to make a choice.

4. Seed generation

Winbase combines four public factors into a unique seed:

Factor Meaning
Raffle ID Unique identifier for this raffle
Participant count Size of the frozen list
Last participant timestamp Final entry in the list
Bitcoin block hash External, neutral source of randomness

These four values are joined as a string and run through the SHA-256 algorithm. The result is a deterministic hex string.

seed_input = "raffle-id:47:2026-05-11T13:00:00Z:0000000000abc123..."
seed_hash  = SHA-256(seed_input)

There are no hidden inputs, no secret salts, and no internal random values. All components are published.

5. Winner selection

A numeric index is derived from the seed:

index = BigInt("0x" + seed_hash) % BigInt(participantCount)
winner = participants[index]

The participant list is sorted by registration timestamp (participated_at ascending) — deterministic and traceable by anyone. The index always points to the same person.

6. Publishing the draw proof

After the draw, the complete Draw Proof is displayed publicly on the result page:

  • All seed components (raffle ID, participant count, last timestamp)
  • Bitcoin block hash + block height
  • Computed SHA-256 seed
  • Winner index in the participant list
  • SHA-256 hash of the frozen participant list (participants_hash)
  • Winner profile

The built-in verification button lets you recalculate the entire draw in your browser in seconds.

Manipulation protection: All known attack vectors

Transparency does not just mean "the algorithm is known" — it also means being honest about potential weaknesses and explaining how they are closed. Here are the five relevant attack vectors and how Winbase prevents them:

Attack vector 1: Reordering the participant list after the fact

The problem: If the operator could still change the sort order of participants before the draw, they could deliberately control who sits at index i — and therefore who wins.

The solution: The participant list hash (participants_hash) proves list integrity. SHA-256 of all participant IDs in exact draw order is computed at freeze time and published. Any change in order would visibly alter the hash. The sort order is immutable: participated_at ASC.

Attack vector 2: Adding or removing participants after the deadline

The problem: If accounts could be inserted or deleted after the entry deadline, the list length would change — and with it, the winner via index = seed % n.

The solution: Two independent protection layers apply simultaneously. First, a hard database constraint blocks writes to raffle_participants once status = 'drawn' is set. Second, the participants_hash in the draw proof would no longer match the published participant list — a contradiction that any third party can immediately spot.

Attack vector 3: Freely choosing the Bitcoin block

The problem: If the operator could test several available block hashes after the raffle ends and pick the "favorable" one, the external entropy would no longer be neutral.

The solution: The block selection is deterministic and fully defined in advance: always the first Bitcoin block whose timestamp falls after ends_at. No human and no code at Winbase makes a decision about the block. Whoever runs the draw — a cron job, an API call, or an independent third party — gets exactly the same hash.

Attack vector 4: Adding hidden seed inputs

The problem: If the operator included secret values (a private salt, a hidden random number) in the seed calculation, they could test combinations until a desired winner emerges.

The solution: All seed inputs are public and visible in the draw proof: raffle ID, participant count, last timestamp, Bitcoin block hash. The formula is known. There are no hidden parameters. Anyone can compute the same SHA-256 hash using exactly these four values.

Attack vector 5: Inconsistent sorting of the participant list

The problem: If the list displayed in the frontend were sorted by time, but the internal calculation list sorted by UUID, the draw would be mathematically correct but not reproducible by users.

The solution: Frontend and backend use exactly the same sort order: registration timestamp ascending (participated_at ASC). The participants_hash in the draw proof is the hash of precisely this sorted list. The participant pool on the result page displays the same order — including index numbers, so everyone can follow participants[index].

Why this approach is fair

Trust is good — verifiability is better.

Three guarantees apply to every Winbase raffle:

Winbase cannot manipulate the result. The Bitcoin block hash is unpredictable and uncontrollable. All other seed inputs are public and immutable after the entry deadline.

The creator cannot interfere. After the raffle ends, the participant list and draw proof are stored immutably in the database. Edits are blocked by database constraints.

Anyone can recalculate the draw. All inputs are public. Anyone with a SHA-256 tool can compute the same result — and with the participants_hash, additionally verify that the displayed participant list is identical to the one used.

How to verify yourself

Visit any completed raffle and expand the Draw Proof section. You will see all input parameters and can calculate everything yourself:

import hashlib

# Step 0: Verify participant list hash
participants = ["user_id_1", "user_id_2", "user_id_3"]  # from the draw proof
ph = hashlib.sha256(":".join(participants).encode()).hexdigest()
print("Participants hash:", ph)  # must match participants_hash in the proof

# Step 1: Compute seed
seed_input = "raffle-123:3:2026-03-15T12:00:00Z:0000000000abc123def456"
seed = hashlib.sha256(seed_input.encode()).hexdigest()
print("Seed:", seed)

# Step 2: Derive winner index
index = int(seed, 16) % len(participants)
print("Winner:", participants[index])

Alternatively, directly in the browser (F12 → Console):

// Step 0: Verify participant list hash
const participants = ["user_id_1", "user_id_2", "user_id_3"];
const phBuf = await crypto.subtle.digest('SHA-256', new TextEncoder().encode(participants.join(':')));
const pHash = Array.from(new Uint8Array(phBuf)).map(b => b.toString(16).padStart(2,'0')).join('');
console.log('Participants hash:', pHash);

// Step 1: Compute seed
const input = "raffle-123:3:2026-03-15T12:00:00Z:0000000000abc123def456";
const buf = await crypto.subtle.digest('SHA-256', new TextEncoder().encode(input));
const seed = Array.from(new Uint8Array(buf)).map(b => b.toString(16).padStart(2,'0')).join('');
const index = Number(BigInt('0x' + seed) % BigInt(participants.length));
console.log('Seed:', seed);
console.log('Winner:', participants[index]);

The built-in "Verify now" button in the draw proof runs exactly this calculation in your browser — including the participants_hash check.

Why the post-end block matters

Bitcoin block hashes are unpredictable — but a block mined before the raffle closed was already public at that point. In theory, someone could use that information to time their entry strategically.

Winbase addresses this by using only the first block mined after the raffle ends. That block does not yet exist when the last participant joins, so its hash cannot be known or calculated by anyone in advance. The fairness guarantee holds unconditionally.

Conclusion

Transparent raffles are not magic — they just require a commitment to openness. Winbase enforces this standard for every raffle on the platform:

  • External, uncontrollable randomness from the Bitcoin network
  • Cryptographic proof of the frozen participant list (participants_hash)
  • All seed inputs public and fully verifiable
  • Deterministic, pre-defined Bitcoin block — no selection possible
  • Consistent sort order in frontend and backend

Fairness at Winbase is not a marketing claim; it is verifiable reality.


Have questions? Check out our How it works page or join an active raffle and follow the draw live.