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.
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.
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.
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:
| Property | seedrandom (our old V1) | ChaCha20 (V2) |
|---|---|---|
| Internal state | Varies by implementation | 256-bit key derived from seed via SHA-256 |
| Algorithm | Ad-hoc, no formal standard | Well-audited stream cipher used in TLS 1.3 |
| Cross-platform reproducibility | Depends on matching the exact npm package version | Deterministic given the same seed (matching Node.js chacha20 cipher mode) |
| Resistant to prediction | State can be recovered from observed outputs | Key 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).
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.
Each flash sale has a fixed total number of tickets (maxEntries, e.g., 1,000). When a user purchases tickets:
startIndex to endIndex).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.
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.
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.
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.
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:
entriesHash)hex(commit.tsr) chaining)| Attack Scenario | Why It Fails |
|---|---|
| Swap seed after seeing participants | commit.tsr timestamp proves seedHash existed before sales — any different seed produces a different hash |
| Claim a different seed was used | reveal.tsr includes the seed plaintext, chained to commit.tsr via its hex content |
| Add fake ghost tickets | reveal.tsr locks entriesHash — any addition changes the hash |
| Remove a user's ticket | User holds their own ticket number and can verify it appears in the published ticket list |
| Forge both signatures after the draw | TSA timestamps are issued by independent third parties with trusted certificate chains; the commit timestamp must predate ticket sales |
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:
commit.tsr and reveal.tsr timestamp tokensSHA-256The 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.
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:
SELECT ... FOR UPDATE pattern prevents TOCTOU (Time-of-Check-Time-of-Use) vulnerabilitiesBuilding 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.
| Property | TSA (V2) | Blockchain (V3) |
|---|---|---|
| Trust model | Trust TSA provider's honesty | Trust blockchain consensus |
| Permanence | Depends on TSA provider's continued operation | Permanent as long as the chain exists |
| Verifier availability | Requires openssl or our browser tool | Any block explorer (e.g., Polygonscan) |
| Barrier to verify | Medium (PKI knowledge helpful) | Low — paste a tx hash into a URL and view the UTF-8 decoded data |
| Censorship resistance | TSA provider can refuse service | No 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.
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:
hashOfSeed (SHA-256 of the draw seed) existed before anyone bought tickets — the platform cannot swap the seed later.prizesHash (SHA-256 of the prize configuration including name, price, and quantity) was also locked at this time — prizes cannot be changed after sales begin.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:
hashOfSeed was public — the seed was not guessable (§1.1).commitTxHash chains transaction ② to transaction ①, proving both transactions belong to the same flash sale. The seed in transaction ② must match the hashOfSeed in transaction ①, and anyone can verify this by computing SHA-256(seed).entriesHash (SHA-256 of the full list) is recorded. The full list is published off-chain in the proof bundle (§6.5), and anyone can verify SHA-256(entries) == entriesHash.entriesCount confirms the total number of participants, preventing the platform from inflating numbers after the fact.With V3, verification requires no specialized software — anyone can use a standard block explorer:
hashOfSeed and prizesHash.commitTxHash matches transaction ①'s hash.SHA-256(seed) from the proof bundle → compare with hashOfSeed from transaction ①.SHA-256(entries) from the proof bundle → compare with entriesHash from transaction ②.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.
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:
openssl or our browser tool.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.
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