What an offer is
An offer is eleven fields and a signature. It says who is making it, what they give, what they want, who may take it, when it starts and ends, and which of the maker's signatures it belongs to. Foil writes exactly one shape of it:
- One thing offered, one thing wanted. Both ERC-20. No bundles, no token ids.
- The amount does not move. Seaport can make a price decay between two times; Foil never writes one and refuses to display one, because the number you were shown would not be the number that trades.
- Everything asked for goes to the maker. No fee item, no second recipient. Foil takes nothing, and an order that pays a third party is refused by the reader before a wallet is ever asked.
- No conduit. Tokens are approved to the exchange itself, for exactly what this trade moves.
Signing costs nothing and is not a transaction. Until somebody fills it, the only place the offer exists is wherever you sent it.
What settles it
Foil deploys no contract. Offers are settled by Seaport 1.6, the exchange contract OpenSea wrote, at the address it has on every chain it is deployed to — including this one, where it was already in use before Foil existed: 78,961 of its events had been emitted here by the time this was measured, the first at block 656,397.
We did not write it, we have not audited it, and nothing here should be read as a claim that it is safe. What can be said precisely is what it does with one of these offers: it checks the signature, checks the order has not been cancelled or filled or expired, moves the offered item from the maker to the filler and the wanted item from the filler to the maker, and reverts the whole transaction if any part of that cannot be done.
The page asks Seaport for its own information() before it will sign anything against it, and tools/verify-addresses.mjs refuses any version but the one above — a different exchange at that address stops the build rather than quietly receiving orders.
- Exchange
- 0x0000000000000068F116a894984e2DB1123eB395
- Foil's contracts
- none
- Approvals asked for
- exactly what the trade moves, to the exchange, each time
Private, public, partial
Private. Name a counterparty and their address becomes the order's zone. Seaport only skips the zone check when the filler is the zone; any other address makes it call the zone as if it were a contract, a plain wallet answers nothing, and the fill reverts. That refusal is executed on chain by property 7, and its control in the same call proves the named address still fills.
Public. With no counterparty, anybody holding the link can fill it. You can also publish the offer into Seaport's own event log, which is what the board reads — there is no database anywhere in Foil.
Partial. Seaport prices a part fill by a fraction applied to every amount, and refuses a fraction that does not divide exactly. Foil fixes the denominator at 10,000 and rounds a partial offer's amounts down to a multiple of it, so any hundredth of a per cent can be taken and neither side can be rounded against.
Cancelling. One offer is cancelled by name. Everything you have ever signed is cancelled by moving your counter — one call, however many offers are outstanding. Both are your wallet talking to Seaport.
How the pool comparison is measured
The number on the front page is not a spread and not a fee schedule. It is a round trip between two people who want opposite things:
- One buys $50,000 of a stock through the pools.
- The other sells those same shares back, from the same pool state — they are strangers, so neither waits for the other.
- What comes back is less than what went in. That gap is what the pools charged the pair of them: fees plus both sides of price impact.
Trading with each other instead, at a price in between, neither pays any of it. Because the measurement is a comparison of two simulated trades rather than a trade against a mid price, it needs no oracle — and it cannot flatter itself the way measuring a pool against its own mid does.
The pools are given their best shot: each order is split across up to 4 pools, fee-aware, walked tick by tick with the real tick data, on both Uniswap v3 and v4. Pools charging over 1% are excluded as traps rather than markets. Gas is not included on either side.
The arithmetic is js/sim.js, checked against Uniswap's own deployed quoters — 59 swaps, exact to the wei, in both directions, on both versions.
What has been checked
Each check below has a control that must fail: a validator that stopped validating looks exactly like a clean build.
| What | Result | How |
|---|---|---|
| Properties, executed on Robinhood Chain | 20/20 | at block 65,601,412, 4,991 bytes of init code, never deployed. Includes a control (13) which writes every balance one storage slot along and MUST fail. |
| Sabotages of the order builder | 19/19 | each caught by the check named for it, after a control run with nothing broken came back 20/20 green. |
| Random sequences on a fork | 2 seeds | 2,527 checks across 84 steps, 9 invariants after every operation; 12/12 deliberate breaks caught by the invariant named for each. |
| The real page in a real browser | 40/40 | Chrome, the deployed Content-Security-Policy, a wallet that signs with a real key, against a fork of this chain. |
| Pool arithmetic against Uniswap | 8/8 | 59 swaps compared with Uniswap's own quoters, exact to the wei, both directions, v3 and v4. |
| The exchange is the one we sign for | yes | its own information() says version 1.6 and reports the domain separator this site computes; its code differs from the same address on Base by 34 bytes, which is where a chain id and a domain separator are compiled in. |
Every figure on this site is computed from the files in data/ by tools/figures.mjs, which throws if a figure is missing, and re-checked by tools/validate.mjs. No measured number is typed into a page by hand.
The case against Foil
The honest version of this argument has to include the part that does not flatter it.
- A pool is always there. A person is not. Foil does not find you a counterparty, and that is the hard half of trading. If you do not already know who is on the other side, an automated market maker is doing something for you that this page does not.
- For small trades in deep names the pools are nearly free. The cheapest stock on this chain round-trips 0.10% at $10,000. Nobody should write an offer to save that.
- An offer is a free option for the person holding it. Until it expires, they can take it if the market moves their way and ignore it if it does not. That is why the default expiry is an hour and the longest Foil will write is a week.
- Somebody has to price it. A pool quotes for you. Here you and your counterparty agree a number, and the page's job is only to tell you both what the pools would have done.
- Seaport is somebody else's code. It is used heavily elsewhere, and this site executes properties against it rather than trusting it — but Foil has not audited it, and has not been audited itself; neither claim is one this page makes.
What Foil does not do
- No order book, no matching, no counterparty discovery beyond a list of what has been published on chain.
- No ETH. Native ETH can only be given by the filler in Seaport, never offered by the maker, so an ETH trade cannot be written symmetrically; wrapped ETH works like any other token.
- No NFTs, no bundles, no criteria orders, no decaying prices, no zones other than a plain counterparty address.
- No fee, and no contract that could take one.
- No custody: Foil never holds anything and has nothing to return.
- No other chains.