Compare Uniswap V3 and V4 routes
Inspect a Uniswap route decision in Determica, from pinned chain state and exact calldata to execution evidence and every check behind PASS or FAIL.
Goal #
A quote gives you a number. It does not show whether the exact transaction reproduces that number against the same state, which code and call contexts it reaches, what balance and final effects survive, how gas changes the ranking, or why a candidate was rejected.
This guide keeps the route decision in one editable Determica notebook. Candidates remain inspectable as data. Contract state is pinned. Selected routes execute as exact calldata. Receipts, observations, effects, checks, rankings, failure reasons, and the selected call trace are published as queryable tables.
Run the route decision #
Set the trade size and sender, then run all eight steps against finalized Ethereum mainnet state. The notebook publishes evidence as queryable tables. It does not sign or send a transaction.
1. Create the market checkpoint #
Create one market checkpoint for all later quotes, simulations, and checks. Pin the client to a finalized Ethereum mainnet block by default. Record the candidate pools, trade inputs, sender, and router deadline. get_gas_price samples the RPC gas price when the notebook runs, while contract reads use the pinned block. Use the pinned Chainlink ETH/USD price to estimate gas cost in USDC. The estimate requires a valid oracle answer no more than two hours old and assumes 1 USDC = 1 USD.
2. Verify runtime-code identity #
Before comparing routes, confirm that each declared dependency and discovered V3 pool matches its expected runtime code. A missing pool or hash mismatch stops the quote step and prevents PASS.
These checks establish code identity at the pinned block. They do not establish contract security or correctness.
3. Compare route quotes #
The quote leaderboard compares gross USDC output across the declared route set at the same pinned block. Gross output excludes gas, so the quote leader is not yet the decision winner.
The notebook carries the highest gross quote from each family into execution. It retains every other quote and later uses the highest unexecuted quote as a conservative comparison bound.
4. Simulate exact router calls #
A quote does not establish that the corresponding router call produces the same output. This step encodes the three family leaders as exact Universal Router calls and executes them against the pinned state.
Each receipt binds a candidate to its payload hash, execution identity, and pinned block. Pre-execution and terminal balance observations record what changed. The notebook does not sign or send a transaction.
5. Rank eligible execution results #
The execution leaderboard first checks whether each call passes every execution, evidence, and call-policy check. Net output is simulated USDC output minus gas valued in USDC. Rejected routes remain visible with their first failed check.
The 0.5×, 1×, and 2× scenarios show whether route order depends on the sampled gas price. Only the 1× ranking controls the decision.
6. Make the route decision #
preflight_decision is the authoritative result for the notebook run. PASS requires complete market, runtime-code, quote, execution, and evidence coverage.
The conservative winner bound compares the leading eligible route’s 1× net output with the highest gross quote among unexecuted routes. A PASS identifies a winner only within the declared route set and pinned state. It does not establish a global optimum or later-state validity.
7. Inspect decision checks #
Use the audit table to determine why a route passed or failed. It expands each route’s ordered checks and the global comparison checks. Rejected routes remain visible with observed values and rejection reasons.
Use preflight_decision as the authoritative outcome. The audit does not expose every evidence and ranking completeness count enforced by the decision.
8. Inspect the selected call path #
After PASS, inspect the selected execution as a normalized call tree. Each row shows which code ran, its call context, and its position in the frame hierarchy.
UNEXPECTED_TARGET identifies code outside the declared route allowlist. The root row includes the retained execution dossier for further review.
Use the decision record #
The output is not only a selected route. It is a queryable decision record that keeps the pinned state, candidate set, exact calldata, execution evidence, policy checks, and rejection reasons together.
Use that record to change the candidate relation or scoring rule, rerun the analysis, and challenge the result without rebuilding a private trace schema. Gas-adjusted rankings support route review, while code identity, call context, balance changes, and effects support execution review.
The result remains bounded to the declared candidates, inputs, pinned block, and sampled gas price. execution_result_root commits only to the simulated execution, not the quote set or ranking logic. The notebook does not authorize or send a transaction.
Functions used in this guide
- get_block
- get_gas_price
- client_context
- pin
- read_contract
- read_contract_multicall
- native_balance
- code_at
- parse_units
- parse_ether
- format_units
- format_ether
- muldiv
- evm_ceil_div
- try_mul
- try_sub
- keccak256
- abi_encode_packed
- encode_function_data
- encode_function_args
- call_decode
- to_timestamp
- client
- program
- execute_call
- assume_no_code
- assume_native_balance
- observation_fact
- observe
- run