BitRaffleDocs

Run competitions

How raffle draws work

Competition winners are drawn on the raffle contract on Arbitrum One with Chainlink VRF: randomness that comes with a cryptographic proof, which nobody can predict or choose. That includes us.

Entries close at the end time commitDraw ledger root + total Chainlink VRF random word + proof Winner seed mod total Every step is a transaction on the raffle contract, readable on the block explorer.
  1. Entries close

    At the competition's end time, sales stop. No draw can start before then.

  2. The ledger is committed

    We commit the full ticket ledger to the contract: a hash of every ticket in order, card-paid tickets included, and the total count. From this point the list the winner is drawn from cannot change.

  3. Chainlink delivers randomness

    The commit asks Chainlink VRF for a random number. Chainlink returns it with a proof the contract checks before accepting it. A pending request cannot be replaced by a new one until it has clearly failed, so a draw cannot be re-rolled.

  4. The contract picks the winner

    winnerIndex = randomWord mod totalTickets. The index points into the committed ledger, and the ticket at that position wins.

Check a draw yourself

Each published winner carries the draw's details. Find the DrawFinalized event for the competition on the block explorer, and check that the seed and index match.

curl https://www.bitraffle.io/api/v1/winners \
  -H "Authorization: Bearer $BITRAFFLE_SECRET_KEY"
const res = await fetch("https://www.bitraffle.io/api/v1/winners", {
  headers: { Authorization: `Bearer ${process.env.BITRAFFLE_SECRET_KEY}` },
});
const { data } = await res.json();
import os, requests

res = requests.get(
    "https://www.bitraffle.io/api/v1/winners",
    headers={"Authorization": f"Bearer {os.environ['BITRAFFLE_SECRET_KEY']}"},
)
data = res.json()["data"]
Response
{
  "data": [
    {
      "competitionId": 61,
      "competitionTitle": "Win a Rolex Datejust 41",
      "winnerWalletAddress": "0x7Fb6…2e19",
      "wonAt": "2026-09-30T14:02:11.000Z",
      "draw": {
        "method": "vrf",
        "seed": "0x5c1e…9a04",
        "winnerIndex": 1287,
        "totalTickets": 2600,
        "vrfRequestId": "8841…2203",
        "fulfillmentTx": "0x2b7d…c1f0",
        "blockNumber": null
      }
    }
  ]
}
FieldMeaning
methodvrf for Chainlink VRF draws. Older draws show blockhash.
seedThe random word Chainlink delivered.
winnerIndexseed mod totalTickets: the winning position in the ledger.
totalTicketsHow many tickets the committed ledger holds.
vrfRequestIdThe Chainlink request, traceable on Chainlink's explorer.
fulfillmentTxThe transaction that delivered the randomness.