TracerDocs
Docs menu
SwapVM programs

Running on the official router

Why v2 has no custom opcodes, and the compatibility evidence for that claim.

Tracer v1 shipped four custom SwapVM opcodes in the unallocated 0xd0..0xef bank. That meant Tracer had to deploy its own router to execute them, which is a strange thing to build on a shared-liquidity layer: every Tracer program was unrunnable on the official one.

v2 has no custom opcodes. Every program is three stock instructions, all of Tracer's logic lives behind the built-in Extruction (0x04) and a maker hook, and the programs run on the unmodified official AquaSwapVMRouter.

The compatibility gate

contracts/test/RouterCompat.t.sol is the evidence, and it ran before any production order encoding depended on the claim. Nothing in it is a Tracer contract: the maker is a bare EOA, pricing comes from a mock ExtructionEcho, and the hook target is a mock HookProbe. The gate measures the router, not Tracer.

Gate 1 — the router deployed at the canonical address

Observed on a Base mainnet fork at block 51,021,219, the canonical SwapVM address 0x111111338c5091E8440b67B168bAe16a668AC0De:

  • holds a SwapVM router that points at canonical Aqua, 0x1111113CCf1426A8E30e2bfF5E005d929bF6a90a;
  • hashes Aqua-mode orders identically to the pinned source — router.hash(order) == keccak256(abi.encode(order)) == the Aqua strategy hash;
  • does not expose the pinned swap ABI: neither quote((address,uint256,bytes),uint256,bytes) (0xb7ebf0c5) nor swap(...) (0xa69f95bd) is dispatchable, so the deployed bytecode is a different SwapVM revision than the submodule this repository pins and cannot be driven through ISwapVM.

The test asserts that observation, not a wish. If a future Base state does expose the pinned ABI, the test turns red and forces the decision to be revisited rather than silently going stale.

Gate 2 — the unmodified official source

The documented fallback for exactly that case is to deploy the official AquaSwapVMRouter from the pinned lib/swap-vm submodule, unmodified, and repeat the gate against it. That test proves the two facts v2 depends on:

  1. Extruction (0x04) calls out to an arbitrary target and lets it fix the swap registers.
  2. A maker postTransferIn hook fires with the amounts the router actually moved.

Both pass. That is the router Tracer deploys and the router every Tracer program runs on.

Why this matters

The claim v2 makes is custom SwapVM programs and external pricing logic, not custom opcodes. Concretely:

v1v2
Opcodes4 custom (0xd0–0xd3)none
RouterTracer's forkofficial AquaSwapVMRouter, unmodified
Where pricing livesinside the routerbehind Extruction, in TracerMarketEngine
Runs on the official routernoyes
Upstream files modifiednonenone

The TRACER_OPCODES table in web/src/lib/program.ts is deliberately empty, and the program viewer on each series page shows you the real thing: stock opcodes all the way down, with one Extruction whose target is Tracer's engine.