前言本文主要对hardhat框架实操的介绍,通过一个简单的智能合约案例,用handhat把开发、测试、部署全流程过一遍。前期准备构建工具:hardhat前端技术栈:React+Ethersjs+Web3UIKit钱包:MetaMask合约层:Solidityehterscan区
本文主要对hardhat框架实操的介绍,通过一个简单的智能合约案例,用handhat把开发、测试、部署全流程过一遍。
前期准备
- 构建工具:hardhat
- 前端技术栈:React+Ethersjs+Web3UI Kit
- 钱包:MetaMask
- 合约层:Solidity
- ehterscan区块链浏览器<br>
开始
项目构建
# 合约部分 # 创建空文件夹 mkdir Web3 # 进入工程目录中 cd Web3 # 项目初始化 npm init # 安装hardhat npm install --save-dev hardhat # hardhat框架初始化选择项目模板 npx hardhat init # 下载项目插件 npm install --save-dev @nomicfoundation/hardhat-toolbox # 运行校验 # 在工程目录下创建文件前端工程目录 # <<<<<<<<<<<<<<<<<<<<<<<<< # 前端部分 # 创建一个dapp项目用于编写前端程序 create-react-app dapp # 进入dapp文件夹 cd dapp # 安装相应的包 # ethers与合约交互 # @web3uikit/core @web3uikit/web3 @web3uikit/icons 钱包相关包 npm install xxx
项目目录结构介绍
web3 |_contracts//智能合约目录 |_test//合约测试目录 |_scripts//合约部署目录 |_artifacts//编译合约自动生成 |___build-info |___contracts//前端调用合约生成的json文件 |_ignition// |_cache// |_deploy//部署合约文件目录 |_tasts//自定任务简化流程 |_front_end//前端项目工程目录 |_hardhat.config.js//hardhat配置文件 |_helper-hardhat-config.js//hardhat集中常用变量汇总文件 |_package.json//工程目录
Hardhat常用指令
# 获取所有指令 npx hardhat # 获取区块网络节点 npx hardhat node # 编译合约 npx hardhat compile # 清除缓存并删除所有工件 npx hardhat clean # 测试合约 npx hardhat test # 部署合约 npx hardhat run scripts/xx.js # 控制台 npx hardhat console # 查看所有指令 npx hardhat
合约开发
// SPDX-License-Identifier: MIT // Compatible with OpenZeppelin Contracts ^5.0.0 pragma solidity ^0.8.22; import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol" import {ERC20Burnable} from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol"; import {ERC20Permit} from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.sol"; import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; contract MyToken is ERC20, ERC20Burnable, Ownable, ERC20Permit { constructor(address initialOwner) ERC20("MyToken", "MTK") Ownable(initialOwner) ERC20Permit("MyToken") { _mint(msg.sender, 1000 * 10 ** decimals()); } //铸造方法 function mint(address to, uint256 amount) public onlyOwner { _mint(to, amount); } } /**
- 合约说明:
- 使用openzeppelin库快速构建一个具备铸造和销毁的ERC20标准的代币合约
- 代币名称 MyToken,符号 MTK,总量:1000MTK
- 方法:铸造,销毁,转账,授权... */
# 合约编译
编译合约指令
npx hardhat compile
# 合约测试
合约测试指令
npx hardhat test
# 合约测试样例 说明:hardhat框架集成了chai测试的工具
const { ethers,getNamedAccounts,deployments} = require("hardhat"); const {assert,expect } = require("chai"); let firstAccount; let nft; // 部署合约 beforeEach(async function () { firstAccount = (await getNamedAccounts()).firstAccount; await deployments.fixture(["all"]); nft=await ethers.getContract("MyNFT",firstAccount); }); // 测试单元 参数说明:测试单元命名 describe("xxx", async () => { it("mint nft", async function () { await nft.safeMint(firstAccount); let owner=await nft.ownerOf(0); expect(owner).to.equal(firstAccount); }); //......... });
# 合约部署指令
npx hardhat run scripts/xxx.js --network <network-name>
npx hardhat run scripts/deploy.js or npx hardhat run scripts/deploy.js --network localhost//指定网络
# 合约部署样例1
const { ethers } = require("hardhat");
async function main() { const [deployer] = await ethers.getSigners();//获取网络节点账号 // console.log(deployer) console.log("Deploying contracts with the account:", deployer.address); const MyToken = await ethers.getContractFactory("MyToken");//获取合约 console.log(MyToken)//获取合约实例 const myToken = await MyToken.deploy();//部署合约 console.log("Token address:", myToken.target);//打印合约地址
} main().then(()=>{ process.exit(0) }).catch((err)=>{ console.error(err) process.exit(1) });
npx hardhat run scripts/xxx.js --network 指定网络节点
# 合约部署样例2
require("hardhat-deploy"); require("@nomicfoundation/hardhat-ethers"); require("hardhat-deploy-ethers");
// module.exports = async (hre) => { // const getNamedAccounts = hre.getNamedAccounts // const deployments = hre.deployments // } const { network } =require("hardhat");
module.exports = async ({getNamedAccounts,deployments}) => { const firstAccount = (await getNamedAccounts()).firstAccount;//获取节点1 const secondAccount = (await getNamedAccounts()).secondAccount;//获取节点2 const {deploy}= deployments//获取部署实例 //部署合约 const FundMe= await deploy("FundMe",{ from: firstAccount,//节点 args: [xx,xxx],//要传的参数xx,xxx log: true,//是否打印log //waitConfirmations: confirmations,//等待的区块数 }) //验证合约是否成功的部署的链上 await hre.run("verify:verify", { address: FundMe.address, constructorArguments: [xx,xxx],//合约要传的参数xx,xxx }); } module.exports.tags = ["all","fundme"];//在执行部署指令时可选参数
npx hardhat deploy --tag fundme or all
npx hardhat run scripts/funfme.js
# 自定义task样例
tasks |_deploy_nft.js |index.js | deploy_tonken.js
const {task} = require("hardhat/config");//hardhat集成的插件
//参数说明,deploy-nft是指令名
task("deploy-fundme", "deploy-fundme").setAction(async (taskArgs, hre) => {
const FundMeFactory = await ethers.getContractFactory("MyNFT");//获取合约
const fundMe = await FundMeFactory.deploy(300);//部署需要传递的参数
await fundMe.waitForDeployment();//几个区块
console.log(address : ${fundMe.target}
)
if(hre.network.config.chainId == 11155111 && process.env.ETHERSCAN_API_KEY){
console.log("Waiting for 5 confirmations")
await fundMe.deploymentTransaction().wait(5) //等待5个区块交易完成
await verifyFundMe(fundMe.target, [300])
}else{
console.log("verification skipped..")
}
}); async function verifyFundMe(factoryAddr,args){ await hre.run("verify:verify", { address: factoryAddr, constructorArguments: [50], }); } exports.default = {};
exports.deployfundme=require("./deploy_nft.js") exports.interactfundme=require("./deploy_token.js") 把自定task引入hardhat.config.js中 require(./tasks);
可以在控制台面板中的AVAILABLE TASKS查看到
npx hardhat deploy-fundme --network xxx //如果有参数传递就后面跟参数 键名 键值
同上修改一下关键参数即可
# hardhat.config.js文件配置
require("@nomicfoundation/hardhat-toolbox");
require("@nomicfoundation/hardhat-verify");//验证合约
// require("@chainlink/env-enc").config();//可以采用此包对.env常量进行加密处理
require("dotenv").config();//读取.env的内容
require("./tasks");//自定义task,作用主要快加高效的执行自定指令,便于高效的开发。
//引入部署插件
require("hardhat-deploy");
require("@nomicfoundation/hardhat-ethers");
require("hardhat-deploy-ethers");
//读取env的常量
process.env.PRIVATE_KEY = process.env.PRIVATE_KEY;
process.env.PRIVATE_KEY_1 = process.env.PRIVATE_KEY_1;
process.env.ALCHEMY_API_KEY = process.env.ALCHEMY_API_KEY;
process.env.ETHERSCAN_API_KEY = process.env.ETHERSCAN_API_KEY;
module.exports = {
solidity: "0.8.27",
defaultNetwork: "hardhat",
mocha: {
timeout: 300000//设置mocha的超时时间为300秒,解决集成测试时间不够问题
},
networks: {
// localhost: {
// url:'http://127.0.0.1:8545/',
// chainId: 31337,
// },
sepolia: {
url: https://sepolia.infura.io/v3/${process.env.ALCHEMY_API_KEY}
,
accounts: [process.env.PRIVATE_KEY,process.env.PRIVATE_KEY_1],
chainId: 11155111
},
},//网络节点设置
etherscan: {
apiKey: {
sepolia: process.env.ETHERSCAN_API_KEY
}
},//设置 Etherscan API 密钥的,用于与 Etherscan 服务进行交互
sourcify: {
enabled: true
},//启动 Hardhat 插件 @nomicfoundation/hardhat-verify,用户验证部署在以太坊区块链上的智能合约的源代码
namedAccounts: {
firstAccount: {
default: 0
},
secondAccount: {
default: 1
}
},//通过名字获取区块节点
gasReporter: {
enabled: false,//控制gas报告的显示
}
};
# 前端调用合约
import myToken from "../json/MyToken.json";//不是之后生成的json文件 import { ethers } from "ethers"; const provider = new ethers.JsonRpcProvider();//获取provider let TokenAddress="0x......"//合约地址 let signer=await provider.signer();//获取签名
const contractWETH = new ethers.Contract(TokenAddress, myToken.abi, signer);
# 插件篇
# 总结
以上就是使用hardhat构建工具,把编写的智能合约从开发,测试,部署上链的整个流程。
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!