UniswapV2 Routing
If you ever wondered how the Uniswap Router works look no further!
I wanted to figure out how Uniswap does routing between tokens, so I took a deep dive into the code behind the function swapExactTokenForTokens
. I recommend reading the official docs and the full code can be found on etherscan.io.
It starts with swapExactTokenForTokens
. The interesting part is that it takes an array of tokens to swap between. But no information regarding where they should be swapped.
Before we go further lets break down the logic behind swapExactTokenForTokens
. It takes the following input:
amountIn
, amount of token swapped by the sender. The router needs to have permission to transfer these.amountOutMin
, the min amount that the router should send to addressto
path
, a list of addresses to tokens.swapExactTokenForTokens
will swap tokens with Uniswap Pairs according to the order of tokens in thepath
.to
, the address we want to recevice tokens.deadline
, time that the transaction is valid.
On a high level swapExactTokenForTokens
does the following four things.
- Calculate the
amounts
to swap with each pair. - Check that the last swap will yield an amount greater than
amountOutMin
. - Transfer from
msg.sender
to the first pair specified inpath
. - Iterate over the
path
and swap until we reach the last pair, then execute the last swap to the address specified into
.
Lets deep dive into the functions used by swapExactTokenForTokens
and see what they do.
UniswapV2Library.getAmountsOut
is then used to calculate the amount to swap with each pair. It does so by looping through the path
and calling getReservers
and getAmountOut
on each pair.
getReserves
and getAmountOut
both use pairFor
to find out which pair to call and then they call the corresponding function of that pair. Uniswap pairs have their tokens in a predetermined order specified when deploying the tokens. Therefore we need to shuffle the reserves so that the token order in the pair matches the token order in the trade.
pairFor
is at first glance a magic function. Uniswap deploys pairs using CREATE2 addresses. That means that given the tokens we can calculate the address of their pair. This works because the UniswapV2 factory only allows one pair with the same tokens.
After we have our amounts we check that amounts[amounts.length-1] > amountOutMin
. We then use safeTransferFrom
to move tokens from msg.sender
to the first pair, this requires that amountIn
has already been approved for transfer. abi.encodeWithSelector
is used to figure out what function on the token to call. Reading the IERC20 API, I am pretty sure that transferFrom
is called here.
Everything up to this point has been a build up in order for us to swap through our path of tokens. That is done through _swap
. There we loop over all tokens in our path and swap with their corresponding pairs.
Before we can swap we once again need to get the pair address which is done with pairFor
mentioned above. We also check if we are on the last swap. If we are, we swap to_to
instead of the next pair.
As mentioned earlier the order of tokens in the pair might be different from the swap order. Therefore the tokens are sorted with sortTokens
.
The internals of swap
will be covered in detail at a later time.