Snappicks' Commitment to E-Commerce Fairness & Technical Whitepaper

Last updated: July 2026

To Our Users, Community, and Ecosystem Partners:

Welcome to Snappicks. In our innovative e-commerce community, we are dedicated to providing a gamified shopping experience where every everyday consumer has the chance to obtain high-value products, such as an iPhone, at a remarkably low threshold.

However, we are fully aware that when low cost meets high value, skepticism naturally follows: "Is this just a marketing gimmick?" "Are the items going to internal bot accounts?" "Can normal users really compete against scalpers and automated scripts?"

As a world-class engineering team, Snappicks believes that the best way to eliminate doubt is not through PR promises, but through mathematical proof and verifiable code.

To achieve this, we have entirely discarded the black-box marketing tools used by traditional e-commerce platforms. Instead, we have built from the ground up a Verifiable Fairness Architecture designed to withstand hacker exploits, penetration testing, and rigorous cryptographic scrutiny, ensuring that every flash sale draw is absolutely pure.


1. Provably Fair Random Draw

The fundamental question every participant asks is: "Was the winner chosen fairly?" Our answer is a deterministic, reproducible random selection algorithm that anyone can independently verify.

1.1 Seed Generation

Before a flash sale opens to the public, the server generates a high-entropy random seed using Node.js crypto.randomUUID() — a cryptographically secure random number generator backed by the operating system's entropy pool. The seed looks like this:

550e8400-e29b-41d4-a716-446655440000

The seed is immediately hashed (SHA-256) and the hash is published before ticket sales begin. The seed itself remains secret until the draw completes.

Why not publish the seed upfront?

If the seed were public before the draw ended, anyone could plug it into the ChaCha20 + Fisher-Yates algorithm and compute the winning positions in advance. This would destroy the suspense of the draw and invite targeted manipulation — for instance, an attacker who knew they would win could buy just one ticket, while others who knew they would lose would have no reason to participate.

Why is it safe to keep the seed secret?

The seed is a UUID v4, which contains 122 bits of cryptographically random data (6 bits are reserved for version/variant markers). The total search space is 2^122 ≈ 5.3 × 10^36 — a number so large that even if every computer on Earth were dedicated to guessing seeds, the heat death of the universe would arrive before a single collision was found. The seed is not guessable, not predictable, and not brute-forceable.

Crucially, even though the seed is hidden during the sale, the platform cannot swap it later: the SHA-256 hash was timelocked by an independent third-party TSA before anyone bought tickets (§2). When the seed is finally revealed after the draw, anyone can verify SHA-256(seed) == published seedHash — confirming that this was the same seed all along.

1.2 ChaCha20 PRNG — Why Not Math.random()

Many lottery systems use simple pseudo-random number generators like Math.random() or seedrandom, which suffer from short periods and are vulnerable to brute-force prediction. We use ChaCha20 (RFC 8439), a well-audited stream cipher that has undergone years of cryptographic scrutiny.

We chose ChaCha20 over simpler alternatives for several reasons:

Propertyseedrandom (our old V1)ChaCha20 (V2)
Internal stateVaries by implementation256-bit key derived from seed via SHA-256
AlgorithmAd-hoc, no formal standardWell-audited stream cipher used in TLS 1.3
Cross-platform reproducibilityDepends on matching the exact npm package versionDeterministic given the same seed (matching Node.js chacha20 cipher mode)
Resistant to predictionState can be recovered from observed outputsKey stream is computationally indistinguishable from random

The ChaCha20 key stream is generated by encrypting blocks of zeros using Node.js's built-in crypto.createCipheriv("chacha20", key, iv). Each 4-byte segment of the key stream is read as a little-endian unsigned 32-bit integer and divided by 2³² to produce a uniformly distributed float in [0, 1).

1.3 Fair Selection — Fisher-Yates Shuffle

Once we have a deterministic RNG, we need to select M winning positions out of N total tickets with equal probability for every position. This is accomplished by a Fisher-Yates partial shuffle:

For i = 0 to M-1:
    rangeSize = N - i
    randomInt = floor(RNG() * rangeSize)
    swap position[randomInt] with position[rangeSize - 1]
    record position[randomInt] as a winning index

This algorithm is mathematically proven: every ticket has exactly the same probability M/N of being selected. There is no modulo bias, and the selection is unbiased regardless of purchase order or ticket quantity. The ChaCha20 key stream ensures that the exact same seed always produces the exact same winning numbers — making the result 100% reproducible.

1.4 Ticket Pool Construction

Each flash sale has a fixed total number of tickets (maxEntries, e.g., 1,000). When a user purchases tickets:

  1. The purchase is recorded as an entry with a unique Snowflake ID (chronologically ordered) and a sequential ticket range (startIndex to endIndex).
  2. All entries are sorted by startIndex (ascending). Each ticket within an entry's range is expanded into a string of the form:
{entryId}_{index with zero-padding}

The zero-padding width is determined by maxEntries: if a flash sale has 1,000 total tickets, the width is 4 digits. Tickets are numbered starting from 1 — ticket 5 becomes 0005; ticket 42 becomes 0042.

  1. The complete list is serialized as a JSON array (no whitespace, compact form) — this is what appears in the proof bundle and is hashed to produce entriesHash.

For example, a flash sale with 1,000 tickets (padLength = 4):

[
  "189392093232_0001",
  "189392093232_0002",
  "189392093232_0003",
  "189392094410_0004",
  "189392094410_0005",
  ...
]

Here, User A (entry 189392093232) purchased 3 tickets first and occupies ticket numbers 1–3; User B (entry 189392094410) purchased 2 tickets later and occupies numbers 4–5.

The Fisher-Yates shuffle selects M unique ticket numbers from this pool. For example, if winningNumbers = [4, 1], then User B wins prize 1 and User A wins prize 2. The pool ordering is deterministic (by entry creation time = chronological order), so anyone can reconstruct it from the published data.


2. Tamper-Proof Timestamp Protocol

A deterministic draw algorithm is only meaningful if the seed and ticket list cannot be manipulated. This is where our two-step RFC 3161 TSA (Trusted Timestamp Authority) protocol comes in.

2.1 What Tamper-Proofing Prevents

A deterministic draw algorithm is only trustworthy if the inputs to that algorithm cannot be manipulated. Our TSA two-step signing protocol is specifically designed to prevent three classes of attack:

Attack 1 — Seed Fishing (Brute-Forcing the Winning Seed)

A dishonest platform could, after seeing all ticket purchases, secretly generate thousands of different seeds and run each one through the ChaCha20 + Fisher-Yates algorithm. For each seed, they check which tickets would win. If they find a seed that gives the prize to a chosen ticket (e.g., an insider's or a friend's), they could quietly use that seed for the draw.

How TSA prevents this: The commit.tsr timestamp proves that seedHash was locked by the TSA before ticket sales opened. After the draw, the platform must reveal the actual seed. Anyone can compute SHA-256(seed) and verify it matches the hash that was published before anyone bought tickets. The platform cannot retroactively swap the seed — doing so would produce a different hash that doesn't match the timestamped commitment.

Attack 2 — Prize Swapping After the Draw

Between the time ticket sales close and the time results are publicly announced, a dishonest platform could modify the prize configuration — for example, replacing an expensive prize (iPhone) with a cheaper one (phone case), or changing the prize quantity so fewer people win. Since prizes determine not only what winners receive but also how many tickets are selected (one index per prize quantity unit), changing prizes changes the entire outcome.

How TSA prevents this: The prize configuration (name, price, quantity) is hashed together with seedHash in the commit signature. The same commit.tsr that locks the seed also locks the prizes. If the platform later tries to claim different prizes were offered, the digest wouldn't match the hash embedded in the TSA timestamp.

Attack 3 — Tampering with the Entry List

After entries close, a dishonest platform could modify the participant list — inserting ghost entries to create fake winners, or deleting real entries to exclude legitimate participants. Since the winning positions are selected from the complete ticket pool (by index), any change to the entry list would alter who wins.

How TSA prevents this: The complete ticket list (every entryId_index, sorted by position) is hashed and its digest is embedded in the reveal.tsr signature, chained to the original commit.tsr. The platform publishes the full entries list in the proof bundle, and anyone can verify SHA-256(entries) == entriesHash and that the hash matches the TSA timestamped value. If a user's ticket is missing from the published list, they hold their own ticket number as evidence.

Crucially, the proof bundle makes the draw fully reproducible. By publishing the seed, the complete entry list, and the winning numbers, any third party can independently re-run the entire ChaCha20 + Fisher-Yates algorithm and confirm the outcome. The platform cannot fabricate results — every step is cryptographically locked and publicly verifiable.

2.2 How TSA Two-Step Signing Solves This

We leverage independent third-party Timestamp Authorities — the same cryptographic infrastructure used by banks, governments, and certificate authorities worldwide. The process works in two steps:

Step 1 — Commit (Before Ticket Sales)

1. Generate seed (randomUUID)
2. Compute seedHash  = SHA-256(seed)
3. Build prizes digest — for each prize, extract `{ id, name, price, quantity }`, sort by id
4. Compute prizesHash = SHA-256(compact JSON of prizes digest)
5. Compute msgImprint = SHA-256(seedHash + "\n" + prizesHash)
6. Submit msgImprint to independent TSA → receive cryptographically signed timestamp token (commit.tsr)
7. Upload commit.tsr to public storage (Cloudflare R2)
8. Publish the download URL — anyone can access it

The TSA is an independent third party (DigiCert, Microsoft, Apple, GlobalSign). The timestamp on commit.tsr proves that seedHash and prizesHash existed before ticket sales opened — the platform could not have changed the seed or prizes after anyone bought tickets.

Step 2 — Reveal (After Entries Close & Draw Completes)

1. Build the complete ticket list (all entries, sorted by index)
2. Compute entriesHash = SHA-256(JSON.stringify(ticketList))
3. Download commit.tsr from public storage
4. Compute msgImprint = SHA-256(seed + "\n" + entriesHash + "\n" + hex(commit.tsr))
5. Submit msgImprint to TSA → receive reveal.tsr
6. Upload reveal.tsr + proof-bundle.json to public storage

The reveal.tsr timestamp proves that:

2.3 Why TSA Verification Guarantees Fairness

Attack ScenarioWhy It Fails
Swap seed after seeing participantscommit.tsr timestamp proves seedHash existed before sales — any different seed produces a different hash
Claim a different seed was usedreveal.tsr includes the seed plaintext, chained to commit.tsr via its hex content
Add fake ghost ticketsreveal.tsr locks entriesHash — any addition changes the hash
Remove a user's ticketUser holds their own ticket number and can verify it appears in the published ticket list
Forge both signatures after the drawTSA timestamps are issued by independent third parties with trusted certificate chains; the commit timestamp must predate ticket sales

2.4 Independent Verification — You Don't Have to Trust Us

We provide two independent verification methods so anyone can confirm the integrity of a draw without relying on Snappicks servers:

Method 1: Browser verifier (tsa.snappicks.io)

A standalone web tool that performs all verification steps in your browser using the Web Crypto API. No data is sent to any server. You provide the proof bundle URL, and the tool:

  1. Downloads and parses the commit.tsr and reveal.tsr timestamp tokens
  2. Reconstructs the message imprints from scratch using SHA-256
  3. Compares against the TSA-embedded hashes
  4. Re-runs the ChaCha20 PRNG with the published seed to reproduce the exact winning numbers

The full source code (TypeScript, ASN.1 DER parser, ChaCha20 implementation, and Python scripts) is embedded directly on the verification page — every line is visible and auditable.

Method 2: OpenSSL CLI (for advanced users)

# Verify commit signature
python3 verify-sig1.py \
  --seed-hash <64-char hex> \
  --prizes-digest <url to prizes-digest.json> \
  --tsr <url to commit.tsr>

# Verify reveal signature + reproduce the draw
python3 verify-sig2.py \
  --bundle <url to proof-bundle.json> \
  --tsr <url to reveal.tsr>

OpenSSL's ts -verify command independently validates the TSA cryptographic signatures against your locally reconstructed preimage data. The Python scripts are included in our source code viewer and freely downloadable.


3. Atomic Concurrency Control — Defeating Bots & Race Conditions

High-value flash sales are prime targets for scalper scripts and concurrent exploit attempts. Malicious actors may attempt to submit thousands of simultaneous requests within a single second, hoping a race condition allows a double-claim or unauthorized purchase.

Our allocation logic operates within strict ACID database transactions using PostgreSQL row-level pessimistic locking. This ensures:


4. On-Chain Attestation (V3) — Public Blockchain Timestamping

Building on the TSA protocol described in §2, we have deployed a third-generation attestation system that replaces third-party TSA providers with direct on-chain evidence on Polygon, a widely-adopted Ethereum Layer 2 blockchain.

4.1 Why On-Chain?

PropertyTSA (V2)Blockchain (V3)
Trust modelTrust TSA provider's honestyTrust blockchain consensus
PermanenceDepends on TSA provider's continued operationPermanent as long as the chain exists
Verifier availabilityRequires openssl or our browser toolAny block explorer (e.g., Polygonscan)
Barrier to verifyMedium (PKI knowledge helpful)Low — paste a tx hash into a URL and view the UTF-8 decoded data
Censorship resistanceTSA provider can refuse serviceNo single party can block the transaction

Blockchains offer decentralized immutability: once a transaction is confirmed in a block, its data is permanently recorded and publicly visible forever. No TSA provider can go out of business, revoke a certificate, or selectively refuse service. The blockchain itself is the notary.

4.2 Two-Transaction Protocol

V3 follows the same two-step structure as V2 (§2.2), but replaces TSA tokens with Polygon transactions from a dedicated attestation wallet (separate from the platform's operational wallets, holding only enough MATIC for gas fees).

Transaction ① — Commit (before ticket sales open)

The platform sends a transaction to its own attestation wallet with value = 0 and the following JSON payload encoded in the transaction's data field:

{
  "type": "flashSaleCommit",
  "flashSaleId": "123",
  "hashOfSeed": "abc123...",
  "prizesHash": "def456..."
}

This transaction is confirmed in a Polygon block before the flash sale opens. Because the block timestamp is set by network consensus and cannot be altered by any single party, it proves that:

Anyone can verify this by opening the transaction on Polygonscan, clicking "View Input as UTF-8", and comparing the on-chain data with the proof bundle.

Transaction ② — Reveal (after entries close and draw completes)

After the draw, the platform sends a second transaction that chains back to the first:

{
  "type": "flashSaleReveal",
  "flashSaleId": "123",
  "seed": "550e8400-e29b-41d4-a716-446655440000",
  "entriesHash": "789abc...",
  "commitTxHash": "0x...",
  "entriesCount": 1000
}

Key design decisions:

4.3 Independent Verification via Polygonscan

With V3, verification requires no specialized software — anyone can use a standard block explorer:

  1. Verify seed commitment time: Open transaction ① on Polygonscan → confirm the block timestamp is before the flash sale start time → decode the UTF-8 input to see hashOfSeed and prizesHash.
  2. Verify the two transactions are linked: Open transaction ② → confirm commitTxHash matches transaction ①'s hash.
  3. Verify seed integrity: Compute SHA-256(seed) from the proof bundle → compare with hashOfSeed from transaction ①.
  4. Verify ticket list integrity: Compute SHA-256(entries) from the proof bundle → compare with entriesHash from transaction ②.
  5. Reproduce the draw: Use the seed and entry list to re-run the ChaCha20 + Fisher-Yates algorithm → compare with winningNumbers in the proof bundle.

Every step can be performed in a browser with no tools beyond Polygonscan and the verification page at verify.snappicks.io.

4.4 V2 vs V3 — Coexistence

V2 (TSA) and V3 (on-chain) share the same core algorithm (ChaCha20 + Fisher-Yates) and produce identical proof bundles. The only difference is how the two attestation steps are recorded:

Both are live on the platform. New flash sales default to V3, while existing V2 flash sales continue to be verifiable through their original TSA proofs. Users do not need to know which version a flash sale uses — the platform's flash sale detail page shows the appropriate verification links automatically.


5. Our Vision

Snappicks was not built for short-term marketing stunts. We aim to provide the world's most transparent gamified shopping experience — one where every draw can be mathematically audited by anyone, anywhere, with nothing more than a web browser. Our ChaCha20 deterministic randomness, dual attestation (TSA signing for V2 and Polygon on-chain for V3), and independent browser, CLI, and Polygonscan verifiers are all live today.

Trust is built on transparency. Verify us anytime.

— The Snappicks Core Engineering Team