Write your half
Pick what you give and what you want for it — a stock for dollars, dollars for a stock, or one stock for another. Choose who may take it and when it expires. Your wallet signs it. Nothing is sent anywhere and nothing is on chain.
Write down what you will give and what you want for it, sign it, and send it to the person on the other side. When they take it, Seaport — an exchange contract already on this chain, and not ours — swaps both sides in a single transaction, or nothing happens at all. There is no pool in the middle, so nothing is lost to price impact and no fee is paid to anybody.
A tally was a hazel rod notched with a debt and split down its length. The lender kept the long half — the stock — and the borrower kept the short half, the foil. Neither proved anything alone. Laid together, the notches had to line up.
Pick what you give and what you want for it — a stock for dollars, dollars for a stock, or one stock for another. Choose who may take it and when it expires. Your wallet signs it. Nothing is sent anywhere and nothing is on chain.
The whole offer travels inside a link. There is no server holding it, because there is no server: the link is the offer. Name a counterparty and it is theirs alone — Seaport will refuse a fill from any other address.
One transaction moves your token to them and theirs to you. If either leg cannot be paid, the whole thing reverts and nobody has moved. Until that moment you can cancel, and the offer expires on its own.
Say you want to buy $50,000 of a stock and somebody else wants to sell the same amount. Through the pools you are strangers: you buy from the pool, they sell to it. What you paid and what they received are not the same number, and the gap is the pools' fee plus both sides of price impact. It is measured here by simulating exactly that — a buy and a sale of the same shares, from the same pool state, split across up to 4 pools the way a good router would.
| Trade size | Median cost | In dollars | Cannot be filled |
|---|---|---|---|
| $10,000 | 1.04% | $104.00 | 0 |
| $50,000 | 2.29% | $1,145 | 1 |
| $250,000 | 25.35% | $63,375 | 4 |
Measured at block 65,580,838 across 48 stocks, each order split across up to 4 pools. "Cannot be filled" counts the stocks whose pools could not absorb a trade that size at all — at $250,000 that is COIN, EWY, RKLB, SOUN. 3 more stocks are not in the table at all: IBM (pool state unreadable: request timeout (code=TIMEOUT, version=6.13.5)); NBIS (only 1 pool(s), all above the fee ceiling); ORCL (only 1 pool(s), all above the fee ceiling).
| Stock | Pools | $10,000 | $50,000 | $250,000 |
|---|---|---|---|---|
| NVDA | 5 | 0.10% | 0.13% | 0.29% |
| SPCX | 4 | 0.10% | 0.13% | 0.29% |
| GOOGL | 5 | 0.11% | 0.15% | 0.39% |
| QQQ | 4 | 0.11% | 0.18% | 0.60% |
| SGOV | 3 | 0.11% | 0.20% | 0.51% |
| SPY | 4 | 0.14% | 0.21% | 0.52% |
| GLD | 5 | 0.17% | 0.43% | 0.91% |
| AAPL | 4 | 0.22% | 0.60% | 1.95% |
| GME | 4 | 0.25% | 1.38% | 64.42% |
| LLY | 7 | 0.27% | 0.75% | 2.93% |
| COST | 6 | 0.40% | 1.02% | 25.35% |
| AMC | 6 | 0.45% | 0.87% | 2.66% |
| HIMS | 6 | 0.62% | 0.80% | 1.82% |
| USO | 3 | 0.62% | 0.86% | 2.01% |
| TSLA | 4 | 0.63% | 0.97% | 2.56% |
| AMZN | 3 | 0.67% | 1.02% | 2.80% |
| MSFT | 4 | 0.69% | 1.05% | 2.83% |
| META | 3 | 0.70% | 0.79% | 1.33% |
| MU | 2 | 0.72% | 1.21% | 4.21% |
| CRCL | 4 | 0.75% | 1.40% | 4.95% |
| MSTR | 6 | 0.75% | 1.43% | 4.26% |
| SLV | 4 | 0.79% | 1.55% | 25.94% |
| PLTR | 2 | 0.98% | 4.15% | 84.01% |
| TTWO | 5 | 1.04% | 2.77% | 62.29% |
| TSM | 5 | 1.08% | 3.27% | 34.94% |
| NFLX | 3 | 1.13% | 4.94% | 80.66% |
| BABA | 6 | 1.25% | 4.30% | 75.98% |
| DJT | 3 | 1.25% | 2.17% | 5.48% |
| RBLX | 3 | 1.31% | 3.00% | 37.56% |
| JNJ | 2 | 1.36% | 36.04% | 86.82% |
| LULU | 4 | 1.39% | 3.34% | 62.99% |
| RDDT | 3 | 1.54% | 2.29% | 4.39% |
| RIVN | 6 | 1.77% | 4.63% | 75.55% |
| DELL | 2 | 1.79% | 4.39% | 80.17% |
| MRNA | 4 | 2.57% | 33.85% | 90.08% |
| NU | 3 | 2.58% | 41.08% | 89.98% |
| QUBT | 3 | 2.65% | 64.86% | 95.96% |
| USAR | 1 | 2.96% | 47.95% | 92.20% |
| AMD | 3 | 3.48% | 72.07% | 95.14% |
| AVGO | 1 | 4.05% | 69.23% | 93.90% |
| INTC | 1 | 4.40% | 62.50% | 92.50% |
| NET | 2 | 4.40% | 72.35% | 96.02% |
| ASML | 3 | 5.12% | 78.72% | 95.56% |
| SNDK | 1 | 5.68% | 48.37% | 89.67% |
| EWY | 3 | 40.59% | 88.73% | cannot fill |
| RKLB | 1 | 55.64% | 92.44% | cannot fill |
| SOUN | 1 | 89.47% | 97.89% | cannot fill |
| COIN | 1 | 93.13% | cannot fill | cannot fill |
An offer is a signature somebody else is holding. That is the whole idea and it is also the whole risk, so here is every way it bites, and what Foil does about each.
Your offer stays fillable at the price you wrote until it expires. If the stock moves against you, taking it is free money for them. Foil defaults to an hour, offers fifteen minutes, and refuses to write anything longer than seven days.
Cancel one offer and Seaport marks it dead. Cancel everything you have ever signed with one call — it moves a counter every one of your signatures was made against. Both are your wallet talking to Seaport; Foil is not involved.
A private offer names the taker as its zone. Seaport only skips the zone check when the filler is the zone, so any other address reverts. Property 7 executes that refusal on chain, and its control proves the same fill succeeds for the named address.
A partial offer can be taken a piece at a time, and every piece is priced by the same fraction on both sides. Seaport refuses a fraction that does not divide exactly, so Foil only writes amounts it can divide — and shows you what is left.
Both sides approve Seaport for exactly the amount this trade moves, never for an unlimited allowance. When the trade is done the allowance is zero again by arithmetic, not by promise.
Foil deploys no contract. Every transaction it builds is your wallet calling the token or calling Seaport, and every one is read back and refused unless it is exactly the trade you were shown. We never hold anything and cannot be asked to give it back.
Every number below came from a run whose output is in this repository, and each check has a control that must fail — a sweep that stopped sweeping looks exactly like a clean build.
Each one is a contract compiled and run inside a single eth_call against Seaport at block 65,601,412 — no deployment, no fork. Every refusal is classified by the error Seaport actually returned, and every one has a control in the same call proving the same thing succeeds when the guard is absent.
A deliberately broken copy of the page's own order builder is put through the properties; each break must be caught by the property named for it. A control with nothing broken passes first, or the sweep is not a sweep.
Offers written, filled in parts, cancelled and counter-bumped in random order on a fork of this chain — 2 seeds, 84 steps, 9 invariants after every single operation. 12 of 12 deliberate breaks were each caught by the invariant named for it.
Chrome drives this site against a fork of the chain under the deployed Content-Security-Policy: write an offer, sign it, open the link as the other party, fill it, cancel one, cancel all.
The comparison this whole site rests on is only worth as much as its swap maths, so every quote is checked against Uniswap's own deployed quoters, to the wei, in both directions and on both v3 and v4.
It costs nothing to write an offer and nothing to send it. Only a fill is a transaction.