FOIL

> HOW IT WORKS

Holding a memecoin is watching a number move. A Foil drop gives the people holding yours something to open — and what comes out is a real asset in their own wallet, not a points balance on somebody's server.

01

THE DROP IS A FIXED LIST

A drop is between 10 and 500 items, written before anything launches. Tiers are dealt across that list rather than rolled per pack:

60
Common in 100
25
Rare in 100
12
Epic in 100
3
Foil in 100

That distinction matters. Rolling per pack makes a 3% tier a probability, and a run of bad luck can mean none exist. Dealing makes it a fact: a 100-pack drop contains exactly three Foils, and when they have been pulled they are gone.

02

THE LIST IS SEALED BEFORE ANYTHING OPENS

The item list is hashed into a Merkle tree and its root is written on chain alongside the coin. The index is inside each leaf, so the root commits to the list in order — items cannot be quietly re-arranged afterwards.

Then the shuffle: seed = SHA256("foil-shuffle-v1" ‖ root ‖ anchorBlockhash), followed by Fisher–Yates with rejection sampling. Pack #k yields item order[k].

The anchor blockhash is the blockhash of the slot the launch landed in. It did not exist while the list was being written, which is exactly the point: a creator cannot arrange their items against a seed they can already see, and we cannot either. That is also why the certificate is written after the launch rather than inside its bundle — the seed does not exist until the launch has a slot.

03

THE HOLDER GATE IS ENFORCED, NOT CHECKED

Checking a balance in our API would be advisory — a wallet could sell between the check and the mint, and we would have handed a pack to somebody who no longer holds the coin.

So the open transaction carries a Lighthouse assertion on the opener's token account. The assertion and the mint are in the same transaction: if the balance is not there at that instant, the whole thing fails. The runtime enforces it, not us.

worth knowing if you read the code: Lighthouse's operator enum puts LessThan at 3 and GreaterThanOrEqual at 4. Hardcoding 3 builds a gate that admits precisely the wallets it should block — and every test still passes, because the mint succeeds either way. It is referenced by name in lib/server/packs.ts for that reason.

04

WHAT OPENING COSTS

Packs are earned by holding, not bought. Opening costs the rent for the asset you receive — about 0.0037 SOL — paid to the network, not to us. You sign, you pay, you own it. The platform co-signs only as the collection's update authority.

Nothing is custodied at any point. There is no pool to hold.

05

WHAT THIS DOES NOT DO

Stated plainly, because the rest of the page is a list of guarantees and these are the holes in them.

  • A collectible is worth what someone pays for it. Frequently that is nothing. The shuffle being honest says nothing about whether the items have value, and nobody here is claiming they do.
  • One pack per wallet is not one pack per person. Somebody holding enough across several wallets can open several packs, and we cannot tell. Every opener is listed publicly.
  • The platform has to co-sign every open. It is the collection's update authority, so it could stop signing and no further packs could be opened. The assets already minted are unaffected — they are in their owners' wallets.
  • Drop state lives in memory. It does not survive a restart, which is a real limitation on a long-running drop and is why the pack queue is short-lived.
  • Nothing here constrains the dev. They can buy and sell the coin like anyone, and a drop says nothing about what they do with theirs. This pad is about what the holders get, not about locking the launcher down.