DEV Community

Cover image for Create a decentralized exchange (DEX) for ERC-20 token
Majid Kareem
Majid Kareem

Posted on

Create a decentralized exchange (DEX) for ERC-20 token

This is the first part in a probably very long series of posts.
In this post, I'll be explaining how to create a decentralized exchange for an ERC-20 token.

Expectations

This post assumes basic knowledge of solidity, the ERC standard, and creating a basic ERC20 token

Creating the ERC20 token

We'll create a basic ERC20 token by importing the ERC20.sol from Openzeppelin. Our token will be named TSTtoken and it's gonna have a total supply of 1 million.

// TSTtoken.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/ERC20.sol";

contract TSTtoken is ERC20 {

uint256 initialSupply = 1000000e18;
    constructor() ERC20("Test", "TST") {
        _mint(msg.sender, initialSupply);
    }
}

Enter fullscreen mode Exit fullscreen mode

Next we will create the smart contract for our DEX in DEX.sol.

//SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/IERC20.sol";
import './TSTtoken.sol';

contract DEX {

    IERC20 public token;

    event Bought(uint256 amount);
    event Sold(uint256 amount);

    constructor(){
        token = new TSTtoken();
    }

    function buy() payable public {
        // TODO
    }

    function sell(uint256 amount) public {
        // TODO
    }

}

Enter fullscreen mode Exit fullscreen mode

Our DEX contract has two functions

  • buy: The user can send ether and receive TSTtoken in exchange

  • sell: The user can send TSTtoken and get back ether

The Buy Function

To code the buy function, we'll have to check the amount ether being sent to the contract in the message (i.e msg.value) and verify that the contract owns enough TSTtoken. If the contract has enough TSTtoken, it sends it to the user and emits the Bought event.

Note:

For simplicity, we'll exchange 1 TSTtoken for 1 Wei

function buy() payable public {
    uint256 amountTobuy = msg.value;
    uint256 dexBalance = token.balanceOf(address(this));
    require(amountTobuy > 0, "You need to send some ether");
    require(amountTobuy <= dexBalance, "Not enough tokens in the reserve");
    token.transfer(msg.sender, amountTobuy);
    emit Bought(amountTobuy);
}

Enter fullscreen mode Exit fullscreen mode

I guess the buy function is pretty easy

The Sell Function

This function will require the user to have approved the sell amount by calling the ERC-20 approve function.

When the sell function is called, we'll call the ERC-20 transferFrom function to transfer the tokens from the caller address to the contract address. If the transfer is successful, we'll send the equivalent amount of Eth back to the caller address.

  function sell(uint256 amount) public {
        require(amount > 0, "You need to sell at least some tokens");
        uint256 allowance = token.allowance(msg.sender, address(this));
        require(allowance >= amount, "Check the token allowance");
        token.transferFrom(msg.sender, address(this), amount);
        payable(msg.sender).transfer(amount);
        emit Sold(amount);
    }

Enter fullscreen mode Exit fullscreen mode

Cool, we've just written a smart contract for a very basic DEX. Now anyone can buy and sell our token with Eth. Here is the complete code for the DEX.sol file.

//SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/IERC20.sol";
import './TSTtoken.sol';

contract DEX {

    IERC20 public token;

    event Bought(uint256 amount);
    event Sold(uint256 amount);

    constructor() {
        token = new TSTtoken();
    }
    function buy() payable public {
        uint256 amountTobuy = msg.value;
        uint256 dexBalance = token.balanceOf(address(this));
        require(amountTobuy > 0, "You need to send some ether");
        require(amountTobuy <= dexBalance, "Not enough tokens in the reserve");
        token.transfer(msg.sender, amountTobuy);
        emit Bought(amountTobuy);
}

    function sell(uint256 amount) public {
        require(amount > 0, "You need to sell at least some tokens");
        uint256 allowance = token.allowance(msg.sender, address(this));
        require(allowance >= amount, "Check the token allowance");
        token.transferFrom(msg.sender, address(this), amount);
        payable(msg.sender).transfer(amount);
        emit Sold(amount);
    }

}

Enter fullscreen mode Exit fullscreen mode

Ways to improve the DEX

  • Implement an exchange of TSTtoken to another ERC20 token e.g DAI, UNI etc

  • Add a fee on Buy and Sell of the token

  • Add the liquidity for TSTtoken with transaction fees generated to uniswap by implementing the addLiquidity/addLiquidityETH function

Top comments (0)

Some comments may only be visible to logged-in visitors. Sign in to view all comments.