hardhat学习笔记

135 阅读4分钟

4.0 Harthat开发框架(JavaScript)

4.1 Harthat编译

npx hardhat compile

4.2 Harthat部署

npx hardhat deploy

类似webpack入口文件实现合约部署

const { ethers } = require("hardhat");
​
async function main() {
    const fundMeFactory = await ethers.getContractFactory("FundMe1");//传入的文件名字是contract文件夹下的合约的名字
    console.log("Deploying FundMe contract...");
    //console.log(ethers);
    
    // Deploy the contract
    const fundMe = await fundMeFactory.deploy(10);//这个时候调用fundMe.sol合约的constructor函数
    await fundMe.waitForDeployment();
    console.log("FundMe contract deployed to:", await fundMe.getAddress());
}
​
// Execute the main function and handle errors
main().then(() => process.exit(0))
    .catch((error) => {
        console.error("Error deploying FundMe contract:", error);
        process.exit(1);
    });

大概最终版本

const { ethers } = require("hardhat");
//const hre = require("hardhat")async function main() {
    const fundMeFactory = await ethers.getContractFactory("FundMe");//传入的文件名字是contract文件夹下的合约的名字
    console.log("Deploying FundMe contract...");
    //console.log(ethers);
    
    // Deploy the contract
    const fundMe = await fundMeFactory.deploy(10);//这个时候调用fundMe.sol合约的constructor函数
    await fundMe.waitForDeployment();
    console.log("FundMe contract deployed to:", await fundMe.getAddress());
    /* 
    //hre.network.chainId获取到的是hardhat.config.ts里面的config属性下边自己配置的network属性,这个属于配置一些测试网的信息
    if(hre.network.chainId = 11155111){
        //等待五个区块确认
        await fundMe.deployTransaction().wait(5);
        console.log("Waiting for 5 blocks confirmation...");
        //验证sepolia地址
        await verifyFundMe(fundMe,10) 
    }else{
        console.log("verification skipped...")
    }
    */
}
 //if you want to verify the cantract on etherscan,you can use the following function
// async function verifyFundMe(fundMe:any,arg:number){
//     await hre.run("verfy:verify",{
//         address: fundMe.target,
//         constructorArguments:[arg]
//     })
// }// Execute the main function and handle errors
main().then(() => process.exit(0))
    .catch((error) => {
        console.error("Error deploying FundMe contract:", error);
        process.exit(1);
    });

4.3 Ether.js

The ethers.js library aims to be a complete and compact library for interacting with the Ethereum Blockchain and its ecosystem.

是一个用于以太坊区块链交互的JavaScript API库

文档链接:

[docs.ethers.org/v5/]:

4.4 Hardhat网络&私钥配置

使用 @chainLink/env-enc加密私钥

安装 @chainLink/env-enc

npm install @chainLink/env-enc --save-dev

加密命令

//设置密码
npx env-enc set-pw
//加密
npx env-enc set

4.4.1 配置sepolia测试网

hardhat.config.ts配置sepolia(一定要在当前的命令行窗口执行命令才会获取到SEPOLIA_URL,PRIVATE_KEY)否则需要执行npx env-enc set-pw后重新在输入密码,不然取到的值就是undefined

import { HardhatUserConfig } from "hardhat/config";
import "@nomicfoundation/hardhat-toolbox";
/* import envEnc from "@chainLink/env-enc";
console.log("env_enc", envEnc); */
require("@chainLink/env-enc").config();
​
const {SEPOLIA_URL,PRIVATE_KEY} = process.env;
​
const config: HardhatUserConfig = {
  solidity: "0.8.28",
  networks: {
    sepolia:{
      url:SEPOLIA_URL,
      accounts:[PRIVATE_KEY as `string`],
    }
  }
};
​
export default config;
​
​

4.4.2 验证etherscan的sepolia地址

参考hardhat-verify | Ethereum development environment for professionals by Nomic Foundation

略第四课1:50:00

4.5 简单的合约交互脚本

// init 2 account
//ethers.js提供的方法,可以获取配置文件配置的两个account
const [firstAccount,secondAccount] = ethers.getSigners()
​
//fund contract with first account
//语法:合约.fund方法({value:ethers.parseEther("0.5")}) 因为0.5是小数,需要ether来转化
const tranxt = await fundMe.fund({value:ethers.parseEther("0.5")})//等待调用fundMe里面的fund函数完成
await tranxt.wait();//等待交易完成,已经写入区块//check balance of contract
const balanceOfContract = await ethers.provider.getBalance(fundMe.getAddress())//ethers.provider.getBalance(fundMe.target)
console.log(`balance of contract is ${balanceOfContract}`)
​
//fund contract with second account 
//.connect(secondAccount)用于指明是哪个账户,不写默认第一个
const tranxtSecondAccount = await fundMe.connect(secondAccount).fund({value:ethers.parseEther("0.6")})//调用fund
await tranxtSecondAccount.wait()//等待入块//check balance of contract
const balanceOfContractWithSecondAccount = await ethers.provider.getBalance(fundMe.getAddress())//ethers.provider.getBalance(fundMe.target)
console.log(`balance of contract is ${balanceOfContractWithSecondAccount}`)
​
//check mapping fundersToAccount
//firstAccount是fundMe里面的mapping结构,查询账户交的钱
const firstAccountBalanceInFundMe = await fundMe.fundersToAcount[firstAccount.address]
const secondAccountBalanceInFundMe = await fundMe.fundersToAcount[secondAccount.address]
console.log(`balance of first account ${firstAccount.address} is ${firstAccountBalanceInFundMe}`)
console.log(`balance of first account ${secondAccount.address} is ${secondAccountBalanceInFundMe}`)
​

4.6 Hardhat Task

类似模块化:可以将脚本变成命令行

deploy-fundMe

import { task } from "hardhat/config"//async (args(入参), hre(运行时候的环境))={}task("deploy-fundMe(命令的名字)", "Deploy FundMe contract(描述)").setAction(async (args, hre) => {
    const fundMeFactory = await ethers.getContractFactory("FundMe");//传入的文件名字是contract文件夹下的合约的名字
    console.log("Deploying FundMe contract...");
    //console.log(ethers);
    
    // Deploy the contract
    const fundMe = await fundMeFactory.deploy(300);//这个时候调用fundMe.sol合约的constructor函数
    await fundMe.waitForDeployment();
    console.log("FundMe contract deployed to:", await fundMe.getAddress());
    /* 
    if(hre.network.chainId = 11155111){
        //等待五个区块确认
        await fundMe.deployTransaction().wait(5);
        console.log("Waiting for 5 blocks confirmation...");
        //验证sepolia地址
        await verifyFundMe(fundMe,10) 
    }else{
        console.log("verification skipped...")
    }
    */
})
​
 //if you want to verify the cantract on etherscan,you can use the following function
// async function verifyFundMe(fundMe:any,arg:number){
//     await hre.run("verfy:verify",{
//         address: fundMe.target,
//         constructorArguments:[arg]
//     })
// }module.exports = {}

以上命令行使用:

npx hardhat deploy-fundMe --network sepolia

interact-fundMe

import {task} from "hardhat/config";
​
task("interact-fundMe", "Interact with FundMe contract").addParam("addr","contract address").setAction(async (args, hre) => {
    const fundMeFactory = await ethers.getContractFactory("FundMe")
    const fundMe = await fundMeFactory.attach(args.addr)//传入合约地址,连接到合约
    //简单的合约交互
   // init 2 account
    //ethers.js提供的方法,可以获取配置文件配置的两个account
    const [firstAccount,secondAccount] = ethers.getSigners()
    //使用本地的account
    /* const firstAccount = await ethers.getSigner(0)//获取第一个账户
    const secondAccount = await ethers.getSigner(1)//获取第二个账户 */
​
    //fund contract with first account
    //语法:合约.fund方法({value:ethers.parseEther("0.5")}) 因为0.5是小数,需要ether来转化
    const tranxt = await fundMe.fund({value:ethers.parseEther("0.5")})//等待调用fundMe里面的fund函数完成
    await tranxt.wait();//等待交易完成,已经写入区块
​
    //check balance of contract
    const balanceOfContract = await ethers.provider.getBalance(fundMe.getAddress())//ethers.provider.getBalance(fundMe.target)
    console.log(`balance of contract is ${balanceOfContract}`)
​
    //fund contract with second account 
    //.connect(secondAccount)用于指明是哪个账户,不写默认第一个
    const tranxtSecondAccount = await fundMe.connect(secondAccount).fund({value:ethers.parseEther("0.6")})//调用fund
    await tranxtSecondAccount.wait()//等待入块
​
    //check balance of contract
    const balanceOfContractWithSecondAccount = await ethers.provider.getBalance(fundMe.getAddress())//ethers.provider.getBalance(fundMe.target)
    console.log(`balance of contract is ${balanceOfContractWithSecondAccount}`)
​
    //check mapping fundersToAccount
    //firstAccount是fundMe里面的mapping结构,查询账户交的钱
    const firstAccountBalanceInFundMe = await fundMe.fundersToAcount[firstAccount.address]
    const secondAccountBalanceInFundMe = await fundMe.fundersToAcount[secondAccount.address]
    console.log(`balance of first account ${firstAccount.address} is ${firstAccountBalanceInFundMe}`)
    console.log(`balance of first account ${secondAccount.address} is ${secondAccountBalanceInFundMe}`)
})

以上命令行使用:

npx hardhat interact-fundMe --addr 部署的地址 --network sepolia

上面命令行的部署的地址会通过args传入。