Venues & routing
The append-only adapter registry, the live dexId table, and how a Route encodes a path across V2, V3, V4 and curve venues.
The trade manager knows nothing about any DEX. It resolves route.dex — a uint8 we call a dexId — through a registry of adapter contracts, and forwards the trade. Each adapter owns one venue’s specifics: router interfaces, approvals, WETH wrapping, callback plumbing, curve pre-checks. Adding a venue is one adapter deploy plus one owner transaction. No new manager, no re-approvals, no subgraph redeploy.
#The registry, and why it is safe to own
- Append-only.
addAdapter(dexId, adapter)reverts withAdapterExistsif that id is already bound. A dexId can never be re-pointed, so a route carries exactly the trust assumptions it had the day it was registered. - Pause is the only mutable bit.
setDexPausedcan disable a venue; it cannot redirect one. The worst an owner can do to an existing route is turn it off — reversibly. - Adapters are custody-free. They never see a user allowance and never hold funds between transactions. Only the manager is ever approved.
- Adapters bind their manager immutably. A new adapter cannot be pointed at an old manager, and an old adapter cannot be reused by a new one.
#The dexId table
Live on mainnet, none currently paused.
| dexId | Venue | Adapter | Address | Status |
|---|---|---|---|---|
| 0 | Uniswap V2 | UniswapV2V3Adapter | 0x5e4235F2…Ea34a6 | Active |
| 1 | Uniswap V3 | UniswapV2V3Adapter | 0x5e4235F2…Ea34a6 | Active |
| 2 | Uniswap V4 (native-ETH pools) | UniswapV4Adapter | 0x2017ddD2…B2A5C4 | Superseded by 7 |
| 3 | Flap curve | FlapAdapter | 0x794704d7…F2Bb11 | Active |
| 4 | Virtuals curve | VirtualsAdapter | 0x81D44e68…fE4233 | Active |
| 5 | SushiSwap V3 | SushiV3Adapter | 0xcA936118…9161Be | Active |
| 6 | Stock-quoted V4 pools | StockPairV4Adapter | 0x5bD5ce5e…1912e2 | Superseded by 7 |
| 7 | Multi-hop V4 (general executor) | MultiHopV4Adapter | 0xF0e2Fe45…4cDd13 | Active |
#The Route struct
The tuple layout is frozen and ABI-compatible back to earlier managers. What the fields mean belongs to the adapter the dexId routes to — a new venue that needs different parameters encodes them into v3Path as opaque bytes rather than changing the struct.
struct Route {
uint8 dex; // the dexId, resolved through the adapter registry
bytes v3Path; // V3: packed path. Others: adapter-defined payload
address[] v2Path; // V2: WETH-anchored token list
uint24 fee; // V4 pool fee
int24 tickSpacing; // V4 only
address hooks; // V4 only
}| dexId | v3Path | v2Path | fee / tickSpacing / hooks |
|---|---|---|---|
| 0 | — | WETH-anchored token list | — |
| 1, 5 | Full packed V3 path (WETH-anchored) | — | — (tiers live in the path) |
| 2 | — | — | V4 pool key; the pool is always (native ETH, token) |
| 3 | — | — | — (the Portal keys on the token) |
| 4 | WETH↔VIRTUAL leg (V3) | WETH↔VIRTUAL leg (V2, when non-empty) | — |
| 6 | The quote leg: packed V3 path | — | V4 pool key of (sort(quote, token), fee, tickSpacing, hooks) |
| 7 | abi.encode(MultiHopPath) — the whole route as opaque bytes | — | — (every key parameter lives inside the payload) |
#dexId 7 — the general V4 executor
One optional Uniswap V3 leg (WETH↔quote) followed by an ordered chain of N Uniswap V4 hops, all inside a single PoolManager unlock. It exists because the most interesting pools on this chain are not quoted in ETH: a Doppler-launched memecoin whose deep pool is priced in a Robinhood stock token, which itself only trades on V4.
ETH ──[V3]──▶ USDG ──[v4, 0.3%]──▶ TSLA stock ──[v4, Doppler dynamic fee]──▶ TSLA-Inc memestruct V4Hop {
address currency0; // sorted; address(0) = native ETH
address currency1;
uint24 fee; // 0x800000 marks a dynamic-fee pool — pass it verbatim
int24 tickSpacing;
address hooks;
}
struct MultiHopPath {
bytes v3Leg; // empty = no V3 leg
V4Hop[] hops;
}- Direction is derived, not declared. Hops carry no direction bit; the adapter works out
zeroForOnefrom the currency it currently holds and revertsBrokenChain()if a hop does not connect or the chain ends off-target. Buys run the V3 leg then the hops; sells run the hops then the V3 leg. - Flash accounting. Intermediate currencies net to zero inside the unlock and are never transferred — one settle at the start, one take at the end.
- Native ETH is a first-class chain currency. A buy with no V3 leg enters natively when the first hop is ETH-keyed, which is why dexId 7 fully supersedes dexId 2.
- Partial fills revert, per hop. Any hop that does not fully consume its input reverts with a typed
PartialFill()rather than over-settling into V4’s undecodableCurrencyNotSettled. That also rejects input-skimming hooks. Either way the trade is atomic.
#Hooked pools and the trust boundary
minAmountOut is the economic backstop: a hostile hook can make a trade worse, and the slippage floor rejects it. If you build your own routes against this adapter, that check is yours to make.Doppler’s decaying anti-snipe fee and creator cut ride afterSwap, and the PoolManager’s returned delta is already net of them, so exact-input chaining stays exact and simulation prices the whole chain correctly. Dynamic-fee pools carry fee = 0x800000 in the pool key — pass it verbatim, byte-for-byte, or the key will not match. A V4 pool id is keccak256(abi.encode(PoolKey)), which is a useful way to verify your key off-chain before you submit.
#Bonding-curve venues
dexIds 3 and 4 reach two pre-graduation curve venues on this chain (Flap and Virtuals), so a token that has not yet listed on a DEX is still tradeable from the terminal with the same ABI, the same fee, and the same slippage guarantees. Curve buys that cross a graduation threshold hand unconsumed ETH back; the manager forwards it and emits EthRefunded.
#Adding a venue
The path is deliberately narrow, and it is the same one dexIds 6 and 7 took: write an adapter extending TradeAdapterBase, with no admin surface and immutable addresses; test it against mocks and then against the live venue on a mainnet fork; deploy and addAdapter the next free id; verify on Blockscout. Ids are never reused and never renumbered — the frontend, the subgraph and the launch registry all key on these numbers.
