Build an ETH & ERC20 Tokens Exchange App With Uniswap

Build an ETH & ERC20 Tokens Exchange App With Uniswap

Introduction

Blockchain technology introduced a public ledger that everybody can use and nobody owns for the first time in the history of humankind. And yet, we have a bunch of centralized exchanges that control hashing power and private keys. Although centralized exchanges are necessary to exchange fiat money with cryptocurrencies, it goes against the original philosophy of bitcoin. The technology was supposed to transfer the power from institutions like the government and corporations to individuals.

 

How can we bring the control back to people? People have been building decentralized protocols to empower individuals. Among them is the decentralized exchange protocols. Each implementation has a different degree of decentralization, but I’m bullish on the Uniswap exchange protocol because they have a high degree of decentralization without compromising the user experience.

 

The only way to replace existing systems is to provide a better service that people want to use. As a developer, this means writing code and building things. We will do just that in this post. We will build a simple application that exchange Ether and ERC20 tokens using the Uniswap. If you follow along, you will be able to allow your dapp or wallet users to exchange Ether and ERC20 tokens easily.

 

I briefly talk about how the Uniswap works and then start building our application.

Uniswap in a Nutshell

Uniswap is a decentralized exchange protocol for Ether and ERC20 tokens. The whole process takes place on-chain and there are no gatekeepers. There is a separate exchange smart contract for each ERC20 token. These exchange contracts hold reserves of both Ether and their associated ERC20. Traders can make trades against the reserves at any time. They send Ether to the contract and get the ERC20 token out and vice versa. These reserves are deposited by liquidity providers who collect fees on every trade. It’s also possible to exchange between ERC20 tokens.

 

The price of the trade is automatically determined by the pricing formula: the Constant Product Market Maker Model. It is calculated so that the quantity of Ether in the contract * the quantity of A tokens in the contract is always constant. This formula applies to ERC20 tokens exchange as well where the quantity of A tokens in the contract * the quantity of B tokens in the contract is always constant.

 

Let’s say you have 10ETH and 1,000DAI in the Dai exchange contract. Then the constant would be 10 * 1000 = 10,000( x * y = k). If you send 1ETH to the contract then now there’s 11ETH in the contract. The contract says the Ether times the Dai in the contract needs to be held constant. So 10,000 / 11 ≒ 909DAI should be in the contract. This also means that the contract doesn’t have to have 1000DAI, and thus it returns 1000 – 909 = 91DAI back to the buyer, which is the difference between the amount that’s in the contract and amount of should be in the contract.

 

This formula is often called x times y equals k formula as well. The graph below shows how the price changes depending on the value of x and y:

 

The Uniswap reduces the cost of coordinating buyers and sellers through their reserve system and automatic pricing formula. As a result, traders can exchange tokens much easier and faster.

Set-Up

All right, let’s get started with our application. We will build a simple nodejs application that exchanges Ether and Dai. I made the GitHub repository for the finished code. I suggest that you take a brief look at it so that you can make a mental map before you start. I’m using macOS High Sierra.

 

Obtain Your Private Key and Address
First, obtain your private key and address from vanity-eth. Click on the “Generate” button. They will be generated for you at the bottom. Do NOT use these other than testing purposes.

 

Get Some Ether in Rinkeby Testnet
If you do not have any Ether in Rinkeby, get some via a faucet. Tweet something like this:

and paste the tweet link in the form. If it takes too much time to get Ether, ask your friends. I might be able to send you some if you tweet me @taisuke_mino.

 

You can check your balance in the Rinkeby Etherscan by searching your address. 0.1ETH should be enough.

 

Start a New Npm Project

*If you don’t have npm and nodejs, install them from here.

 

Initialize Git


Install the web3 Package

web3 is the Ethereum JavaScript API. It is an interface to Ethereum networks(including testnets). It communicates with an Ethereum node or transacts with smart contracts deployed on the blockchain from your JavaScript application.

 

Get the Infura Endpoint
We will use Infura as a provider to communicate with the Ethereum network. Make an Infura account and get the endpoint at Rinkeby by making a new project. It should look something like this:

 

Install the ethereumjs-tx Package

We use ethereumjs-tx to create and sign transactions.

Exchange Ether with Dai

Now we will start writing codes. You can see the finished code here.

 

Make a New File
Make a new file EthToDaiRinkeby.mjs. mjs is a file extension that allows you to write with ES6 syntax.

 

Import Packages


Declare the Exchange Contract Address and Abi Variables
This is the exchange contract address and the abi of Dai in Rinkeby testnet. I grabbed them from here. You use them to interact with the exchange smart contract.

 

the exchange contract address:

*you can see the contract in Etherscan.

 

the exchange contract abi:


Declare Your Address and Private Key Variables


Set Up Web3
Set up Web3 to use Infura as your web3 provider:


Instantiate the Contract
You use the Contract method of web3 with the address and abi to instantiate the contract. Pass those values as arguments to web3.eth.Contract.

Now we are ready to call the exchange contract function to exchange Ether with Dai.

 

Declare the ETH_SOLD Const Variable
First, I declare a const variable to specify the number of Ether I want to exchange with Dai:

 

Encode the Abi for the ethToTokenSwapInput Function
We use the ethToTokenSwapInput function to exchange Ether with Dai.

They take two arguments: min_tokens and deadline. The min_tokens argument specifies the minimum amount of Dai bought. The deadline argument is literally a transaction deadline. It says “this transaction can only execute within this time frame.”

 

These arguments can mitigate the risk of front-running by miners. Let’s say you are selling 1ETH and the current price is 200 DAI. You can say “If I get anything less than 199 DAI I want the transaction to fail.” Malicious front-runner might push the price ahead of you but you say that your transaction should go through only up to the amount you’ve specified in your transaction. The deadline helps you to mitigate the risk by preventing miners from holding transactions and executing them at a time where it’s more profitable for them. You can learn more about the front-running here.

 

I declare another const variable that I pass to min_tokens argument.

You want to choose the amount that is not too low because it’s easy to exploit for front-runners and not too high because your transaction could easily fail.

 

I declare another const variable that I pass to the deadline argument. This number below is the Unix timestamp of 10/01/2019 @ 12:00am (UTC). You’d want to specify the number depending on when you are reading this post. You can use an online converter tool here.

Now, pass two const variables as arguments of the ethToTokenSwapInput function and encode the abi for it:


Declare the
sendSignedTx Function
Next, make a function to sign a transaction object and then propagate that to an Ethereum network:


Construct a Transaction Object and Then Execute
sendSignedTx

Beware that I am passing exchangeEncodedABI and ETH_SOLD to data and value property for each.

 

Run the File

Once you get a transaction hash like this 0xbbc617c97323301d7376683a0ae58db012b418f27963e54866eb92bec4839e10, you can go to Etherscan to see the detail of your transaction. Below is my transaction as an example.

https://rinkeby.etherscan.io/tx/0xbbc617c97323301d7376683a0ae58db012b418f27963e54866eb92bec4839e10

If it were successful, now you can see that you received some DAI in your address from the Erc20 Token Txns tab.


Great!

Exchange Dai with Ether

Let’s exchange DAI with Ether next. This is going to be a bit tricky. We are going to make two transactions. First, we give the approval to the Uniswap Dai exchange contract so that the contract can spend Dai on behalf of our account. Second, we call the tokenToEthSwapInput function to exchange Dai with Eth.

Giving the approval to the Uniswap Dai exchange contract

We make another file for this: approveDaiExchangeRinkeby.mjs. I am going to skip the detail as most of the code is going to be the same. You can see the finished code here.

 

Declare the Token Contract Address and Abi Variables
This is the Dai token contract address and abi in Rinkeby testnet.

 

the token contract address:

*you can see it in Etherscan.

 

the token contract abi:

*token abis are usually all the same for ERC20 tokens if you want to integrate other ERC20 tokens.

 

Declare the daiExchangeAddress Variable

You give this address the approval to transfer Dai on behalf of your account.

 

Instantiate the Dai Token Contract


Declare Const Variables to Pass to the
approve Function

We give daiExchangeAddress the approval to transfer 1DAI.

 

Encode the Abi for the approve Function


Declare the
sendSignedTx Function
Make a function to sign a transaction object and then propagate that to an Ethereum network:


Construct a Transaction Object and Then Execute
sendSignedTx


Run the File

Once you get a transaction hash like this 0x1d16e0ccb3947ecbd34e16f9ae9378a17b16e11c701f1d0f44e5262d0e8f018a, you can go to Etherscan to see the detail of your transaction. Below is my transaction as an example.

https://rinkeby.etherscan.io/tx/0x1d16e0ccb3947ecbd34e16f9ae9378a17b16e11c701f1d0f44e5262d0e8f018a

2. Exchange Dai with Ether

Finally, let’s exchange Dai with Ether. Again, I am going to skip the detail as most of the code is going to be the same. I make another file, DaiToEthRinkeby.mjs, and call the tokenToEthSwapInput function.

There are three arguments. tokens_sold is the amount of ERC20 tokens sold. min_eth is the minimum Ether bought. deadline is a transaction deadline.

Now, pass three const variables as arguments of the tokenToEthSwapInput function and encode the abi for it:

Pass this tokenToEthEncodedABI to the data property of a transaction object.
Run the file:

Once you get the transaction hash 0x6011a9f50b80dba7a2cb3f9dbf327f0f4c28ec6a4205c2b4002b3a008aa480f4, you can go to Etherscan to see the detail of your transaction. Below is my transaction as an example.

https://rinkeby.etherscan.io/tx/0x6011a9f50b80dba7a2cb3f9dbf327f0f4c28ec6a4205c2b4002b3a008aa480f4

Now you can see that your DAI is subtracted from your address.


and the Ether is added to your address.


If you want to integrate other ERC20 tokens for exchange, you can do so by merely changing a token address in your code.

 

I hope you found this article useful to build a service the world has yet to see. 😎

 

Profile

Taisuke Mino
Crypto Developer
Tai is currently building on a mobile wallet specifically designed for MakerDAO. He is also involved in a dapps game in ICOVO as a software engineer.