# πŸš€ From Zero to a Web3 Developer πŸ”₯ Ethers & Hardhat Bootcamp ⚑ Daily Updates & Code! **Published by:** [ztmyo](https://paragraph.com/@ztmyo-2/) **Published on:** 2025-03-06 **URL:** https://paragraph.com/@ztmyo-2/from-zero-to-a-web3-developer-ethers-hardhat-bootcamp-daily-updates-code ## Content 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 JavaScriptThe learning plan was to learn some lessons of this course:β˜… Ethers.js Simple Storageβ˜… Hardhat Simple Storageβ˜… Hardhat Fund Meβ˜… NextJS Smart Contract Lottery (Full Stack / Front End)β˜… Hardhat Starter Kitβ˜… Hardhat DeFi & Aaveβ˜… NextJS NFT Marketplace (Full Stack / Front End)Daily Updates Include:New knowledge encountered in today's study -β†’ πŸ“Œ harvestMy practice (if I had done it) -β†’ πŸ“Œ practicelearning summary and feelings -β†’ πŸ“Œ sum & F lesson 15 Mar:πŸ“Œ harvest:decompile bytecode docs.ethers πŸ”Ή.use private key in jsPRIVATE_KEY_PASSWORD=password node deploy.js // clear history history -c 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) πŸ”Ή.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 = {} // hardhat.config.js // import this task require("./tasks/block-number") yarn hardhat block-number --network rinkeby scripts and tasks both can basically do the same thing. πŸ”Ή.hardhat node# start a local hardhat test net yarn hardhat node localhost: { url: "http://127.0.0.1:8545", chainId: 31337, }, πŸ”Ή.hardhat consoleyarn hardhat console --net work localhost you can do anything in these consoles(terminal), and they're great ways to quickly test and tinker in interact with contracts. lesson 26 Mar:πŸ“Œ harvest:πŸ”Ή.hardhat unit testconst { 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) }) } run only specific tests:yarn hardhat test --grep store // use only keyword it.only("Should start with a favorite number of 0", async function () πŸ”Ή.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, }, https://www.npmjs.com/package/hardhat-gas-reporter πŸ”Ή.coverage -> [t=35080] lesson 3πŸ”Ή.use hardhat to deployconst 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, }) πŸ”Ή.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); 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" ); πŸ”Ή.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 () Staging : Testing our code in a real environment that is not prod.this is the last step in your development journey. lesson 47 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); πŸ”Ή.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) 8 Mar:πŸ“Œ harvest:πŸ”Ή.Moralisconst { enableWeb3, isWeb3Enabled, isWeb3EnableLoading, account, Moralis, deactivateWeb3 } = useMoralis() lets front-end developers get on-chain data directly without running their own blockchain nodesprovides Web3 login, wallet connection, transaction query and other functions to simplify dApp developmentBut no longer update. πŸ”Ή.web3uikit Beautiful and lightweight UI components for web3 developers. But no longer update, only support react 18. πŸ”Ή.Front-end stackReact+Next.jsEthers.js/viem/web3j.sRainbowKit + wagmiNow, we can scaffold a RainbowKit(web3uikit) + wagmi(Moralis) + Next.js app as an alternative. πŸ”Ή.create a update-front-end.jsconst 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)) } ... 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 workcreate 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 59 Mar:πŸ“Œ harvest:πŸ”Ή.Forking networks: { hardhat: { chainId: 31337, forking: { url: MAINNET_RPC_URL } }, } const iWeth = await ethers.getContractAt( "IWeth", // @ztmy get Contract derictly from forked main net "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", signer ) Pros: Quick, easy, resemble what's on mainnetCons: We need an API, some contracts are complex to work withπŸ”Ή.hardhat-deploymodule.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']; yarn add --dev hardhat-deploy We us hardhat-deploy to deploy contract, this is a community plugin. Community plugins πŸ”Ή.Aave BorrowgetWethgetLendingPoolapproveErc20depositgetBorrowUserDatagetDaiPriceborrowDaigetBorrowUserDatarepaygetBorrowUserData ## Publication Information - [ztmyo](https://paragraph.com/@ztmyo-2/): Publication homepage - [All Posts](https://paragraph.com/@ztmyo-2/): More posts from this publication - [RSS Feed](https://api.paragraph.com/blogs/rss/@ztmyo-2): Subscribe to updates