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

Written by luisacerv | Published 2023/03/22
Tech Story Tags: defi | ethereum-blockchain | smart-contracts | solidity | cryptocurrency | blockchain | programming | ethereum | web-monetization

TLDRThis 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.via the TL;DR App

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.


Written by luisacerv | Writing colorful characters in text files since 2011
Published by HackerNoon on 2023/03/22