The order, not the trade
A swap is only dangerous to you before it settles. Once filled, the information is worthless. Umbra keeps the order sealed for exactly the window where it matters.
Umbra is a dark pool for Uniswap v4. Orders arrive sealed, open together, and cross against each other before anything reaches the curve. Everyone on the same side of a batch fills at the same price.
Every order you send on chain is public before it is filled. It sits in the mempool wearing everything it knows about you, and the distance between broadcast and inclusion is where the trade is taken apart. This has been treated as a law of nature. It is a design choice, and it can be made differently.
A swap is only dangerous to you before it settles. Once filled, the information is worthless. Umbra keeps the order sealed for exactly the window where it matters.
Sandwiching, front-running and back-running are all the same trade: act on an order you were shown for free. Take the reading away and the trade has no edge left.
It does not arrive as a fee. It arrives as a worse price than the one you saw, on the trades that were worth taking, which is exactly when it hurts.
A batch is a commitment scheme with a settlement at the end of it. Nothing about your order exists on chain until the window where reading it can no longer help anyone.
You send keccak256 of your order and a bond that is the same for everybody. No amount, no direction, no funds move. On chain, one commit is indistinguishable from another.
The window shuts and the pool goes dark. Inside the dark each trader hands over the preimage. A hash that does not match is not an order, and a commit that never opens loses its bond.
Buys and sells are crossed against each other at the pool mid. Only what has no counterparty is sent to the curve, as one swap, with a hard bound on how far it may move the price.
Inside a batch there is no first and no last, so there is nothing to pay for position. Every buyer fills at the same price and every seller fills at the same price. Being faster buys you nothing, which is the point.
| From the fork tests | Result |
|---|---|
| Two buyers, 1 ETH and 3 ETH, same batch | Both filled at 5367359687735004061440118 UMBRA per ETH, identical to the last digit |
| A batch where buys and sells cancel | Pool price moved by 4.0e-10 of itself, which is rounding dust and nothing else |
| A public swap during the open window | Reverted, PoolIsDark() |
| A revealed order that grew after being sealed | Reverted, BadPreimage() |
A commitment scheme alone would still leak: preimages are public, and a searcher who watches them open could trade ahead of the settlement. So the hook shuts the door. While a batch is opening, every swap that is not that batch reverts. Nothing can be placed in front of orders it was never allowed to read.
It reopens by itself. If a batch is never settled, a grace period expires and the pool goes back to being an ordinary pool, so a stuck batch can never hold the market shut.
// UmbraHook.beforeSwap if (sender == address(dark)) return NO_TOLL; // the batch settles free if (dark.isDark()) revert PoolIsDark(); // everyone else waits
This is a dark pool, not a mixer and not a privacy chain. Deposits and withdrawals are ordinary transfers and anyone can read them. What Umbra removes is the window in which your intent is public and unfilled: the size, the side and the timing of a trade that has not happened yet. Your balance is visible. Your order is not.
Until the batch opens, and by then it is being settled. Fills come out as one aggregate, so a single trade has no shape of its own on the curve.
Balances live in the contract and move in the open. Deposit early and unrelated to any order, which costs you nothing and tells watchers nothing.
Excluding an order that misses its limit means sorting the book, and sorting is a loop. Instead the whole batch is bounded: the residue may not move the price past a fixed cap, and what the cap will not take comes back to you.
Token, hook, LP manager and dark pool are on Ethereum mainnet and verified on Etherscan. The hook is wired to the dark pool and frozen there. Addresses are in the docs.
Initialised with the hook in its key and seeded single-side, so the whole supply went in and no ETH did. Batches settle into this pool and nowhere else.
There was no presale and there is no allocation to claim. The only way in is the pool, and 20 of 20 tests are green against the live contracts on a fork.