POWERGACHA
FAIRNESS COMMIT-REVEAL

Built so nobody - including us - can rig it.

The operator cannot bias which holder wins. The result is reproducible by anyone who downloads the snapshot. Every value used in the roll exists on a public ledger before it is used.

FOUR STEPS - ONE VIEWPORT
Commit > Snapshot > Reveal > Roll
  1. Commit
    We publish SHA-256 of the seed before the window opens
    A 256-bit server seed is generated and its hash lands as an SPL memo on the project wallet before the draw goes live. SHA-256 collisions are not feasible.
    memo: SHA-256(serverSeed) > on-chain
  2. Snapshot
    Every holder balance is recorded at the close slot
    When the window closes we record a Merkle root of every eligible $GACHA balance at that exact Solana slot. Nobody touches your balance — we just take a tamper-evident snapshot. The root ships in the reveal memo so anyone can re-derive it.
    snapshotMerkleRoot = MerkleRoot(holders[closeSlot])
  3. Reveal
    We publish the seed itself
    Once the slot lands we reveal the serverSeed plus the snapshotMerkleRoot. Anyone hashes the seed to confirm it matches the commit.
    memo: serverSeed ‖ snapshotMerkleRoot
  4. Roll
    HMAC-SHA-256 picks the winner
    The roll is HMAC(seed, slotHash ‖ drawId). We walk the prefix-sum of weights with roll mod T > first holder whose slice covers the offset wins.
    roll = HMAC-SHA-256(seed, slotHash ‖ drawId)
SECTION 02

Recompute the roll. Right here. In your browser.

The widget loads three shipped draws and runs the same HMAC-SHA-256 routine the worker runs. The proof is the recompute - if our published roll does not match the one your browser computes, the badge turns red.

● COMMIT-REVEAL VERIFIER
Paste a draw id. Recompute the roll in your browser.

Try #647, #645, #642

Enter a draw id to verify.
REFERENCE IMPLEMENTATION

Copy-paste. Run it locally. Same answer.

import { createHmac } from 'node:crypto';

export function rollFromSeed(
  serverSeedHex: string,
  slotHashHex: string,
  drawId: number,
): string {
  const mac = createHmac('sha256', Buffer.from(serverSeedHex, 'hex'));
  mac.update(Buffer.from(slotHashHex, 'hex'));
  mac.update(Buffer.from(String(drawId), 'utf8'));
  return mac.digest('hex');
}

Node ≥ 20 - no dependencies - same output as the browser widget.

SECTION 03

What we cannot do