<Swap/> with Uniswap [WIP]

Uniswap is a DeFi household name. If you have participated in any of the antics of the last 6 months, you have likely benefited from the unicorn protocol’s automated token liquidity 🦄.

Image for post
Image for post
Uniswap meets scaffold-eth
  • 💱 Grok swaps on Uniswap
  • 📝 Learn about token-lists

What is Uniswap? 🦄

Image for post
Image for post
All you could possibly need
  • The token we want: tokenOut
  • A fixed amount, specified either in tokenIn or tokenOut You can specify either the amount of tokens you have (EXACT_INPUT), or the amount of tokens you want (EXACT_OUTPUT). The other side will then be determined at point of transaction.

Forking main-net side-quest 🍴

Our first challenge was less to do with Uniswap, more to do with the fact that to develop new apps on top of DeFi, you need a realistic recreation of deployed protocols in your local setup.

yarn fork

The Uniswap SDK 🦄

Now we’ve got a local mainnet fork running, we are ready to integrate! Uniswap is kind enough to provide a javascript SDK for developers. The SDK primarily provides two things for our widget:

  • An easy way to Fetch the current on-chain state of Uniswap Pairs (i.e. the reserves of each Token).
  • It doesn’t know about ETH. While Ether is a first-class citizen when interacting with the Router, within the SDK you have to treat ETH as Wrapped ETH (WETH) 🎁
  • It doesn’t prepare or send transactions. The developer has to take the information about potential Trades from the SDK and prepare the appropriate transactions to actually exchange tokens with Uniswap ⚡

Token List side-quest ⚔️

While anyone can deploy an erc20 token contract on Ethereum, and anyone can see those contracts, that freedom and open-ness makes it hard for people to filter high quality legitimate tokens from scams and fakes. Announced in August 2020 by Uniswap, Token Lists are an effort to create a common standard for different organisations maintaining lists of tokens-of-interest:

Estimating trades with the SDK

Before we get a Uniswap Trade, we need to instantiate the required Tokens (which could be done using information from a token list!), and fetch the corresponding Pair data from our local chain:

import { ChainId, Token, WETH, Fetcher } from '@uniswap/sdk'const DAI = new Token(ChainId.MAINNET, '0x6B175474E89094C44Da98b954EedeAC495271d0F', 18)const pair = await Fetcher.fetchPairData(DAI, WETH[DAI.chainId], provider)
const DAI_TO_ETH = new Route([pair], DAI)const trade = new Trade(DAI_TO_ETH, new TokenAmount(DAI, '1000000000000000'), TradeType.EXACT_INPUT)
Trade.bestTradeExactIn(
pairs: Pair[],
amountIn: TokenAmount,
tokenOut: Token,
{ maxNumResults = 3, maxHops = 3 }: BestTradeOptions = {}):
  1. Get Pair information for all the possible combinations of the tokens in our list, where a Pair contract exists 🔭
  2. Use the relevant bestTrade method to identify the optimum Route from tokenIn to tokenOut across all those Pairs, and the estimated variable amount and corresponding price 💱

Swapping via the Router

The Router contract is our gateway to Uniswap. Before we are ready to submit our transaction, we need to think about two things. What are our safety parameters? And are we trading tokens or ETH?

What are our safety parameters? 🥽

Ethereum is an adversarial and unpredictable environment. As a result Uniswap has some built in controls to ensure that Swaps don’t go badly wrong. While a given trade will only specify one of an amountIn or an amountOut, the upper or lower bound for the other side is an additional parameter, as amountInMax or amountInMin.

Are we trading tokens or ETH?

The Uniswap Router treats ETH as a first-class citizen, but using ETH rather than a token does introduce some different requirements…

  • swapTokensForExactTokens
  • swapExactETHForTokens
  • swapTokensForExactETH
  • swapExactTokensForETH
  • swapETHForExactTokens

Executing the swap 🏁

With all that cleared up, we are ready to execute the trade. The Router ABI is available at @uniswap/v2-periphery/build/IUniswapV2Router02.json, so all that remains is to instantiate an ethers.js contract with our user’s signer and call the appropriate function with the parameters as required.

The finished widget

<Swap/> is a minimum viable component, taking great inspiration from the original Uniswap app.

Image for post
Image for post
Logos FTW!
  • Update it to work with non-mainnet Uniswap deployments (testnets, Honeyswap)
  • Extend the widget to visualise the changing price for different trade sizes
  • Set up a TWAP Swap
  • Build in other liquidity providers to get even better pricing (next stop 1inch!)
  • Get racy with Flash Swaps
  • Strip it down to a simple Swap button to keep things simple
  • [Your idea here!]
Image for post
Image for post
Who doesn’t want SOCKS?

Written by

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store