当前位置: 首页 > news >正文

Hardhat 环境搭建及教程示例

一.安装node.js

curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh | bash
nvm install 18
nvm use 18
nvm alias default 18
npm install npm --global # Upgrade npm to the latest version

二. 安装hardhat

2.1 创建hardhat安装目录

mkdir hardhat
cd hardhat

2.2 安装hardhat

npm install --save-dev hardhat
ls
# 安装后的目录
# node_modules      package-lock.json package.json

2.3 在安装hardhat的目录下运行hardhat

npx hardhat

选择创建hardhat配置文件

 2.4 hardhat架构

Hardhat是围绕**task(任务)和plugins(插件)**的概念设计的。 **Hardhat **的大部分功能来自插件,作为开发人员,你可以自由选择你要使用的插件。

2.5 Task(任务)

每次你从CLI运行Hardhat时,你都在运行任务。 例如 npx hardhat compile正在运行compile任务。 要查看项目中当前可用的任务,运行npx hardhat。 通过运行npx hardhat help [task],可以探索任何任务。

2.6 Plugins(插件)

Hardhat 不限制选择哪种工具,但是它确实内置了一些插件,所有这些也都可以覆盖。 大多数时候,使用给定工具的方法是将其集成到Hardhat中作为插件。

在本教程中,我们将使用hardhat-toolbox插件。 通过他们与以太坊进行交互并测试合约。 稍后将解释它们的用法。 要安装它们,请在项目目录中运行:

npm install --save-dev @nomicfoundation/hardhat-toolbox

在hardhar.config.js文件中添加下面的代码

require("@nomicfoundation/hardhat-toolbox");/** @type import('hardhat/config').HardhatUserConfig */
module.exports = {solidity: "0.8.18",
};

三. 编写、编译、测试、调试智能合约

3.1 写一个简单的智能合约

在hardhat目录下创建一个新的目录

mkdir contracts
cd contracts

添加Token.sol智能合约

//SPDX-License-Identifier: UNLICENSED// Solidity files have to start with this pragma.
// It will be used by the Solidity compiler to validate its version.
pragma solidity ^0.8.9;// This is the main building block for smart contracts.
contract Token {// Some string type variables to identify the token.string public name = "My Hardhat Token";string public symbol = "MHT";// The fixed amount of tokens, stored in an unsigned integer type variable.uint256 public totalSupply = 1000000;// An address type variable is used to store ethereum accounts.address public owner;// A mapping is a key/value map. Here we store each account's balance.mapping(address => uint256) balances;// The Transfer event helps off-chain applications understand// what happens within your contract.event Transfer(address indexed _from, address indexed _to, uint256 _value);/*** Contract initialization.*/constructor() {// The totalSupply is assigned to the transaction sender, which is the// account that is deploying the contract.balances[msg.sender] = totalSupply;owner = msg.sender;}/*** A function to transfer tokens.** The `external` modifier makes a function *only* callable from *outside** the contract.*/function transfer(address to, uint256 amount) external {// Check if the transaction sender has enough tokens.// If `require`'s first argument evaluates to `false` then the// transaction will revert.require(balances[msg.sender] >= amount, "Not enough tokens");// Transfer the amount.balances[msg.sender] -= amount;balances[to] += amount;// Notify off-chain applications of the transfer.emit Transfer(msg.sender, to, amount);}/*** Read only function to retrieve the token balance of a given account.** The `view` modifier indicates that it doesn't modify the contract's* state, which allows us to call it without executing a transaction.*/function balanceOf(address account) external view returns (uint256) {return balances[account];}
}

3.2 编译

npx hardhat compile

3.3 测试 

创建test文件夹,创建测试文件Token.js

mkdir test
cd test
const { expect } = require("chai");describe("Token contract", function () {it("Deployment should assign the total supply of tokens to the owner", async function () {const [owner] = await ethers.getSigners();const Token = await ethers.getContractFactory("Token");const hardhatToken = await Token.deploy();const ownerBalance = await hardhatToken.balanceOf(owner.address);expect(await hardhatToken.totalSupply()).to.equal(ownerBalance);});
});

运行test命令

npx hardhat test

 

 

3.4 调试智能合约

Hardhat内置了Hardhat Network ,这是一个专为开发而设计的以太坊网络。 它允许你部署合约,运行测试和调试代码。 这是Hardhat所连接的默认网络,因此你无需进行任何设置即可工作。 你只需运行测试就好。

Solidity 中使用 console.log
在Hardhat Network上运行合约和测试时,你可以在Solidity代码中调用console.log()打印日志信息和合约变量。 你必须先从合约代码中导入**Hardhat **的console.log再使用它。

修改只能合约

pragma solidity ^0.8.9;import "hardhat/console.sol";contract Token {//...
}
function transfer(address to, uint256 amount) external {require(balances[msg.sender] >= amount, "Not enough tokens");console.log("Transferring from %s to %s %s tokens",msg.sender,to,amount);balances[msg.sender] -= amount;balances[to] += amount;emit Transfer(msg.sender, to, amount);
}

修改测试文件

// This is an example test file. Hardhat will run every *.js file in `test/`,
// so feel free to add new ones.// Hardhat tests are normally written with Mocha and Chai.// We import Chai to use its asserting functions here.
const { expect } = require("chai");// We use `loadFixture` to share common setups (or fixtures) between tests.
// Using this simplifies your tests and makes them run faster, by taking
// advantage of Hardhat Network's snapshot functionality.
const { loadFixture } = require("@nomicfoundation/hardhat-network-helpers");// `describe` is a Mocha function that allows you to organize your tests.
// Having your tests organized makes debugging them easier. All Mocha
// functions are available in the global scope.
//
// `describe` receives the name of a section of your test suite, and a
// callback. The callback must define the tests of that section. This callback
// can't be an async function.
describe("Token contract", function () {// We define a fixture to reuse the same setup in every test. We use// loadFixture to run this setup once, snapshot that state, and reset Hardhat// Network to that snapshot in every test.async function deployTokenFixture() {// Get the ContractFactory and Signers here.const Token = await ethers.getContractFactory("Token");const [owner, addr1, addr2] = await ethers.getSigners();// To deploy our contract, we just have to call Token.deploy() and await// its deployed() method, which happens once its transaction has been// mined.const hardhatToken = await Token.deploy();await hardhatToken.deployed();// Fixtures can return anything you consider useful for your testsreturn { Token, hardhatToken, owner, addr1, addr2 };}// You can nest describe calls to create subsections.describe("Deployment", function () {// `it` is another Mocha function. This is the one you use to define each// of your tests. It receives the test name, and a callback function.//// If the callback function is async, Mocha will `await` it.it("Should set the right owner", async function () {// We use loadFixture to setup our environment, and then assert that// things went wellconst { hardhatToken, owner } = await loadFixture(deployTokenFixture);// `expect` receives a value and wraps it in an assertion object. These// objects have a lot of utility methods to assert values.// This test expects the owner variable stored in the contract to be// equal to our Signer's owner.expect(await hardhatToken.owner()).to.equal(owner.address);});it("Should assign the total supply of tokens to the owner", async function () {const { hardhatToken, owner } = await loadFixture(deployTokenFixture);const ownerBalance = await hardhatToken.balanceOf(owner.address);expect(await hardhatToken.totalSupply()).to.equal(ownerBalance);});});describe("Transactions", function () {it("Should transfer tokens between accounts", async function () {const { hardhatToken, owner, addr1, addr2 } = await loadFixture(deployTokenFixture);// Transfer 50 tokens from owner to addr1await expect(hardhatToken.transfer(addr1.address, 50)).to.changeTokenBalances(hardhatToken, [owner, addr1], [-50, 50]);// Transfer 50 tokens from addr1 to addr2// We use .connect(signer) to send a transaction from another accountawait expect(hardhatToken.connect(addr1).transfer(addr2.address, 50)).to.changeTokenBalances(hardhatToken, [addr1, addr2], [-50, 50]);});it("Should emit Transfer events", async function () {const { hardhatToken, owner, addr1, addr2 } = await loadFixture(deployTokenFixture);// Transfer 50 tokens from owner to addr1await expect(hardhatToken.transfer(addr1.address, 50)).to.emit(hardhatToken, "Transfer").withArgs(owner.address, addr1.address, 50);// Transfer 50 tokens from addr1 to addr2// We use .connect(signer) to send a transaction from another accountawait expect(hardhatToken.connect(addr1).transfer(addr2.address, 50)).to.emit(hardhatToken, "Transfer").withArgs(addr1.address, addr2.address, 50);});it("Should fail if sender doesn't have enough tokens", async function () {const { hardhatToken, owner, addr1 } = await loadFixture(deployTokenFixture);const initialOwnerBalance = await hardhatToken.balanceOf(owner.address);// Try to send 1 token from addr1 (0 tokens) to owner.// `require` will evaluate false and revert the transaction.await expect(hardhatToken.connect(addr1).transfer(owner.address, 1)).to.be.revertedWith("Not enough tokens");// Owner balance shouldn't have changed.expect(await hardhatToken.balanceOf(owner.address)).to.equal(initialOwnerBalance);});});
});

运行测试

npx hardhat test

 看到输出了log

四. 部署合约到网络

4.1 创建scripts文件夹,添加deploy.js文件

async function main() {const [deployer] = await ethers.getSigners();console.log("Deploying contracts with the account:", deployer.address);console.log("Account balance:", (await deployer.getBalance()).toString());const Token = await ethers.getContractFactory("Token");const token = await Token.deploy();console.log("Token address:", token.address);
}main().then(() => process.exit(0)).catch((error) => {console.error(error);process.exit(1);});

4.2 发布到hardhat自己的网络实例

npx hardhat run scripts/deploy.js

Deploying contracts with the account: 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266
Account balance: 10000000000000000000000
Token address: 0x5FbDB2315678afecb367f032d93F642f64180aa3

4.3 发布到Ganache网络

修改配置文件hardhat.config.js

require("@nomicfoundation/hardhat-toolbox");/** @type import('hardhat/config').HardhatUserConfig */
module.exports = {solidity: "0.8.18",networks: {deployment: {url: `http://127.0.0.1:7545`,accounts: ["bc549ba74b85bf9cc89309fc094cd868ff39215570b64271e19be9c1977df279"]}}
};
npx hardhat run scripts/deploy.js --network deployment

Deploying contracts with the account: 0xEb110D13835ff1e9B65320682601634D041dD505
Account balance: 98996267410475486878
Token address: 0x3f4f9B074bfd9B0C4920FD28b374e2B8E7B618f4

 看到Ganache已经有记录

4.4 发布到sepolia测试网

修改配置文件hardhat.config.js

require("@nomicfoundation/hardhat-toolbox");// Go to https://infura.io, sign up, create a new API key
// in its dashboard, and replace "KEY" with it
const INFURA_API_KEY = "KEY";// Replace this private key with your Sepolia account private key
// To export your private key from Metamask, open Metamask and
// go to Account Details > Export Private Key
// Beware: NEVER put real Ether into testing accounts
const SEPOLIA_PRIVATE_KEY = "YOUR SEPOLIA PRIVATE KEY";module.exports = {solidity: "0.8.9",networks: {sepolia: {url: `https://sepolia.infura.io/v3/${INFURA_API_KEY}`,accounts: [SEPOLIA_PRIVATE_KEY]}}
};
npx hardhat run scripts/deploy.js --network sepolia

这个我没有试,有兴趣的可以试一下

参考文档:

hardhat官网教程

[译] Hardhat 入门教程 | 登链社区 | 区块链技术社区

相关文章:

Hardhat 环境搭建及教程示例

一.安装node.js curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh | bash nvm install 18 nvm use 18 nvm alias default 18 npm install npm --global # Upgrade npm to the latest version 二. 安装hardhat 2.1 创建hardhat安装目录 mkdir hard…...

复杂链表的复制-剑指Offer35-java

一、题目描述 请实现 copyRandomList 函数,复制一个复杂链表。在复杂链表中,每个节点除了有一个 next 指针指向下一个节点,还有一个 random 指针指向链表中的任意节点或者 null。 示例 1: 输入:head [[7,null],[13,…...

【Linux】进程理解与学习Ⅰ-进程概念

环境:centos7.6,腾讯云服务器Linux文章都放在了专栏:【Linux】欢迎支持订阅🌹相关文章推荐:【Linux】冯.诺依曼体系结构与操作系统进程概念什么是进程?进程是什么?我们打开任务管理器可以看到有…...

WebKitX ActiveX 6.0 X86 Crack

WebKitX ActiveX将 Chromium Embedded Framework (CEF3) 包装到一个进程外的 ActiveX 组件中,以便与 OLE/COM 语言一起使用。Chromium Embedded Framework 封装了 WebKit Blink HTML5 Renderer 和 Google V8 JavaScript Engine。这是一个用于商业用途的生产级稳定组…...

开源项目:数据库表结构生成文档工具

目录 一、软件介绍 二、技术框架 三、功能介绍 四、代码展示 1、获取数据库信息部分代码 2、导出Html文档代码 五、运行效果 六、项目开源地址 一、软件介绍 今天给大家分享我自己编写的数据库表结构文档生成工具,方便大家在实际开发当中,可以很方便导出…...

spring的两种拦截器HandlerIntercepter和MethodIntercepter

介绍 Spring有两种拦截器提供给我们使用,一种是HandlerIntercepter,另一种是MethodIntercepter。这两种的来源不同,实现方式也不同,具体的下面来看一下。 HandlerIntercepter 来源 来源于spring-webmvc包 HandlerIntercepter拦…...

初级算法-字符串

主要记录算法和数据结构学习笔记,新的一年更上一层楼! 初级算法-字符串一、反转字符串二、反转字符串(二)三、替换空格四、翻转字符串里的单词五、左旋转字符串六、实现 strStr()七、重复的子字符串字符串中元素只能是字符String…...

华为OD机试题 - 寻找目标字符串(JavaScript)| 机考必刷

更多题库,搜索引擎搜 梦想橡皮擦华为OD 👑👑👑 更多华为OD题库,搜 梦想橡皮擦 华为OD 👑👑👑 更多华为机考题库,搜 梦想橡皮擦华为OD 👑👑👑 最近更新的博客 华为od 2023 | 什么是华为od,od 薪资待遇,od机试题清单华为OD机试真题大全,用 Python 解华为…...

删除Terminating状态的namespace:cattle-system

这里以cattle-system为例!执行删除命令后namespace(也是用其他k8s object)仍然存在,首先执行 kubectl edit namespace cattle-system 查看是否存在spec.finalizers: kubernetes,如: spec: finalizers:…...

MiniOB 并发B+树实现解析

MiniOB 是 OceanBase 联合华中科技大学推出的一款用于教学的小型数据库系统,希望能够帮助数据库爱好者系统性的学习数据库原理与实战。 B 树介绍 B 树是传统数据库中常见的索引数据结构,比如MySQL、PostgreSQL都实现了B树索引。B 树是一个平衡多叉树&am…...

SpringCloud负载均衡服务调用——Ribbon

Ribbon 本专栏学习内容来自尚硅谷周阳老师的视频 有兴趣的小伙伴可以点击视频地址观看 简介 Spring Cloud Ribbon是基于Netflix Ribbon实现的一套客户端负载均衡的工具。 简单的说,Ribbon是Netflix发布的开源项目,主要功能是提供客户端的软件负载均衡算…...

各种邮箱服务软件对比

1.宝塔邮局管理器 特点:简单易用,可视化操作,小白也能搞,还有备份功能,一般足够用了 缺点:稳定性真是差,隔三差五的不能收发.没有接口,不能任意修改邮箱密码,只能管理员修改 注意要点:一定要开启ssl,否则有些邮箱给你发邮件你收不到 建议:不要入坑.坏了之后没法修复,哭都没地方…...

相机单独标定的实现过程[autoware标定]、tmp文件的查看方式

安装了autoware1.13和calibration标定包,发现实现相机单独标定的过程较为坎坷,参考了一些博主的方法,发现下面的过程更加适合自己,做个笔记。 1安装标定箱(与calibration标定包的安装并不冲突) 标定工具箱…...

4.10.1、IP 多播技术的相关基本概念

多播(Multicast,也称为组播)是一种实现 “一对多” 通信的技术,与传统单播“一对一”通信相比,多播可以极大地节省网络资源。 在因特网上进行的多播,称为 IP 多播。 1、单播 & 多播 如下所示&#xf…...

PIGOSS BSM监控国产数据库Oscar

前言神通数据库(原OSCAR数据库)是天津神舟通用数据技术有限公司(简称“神舟通用公司”)拥有自主知识产权的企业级、大型通用关系型数据库管理系统。PIGOSS BSM作为网利友联科技完全自主研发的纯国产基础 IT 架构运行状态监测平台软件&#xf…...

Spring Boot中文件上传

Spring Boot中文件上传 前言 本篇主要参考Spring官方文档,整理了Spring Boot中文件上传如何实现,以及在代码中使用RestTemplate和HttpClient两种方式实现文件上传。 创建Spring Boot项目 首先创建一个Spring Boot Web项目,使用的Spring B…...

Github上传大文件(>25MB)教程

Github上传大文件(>25MB)教程Github上传大文件(>25MB)教程安装git安装Git Large File Storage实例踩坑点1:failed to push some refs to踩坑点2:main与master踩坑点3:Failed to connect t…...

面试官:mysql索引会缓存内存吗?

文章目录 InnoDB缓冲池如何设置方法一:使用 `innodb_buffer_pool_size` 变量方法二:修改my.ini配置文件InnoDB缓冲池 InnoDB存储引擎是基于磁盘存储表文件和索引的,并将数据按页的方式管理,由于访问磁盘的速度较慢,多次访问磁盘会造成数据库性能的下降,为此,InnoDB在内…...

bs4解析数据和csv文件

\b 检测所在的位置是否是单词边界(任何可以将不同的单词进行区分的符号:空白符号,标点符号,字符串开头,字符串结尾) ^ 检测是否是字符串开头 $ 检测是否是字符串结尾 csv保存数据 什么是csv文件 读操作…...

Linux中Buffer和Cache的区别

Linux中Buffer和Cache的区别 free命令中会有一项buff/cache, 通过man free可以看到这里的关于buff/cache的介绍 buff/cache包含两部分 buffers:内核缓存区用到的内存,对应/proc/meminfo中Buffers的值 cache:内核页缓存和Slab用到的内存,对应/proc/mem…...

接口测试中缓存处理策略

在接口测试中,缓存处理策略是一个关键环节,直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性,避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明: 一、缓存处理的核…...

多云管理“拦路虎”:深入解析网络互联、身份同步与成本可视化的技术复杂度​

一、引言:多云环境的技术复杂性本质​​ 企业采用多云策略已从技术选型升维至生存刚需。当业务系统分散部署在多个云平台时,​​基础设施的技术债呈现指数级积累​​。网络连接、身份认证、成本管理这三大核心挑战相互嵌套:跨云网络构建数据…...

Chapter03-Authentication vulnerabilities

文章目录 1. 身份验证简介1.1 What is authentication1.2 difference between authentication and authorization1.3 身份验证机制失效的原因1.4 身份验证机制失效的影响 2. 基于登录功能的漏洞2.1 密码爆破2.2 用户名枚举2.3 有缺陷的暴力破解防护2.3.1 如果用户登录尝试失败次…...

使用VSCode开发Django指南

使用VSCode开发Django指南 一、概述 Django 是一个高级 Python 框架,专为快速、安全和可扩展的 Web 开发而设计。Django 包含对 URL 路由、页面模板和数据处理的丰富支持。 本文将创建一个简单的 Django 应用,其中包含三个使用通用基本模板的页面。在此…...

DeepSeek 赋能智慧能源:微电网优化调度的智能革新路径

目录 一、智慧能源微电网优化调度概述1.1 智慧能源微电网概念1.2 优化调度的重要性1.3 目前面临的挑战 二、DeepSeek 技术探秘2.1 DeepSeek 技术原理2.2 DeepSeek 独特优势2.3 DeepSeek 在 AI 领域地位 三、DeepSeek 在微电网优化调度中的应用剖析3.1 数据处理与分析3.2 预测与…...

k8s从入门到放弃之Ingress七层负载

k8s从入门到放弃之Ingress七层负载 在Kubernetes(简称K8s)中,Ingress是一个API对象,它允许你定义如何从集群外部访问集群内部的服务。Ingress可以提供负载均衡、SSL终结和基于名称的虚拟主机等功能。通过Ingress,你可…...

Cesium1.95中高性能加载1500个点

一、基本方式&#xff1a; 图标使用.png比.svg性能要好 <template><div id"cesiumContainer"></div><div class"toolbar"><button id"resetButton">重新生成点</button><span id"countDisplay&qu…...

高危文件识别的常用算法:原理、应用与企业场景

高危文件识别的常用算法&#xff1a;原理、应用与企业场景 高危文件识别旨在检测可能导致安全威胁的文件&#xff0c;如包含恶意代码、敏感数据或欺诈内容的文档&#xff0c;在企业协同办公环境中&#xff08;如Teams、Google Workspace&#xff09;尤为重要。结合大模型技术&…...

【HTML-16】深入理解HTML中的块元素与行内元素

HTML元素根据其显示特性可以分为两大类&#xff1a;块元素(Block-level Elements)和行内元素(Inline Elements)。理解这两者的区别对于构建良好的网页布局至关重要。本文将全面解析这两种元素的特性、区别以及实际应用场景。 1. 块元素(Block-level Elements) 1.1 基本特性 …...

MySQL中【正则表达式】用法

MySQL 中正则表达式通过 REGEXP 或 RLIKE 操作符实现&#xff08;两者等价&#xff09;&#xff0c;用于在 WHERE 子句中进行复杂的字符串模式匹配。以下是核心用法和示例&#xff1a; 一、基础语法 SELECT column_name FROM table_name WHERE column_name REGEXP pattern; …...