The operator cannot bias which holder wins. The server seed is committed before the window closes; the roll is HMAC-SHA-256 of the resolved slot hash keyed by that seed, walked over the weighted holder snapshot. Recompute it here and check the winner yourself — we never ask you to trust our outcome flag.
The widget re-runs the same HMAC-SHA-256 the worker ran, confirms the revealed seed hashes to the pre-window commit, and compares the published roll. If our published roll diverges from what your browser computes, the badge turns red. The reveal has not landed for this draw yet, so the verifier reports the seed as missing — that is the honest current state, not an error.
The roll lands once the target slot resolves on-chain: the operator reveals the committed server seed and the resolved slot hash. This verifier then re-checks everything in your browser.
An operational error voided this draw — no winner was named. The opened cards rolled forward to draw #938.
No packs were opened during this window
An operational failure (e.g. a reveal-block abort) aborted this draw — an error state, shown unedited, not a fair no-winner result. The opened cards rolled forward to draw #938.
import { createHmac } from 'node:crypto';
// Mirrors the draw-runner's roll derivation.
export function raffleRoll(
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 '0x' + mac.digest('hex');
}
// Map the roll into [0,1), then walk the holder snapshot's weight
// prefix-sum (sorted by address, Merkle-committed) — the first holder
// whose cumulative slice covers the offset wins the whole pot.Node ≥ 20 · no dependencies · same output as the browser widget.