What's the 101? 

Building a Decentralized Exchange with Solidity

What's the 101? Building a Decentralized Exchange with Solidity

Learn what a Decentralized exchange is, and how to build one with Solidity, Hardhat, Moralis, PancakeRouter, Metamask and React!

Hello Degens!

Welcome to the birth of a new series, I'm super excited to take you through this marvelous project as we look to up our skills in full-stack web 3 engineering.

This article-tutorial series is built in partnership with Gabi, AKA CleverBlocks on youtube, a Fullstack Engineer at Weave Financial.

The video code content on his channel will be broken down more explicitly via these articles, as we seek to put more emphasis on the more complex topics in smart contract engineering.

Before diving into build mode, let's have a brief overview of what decentralized exchanges are and how they work.

What is a DEX?

markus-spiske-XrIfY_4cK1w-unsplash.jpg

A decentralized exchange (DEX) is an automated medium for the user-driven exchange of digital tokens. The term user-driven indicates a lack of intermediaries; meaning, users get to transact directly with each other and can do so without the need of a third-party such as a bank, broker, or other forms of centralized authority.

Read more about DEXs here! coindesk.com/learn/2021/08/20/what-is-an-au..

How does this all work?

Well, DEXes are smart-contract powered; meaning, a piece of code living on the blockchain dictates the rules of these token swaps between users and automates transactions. On the back-end, users can also stake their funds as liquidity - meaning, "Hey, I'll put my funds down as some sort of collateral for transactions, and in return, I earn a % return on these transactions". This entire structure creates a trustless ecosystem where digital assets can be securely and consistently transacted.

A few examples of such exchanges are uniswap, sushiswap, pancakeswap, and apeswap. Each of these platforms runs on native blockchain code and features a large list of compatible tokens for swapping.

As we get deeper in this series, we'll also detail the process of implementing liquidity pools and liquidity tokens, utilizing pancakeswap's Masterchef contract, and more!

At the end of this series, we'll be covering a lot more than simple solidity; this course goes into implementing smart contract inheritance, reentrancy securities, testing with hardhat, forking the mainnet blockchain with moralis, integrating our local blockchain with MetaMask, and writing custom solidity with detailed explanations, patterns, and documentation on every feature we implement!

Ready to get started? Let's get you all set up!

Setting up a local development environment

Head over to an IDE of your choice (I'll be using VSCode, which can be downloaded at "link"), open up a terminal, and type in the following command to initialize a project.

npm init

Following the prompts should generate a package.json file that contains information about your base project. After this, make your way to hardhat.org to get started installing the hardhat suite.

Copy the following command to your terminal

npm install - save-dev hardhat

Next, type in the following to run hardhat locally

npx hardhat

This command should present you with a short list of options, we'll stick with the first "Create a basic sample project" and hit enter.

Following the remaining prompts should get you set up with a gitignore and a project root folder.

Once you're done following the prompts and creating a hardhat project, we can get to importing smart contract dependencies and setting up our contracts folder!

PancakeRouter? Why?

The first dependency we need for our DEX is a Router contract. The router contains the core logic for swapping different token types, adding and removing liquidity , and functions that tell a user how many tokens they receive for their particular input amounts. It essentially acts as an intermediary between the users and other smart contracts.

We'll be writing our function implementations based on the interface for the PancakeRouter and connecting that to the pre-existing PancakeRouter contract on the Binance Smart Chain.

We'll also take a look at some transactions on the Binance Smart Chain to closely examine live examples of swap transactions.

Go ahead and open this link to view the different versions of PancakeRouter available.

For this series, we'll be using v1 and v2 as the base interfaces for our smart contracts. (learn how interfaces work in smart contracts here…)

Next Steps

Copy the contents of the v1 and v2 files and put them into a single file in your local directory named DexRouter.sol

Next, you should create a new file named DexterExchange.sol and import the interfaces in DexRouter.sol…at this point, your project should look like this.

Screenshot 2022-06-04 143836.png

Implementing Our Constructor

Congrats! We've learned a lot today. But before we round up, we'll be putting down a few lines of code and explaining what they do.

Navigate to your DexterExchange.sol and let's create our Router variable. This variable will be initialized to the address of PancakRouter currently active on the Binance Smart Chain. We'll be calling all the internal functions of the router via this variable.

...
import './DexRouter.sol'

contract DexterExchange {

       // declare state variable of type PancakeRouter02 interface
       IPancakeRouter02 public pancakeRouter;

      // the pancakeRouter variable will hold all internal methods of any contract with its      address specified in the constructor 
       constructor(address _pancakeRouter) {
           pancakeRouter = IPancakeRouter02(_pancakeRouter);
       }
}

Screenshot 2022-06-04 145218.png

Nice work! Now when we deploy DexterExchange, we'll pass in the address of pancakeRouter currently active on the Binance Smart Chain and run our Dex transactions with it!

Closing Remarks - Next Lesson Peek

mike-van-den-bos-jf1EomjlQi0-unsplash.jpg

Thanks for joining us today! I truly hope you find this guide helpful for getting started on building a DEX. In the next session, we'll be writing a function to swap BNB for an exact amount of tokens provided by the user.

We'll dive deep into payable functions, the IERC20 dependency, sending tokens to a contract, and granting our pancakeRouter permissions to transact tokens sent to payable functions. We'll also cover testing our first function with hardhat, forking the binance smart chain mainnet with Hardhat, and setting up our local chain with Metamask!

If you're looking to get ahead of the class, check out Gabi's Youtube for more videos on this course.

Catch up with Gabi and Me on Twitter for weekly solidity code review and request to join our dev discord!