<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Ernesto</title>
    <description>The latest articles on DEV Community by Ernesto (@ernestothagreat).</description>
    <link>https://dev.to/ernestothagreat</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F444633%2F9f038475-6302-4b98-94e8-e5d747cfdb65.jpeg</url>
      <title>DEV Community: Ernesto</title>
      <link>https://dev.to/ernestothagreat</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ernestothagreat"/>
    <language>en</language>
    <item>
      <title>How to build a Liquidity Pool Smart Contract Using ERC-4626</title>
      <dc:creator>Ernesto</dc:creator>
      <pubDate>Tue, 22 Oct 2024 13:08:39 +0000</pubDate>
      <link>https://dev.to/ernestothagreat/how-to-build-a-liquidity-pool-smart-contract-using-erc-4626-2im8</link>
      <guid>https://dev.to/ernestothagreat/how-to-build-a-liquidity-pool-smart-contract-using-erc-4626-2im8</guid>
      <description>&lt;p&gt;In this tutorial we will walk you through how to build a functional liquidity pool which leverages the ERC-4626 standard for tokenized vaults, we will be using the ERC20 standard for the underlying token. This contract will allow users to deposit ERC20 tokens into a liquidity pool and receive Liquidity Pool tokens in return which represents their share of the pool.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prerequisite&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You should have a basic understanding of Solidity&lt;/li&gt;
&lt;li&gt;You should have a basic knowledge of React Js.&lt;/li&gt;
&lt;li&gt;You should have Nodejs and Foundry installed on your PC. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Project Setup and Installation For Solidity&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Run the command below to initiate a foundry project, we will be using foundry framework to build the  smart contract.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; forge init vault
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Open the vault folder on Vscode or your favorite code editor, and delete the scripts/counter.s.sol, src/counter.sol, and test/counter.t.sol.&lt;/p&gt;

&lt;p&gt;Install all dependencies&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    forge install foundry-rs/forge-std --no-commit &amp;amp;&amp;amp; forge install OpenZeppelin/openzeppelin-contracts --no-commit
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Overview of the Liquidity Pool Contract
&lt;/h3&gt;

&lt;p&gt;The contract will allow:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Users to deposit the allowed underlying token into the vault&lt;/li&gt;
&lt;li&gt;Users to get liquidity tokens when they make deposits&lt;/li&gt;
&lt;li&gt;Users to withdraw deposits and interest or yield generated&lt;/li&gt;
&lt;li&gt;Owner to add yield to the vault.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Code Overview
&lt;/h3&gt;

&lt;p&gt;The complete code for the smart contract can be found&lt;a href="https://github.com/Josh4324/liquidity-pool" rel="noopener noreferrer"&gt; here &lt;/a&gt;. The Vault contract is  deployed on sepolia-0xfB3F6E30e0A79d6D2213A91cfbc819e81E4757Af. &lt;/p&gt;

&lt;p&gt;You can also check out the live dapp &lt;a href="https://lambent-pony-3c5b6f.netlify.app/" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ERC-4626 (Tokenized Vault Standard)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;ERC-4626 is a standard on Ethereum that defines a tokenized vault for yield-bearing tokens, aimed at improving the efficiency and uniformity of DeFi protocols. &lt;/p&gt;

&lt;p&gt;It is an extension of the ERC-20 token standard, specifically designed to make it easier to create vaults that accept ERC-20 tokens as deposits and automatically generate yield on those assets. &lt;/p&gt;

&lt;p&gt;It allows assets to be wrapped and tokenized, enabling depositors to receive yield-bearing shares. It provides functions to deposit and withdraw assets, and track total assets in the vault.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ERC-20 (Fungible Token Standard)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;ERC-20 is a widely used standard for creating fungible tokens on the Ethereum blockchain. &lt;/p&gt;

&lt;p&gt;Fungible tokens are interchangeable, meaning that one token is equivalent to another of the same type (like how 1 US dollar is equal to another dollar). &lt;/p&gt;

&lt;p&gt;The ERC-20 standard provides a set of rules that developers must follow to ensure that tokens are compatible with the broader Ethereum ecosystem, including wallets, exchanges, and decentralized applications (dApps).&lt;/p&gt;

&lt;p&gt;Imports&lt;/p&gt;

&lt;p&gt;We import three contracts from OpenZeppelin:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  ** ERC20**: Standard implementation for fungible tokens.&lt;/li&gt;
&lt;li&gt;    &lt;strong&gt;ERC4626&lt;/strong&gt;: Implements the tokenized vault functionality.&lt;/li&gt;
&lt;li&gt;    &lt;strong&gt;Ownable&lt;/strong&gt;: Provides the access control mechanism for the owner.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; import "lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol";
    import "lib/openzeppelin-contracts/contracts/token/ERC20/extensions/ERC4626.sol";
    import "lib/openzeppelin-contracts/contracts/access/Ownable.sol";
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  State Variables
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;IERC20 public underlyingToken
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This stores the ERC-20 token that users will deposit into the liquidity pool.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Constructor&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The constructor initializes the liquidity pool and sets the underlying ERC-20 token. The vault’s name is set to &lt;code&gt;"Liquidity Pool Token" (LPT)&lt;/code&gt;. The contract inherits from &lt;code&gt;ERC4626&lt;/code&gt;, which will handle vault shares. It also inherits from &lt;code&gt;Ownable&lt;/code&gt; to restrict certain functions (like adding yield) to the owner.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  // ERC4626 constructor: Underlying token, Vault Token (e.g., "LP Token", "LPT")
        constructor(address _underlyingToken)
            ERC4626(IERC20(_underlyingToken))
            ERC20("Liquidity Pool Token", "LPT")
            Ownable(msg.sender)
        {
            underlyingToken =  IERC20(_underlyingToken);
        }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Deposit Function&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Users can deposit ERC-20 tokens into the liquidity pool by calling the &lt;code&gt;deposit()&lt;/code&gt; function. The function checks that the user is depositing more than zero tokens. After depositing, the user will receive vault tokens representing their share of the pool.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  // Function to deposit tokens into the pool
        function deposit(uint256 assets, address receiver) public override returns (uint256) {
            require(assets &amp;gt; 0, "Cannot deposit 0 assets");
            return super.deposit(assets, receiver);
        }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Withdraw Function&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Users can withdraw their deposited ERC-20 tokens by calling the &lt;code&gt;withdraw()&lt;/code&gt; function. This burns their vault tokens and transfers the corresponding amount of the underlying tokens back to them.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  // Function to withdraw tokens from the pool
        function withdraw(uint256 assets, address receiver, address owner) public override     returns (uint256) {
            return super.withdraw(assets, receiver, owner);
        }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Add Yield Function&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;addYield()&lt;/code&gt; function allows the contract owner to manually add yield (extra tokens) to the pool. This simulates the generation of interest or returns on the underlying assets. Only the contract owner can call this function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Example function: Simulate adding yield to the pool
        function addYield(uint256 amount) external onlyOwner {
            underlyingToken.transferFrom(msg.sender, address(this), amount);
        }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Total Assets Function&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This function returns the total number of ERC-20 tokens currently held in the pool. It overrides the ERC-4626 &lt;code&gt;totalAssets()&lt;/code&gt; function to reflect the pool's holdings.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    // Returns the total amount of underlying assets (ERC20 tokens) in the pool
        function totalAssets() public view override returns (uint256) {
            return underlyingToken.balanceOf(address(this));
        }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Project Setup and Installation For React.js
&lt;/h3&gt;

&lt;p&gt;Run the command below and follow the prompt to initiate a React project, we will be using react.js to build the frontend for the Liquidity Pool platform.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  npm create vite@latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Install the necessary dependencies.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  npm install npm install ethers react-toastify 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  App.js Overview
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Imports&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;App.css&lt;/strong&gt; -  contains styling for the components.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;tokenABI and vaultABI&lt;/strong&gt; - These JSON files contain the ABI (Application Binary Interface) definitions of the token and vault contracts, respectively, which are necessary for interacting with the contracts via &lt;code&gt;ethers.js&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ethers.js&lt;/strong&gt; -  A JavaScript library that allows interactions with the Ethereum blockchain. It is used to create contract instances, send transactions, and interact with smart contracts.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;react-toastify&lt;/strong&gt; - A notification system used to display messages to users, such as transaction success or failure.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    import './App.css'
    import tokenABI from "../abi/token.json";
    import vaultABI from "../abi/vault.json";
    import { ethers } from "ethers";
    import { toast } from "react-toastify";
    import { useState, useRef, useEffect } from "react";
    import "react-toastify/dist/ReactToastify.css";
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;State and Refs&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;useRef&lt;/strong&gt;: Used to track form input values for deposit, withdrawal, and yield operations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;useState&lt;/strong&gt;: Manages different states such as user address, wallet balance, token allowances, and vault asset data.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    const amountRef = useRef();
      const amountRef2 = useRef();
      const amountRef3 = useRef();
      const receiverRef = useRef();
      const receiverRef2 = useRef();

      const [address, setAddress] = useState("");
      const [balance, setBalance] = useState(0);
      const [allowance, setAllowance] = useState(0);
      const [totalA, setTotalAsset] = useState(0);
      const [UserA, setUSerAsset] = useState(0);
      const [amount, setAmount] = useState(0);

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Contract Creation Functions
&lt;/h3&gt;

&lt;p&gt;These functions create instances of the token and vault contracts, enabling read and write operations on the blockchain.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;createWriteContractToken&lt;/strong&gt;: Returns a token contract instance that can send transactions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;createGetContractToken&lt;/strong&gt;: Returns a token contract instance for reading values without modifying blockchain state.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;createWriteContractVault&lt;/strong&gt;: Returns a vault contract instance for sending transactions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;createGetContractVault&lt;/strong&gt;: Returns a vault contract instance for reading data.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    const createWriteContractToken = async () =&amp;gt; {
        const { ethereum } = window;
        const provider = new ethers.providers.Web3Provider(ethereum)
        const signer = await provider.getSigner();
        const tokenContract = new ethers.Contract(tokenAddress, tokenABI.abi, signer);
        return tokenContract;
      };
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This function uses the ethereum injected into the browser by Metamask, this allows the dapp to interact with ethereum provider and allows users to connect to the blockchain with metamask, the signer represents the user account and enables the contract to send transaction on behalf of the user. The &lt;code&gt;tokenContract&lt;/code&gt; instantiates the smart contract using the &lt;code&gt;ABI&lt;/code&gt;, &lt;code&gt;contract address&lt;/code&gt;, and &lt;code&gt;signer/provider&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Approve Function&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;approve&lt;/code&gt; function allows the user to give permission to the vault contract to spend their tokens. This function allows the vault to spend tokens on the user’s behalf, it uses the parseEther function to convert amount entered by the user into wei. The function also displays a loading message when the transaction is still loading.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
    const approve = async (evt) =&amp;gt; {
        evt.preventDefault();
        const contract = await createWriteContractToken();
        const id = toast.loading("Approval in progress..");
        try {
          const tx = await contract.approve(vaultAddress, ethers.utils.parseEther(amountRef.current.value));
          await tx.wait();
          setTimeout(() =&amp;gt; {
            window.location.href = "/";
          }, 10000);
          toast.update(id, {
            render: "Transaction successfull",
            type: "success",
            isLoading: false,
            autoClose: 10000,
            closeButton: true,
          });
        } catch (error) {
          console.log(error);
          toast.update(id, {
            render: `${error.reason}`,
            type: "error",
            isLoading: false,
            autoClose: 10000,
            closeButton: true,
          });
        }
      };
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Deposit and Withdraw Functions&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;These functions allow users to deposit tokens into the vault and withdraw their share of the pool's assets.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Deposit&lt;/strong&gt;: Transfers the specified amount of tokens to the vault contract and assigns vault shares to the user.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Withdraw&lt;/strong&gt;: Redeems the user's shares for the underlying token.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;code&gt;deposit&lt;/code&gt; function:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Calls the vault contract's &lt;code&gt;deposit&lt;/code&gt; function.&lt;/li&gt;
&lt;li&gt;Transfers the tokens from the user to the vault.&lt;/li&gt;
&lt;li&gt;The user receives shares representing ownership of a portion of the vault's assets.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;code&gt;withdraw&lt;/code&gt; function:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Calls the vault contract's &lt;code&gt;withdraw&lt;/code&gt; function.&lt;/li&gt;
&lt;li&gt;Transfers the tokens from the vault to the user.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; const deposit = async (evt) =&amp;gt; {
        evt.preventDefault();
        const contract = await createWriteContractVault();
        const id = toast.loading("Deposit in progress..");
        try {
          const tx = await contract.deposit(ethers.utils.parseEther(amountRef.current.value), receiverRef.current.value);
          await tx.wait();
          setTimeout(() =&amp;gt; {
            window.location.href = "/";
          }, 10000);
          toast.update(id, {
            render: "Transaction successfull",
            type: "success",
            isLoading: false,
            autoClose: 10000,
            closeButton: true,
          });
        } catch (error) {
          console.log(error);
          toast.update(id, {
            render: `${error.reason}`,
            type: "error",
            isLoading: false,
            autoClose: 10000,
            closeButton: true,
          });
        }
      };
      const withdraw = async (evt) =&amp;gt; {
        evt.preventDefault();
        const contract = await createWriteContractVault();
        const id = toast.loading("Withdrawal in progress..");
        try {
          const tx = await contract.withdraw(ethers.utils.parseEther(amountRef2.current.value), receiverRef2.current.value, address);
          await tx.wait();
          setTimeout(() =&amp;gt; {
            window.location.href = "/";
          }, 10000);
          toast.update(id, {
            render: "Transaction successfull",
            type: "success",
            isLoading: false,
            autoClose: 10000,
            closeButton: true,
          });
        } catch (error) {
          console.log(error);
          toast.update(id, {
            render: `${error.reason}`,
            type: "error",
            isLoading: false,
            autoClose: 10000,
            closeButton: true,
          });
        }
      };

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Add Yield Function&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is an administrative function that allows the contract owner to add yield to the vault, increasing the overall pool assets. This means users can have more assets based on the shares they have in the pool.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; const addYield = async (evt) =&amp;gt; {
        evt.preventDefault();
        const contract = await createWriteContractVault();
        const id = toast.loading("Add Yield in progress..");
        try {
          const tx = await contract.addYield(ethers.utils.parseEther(amountRef3.current.value));
          await tx.wait();
          setTimeout(() =&amp;gt; {
            window.location.href = "/";
          }, 10000);
          toast.update(id, {
            render: "Transaction successfull",
            type: "success",
            isLoading: false,
            autoClose: 10000,
            closeButton: true,
          });
        } catch (error) {
          console.log(error);
          toast.update(id, {
            render: `${error.reason}`,
            type: "error",
            isLoading: false,
            autoClose: 10000,
            closeButton: true,
          });
        }
      };

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Fetching Data and State&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;getBalance&lt;/strong&gt;: This function fetches the user’s wallet balance, total assets in the vault, and the user’s share of the assets.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    const getBalance = async () =&amp;gt; {
        const { ethereum } = window;
        const provider = new ethers.providers.Web3Provider(ethereum);
        const contract = await createGetContractVault();
        const signer = await provider.getSigner();
        const address = await signer.getAddress()
        const balance = await provider.getBalance(address);
        const total = await contract.totalAssets();
        setTotalAsset(Number(total));
        const userAsset = await contract.maxWithdraw(address);
        setBalance(Number(balance));
        setUSerAsset(Number(userAsset));
        setAddress(address);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;getAllowance&lt;/strong&gt;:  This function checks if the user has already approved the vault to spend their tokens.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    const getAllowance = async () =&amp;gt; {
        const { ethereum } = window;
        const provider = new ethers.providers.Web3Provider(ethereum);
        const signer = await provider.getSigner();
        const taddress = await signer.getAddress()
        const contract = await createGetContractToken();
        const allow = await contract.allowance(taddress, vaultAddress);
        setAllowance(allow);
      };

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;User Interface&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The UI consists of multiple sections where users can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;View their current balance and shares in the liquidity pool.&lt;/li&gt;
&lt;li&gt;Deposit tokens into the vault.&lt;/li&gt;
&lt;li&gt;Withdraw their shares from the vault.&lt;/li&gt;
&lt;li&gt;Admins can add yield to the vault.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4q4n1nu0n9sg8hsruij9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4q4n1nu0n9sg8hsruij9.png" alt="final ui" width="800" height="454"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Each function is linked to a button that triggers the appropriate smart contract interaction. Notifications are handled by &lt;code&gt;react-toastify&lt;/code&gt;, providing feedback on whether transactions succeed or fail.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;In this tutorial we covered how to build a Liquidity pool platform with Solidity and React, we explored creating a vault, depositing into the liquidity pool, adding yield to the pool, withdrawing assets from the pool, and viewing information about users and the liquidity pool. We now have a functional liquidity pool that runs on the ethereum blockchain.&lt;/p&gt;

&lt;p&gt;This setup can be further extended to include more complex yield strategies, tokenomics, and governance systems.&lt;/p&gt;

</description>
      <category>react</category>
      <category>solidity</category>
      <category>erc4626</category>
      <category>blockchain</category>
    </item>
    <item>
      <title>How to build a Lottery App with Solidity, Chainlink VRF V2.5 and React.js(Vite)</title>
      <dc:creator>Ernesto</dc:creator>
      <pubDate>Tue, 22 Oct 2024 11:06:39 +0000</pubDate>
      <link>https://dev.to/ernestothagreat/how-to-build-a-lottery-app-with-solidity-chainlink-vrf-v25-and-reactjsvite-445n</link>
      <guid>https://dev.to/ernestothagreat/how-to-build-a-lottery-app-with-solidity-chainlink-vrf-v25-and-reactjsvite-445n</guid>
      <description>&lt;p&gt;In this tutorial, we will walk through how to build a decentralized lottery system using Solidity and Chainlink VRF.&lt;/p&gt;

&lt;p&gt;The Smart Lottery contract allows users to create and enter lotteries, with a winner chosen at random after the lottery ends. To ensure fairness and transparency, we’ll leverage Chainlink's Verifiable Random Function (VRF) for random number generation, which guarantees a tamper-proof selection process. &lt;/p&gt;

&lt;p&gt;By the end of this tutorial, you’ll have a comprehensive understanding of the contract structure and how to integrate Chainlink VRF for secure randomness in smart contracts.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Chainlink VRF Overview&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Chainlink VRF is a decentralized oracle solution that provides verifiable randomness to smart contracts. In the context of the lottery, it ensures that the winner is chosen randomly, and the process is tamper-proof. Chainlink's VRF uses cryptographic proofs to guarantee the integrity of the random number used in the lottery.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key Features&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Multiple Lotteries: The contract allows for multiple lotteries, each with its own ID, entry fee, start time, and end time.&lt;/li&gt;
&lt;li&gt;Random Winner Selection: Chainlink VRF ensures that a provably random winner is selected for each lottery.&lt;/li&gt;
&lt;li&gt;Secure Fund Distribution: After the lottery ends, the winner can withdraw the pooled funds.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Prerequisite&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You should have a basic understanding of Solidity&lt;/li&gt;
&lt;li&gt;You should have a basic knowledge of React Js.&lt;/li&gt;
&lt;li&gt;You should have Nodejs and Foundry installed on your PC. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Project Setup and Installation For Solidity&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Run the command below to initiate a foundry project, we will be using foundry framework to build the smart contract.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; forge init lottery
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Open the lottery folder on Vscode or your favorite code editor, and delete the &lt;code&gt;scripts/counter.s.sol&lt;/code&gt;, &lt;code&gt;src/counter.sol&lt;/code&gt;, and &lt;code&gt;test/counter.t.sol&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Install all dependencies&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  forge install foundry-rs/forge-std --no-commit &amp;amp;&amp;amp; forge install smartcontractkit/chainlink-brownie-contracts --no-commit 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Code Overview&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If your style learning is code first, you can find the code for the smart contracts &lt;a href="https://github.com/Josh4324/Bet-Smart-Contract" rel="noopener noreferrer"&gt;here&lt;/a&gt;(Frontend can be found &lt;a href="https://github.com/Josh4324/lottery-fe" rel="noopener noreferrer"&gt;here&lt;/a&gt;). This dapp is also deployed live and you can interact with it &lt;a href="https://wondrous-malasada-ec1ed3.netlify.app/" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;br&gt;
The smart contract is deployed on sepolia - 0x62251FD8F91e7D4D09dB5251bD9fBC0fB92A16f5&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Imports and Interfaces&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;VRFConsumerBaseV2Plus.sol&lt;/strong&gt;:  is the base contract that the contract inherits from. It provides the necessary functions and structure to interact with Chainlink’s VRF V2.5. &lt;/p&gt;

&lt;p&gt;By inheriting from this, the contract can securely request and receive random numbers from Chainlink's VRF service, which ensures that the random numbers used (for picking lottery winners, in this case) are provably fair and tamper-proof.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;VRFV2PlusClient.sol&lt;/strong&gt; : contains the low-level functions and data structures required to interact with the Chainlink VRF V2.5 service. It helps handle the details of submitting randomness requests, managing gas limits, and other settings for the VRF process. &lt;/p&gt;

&lt;p&gt;In this context, it ensures that the lottery can request random numbers with parameters like gas limits and request confirmations, and securely retrieve those numbers from Chainlink’s nodes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  import "lib/chainlink-brownie-contracts/contracts/src/v0.8/dev/vrf/VRFConsumerBaseV2Plus.sol";
    import "lib/chainlink-brownie-contracts/contracts/src/v0.8/dev/vrf/libraries/VRFV2PlusClient.sol";
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;State variables&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;vrfCoordinator&lt;/code&gt;: The address of the Chainlink VRF coordinator, which is responsible for handling the random number request.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;s_subscriptionId&lt;/code&gt;: Chainlink VRF subscription ID, which allows the contract to fund and receive VRF services.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;keyHash&lt;/code&gt;: A unique identifier for the VRF key associated with the subscription.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;requestConfirmations&lt;/code&gt;, &lt;code&gt;callbackGasLimit&lt;/code&gt;, &lt;code&gt;numWords&lt;/code&gt;: These parameters specify how the Chainlink VRF will handle the random number request, including the number of confirmations, gas limits, and words (numbers) returned.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;lotteryId&lt;/code&gt;: Tracks the current lottery being managed by the contract.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;       address vrfCoordinator = 0x9DdfaCa8183c41ad55329BdeeD9F6A8d53168B1B;
        uint256 s_subscriptionId;
        bytes32 keyHash = 0x787d74caea10b2b357790d5b5247c2f63d1d91572a9846f780606e4d953677ae;
        uint16 requestConfirmations = 3;
        uint32 callbackGasLimit = 100000;
        uint32 numWords = 1;
        uint256 public lotteryId = 0;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Lottery Struct&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;Lottery&lt;/code&gt; struct models the data for each individual lottery, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;LotteryId&lt;/code&gt;: A unique identifier for each lottery.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;players&lt;/code&gt;: An array that stores the addresses of participants.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;entryFee&lt;/code&gt;: The amount of ETH required to enter the lottery.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;winner&lt;/code&gt;: The address of the randomly selected winner.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;lotteryStartTime&lt;/code&gt; and &lt;code&gt;lotteryEndTime&lt;/code&gt;: The timestamps for when the lottery starts and ends.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;s_requestId&lt;/code&gt;: The request ID associated with the Chainlink VRF service call for random number generation.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;creator&lt;/code&gt;: The address of the user who created the lottery.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; struct Lottery {
            uint256 LotteryId;
            address[] players;
            uint256 entryFee;
            address winner;
            uint256 lotteryStartTime;
            uint256 lotteryEndTime;
            uint256 s_requestId;
            address creator;
        }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Events&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Events are used to log significant occurrences within the contract. In this contract, the following events are defined:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;LotteryCreated&lt;/code&gt;: Emitted when a new lottery is created.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;LotteryEntered&lt;/code&gt;: Emitted when a player enters the lottery.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;WinnerPicked&lt;/code&gt;: Emitted when a winner is selected.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;RequestFulfilled&lt;/code&gt;: Emitted when a random number request is fulfilled by Chainlink VRF.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;        event LotteryCreated(uint256 indexed lotteryId);
        event LotteryEntered(address indexed player);
        event WinnerPicked(address indexed winner);
        event RequestFulfilled(uint256 requestId, uint256[] randomWords);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Mappings&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Mappings are used for key-value storage in Solidity. This contract uses mappings for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;idToLottery&lt;/code&gt;: Maps a lottery ID to the corresponding &lt;code&gt;Lottery&lt;/code&gt; struct, allowing the contract to manage multiple lotteries at once.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;RequestIdToId&lt;/code&gt;: Maps the Chainlink VRF request ID to the specific lottery ID, ensuring that the random number returned is linked to the correct lottery.&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
       // Mapping
        mapping(uint256 =&amp;gt; Lottery) public idToLottery;
        mapping(uint256 =&amp;gt; uint256) public RequestIdToId;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Constructor&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The constructor is called once when the contract is deployed. It initializes the Chainlink VRF subscription ID and sets up the necessary configurations for interacting with Chainlink’s random number service.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;     constructor(uint256 subscriptionId) VRFConsumerBaseV2Plus(vrfCoordinator) {
            s_subscriptionId = subscriptionId;
        }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Core Functions&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;createLottery&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This function allows users to create a new lottery. The creator specifies the entry fee, start time, and end time. This function stores the relevant details in the &lt;code&gt;idToLottery&lt;/code&gt; mapping.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    // Create a Lottery
        function createLottery(uint256 entryFee, uint256 startTime, uint256 endTime) public payable {
            idToLottery[lotteryId].LotteryId = lotteryId;
            idToLottery[lotteryId].entryFee = entryFee;
            idToLottery[lotteryId].lotteryStartTime = startTime;
            idToLottery[lotteryId].lotteryEndTime = endTime;
            idToLottery[lotteryId].creator = msg.sender;
            emit LotteryCreated(lotteryId);
            lotteryId++;
        }


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;enterLottery&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This function allows users to participate in a lottery by paying the required entry fee. This function checks if the lottery is ongoing and if the correct amount of ETH is provided before adding the player to the list of participants.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    // Enter the lottery by paying the entry fee
        function enterLottery(uint256 id) public payable {
            require(id &amp;lt; lotteryId, "Lottery does not exists");
            require(idToLottery[id].lotteryStartTime &amp;lt; block.timestamp, "Lottery still ongoing");
            require(idToLottery[id].lotteryEndTime &amp;gt; block.timestamp, "Lottery has ended");
            require(msg.value &amp;gt;= idToLottery[id].entryFee, "Not enough ETH to enter");
            idToLottery[id].players.push(msg.sender);
            emit LotteryEntered(msg.sender);
        }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;DrawLotteryWinner&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This function is used to initiate the process of selecting a winner once the lottery has ended. This function calls Chainlink VRF’s &lt;code&gt;requestRandomWords&lt;/code&gt; to get a random number.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  function DrawLotteryWinner(uint256 id) external returns (uint256 requestId) {
            require(msg.sender == idToLottery[id].creator, "Only Lottery creator can draw lottery");
            require(idToLottery[id].lotteryEndTime &amp;lt; block.timestamp, "Lottery still ongoing");
            requestId = s_vrfCoordinator.requestRandomWords(
                VRFV2PlusClient.RandomWordsRequest({
                    keyHash: keyHash,
                    subId: s_subscriptionId,
                    requestConfirmations: requestConfirmations,
                    callbackGasLimit: callbackGasLimit,
                    numWords: numWords,
                    extraArgs: VRFV2PlusClient._argsToBytes(VRFV2PlusClient.ExtraArgsV1({nativePayment: false}))
                })
            );
            RequestIdToId[requestId] = id;
            return requestId;
        }

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;fulfillRandomWords&lt;/strong&gt;&lt;br&gt;
This internal function is triggered automatically when Chainlink VRF returns the random number. It calculates the winner by taking the modulo of the random number and the number of participants, to ensure fairness.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  function fulfillRandomWords(uint256 _requestId, uint256[] memory _randomWords) internal override {
            uint256 id = RequestIdToId[_requestId];
            uint256 winnerIndex = _randomWords[0] % idToLottery[id].players.length;
            idToLottery[id].winner = idToLottery[id].players[winnerIndex];
            emit RequestFulfilled(_requestId, _randomWords);
        }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;withdrawWinnings&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This function allows the winner to withdraw the prize, which is the total of all the entry fees pooled together.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   function withdrawWinnings(uint256 id) public {
            require(msg.sender == idToLottery[id].winner, "You are not the winner");
            address payable winner = payable(idToLottery[id].winner);
            uint256 amount = idToLottery[id].players.length * idToLottery[id].entryFee;
            (bool sent, bytes memory data) = winner.call{value: amount}("");
            require(sent, "Failed to send Ether");
        }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Project Setup and Installation For React.js&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Run the command below and follow the prompt to initiate a React project, we will be using react.js to build the frontend for the Lottery App.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; npm create vite@latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Install the necessary dependencies.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  npm install npm install ethers react-toastify 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  App.js Overview
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Imports&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;App.css -  contains styling for the components.&lt;br&gt;
lotteryABI - The JSON files contain the ABI (Application Binary Interface) definitions of the smart contracts, which is necessary for interacting with the contracts via &lt;code&gt;ethers.js&lt;/code&gt;.&lt;br&gt;
ethers.js -  A JavaScript library that allows interactions with the Ethereum blockchain. It is used to create contract instances, send transactions, and interact with smart contracts.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    import './App.css'
    import { ethers } from "ethers";
    import lotteryABI from "../abi/lottery.json";
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;State, UseEffect and Refs&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;They are used to manage state and refer to user input. The lottery data (&lt;code&gt;list&lt;/code&gt;, &lt;code&gt;gId&lt;/code&gt;, &lt;code&gt;lot&lt;/code&gt;, &lt;code&gt;winner&lt;/code&gt;, etc.) is stored in state, while &lt;code&gt;useRef&lt;/code&gt; references HTML input elements like the start and end time for lotteries.&lt;/p&gt;

&lt;p&gt;The useEffect is used to triggers the retrieval of past lottery data (&lt;code&gt;getLastLottery&lt;/code&gt;) and fetches real-time information whenever the user changes the selected lottery ID.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;     const startRef = useRef();
      const endRef = useRef();
      const entryRef = useRef();
      const selectRef = useRef();
      const selectRef2 = useRef();
      const selectRef3 = useRef();

      const [list, setList] = useState([]);
      const [gId, setGID] = useState(0);
      const [gId2, setGID2] = useState(0);
      const [lot, setLot] = useState({});
      const [winner, setWinner] = useState("0x");

     useEffect(() =&amp;gt; {
        getlastLottery();
        getLottery();
        getWinner();
      }, [gId, gId2]);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Smart Contract Interaction
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;createWriteContract&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This function sets up a connection to the contract via a Web3 provider using the current user's wallet (Metamask), allowing them to interact with the contract in a writable (state-changing) manner.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  const createWriteContract = async () =&amp;gt; {
        const { ethereum } = window;
        const provider = new ethers.providers.Web3Provider(ethereum);
        const signer = await provider.getSigner();
        const priceContract = new ethers.Contract(lotteryAddress, lotteryABI.abi, signer);
        return priceContract;
      }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;createGetContract&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This function creates a read-only connection to the contract, enabling the frontend to fetch data from the blockchain without altering its state.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   const createGetContract = async () =&amp;gt; {
        const { ethereum } = window;
        const provider = new ethers.providers.Web3Provider(ethereum)
        const priceContract = new ethers.Contract(lotteryAddress, lotteryABI.abi, provider);
        return priceContract;
      }

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;createLottery&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7l9m82hu7cswapo13n2q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7l9m82hu7cswapo13n2q.png" alt="create lottery" width="800" height="229"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;createLottery&lt;/code&gt; function allows users to create a new lottery by providing three inputs: the entry fee, start date, and end date. These values are captured from the input fields, converted to appropriate formats (e.g., Ether to Wei for the entry fee and UNIX timestamps for dates), and then sent to the smart contract. The blockchain transaction is processed asynchronously, with real-time feedback provided to the user using &lt;code&gt;react-toastify&lt;/code&gt; notifications.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const createLottery = async (evt) =&amp;gt; {
        evt.preventDefault();
        const contract = await createWriteContract();
        const id = toast.loading("Creating Lottery....");
        try {
          const start = Math.floor(new Date(startRef.current.value).getTime() / 1000);
          const end = Math.floor(new Date(endRef.current.value).getTime() / 1000);
          const entry = ethers.utils.parseEther(entryRef.current.value);
          const tx = await contract.createLottery(entry, start, end);
          await tx.wait();
          setTimeout(() =&amp;gt; {
            window.location.href = "/";
          }, 10000);
          toast.update(id, {
            render: "Transaction successfull",
            type: "success",
            isLoading: false,
            autoClose: 10000,
            closeButton: true,
          });
        } catch (error) {
          console.log(error);
          toast.update(id, {
            render: `${error.reason}`,
            type: "error",
            isLoading: false,
            autoClose: 10000,
            closeButton: true,
          });
        }
      };
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;getlastLottery&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This function fetches the total number of lotteries created by querying the smart contract’s &lt;code&gt;lotteryId()&lt;/code&gt; function and updates the state with the list of lotteries available for selection. Each lottery is displayed as an option in a dropdown menu.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const getlastLottery = async () =&amp;gt; {
        const contract = await createGetContract();
        const lotteryCount = await contract.lotteryId();
        let arr = [];
        for (let i = 0; i &amp;lt; Number(lotteryCount); i++) {
          arr.push({ lotteryId: i, lotteryName: "Lottery " + i })
        }
        setList(arr);
      };
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;getLottery&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9etsegnby0p7liy5ciwz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9etsegnby0p7liy5ciwz.png" alt="get lottery" width="800" height="158"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This function fetches details (start time, end time, entry fee) of the currently selected lottery from the blockchain using its ID (&lt;code&gt;gId&lt;/code&gt;).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; const getLottery = async () =&amp;gt; {
        const contract = await createGetContract();
        const lottery = await contract.idToLottery(gId);
        let obj = {
          startTime: Number(lottery.lotteryStartTime),
          endTime: Number(lottery.lotteryEndTime),
          entryFee: Number(lottery.entryFee),
        }
        setLot(obj);
      };
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;getWinner&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyynn8irtwurs7m83yl1p.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyynn8irtwurs7m83yl1p.png" alt="get winner" width="800" height="187"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The lottery winner is determined through the smart contract, which uses Chainlink's Verifiable Random Function (VRF) for randomness. Once a lottery is concluded, users can check the winner by selecting a lottery ID (&lt;code&gt;gId2&lt;/code&gt;), and the winner’s Ethereum address is fetched from the blockchain using the contract’s &lt;code&gt;idToLottery()&lt;/code&gt; function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; const getWinner = async () =&amp;gt; {
        const contract = await createGetContract();
        const lottery = await contract.idToLottery(gId2);
        setWinner(lottery.winner);
      };
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;withdrawWinning&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcfphfihf0tetqrhzw3ie.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcfphfihf0tetqrhzw3ie.png" alt="withdraw winning" width="800" height="187"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Winners can withdraw their earnings using the &lt;code&gt;withdrawWinning&lt;/code&gt; function, which interacts with the smart contract’s &lt;code&gt;withdrawWinnings()&lt;/code&gt; function. The user's wallet signs the transaction, and upon success, the winnings are transferred to the winner’s account.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; const withdrawWinning = async (evt) =&amp;gt; {
        evt.preventDefault();
        const contract = await createWriteContract();
        const id = toast.loading("Withdrawing....");
        try {
          const tx = await contract.withdrawWinnings(selectRef3.current.value);
          await tx.wait();
          setTimeout(() =&amp;gt; {
            window.location.href = "/";
          }, 10000);
          toast.update(id, {
            render: "Transaction successfull",
            type: "success",
            isLoading: false,
            autoClose: 10000,
            closeButton: true,
          });
        } catch (error) {
          console.log(error);
          toast.update(id, {
            render: `${error.reason}`,
            type: "error",
            isLoading: false,
            autoClose: 10000,
            closeButton: true,
          });
        }
      };
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Frontend UI
&lt;/h3&gt;

&lt;p&gt;The UI is divided into four main sections:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Create Lottery&lt;/strong&gt;: Users can input the entry fee, start date, and end date for a new lottery, which is then created on the blockchain.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Enter Lottery&lt;/strong&gt;: Displays the available lotteries, including details like entry fees, start and end dates, fetched from the smart contract and users can participate in a lottery.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Check Winner&lt;/strong&gt;: After selecting a lottery, users can see the address of the winner for concluded lotteries.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Withdraw Winnings&lt;/strong&gt;: If the user is the winner, they can withdraw their winnings by selecting the appropriate lottery and initiating the withdrawal process.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvyhyu8wb38a3yur7q4pi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvyhyu8wb38a3yur7q4pi.png" alt="final ui" width="800" height="454"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;This tutorial demonstrates how to build a lottery app with solidity, chainlink VRF 2.5 and react.js. This guide covers the essential components of creating a secure and transparent lottery system by integrating smart contracts, randomness via Chainlink VRF (Verifiable Random Function), and a responsive user interface with React.js.&lt;/p&gt;

&lt;p&gt;Solidity enables you to write the smart contract logic that governs the lottery, ensuring fairness and immutability. Chainlink VRF guarantees a tamper-proof randomness source for selecting winners, ensuring that no entity, including developers, can influence the outcome.&lt;/p&gt;

&lt;p&gt;React.js offers an intuitive interface for users to interact with the smart contract, submit transactions, and retrieve data in real time. Using ethers.js to bridge the blockchain with the frontend, users can seamlessly participate in the lottery, check results, and withdraw winnings.&lt;/p&gt;

</description>
      <category>chainlink</category>
      <category>solidity</category>
      <category>vite</category>
      <category>react</category>
    </item>
  </channel>
</rss>
