How Uniswap Auto Router Works
Library to get the best route on uniswap used in production
Uniswap Auto Router gives you the best route on uniswap by splitting the trade. It is used in production and basically you input the tokens to trade and the amount, it will tell you the best route, quote, gas adjusted quote, etc.
I’m just curious how it made possible to get the optimized trade part, so I looked into it. It has so much code, so it took me while to figure out how it works.
Get pool data
The auto router gets the pool data from subgraph pools with the following uri:
https://cloudflare-ipfs.com/ipns/api.uniswap.org/v1/pools/${protocol}/${chainName}.json
For example, you can get uniswap V3 pool data on polygon mainnet with https://cloudflare-ipfs.com/ipns/api.uniswap.org/v1/pools/v3/polygon-mainnet.json.
The json data contains an array of each pool info like the following:
{
"id": "0x0004302b6a85e5e4ecc88317efe3ce4da7f7f05e",
"token0": {
"id": "0x0d500b1d8e8ef31e21c99d1db9a6444d3adf1270"
},
"token1": {
"id": "0x6e6dab6be7c102eb4ff73e82046dd9d0f9bbc3aa"
},
"feeTier": "100",
"liquidity": "49999990208047568803",
"tvlETH": 0.0025879711685522673,
"tvlUSD": 3.34181459860312
}
id
means an address, and tvlUSD
means the total market value of the pool that has in USD.
This is useful when you want to get all uniswap pool info without a node rpc url.
Get candidate pools
In order to speed up getting the best route, it first filter out pools by checking whether it has blocked tokens, tokens to trade, etc.
Computing all routes
After getting all relevant pools, it computes the possible routes to connect token in and token out. computeAllRoutes
is the function that gets the possible routes. It figures out what pools fit in the next with loop and does this recursively.
When I was doing MEV, I used Neo4j to find possible routes and cache the result to key-value DB, so I’m interested in which is the better approach. This is where you can optimize with the compiled language like Rust for better performance. I hope Uniswap team build the next router with Rust or Go.
Get quotes
After getting routes, it will get quotes for the combination of every route and every amount. In the next part, it will combine all the quotes for small parts to get the best combinations of routes and trading parts. In order to do that, first it have to get all the quotes for each small trading part of each route. It quotes uniswap V3 prices with Quoter
contract, which you can simulate the swap with eth_call
method using a node api.
e.g.
Found 26 possible routes
percentages: [5%, 10%, 15%, … 100%] (20 parts)
Number of Quotes: 26 * 20 = 520
Speaking of quoting uniswap V3 prices, when I was doing MEV, I stored all the uniswap V3 pool states on Redis and query prices using that Redis. You can update the pool states with just listening to liquidity and swap events, so I like this method. It’s fast and doesn’t even require to run a node.
Get the best route
With all the possible routes and quotes, you can finally estimate the best route for a swap. First, it seeds a queue with the best quotes for each percentage. For routes without splitting, it can order by their 100% quotes. Quotes that are less than 100% need other parts to complete the swap, so it construct the swaps by filling other quotes to fit in. Pools for each split need to be different.
e.g. 1900 USDC -> WETH
(): percentage of trade
1 split
- USDC/WETH 0.5% fee (100%)
- USDC/WETH 0.1% fee (100%)
2 splits
- USDC/WETH 0.5% fee (95%), USDC/DAI 0.1% fee (5%) -> DAI/WETH 0.5% fee
- USDC/WETH 0.5% fee (95%), USDC/WBTC 0.5% fee (5%) -> WBTC/WETH 0.5% fee
Top 5 quotes for each split can be added to the best route queue. And after the gas factored in, it orders them by the highest quotes, and that’s how it get the best route.
I might have skipped important parts, so please correct me if I’m wrong. This could work with any Dex protocols except the quoting part. Splitting trade increases the gas use and need so many quotes, but it increase the amount you receive especially when you trade low-cap tokens or a huge amount of capitals.
Final Thoughts
Overall, the core algorithm of Uniswap Auto Router was not so complicated. I initially thought they might have some fancy math formulas to get the best route. However, what it does is to divide into small parts, to quote each one by one with the Quoter
contract, and to combine all quotes like building LEGO.
I’m currently experimenting a tool to get the best route. This library gave me some insights on how to approach it. I’m doing this because I hope to build something that helps people trade safely, but who knows. Let’s see how it goes. I feel better because I can opensource every single piece of code I write now.
If you have any trading strategy you want to try but don’t know how to build, please reach me out on twitter. I can help you build your bots with ~$1,000.
Thank you for reading😁