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 basic 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);
}
}
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
}
}
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);
}
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);
}
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/openzeppelincontracts/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);
}
}
Ways to improve the DEX
-
Implement an exchange of TSTtoken to another ERC20 token e.g DAI, UNI etc
-
Add our 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