DEV Community

Cover image for πŸš€ From Zero to a Web3 Developer πŸ”₯ Ethers & Hardhat Bootcamp ⚑ Daily Updates & Code!
MY ZT
MY ZT

Posted on • Edited on

πŸš€ From Zero to a Web3 Developer πŸ”₯ Ethers & Hardhat Bootcamp ⚑ Daily Updates & Code!

This series of learning plans:

fist and formost,I want to say thinks to Patrick Collins for this fantastic course
Full Stack Web3 Development with JavaScript

The learning plan was to learn some lessons of this course:

  1. β˜… Ethers.js Simple Storage
  2. β˜… Hardhat Simple Storage
  3. β˜… Hardhat Fund Me
  4. β˜… NextJS Smart Contract Lottery (Full Stack)
  5. β˜… [Hardhat DeFi & Aave]
  6. β˜… NextJS NFT Marketplace (Full Stack)

Daily Updates Include:

  • New knowledge encountered in today's study -β†’ πŸ“Œ harvest
  • My practice (if I had done it) -β†’ πŸ“Œ practice
  • learning summary and feelings -β†’ πŸ“Œ sum & F

lesson 1

5 Mar:

πŸ“Œ harvest:

decompile bytecode
docs.ethers

πŸ”Ή.use private key in js

PRIVATE_KEY_PASSWORD=password node deploy.js
// clear history
history -c
Enter fullscreen mode Exit fullscreen mode

build a script to encrypt our private key.

πŸ”Ή.transaction response and transaction receipts

  const deploymentReceipt = await contract.waitForDeployment();
  console.log(`Contract deployed to ${await contract.getAddress()}`);

//   @ztmy
//   transaction receipts and transaction response are different.
//   receipt is what you get when you wait for a transaction to finish. 
//   And then response is just what you initially get.

  console.log("Here is the transaction:")
  console.log(contract.deploymentTransaction())
  console.log("Here is the receipt:")
  console.log(deploymentReceipt)
Enter fullscreen mode Exit fullscreen mode

πŸ”Ή.create a task

// create a tesk at tesks folder
const { task } = require("hardhat/config")

task("block-number", "Prints the current block number").setAction(
// @ztmy hre: hardhat runtime environment
  async (taskArgs, hre) => {
    const blockNumber = await hre.ethers.provider.getBlockNumber()
    console.log(`Current block number: ${blockNumber}`)
  }
)

module.exports = {}
Enter fullscreen mode Exit fullscreen mode
// hardhat.config.js
// import this task
require("./tasks/block-number")
Enter fullscreen mode Exit fullscreen mode
yarn hardhat block-number --network rinkeby
Enter fullscreen mode Exit fullscreen mode

scripts and tasks both can basically do the same thing.

πŸ”Ή.hardhat node

# start a local hardhat test net
yarn hardhat node
Enter fullscreen mode Exit fullscreen mode
    localhost: {
      url: "http://127.0.0.1:8545",
      chainId: 31337,
    },
Enter fullscreen mode Exit fullscreen mode

πŸ”Ή.hardhat console

yarn hardhat console --net work localhost
Enter fullscreen mode Exit fullscreen mode

you can do anything in these consoles(terminal), and they're great ways to quickly test and tinker in interact with contracts.


lesson 2

6 Mar:

πŸ“Œ harvest:

πŸ”Ή.hardhat unit test

const { ethers } = require("hardhat")
const { expect, assert } = require("chai")

// describe("SimpleStorage", () => {})
describe("SimpleStorage", function () {
  let simpleStorageFactory, simpleStorage
  beforeEach(async function () {
    simpleStorageFactory = await ethers.getContractFactory("SimpleStorage")
    simpleStorage = await simpleStorageFactory.deploy()
  })
  // @ ztmy write a unit test
  it("Should start with a favorite number of 0", async function () {
    const currentValue = await simpleStorage.retrieve()
    const expectedValue = "0"
    // assert
    // expect
    assert.equal(currentValue.toString(), expectedValue)
    // expect(currentValue.toString()).to.equal(expectedValue)
  })
}
Enter fullscreen mode Exit fullscreen mode

run only specific tests:

yarn hardhat test --grep store
Enter fullscreen mode Exit fullscreen mode
// use only keyword
it.only("Should start with a favorite number of 0", async function ()
Enter fullscreen mode Exit fullscreen mode

πŸ”Ή.gas reporter & coinmarketcap ->[t=34730]

  gasReporter: {
    enabled: true,
    currency: "USD",
    outputFile: "gas-report.txt",
    noColors: true,
    // has the USD price of each one of these transactions
    coinmarketcap: COINMARKETCAP_API_KEY,
  },
Enter fullscreen mode Exit fullscreen mode

hardhat-gas-reporter

πŸ”Ή.coverage -> [t=35080]


lesson 3

πŸ”Ή.use hardhat to deploy

const fundMe = await deploy("FundMe", {
    from: deployer,
    args: [ethUsdPriceFeedAddress],
    log: true,
    // we need to wait if on a live network so we can verify properly
    waitConfirmations: network.config.blockConfirmations || 1,
})
Enter fullscreen mode Exit fullscreen mode

πŸ”Ή.get recent deoploy & connect

// To get the most recently deployed instance, you'll need the deployed addresses
// You might need to get these from your deployment artifacts or a helper function
const fundMeDeployment = await hre.deployments.get("FundMe");
const mockV3AggregatorDeployment = await hre.deployments.get(
    "MockV3Aggregator"
);

// Connect to the deployed contracts with the deployer as signer
fundMe = FundMeFactory.attach(fundMeDeployment.address).connect(
    deployer
);
mockV3Aggregator = MockV3AggregatorFactory.attach(
    mockV3AggregatorDeployment.address
).connect(deployer);
Enter fullscreen mode Exit fullscreen mode

This sets the signer (wallet) that will be used when sending transactions to this contract. The "deployer" variable is typically a wallet/signer object. When you call methods on this contract that change state (non-view functions), they'll be signed by this deployer account.

// @ztmy connect to other address to test require ower.
it("Only allows the owner to withdraw", async function () {
    const accounts = await ethers.getSigners();
    const fundMeConnectedContract = await fundMe.connect(accounts[1]);
    await expect(fundMeConnectedContract.withdraw()).to.be.revertedWithCustomError(fundMe,
    "FundMe__NotOwner"
    );
Enter fullscreen mode Exit fullscreen mode

πŸ”Ή.Staging Tests

// Staging Tests - Need to be run on an actual test network, such as Sepolia.
developmentChains.includes(network.name)
    ? describe.skip
    : describe("FundMe Staging Tests", function ()

// Unit Tests - run only on local hardhat or localhost.
!developmentChains.includes(network.name)
  ? describe.skip
  : describe("FundMe", function ()
Enter fullscreen mode Exit fullscreen mode

Staging : Testing our code in a real environment that is not prod.this is the last step in your development journey.


lesson 4

7 Mar:

πŸ“Œ harvest:

πŸ”Ή.Common contract-related Ethers operations

// Get contract factories
const ContractFactory = await ethers.getContractFactory("Contract");


// Get deployment Information
const ContractDeployment = await hre.deployments.get(
    "Contract"
    );


// Get contract instance
Contract = await ethers.getContractAt(
    "Contract",
    ContractDeployment.address
)

// Connect to the deployed contracts with the deployer
fundMe = Contract .connect(deployer);
Enter fullscreen mode Exit fullscreen mode

πŸ”Ή.get return from Event

// create VRFV2 Subscription
VRFCoordinatorV2_5MockAddress = VRFCoordinatorV2_5MockDeployment.address

const transactionResponse = await VRFCoordinatorV2_5Mock.createSubscription()
const transactionReceipt = await transactionResponse.wait()

// @ztmy transaction After sending a transaction, we can only get a transaction response and cannot get the return value directly.
// @ztmy We can only find Events from the response to get these information

// Query events from the VRFCoordinatorV2_5Mock contract
const events = await VRFCoordinatorV2_5Mock.queryFilter(
// - Use filters.SubscriptionCreated() to only get SubscriptionCreated events
    VRFCoordinatorV2_5Mock.filters.SubscriptionCreated()
)

subscriptionId = events[0].args[0]
log(subscriptionId)
Enter fullscreen mode Exit fullscreen mode

8 Mar:

πŸ“Œ harvest:

πŸ”Ή.Moralis

const { enableWeb3, isWeb3Enabled, isWeb3EnableLoading, account, Moralis, deactivateWeb3 } =
    useMoralis()
Enter fullscreen mode Exit fullscreen mode
  • lets front-end developers get on-chain data directly without running their own blockchain nodes
  • provides Web3 login, wallet connection, transaction query and other functions to simplify dApp development

But no longer update.

πŸ”Ή.web3uikit

Beautiful and lightweight UI components for web3 developers.

But no longer update, only support react 18.

πŸ”Ή.Front-end stack

  • React+Next.js
  • Ethers.js/viem/web3j.s
  • RainbowKit + wagmi

Now, we can scaffold a RainbowKit(web3uikit) + wagmi(Moralis) + Next.js app as an alternative.

πŸ”Ή.create a update-front-end.js

const frontEndContractsFile = "../nextjs-smartcontract-lottery-fcc/constants/contractAddresses.json"
const frontEndAbiFile = "../nextjs-smartcontract-lottery-fcc/constants/abi.json"

async function updateAbi() {
    const raffle = await ethers.getContract("Raffle")
    fs.writeFileSync(frontEndAbiFile, raffle.interface.format(ethers.utils.FormatTypes.json))
}
...
Enter fullscreen mode Exit fullscreen mode

create a update-front-end.js under the deploy folder, when we redeployment contract, we can run this to automated the process of updating our contract information and pass them to front end codebase.

πŸ”Ή.the rest of work

  • create a hook entranceFee and show it.
  • add notification provider.
  • show numPlayers,recentWinner.
  • run mockOffchain to test.
  • use tailwindcss to Optimized style. ->[t=18.05.55]
  • use fleek to deploy front end.

πŸ“Œ sum & F

I only learned the basic idea of making a front end, and I will use the latest set of dependencies in my later practice.


lesson 5

9 Mar:

πŸ“Œ harvest:

πŸ”Ή.Forking

 networks: {
    hardhat: {
      chainId: 31337,
      forking: {
        url: MAINNET_RPC_URL
      }
    },
 }
Enter fullscreen mode Exit fullscreen mode
const iWeth = await ethers.getContractAt(
    "IWeth",
// @ztmy get Contract derictly from forked main net 
    "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
    signer
)
Enter fullscreen mode Exit fullscreen mode
  • Pros: Quick, easy, resemble what's on mainnet
  • Cons: We need an API, some contracts are complex to work with

πŸ”Ή.hardhat-deploy

module.exports = async ({getNamedAccounts, deployments}) => {
  const {deploy} = deployments;
  const {deployer} = await getNamedAccounts();
  await deploy('MyContract', {
    from: deployer,
    args: ['Hello'],
    log: true,
  });
};
// only execute deploy scripts with the given tags
module.exports.tags = ['MyContract'];
Enter fullscreen mode Exit fullscreen mode

yarn add --dev hardhat-deploy
We us hardhat-deploy to deploy contract, this is a community plugin.
Community plugins

πŸ”Ή.Aave Borrow

  • getWeth
  • getLendingPool
  • approveErc20
  • deposit
  • getBorrowUserData
  • getDaiPrice
  • borrowDai
  • getBorrowUserData
  • repay
  • getBorrowUserData

lesson 5

9 Mar:

πŸ“Œ harvest:

πŸ”Ή.__


Enter fullscreen mode Exit fullscreen mode

πŸ”Ή.__


Enter fullscreen mode Exit fullscreen mode

πŸ”Ή.__


Enter fullscreen mode Exit fullscreen mode

πŸ”Ή.__


Enter fullscreen mode Exit fullscreen mode

πŸ”Ή.__


Enter fullscreen mode Exit fullscreen mode

Top comments (0)