paint-brush
Creating a Simple DeFi Protocol on Ethereum with Hardhat: A Step-by-Step Guideby@luisacerv
638 reads
638 reads

Creating a Simple DeFi Protocol on Ethereum with Hardhat: A Step-by-Step Guide

by LuisAcervMarch 22nd, 2023
Read on Terminal Reader
Read this story w/o Javascript
tldt arrow

Too Long; Didn't Read

This guide walks you through the process of creating a simple DeFi protocol. We'll use Hardhat, a powerful development environment for Ethereum. This article is for educational purposes only. Do not use this information to build a real-world DeFi Protocol without proper research, security audits and legal advice.
featured image - Creating a Simple DeFi Protocol on Ethereum with Hardhat: A Step-by-Step Guide
LuisAcerv HackerNoon profile picture

Decentralized finance (DeFi) has been revolutionizing the financial industry, with Ethereum at the core of this transformation. In this guide, we'll walk you through the process of creating a simple DeFi protocol on Ethereum using Hardhat, a powerful development environment for Ethereum. By the end of this tutorial, you'll have a basic understanding of the tools and techniques required to build your own DeFi protocol.


Disclaimer: This article is for educational purposes only. Do not use this information to build a real-world DeFi protocol without proper research, security audits, and legal advice.


  1. Prerequisites:


To follow this tutorial, you'll need:

  • A basic understanding of blockchain technology and Ethereum
  • Familiarity with the Solidity programming language
  • Node.js installed on your computer
  • An Ethereum wallet, such as MetaMask


  1. Set up the development environment:

We'll use Hardhat, a popular development environment for Ethereum. To install Hardhat, open your terminal and run:


npm install --global hardhat


  1. Create a new Hardhat project:


Navigate to your desired project folder and run:


npx hardhat


Select "Create an empty hardhat.config.js" to create a new Hardhat project.


  1. Install necessary packages:

To interact with Ethereum, you'll need the following packages:


npm install --save-dev @nomiclabs/hardhat-ethers ethers @nomiclabs/hardhat-waffle ethereum-waffle chai


  1. Update hardhat.config.js:


Add the following code to your hardhat.config.js file to configure the Hardhat project:

require("@nomiclabs/hardhat-ethers");

module.exports = {
  solidity: "0.8.4",
};


  1. Write the smart contract:


In the "contracts" folder, create a new file called SimpleDeFi.sol. This file will contain the Solidity code for our DeFi protocol. Here's an example contract:

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

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";

contract SimpleDeFi {
  using SafeERC20 for IERC20;
  IERC20 public token;
  address public owner;

  constructor(address _token) {
    token = IERC20(_token);
    owner = msg.sender;
  }

  function deposit(uint256 amount) external {
    require(amount > 0, "Amount must be greater than zero");
    token.safeTransferFrom(msg.sender, address(this), amount);
  }

  function withdraw(uint256 amount) external {
    require(token.balanceOf(address(this)) >= amount, "Insufficient balance");
    require(msg.sender == owner, "Only owner can withdraw");
    token.safeTransfer(owner, amount);
  }
}


This simple DeFi protocol allows the owner to deposit and withdraw ERC20 tokens.


  1. Write and run tests:

In the "test" folder, create a new file called SimpleDeFi.test.js. Write tests to ensure the smart contract behaves as expected:

const { expect } = require("chai");

describe("SimpleDeFi", function () {
  let SimpleDeFi, simpleDeFi, Token, token, owner, addr1;

  beforeEach(async () => {
    Token = await ethers.getContractFactory("ERC20Mock");
    token = await Token.deploy();
    await token.deployed();

    SimpleDeFi = await ethers.getContractFactory("SimpleDeFi");
    simpleDeFi = await SimpleDeFi.deploy(token.address);
    await simpleDeFi.deployed();

    [owner, addr1] = await ethers.getSigners();
  });

  describe("Deployment", () => {
    it("Should set the correct owner", async () => {
      expect(await simpleDeFi.owner()).to.equal(owner.address);
    });

    it("Should set the correct token", async () => {
      expect(await simpleDeFi.token()).to.equal(token.address);
    });
  });

  describe("Deposit and Withdraw", () => {
    it("Should deposit tokens to the contract", async () => {
      const amount = ethers.utils.parseEther("100");
      await token.transfer(owner.address, amount);
      await token.connect(owner).approve(simpleDeFi.address, amount);

      await simpleDeFi.connect(owner).deposit(amount);
      expect(await token.balanceOf(simpleDeFi.address)).to.equal(amount);
    });

    it("Should allow the owner to withdraw tokens", async () => {
      const depositAmount = ethers.utils.parseEther("100");
      const withdrawAmount = ethers.utils.parseEther("50");

      await token.transfer(owner.address, depositAmount);
      await token.connect(owner).approve(simpleDeFi.address, depositAmount);

      await simpleDeFi.connect(owner).deposit(depositAmount);
      await simpleDeFi.connect(owner).withdraw(withdrawAmount);

      expect(await token.balanceOf(simpleDeFi.address)).to.equal(depositAmount.sub(withdrawAmount));
      expect(await token.balanceOf(owner.address)).to.equal(withdrawAmount);
    });

    it("Should not allow non-owners to withdraw tokens", async () => {
      const depositAmount = ethers.utils.parseEther("100");

      await token.transfer(owner.address, depositAmount);
      await token.connect(owner).approve(simpleDeFi.address, depositAmount);

      await simpleDeFi.connect(owner).deposit(depositAmount);

      await expect(simpleDeFi.connect(addr1).withdraw(depositAmount)).to.be.revertedWith("Only owner can withdraw");
    });
  });
});


  1. Run the tests:

In the terminal, execute the following command to run the tests:

npx hardhat test


This will execute the tests and show the results.


  1. Deploy the smart contract:


Create a deployment script in the "scripts" folder. Name it deploy.js and add the following code:

async function main() {
  const Token = await ethers.getContractFactory("ERC20Mock");
  const token = await Token.deploy();
  await token.deployed();
  console.log("Token deployed to:", token.address);

  const SimpleDeFi = await ethers.getContractFactory("SimpleDeFi");
  const simpleDeFi = await SimpleDeFi.deploy(token.address);
  await simpleDeFi.deployed();
  console.log("SimpleDeFi deployed to:", simpleDeFi.address);
}

main()
  .then(() => process.exit(0))
  .catch((error) => {
    console.error(error);
    process.exit(1);
  });


To deploy the smart contract, run the following command:

npx hardhat run scripts/deploy.js


  1. Interact with the DeFi protocol:


You can use Hardhat's console to interact with the deployed DeFi protocol. First, create a console.js script in the "scripts" folder with the following code:


const hre = require("hardhat");

async function main() {
  const [owner, addr1] = await hre.ethers.getSigners();
  const tokenAddress = "YOUR_TOKEN_ADDRESS";
  const simpleDeFiAddress = "YOUR_SIMPLEDEFI_ADDRESS";

  const Token = await hre.ethers.getContractFactory("ERC20Mock");
  const token = Token.attach(tokenAddress);

  const SimpleDeFi = await hre.ethers.getContractFactory("SimpleDeFi");
  const simpleDeFi = SimpleDeFi.attach(simpleDeFiAddress);

  // Example: Deposit tokens
  const depositAmount = hre.ethers.utils.parseEther("100");
  await token.connect(owner).approve(simpleDeFi.address, depositAmount);
  await simpleDeFi.connect(owner).deposit(depositAmount);

  // Example: Check the contract's token balance
  const balance = await token.balanceOf(simpleDeFi.address);
  console.log("Contract balance:", hre.ethers.utils.formatEther(balance));
}

main()
  .then(() => process.exit(0))
  .catch((error) => {
    console.error(error);
    process.exit(1);
  });


Don't forget to replace YOUR_TOKEN_ADDRESS and YOUR_SIMPLEDEFI_ADDRESS with the actual addresses from your deployment.


Run the console.js script using the following command:


npx hardhat run scripts/console.js

You can modify the console.js script to interact with your DeFi protocol in different ways, such as depositing, withdrawing, and checking balances.


Conclusion:

In this tutorial, we've shown you how to create a simple DeFi protocol on Ethereum using Hardhat. We covered the basics of setting up a Hardhat project, writing a smart contract, testing, deploying, and interacting with the deployed contract. This is just the beginning; you can now extend and modify this basic DeFi protocol to create more complex and feature-rich financial applications on the Ethereum blockchain.