SealedFi

Technical whitepaper

A private market for graded collectibles

How SealedFi lets someone buy, hold and trade physically-backed graded cards without publishing their collection on a public ledger — and, just as importantly, what it does not claim to hide.

Version 1.0 August 2026 Robinhood Chain (EVM, chain id 4663)

Abstract

Tokenising a physical collectible makes it liquid and makes it public in the same stroke. Every purchase, every holding and every sale is written to a ledger anyone can read, and a wallet address is a durable identifier — so a collection assembled on-chain is a collection published on-chain, permanently, to competitors, to counterparties and to anyone who has ever learned which address is yours.

SealedFi is a market for graded trading cards that separates paying from receiving. Buyers fund a shielded pool with fixed-denomination notes and spend a note through a zero-knowledge proof that authorises a payment without revealing which deposit it came from. The proof is generated in the buyer's own browser; no server ever holds a note secret, a spending key or a witness. The cards themselves are graded slabs held in a third-party vault and never move at purchase time.

This paper describes the payment layer, the two purchase mechanisms, how the system measures and reports the strength of a buyer's privacy rather than asserting it, and the specific disclosures where privacy does not hold.

1 · The problem

A public blockchain is an excellent settlement layer and a poor privacy layer. The properties that make on-chain ownership worth having — anyone can verify it, nobody can quietly revise it — are the same properties that make it a permanent, searchable, adversarially-indexed record of everything you have ever bought.

For collectibles this is worse than for fungible assets, for three reasons.

  • Holdings are individually identifiable. A balance of a fungible token says how much. A collectible says exactly which — a specific card, a specific grade, a specific certification number.
  • Collections are strategy. Accumulating a position in a set is information a competing buyer can act on, and does — front-running a visible accumulation is trivial when the accumulation is public in real time.
  • Value attracts attention. A public list of high-value items joined to a persistent identifier is a targeting list, and one that cannot be recalled once published.

None of this is solved by pseudonymity. An address is pseudonymous only until one transaction ties it to a person — an exchange withdrawal, a public sale, a shipping address — and that link is retroactive: it exposes the entire history, not just what came after.

2 · Goals and non-goals

A privacy system that is vague about its boundary is worse than one with a narrow, well stated boundary. SealedFi's boundary is deliberately narrow.

Goals

  • Which cards a person holds is not derivable from public data.
  • A payment cannot be linked to the wallet that funded it, by us or by an observer.
  • Secrets are generated and used client-side, never transmitted.
  • Every asset is backed 1:1 by a specific graded slab in third-party custody.
  • The strength of a given buyer's privacy is measured and shown before they spend, not asserted afterwards.

Non-goals

  • Hiding that you are a user. Funding the pool is a public, screened on-chain action.
  • Anonymous physical delivery. Shipping a card requires a real name and address.
  • Censorship resistance. The underlying chain is operator-controlled and can filter transactions.
  • Evading sanctions screening or any other lawful compliance control.
  • Being a general-purpose mixer. This is a market that settles privately.

The last non-goal is a design constraint rather than a disclaimer. Withdrawing funds privately exists as a secondary action so that money entering the pool is not trapped there, but the primary path a note is built for is buying a card.

3 · System overview

Four components, with a deliberate split of what each is trusted for.

The client

A browser application. It derives note keys, builds transactions, reconstructs the pool's state from public logs, and generates every zero-knowledge proof locally. It holds all secrets and sends none of them.

The shielded pool

Smart contracts on Robinhood Chain, from an established third-party privacy protocol rather than a bespoke implementation. Deposits are commitments in a Merkle tree; spends are proofs that consume a commitment without naming it.

The coordination service

Serves the catalogue, quotes and pool metadata, accepts proofs for broadcast, and runs the assignment draw. It never receives a wallet address, a session or a secret, and it cannot compute which deposit a proof came from.

Custody

Graded slabs are held by the vault operator that authenticated them. At purchase time the physical card does not move; ownership transfers against an isolated redemption identity, which is what keeps a purchase from generating a logistics-side record of who bought what.

The trust assumption worth stating plainly: the client is trusted with secrets and trusts nothing else. It verifies the pool's registered configuration on-chain rather than accepting it, rebuilds the Merkle root itself rather than taking one from an API, and verifies every proof locally before releasing it.

4 · The shielded payment layer

4.1 Fixed denominations

A shielded payment hides in a crowd of payments that look identical to it. An amount is a fingerprint: a note worth $317.42 stands alone no matter how large the pool is, and spending it identifies the deposit that funded it by arithmetic alone.

SealedFi therefore denominates in a published ladder, and refuses anything off it:

$25 $50 $100 $200 $400 $800 $2,000 $4,000

Funding at a tier deposits some whole number of byte-identical notes at that size. Any sub-denomination remainder is deliberately not shielded — it stays in the funding wallet, because depositing it would create a one-of-a-kind note that damages the privacy of everything else the same wallet does.

A consequence worth being explicit about: because payment sizes are fixed, cards are sold at ladder prices rather than at arbitrary asking prices. Pricing follows the denomination, not the other way around.

4.2 Deposit

Each note's keys are derived from a signature the user's wallet produces over structured, human-readable typed data, combined with a note index. From those keys the client computes a precommitment, and the deposit transaction publishes only that — a hash which reveals nothing about the keys behind it.

Three checks run before anything is broadcast.

  • The pool's registered configuration is asserted, not trusted. The on-chain entry point is read and required to match the expected pool, the expected vetting fee and a minimum that still admits the smallest tier. The value committed to the note is then derived from the expected constants. A configuration drift on a contract we do not own would otherwise silently start a second anonymity set containing exactly one note, with no error raised anywhere.
  • Idempotency is established on-chain, not locally. Before building transactions the client scans the pool's own deposit events for this note's precommitment. If it is already present, the deposit resumes instead of repeating.
  • Local records are reconciled against the chain. If the chain shows more deposits for this wallet than this browser knows about — a second device, cleared site data — depositing is blocked until a recovery scan reconciles the two.

4.3 Spending a note

Spending proves membership without disclosing which member. The client rebuilds the pool's Merkle tree from public logs, produces a Groth16 proof that it knows the keys behind some commitment in that tree, and publishes a nullifier that prevents the same note being spent twice. The proof reveals the value being withdrawn and the recipient; it does not reveal the deposit.

The client refuses to proceed unless its independently reconstructed root equals the root the contract reports. It trusts its own reconstruction over any server's answer, and it verifies the finished proof locally before it is released for broadcast. Log queries are chunked and floored at the pool's first event, because an unbounded query is the classic route to a wrong root: some providers error, others silently truncate, and a truncated leaf set hashes to a root that is simply not the pool's.

4.4 Proving happens in your browser

This is the load-bearing architectural commitment, and everything unusual about the client exists to serve it. Proving keys and circuits are fetched same-origin and verified — length, format and a pinned SHA-256 digest — before they are allowed near the prover, because a swapped or truncated proving key is a silent and catastrophic failure rather than a loud one. Circuit versions are published as new immutable paths and never overwritten in place.

Proof Generate Verify
Commitment ~0.3 s ~13 ms
Withdrawal ~1.5 s ~10 ms

Measured in a production build under the enforced content-security policy on commodity hardware.

5 · Buying a card

5.1 Payment and claim are bound together

A purchase is a spend whose recipient is the treasury, submitted together with a commitment to a secret only the buyer knows. Under this shape every buyer's payment tuple is byte-identical, so a purchase carries nothing that distinguishes one buyer from another — which is precisely why the claim commitment must travel with the proof and cannot be attached afterwards. Settlement events are public; a payment referenced after the fact could be claimed by whoever saw it first.

The buyer's secret is written to local storage before any network call is made. This is a real trade and the product states it rather than hides it: a lost secret is a lost claim, and it is not recoverable. The only recovery mechanism that could exist would work by correlating a person to a purchase — the exact disclosure the system is built to prevent.

The tier being claimed is never taken from the request body. It is derived from the proof's own public signals, because a tier supplied by the caller would let a small payment claim a large card.

5.2 Two ways to buy

Because payments are fixed-size, each card sits at exactly one tier, and that determines how it can be bought.

Catalogue — you pick

Cards whose value sits close beneath a ladder tier are listed at that tier and bought directly. You browse, you choose, you pay one fixed price.

Sealed pool — a draw picks

Everything else enters a sealed pool at the tier below it. You pay the tier and a published, checkable procedure assigns you a card from that pool.

Browsing is unauthenticated and requires no wallet. A wallet is requested only by an action that genuinely needs one — connection is a step in a purchase, not a door on the front of the market.

6 · Anonymity as a measured quantity

Privacy systems commonly present anonymity as a binary — the transaction is shielded, therefore you are private. That is misleading. A spend hides among the unspent notes of the same denomination that exist at that moment, and that number moves continuously as people deposit and spend.

SealedFi treats the size of that set as a number the buyer is entitled to see before committing, and names its strength in plain terms rather than hiding it behind a permitted/refused flag. Being allowed to spend and being private when you do are different claims, and the difference belongs to the person spending the money.

Identical unspent notes How it is described
16 or more Strong
8 to 15 Moderate — decent, not strong
Fewer than 8 Weak — an observer has a real chance of picking yours out

A tier opens as enough identical unspent notes accumulate and closes again as they are spent. Two further commitments follow from taking the number seriously:

  • The count is never inflated. Seeding notes of our own to make a tier look busier would be both discoverable — every depositor address is public — and a lie told to someone about to spend money.
  • "Not measured" is distinguished from "zero". An unavailable measurement is reported as unavailable rather than rendered as a confident count of nobody.

7 · Fairness

There are two separate fairness claims in a sealed-pool purchase, and collapsing them into one is the mistake that makes the guarantee sound stronger than it is.

The draw

Whether the card that came out of a pack was random. This is established by the vault operator's on-chain verifiable random function, whose verifier is open source and whose proofs anyone can check. It is a claim about their conduct, not ours.

The handout

Which of the already-drawn cards you receive. This is the claim about SealedFi's conduct, and the one that matters if you suspect cherry-picking. Before any card is assigned, a sealed commitment is published over the whole pre-opened pool and its size is fixed at that moment. Your card is then selected by a seed built from that pool commitment, your own commitment, your position in the queue, and a probe counter that advances when a pick lands on a card someone already has.

Packs are opened in advance so that their contents can enter the sealed pool. The reveal animation shows which pre-drawn card you were assigned; it does not run the draw, and the product says so rather than implying otherwise.

Verifying it properly takes a step people skip. Each assignment publishes its seed inputs, its Merkle proof and its probe counter. Recomputing the seed and checking the proof is not sufficient — you must also replay every skipped probe against the public reveal log and confirm each one really did land on an already-taken card. Without that step the probe counter could in principle be run up until the pick landed somewhere convenient.

Stated, not buried

Of the four seed inputs, the queue position is the only one SealedFi chooses, and it is not yet independently checkable. It is derived from pool state rather than from anything about you, but until the published proof pins it down, that part rests on our word. An unqualified "neither side can steer it" would not be defensible today, so we do not make one.

Assignment proofs are also not kept forever. The link between a claim and a specific card is retained for a window and then destroyed, after which verification answers "scrubbed" rather than confirming an assignment — a permanent record of which claim got which card is a permanent record of who someone is. The card is unaffected; it remains yours long after the proof has gone.

8 · Keys, recovery and the escape hatch

Note keys derive deterministically from a wallet signature and a note index, with no stored per-note randomness. That choice makes every note recoverable from nothing but the wallet — there is no seed file to back up and no export to lose — and it imposes a hard rule: an index must never be reused. Reusing one reproduces a prior note exactly, including its already-spent nullifier, and the funds behind it become permanently unspendable. Indices therefore only ever move forward, are reserved before any broadcast, and an abandoned reservation stays burned. Indices are free; reuse is not.

The signature request is typed data, not an opaque string. This is a security boundary rather than a formatting preference. A signature over a plain string is portable — any website could ask a wallet to sign the same string and walk away with spending authority — because such a request carries no origin, no chain and no contract for the wallet to show the user. Typed data carries a domain that wallets display, and the request states in the prompt itself where it is legitimate and that it should not be signed anywhere else. The copy deliberately warns rather than reassures: soothing language inside a signing prompt is exactly what a phishing page wants to borrow.

Recovery re-derives note indices from the wallet upward and matches them against that wallet's own public deposit events. It costs one signature per index probed — the honest price of a derivation with no stored randomness — and stops after a run of misses so that a wallet with no SealedFi deposits cannot be ground through signature after signature.

Public recovery is the escape hatch, and its cost is stated in a blocking confirmation before it runs. It returns a note's full committed value to the original funding wallet by proving the commitment directly. Doing so names the depositor on-chain, so that note's privacy is forfeited permanently. It is available precisely because it depends on the lightest proof in the system and therefore works in conditions where the heavier spending path would not.

9 · Security architecture

  • No server-side secrets. Note secrets, spending keys and witnesses exist only in the browser that created them. There is no account, no session and no password, and the coordination service never receives a wallet address.
  • Established cryptography, not a bespoke construction. The pool is a deployment of an existing third-party privacy protocol with real usage behind it. We integrate and verify it; we did not write our own.
  • Pinned circuit artifacts. Proving material is served same-origin and checked by digest before use, and a version bump publishes a new immutable path rather than overwriting an old one.
  • A strict content-security policy is enforced by response header, allowing only the origins measured from source and permitting WebAssembly compilation narrowly — without re-enabling JavaScript evaluation. The policy is exercised by an automated test that reads the policy out of the deployed configuration and runs a real proof under it in a real browser, so the two cannot drift apart.
  • Client-side verification of chain state. The pool's registered configuration is asserted, the Merkle root is independently reconstructed, and every proof is verified locally before release.
  • Property testing where the failure is unrecoverable. The one invariant whose violation costs a user their funds — an index is never issued twice — is tested against a deliberately hostile storage layer that throws, silently drops writes and returns corrupt data, and this runs on every change.
  • Locally-stored data is limited to what is already public in the user's own transactions. Timing metadata that could join a funding wallet to a public settlement is deliberately not recorded, because anyone later reading a browser profile would otherwise be handed a link the chain does not itself carry.

Vulnerability reports go to team@sealedfi.com. Privacy defects — anything that links a person to a card they hold — are treated as security issues rather than bugs, and are the reports we want most.

10 · Disclosures and limitations

Published up front, because a paper that overstates readiness is worse than a short one.

  • The money-path cryptography has not had an independent audit. That gate is named in the source and has not moved.
  • Being a SealedFi user is public. Funding the pool is an on-chain, screened action. What is private is which cards you hold — not that you hold some.
  • Physical redemption is not private. Shipping a card requires a name, an address and an account with the vault operator. Privacy covers holding and trading. A delivery address is given at redemption time, separately, and not before.
  • The underlying chain is operator-controlled. Its sequencer can screen and filter transactions. We cannot offer censorship resistance and do not claim to.
  • Public recovery forfeits that note's privacy permanently, by design. It is an escape hatch, not a routine action.
  • Privacy degrades in a thin pool. Small anonymity sets are genuinely weak. The product shows the real number rather than waiting for a buyer to discover this afterwards.
  • Timing and amount analysis remain possible. Fixed denominations remove the amount channel; they do not remove every channel. Depositing and spending in immediate succession narrows the set an observer must consider.
  • A lost claim secret is a lost claim. There is no recovery, and the only mechanism that could provide one would defeat the purpose of the system.
  • Some capabilities described here belong to the vault operator, not to SealedFi — grading, the pack draw itself, buyback and physical redemption. They are labelled as such in the product.
  • Features ship behind deployment gates. Where a required on-chain or service-side prerequisite is not yet live, the corresponding action is not rendered at all rather than offered and failed.

Nothing in this paper is investment advice, an offer, or a solicitation. Collectibles are illiquid and their values fluctuate.

Glossary

Note
A single fixed-denomination deposit in the shielded pool, spendable exactly once.
Commitment
A hash published on-chain that binds a note's secret keys without revealing them.
Nullifier
A value published when a note is spent, which prevents the same note being spent twice without revealing which note it was.
Anonymity set
The unspent notes of the same denomination a given spend is indistinguishable among. Larger is stronger.
Groth16
The zero-knowledge proof system used here: small proofs, fast verification, and a per-circuit proving key.
Slab
A trading card sealed in a tamper-evident case by a grading authority, carrying its assigned grade and certification number.

Buy sealed, stay sealed.

Questions, corrections and security reports are all welcome.