Sigillo How it works Verify a disclosure Launch app→

How it works

The details behind the highlights — including where it stops.

How it works

Your wallet
a fixed amount — 0.1, 0.5, 1, 5 or 10 ETH
The pool
your deposit sits with everyone else's; only your key can spend it
Private transferstays in the pool · nothing public
Public withdrawalany wallet · address and amount public
Stealth payouta one-time address · amount public
  1. 1
    Connect and sign once. Your private-transfer keys come from one signature in the wallet you already use. Registering publishes the key others pay you with — once, and best before anyone needs it.
  2. 2
    Add funds in a fixed amount. 0.1, 0.5, 1, 5 or 10 ETH, so your deposit looks like everyone else's. "Fund a transfer" adds the small fee note alongside it in the same step.
  3. 3
    Send. Choose private, public or stealth; the page shows where the money ends up before you confirm. Proofs are built on your device — about half a minute — and a relayer submits the transaction.
  4. 4
    Prove it later, only if you need to. Give one person a receipt or a disclosure key. They check it on the verify page, without a wallet.

What it solves

On Ethereum, every payment shows who paid, who was paid and how much — to anyone, for ever.
Private transfer. Neither your address nor the recipient's appears in any public data of the transfer.
Privacy tools usually leave you unable to prove anything when you need to — to a tax office, an exchange, an auditor.
Selective disclosure. Prove a single transfer to a single party, with your own proof — and see exactly what they will learn before you hand it over.
Being paid privately usually means the other person has to install something or set something up first.
Stealth payouts. Pay a one-time address from their public receive code. They need no account, no gas, no transaction.
Using a privacy service usually means handing it your money or trusting its word.
Nothing to trust with funds. The contract pays the recipient directly, proofs are built on your device, and the relay fee is recomputed by your browser rather than believed.

Three ways money can arrive

Private transfer
stays in the pool → their private balance

Nothing is public: no amount, no recipient. They must have registered once.

Source: the recipient cannot show where it came from on their own — only you can prove your side.

Public withdrawal
leaves the pool → any wallet balance

The address and amount are public. Who sent it is not — a relayer submits it.

Source: you can prove it came from your own deposit — the depositing address and amount.

Stealth payout
leaves the pool → a one-time address

The amount is public; nothing ties the address to its owner or to other payments.

Source: you can prove it came from your own deposit, as with a public withdrawal.

No single mode fits every case. If you may need to show where money came from, send from funds you deposited yourself by public withdrawal or stealth payout. If you need nobody to see the payment at all, use a private transfer — and accept that its source cannot be traced back for an audit.

Where disclosure records live: Ethereum calldata, via Facet

A receipt needs nothing stored anywhere — it is a proof you make when asked. A disclosure key is different: it opens a record you chose to write when you sent. That record is not kept on our server or in a contract we control. It is written into Ethereum's own transaction data, in Facet's format, where anyone can read it back and no one can change it.

  1. 1
    Sealed on your device. When you tick "Attach a disclosure record", the page encrypts what the transfer was — which note was spent, the amount, the recipient, your memo — to your own key, with the same post-quantum scheme as the payment itself (ML-KEM-768 + AES-GCM).
  2. 2
    Published by the relayer, separately. Right after the transfer, the relayer sends the sealed bytes to Facet's inbox address as a transaction of its own. It handles ciphertext only and cannot read it. It is sent by the relayer, not by you, so that writing a record does not reveal you as the sender. It costs you nothing extra.
  3. 3
    Permanent. Facet's state is derived from Ethereum calldata, so the record can be rebuilt by anyone replaying the chain. No operator — us included — can edit, withhold or delete it. That is also why writing one is your choice, per transfer: once written, it cannot be taken back.
  4. 4
    Opened by one key. The disclosure key is the record's id, the transaction that published it, and a key for that record only. The verify page reads the transaction from a public node, decrypts it, then checks the claim against the pool: the spend must exist, and for a public withdrawal the amount and recipient must match the chain. A private transfer has no public amount to compare, and the page says so. A match shows what was paid, not who paid it: anyone who saw a public payment could write a record that matches. To show a payment was yours, give a receipt.
What goes on chain
to     0x…face7     Facet inbox
from   relayer      not you
value  0

data   0x46 ‖ rlp(
         chain_id, to=0, value=0,
         gas_limit=0, data,
         mine_boost=0 )

data = "SIGILLO-DISCLOSE-v1"
     ‖ recordId     32 bytes
     ‖ sealed body  ML-KEM+AES
Size
about 1.7 KB
L1 gas
about 84,000, measured on Sepolia
Executes
nothing — it is data, not a call
A record, not a gatekeeper. The pool on Ethereum cannot read Facet, and no transfer waits for a record. If publishing the record fails, your money still moves — the record is an extra, never a condition.
No backup file. Your records are found again from your wallet signature alone — "Find my disclosure keys" in the app. Another wallet following the same format finds the same records.
One key opens one record. Handing over a key reveals that transfer and nothing else. There is deliberately no key that opens all of them.

Points

Deposits earn points. They are worked out in your browser, from the pool's public deposit events and the rule below — no server keeps a list of anyone's points, and anyone can recount them from the chain. Points are not a token, cannot be transferred, and nothing has been decided about what they will become.

What earns points
Every deposit into the pool, at every size — the 0.02 fee note included. Transfers, withdrawals and registering earn nothing.
How many
Amount in ETH × 100 × the early rate. 0.1 ETH at 3× is 30 points. One deposit of 1 ETH earns the same as ten of 0.1, so splitting buys nothing but gas.
The early rate
Set by the week of the season the deposit is made in: 3× in weeks 1–4, 2× in weeks 5–12, 1.5× in weeks 13–26, then 1×. By date rather than by how much has been deposited, so nobody's deposits can run the rate down for anyone else.
Whose they are
The address that sent the deposit — which the chain shows anyway, so counting it reveals nothing new about anyone.
The season
Season 1 begins when the mainnet pool is deployed. Its end is announced here at least 30 days ahead.
Changes
This is rule v1. A change applies only to deposits made after it, and is written here before it takes effect. Points already counted are never recounted.
Time in the pool
A second kind, time points, for ETH that stays in the pool. Its rule is below. Depositing and withdrawing at once earns deposit points and no time points.
On the test network
On Sepolia the same rule runs, from the day the test pool was deployed, as a demonstration. Those points count for nothing.

Time points

The longer ETH stays in the pool, the larger the crowd every payment hides in — so time kept there earns points too. They are counted per note, not per address, and claimed after each season with a zero-knowledge proof that reveals only the total: never which deposit was yours, nor when or where it was spent.

How many
Amount × days held within the season, both rounded down: the amount to 0.1, 0.2, 0.5, 1, 2, 5, 10, 20, 50 or 100 ETH; the days to 7, 14, 30, 60, 90, 120, 150 or 182. 1 ETH kept the whole 26-week season earns 182; 0.5 ETH kept 100 days earns 45.
Why rounded
An exact amount × an exact time would factor back into one deposit and one spend — on the test pool, 97 claims in 100 would have. Rounded, none did.
What does not count
Under 7 days, and notes under 0.1 ETH — so the 0.02 fee note earns none. Paying from a note ends its time; the person paid starts their own.
Still in the pool
Counts up to the season's end. Nothing has to be withdrawn or moved to claim.
Claiming
After a season ends, in a 28-day window. The claim is being built; until it is, the wallet shows an estimate, worked out from its own notes in your browser.
Changes
This is rule v0. A change applies only from the season after it is written here, and points already earned are never recounted.

What it does not do — yet

  • Testnet only. It runs on Sepolia. There is no mainnet deployment.
  • Few people use it so far. The cryptography holds at any size, but with a small crowd, timing and amounts can narrow down who is who. Privacy grows with users.
  • Not independently audited. Do not use it for money you cannot lose.
  • Deposits and public withdrawals show their amount. That is why amounts come in fixed sizes — 0.1, 0.5, 1, 5, 10 ETH — so yours looks like everyone else's.
  • One relayer, run by us. It sees the recipient, amount and time of public withdrawals. More independent relayers are the plan.
  • The node this page reads from sees your IP address. By default it is a public node we do not run; you can use your own instead. It can tie your IP address to your wallet address — what it sees.
  • This page cannot hold a transfer back for you. Sending right after depositing links the two by timing. The browser extension holds a transfer back for you — for hours on mainnet; on this test network, a couple of minutes, since there is no one else's traffic to hide in. A web page cannot hold anything once its tab is closed.

Works with

MetaMask & any EIP-1193 wallet App-layer private transfer ERC draft — its reference pool ERC-5564 stealth addresses EIP-7702 smart accounts EIP-5792 batched calls Facet calldata records

Questions

Why only fixed amounts?

A deposit's amount is public, and so is a public withdrawal's. If you deposit 0.017 ETH and later 0.017 ETH leaves the pool, anyone can pair the two — however many people use it. When everyone moves 0.1 or 0.5, amounts stop pointing at anyone.

Why does funding a 0.1 transfer take 0.12 ETH?

The relay fee is paid from a second, small note so the recipient receives exactly 0.1 rather than 0.1 minus a fee — otherwise the amount they receive would be unique again. The 0.02 note is reused for later transfers until it runs down, and what is left stays yours.

What does the relayer see?

For every transfer: the network address the request came from, and when. For a public withdrawal, also the recipient and the amount. For a private transfer it forwards encrypted data and sees neither the amount nor the recipient. It can refuse to send; it cannot take or redirect money — the contract pays the recipient directly. Today there is one relayer, and we run it.

What does the node this page reads from see?

This page and the extension read the chain through a public Ethereum node — by default Tenderly’s Sepolia gateway, which we do not run. It sees your IP address and every request. You can point both at your own node instead: in the app, under Advanced; in the extension, under Settings → Your own node. The wallet checks the node can do everything it needs before it switches.

Most requests tell it nothing about you: to find your notes, the page downloads the pool’s whole history and decides locally which are yours, so the node never learns which ones they are. Your keys and your notes never leave your device.

How a transfer you sent is going is asked of the relayer, not the node. The relayer already knows the transfer is yours — you just handed it over — so asking it reveals nothing new, while a node asked the same question from your IP address, seconds after the transfer went out, would learn whose transfer it was.

A few requests to the node are still yours alone. The balance of your wallet address. In the extension, a one-time address when you pay from it, or check how much you can — the payment itself goes out through the node from your IP address anyway. Checking for payments does not ask about any one address: the extension reads the balances of every announced address at once, the same request any wallet reading those blocks sends. And on the verify page, which transaction you are checking.

Finding your disclosure keys again, in a new browser, reads the few blocks after every transfer in the pool, not only yours — the same blocks for every wallet — and recognises yours on your device.

A VPN or Tor hides your IP address from the node; it does not hide that one session asked about these things together. Your own node is the fix that covers all of them.

Who can see my private balance?

Only someone holding the signature your keys derive from — which is you, in your wallet. This page stores nothing on a server. Closing the tab clears what it held in the browser.

What if I lose this browser, or this site goes away?

Your funds sit in a contract that nobody — including us — can change or pause, and your keys come from your wallet's signature, so they are never lost with a browser: signing again from the same wallet finds the same notes. But be clear about today: finding and moving them needs software like this page or our wallet extension, and sending needs a relayer, of which there is currently one. A site that disappears does not take your money, but it does take the easy way to reach it.

Is this compliant with the rules where I live?

We cannot answer that for you. What exists is technical: our relayer screens public recipients against the OFAC sanctions list (see below), and you can prove any single transfer to a party you choose. Whether that meets your obligations is a question for your own adviser.

What does a receipt show the person I give it to?

That the spend was yours, plus everything the public chain already ties to that note once the link is shown: the address your identity is registered to, the transaction that created the note — and, if the note came straight from a deposit, the depositing address and the amount deposited — the transaction that spent it, and anything it paid out publicly.

None of this can be left out of a receipt, because the person checking it reads it from the chain, not from us. So the app lists every line before it makes one, and you decide whether to hand it over.

What is screened, and by whom?

Two different checks, often confused:

Our relayer screens who gets paid. Before it submits a public withdrawal or a stealth payout, it checks the recipient address in that transaction against the OFAC SDN list and refuses a listed one. If its copy of the list is more than a day old, it refuses to submit anything until it refreshes. A private transfer has no public recipient, so there is nothing to check. This is a setting of the relayer, not of the pool or of your payment: ours has it on and publishes that in its details; anyone running their own relayer decides for themselves.

A screened pool checks who deposits. A separate pool — deployed on Sepolia, but not the one this app uses yet — accepts a deposit only with a recent attestation that the depositing address is not on the same list. The pool's contract enforces that, so no relayer setting changes it, and the attestation can be recomputed by anyone from the public list.

Can I prove where my money came from?

Yes, if you deposited it yourself and send it out publicly. A receipt for a public withdrawal or stealth payout shows the depositing address, the amount and where it was paid — an auditor or an exchange then applies its own checks to that address.

No, not past a private transfer. Money received by private transfer carries no record of its origin; the receipt says "received inside the pool" and the trail stops there. Only the person who sent it can prove their side. The same applies if you later withdraw money you received privately: its source cannot be shown.

This is a deliberate boundary, not a missing feature. Choose the mode that fits what you may need to prove later.

Do I need to install anything?

No — a wallet such as MetaMask is enough. There is also a browser extension wallet, which holds a transfer back after you deposit so the two are not linked by timing — for hours on mainnet, a couple of minutes on this test network, where there is no other traffic to hide in. A web page cannot do that once its tab is closed.

Launch app