Hardhat以太坊智能合约开发框架基础教程
一、Hardhat框架介绍
Hardhat是一个基于javascript和solidity的开发框架。可实现编译、部署、测试、开源和调试以太坊应用的开发环境。Hardhat是一个围绕任务和插件的概念设计的;Hardhat 的大部分功能来自插件。Chain区块链开发群593674370
二、Hardhat框架优点
1、Hardhat 拥有大量插件,并允许自定义、灵活性和可扩展性。
2、Hardhat运行同时使用ether.js和web3.js。
3、Hardhat有良好的 console.log() 调试能力;会在调试时提供代码中发生的堆栈跟踪。
4、Hardhat 提供原生Typescript
支持,并且还有一个Vscode扩展,为 Vscode 编辑器添加了可靠的支持。
5、Hardhat 带有一个内置的本地以太坊网络,称为Hardhat Network,用于在本地机器上运行和部署智能合约,是一个专为开发而设计的本地以太坊网络节点。
三、哪些项目在使用Hardhat
Chainlink ;Uniswap;Aave ;SushiSwap ; ENS 等主流项目。
四、Hardhat环境搭建
1、请安装node.js 12.x及以上的版本
2、Hardhat先安装到本地。
npm install --save-dev hardhat
3、先创建一个空文件夹执行安装命令;通过执行 npx hardhat 创建项目。
npx hardhat
初始化后项目结构。
五、创建编译合约
1、在contracts目录下编写一个合约文件 Token.js
// SPDX-License-Identifier: MITpragma solidity ^0.8.8;library SafeMath {function add(uint256 a, uint256 b) internal pure returns (uint256) {uint256 c = a + b;require(c >= a, "SafeMath: addition overflow");return c;}function sub(uint256 a, uint256 b) internal pure returns (uint256) {require(b <= a, "SafeMath: subtraction overflow");uint256 c = a - b;return c;}function mul(uint256 a, uint256 b) internal pure returns (uint256) {if (a == 0) {return 0;}uint256 c = a * b;require(c / a == b, "SafeMath: multiplication overflow");return c;}function div(uint256 a, uint256 b) internal pure returns (uint256) {// Solidity only automatically asserts when dividing by 0require(b > 0, "SafeMath: division by zero");uint256 c = a / b;// assert(a == b * c + a % b); // There is no case in which this doesn't holdreturn c;}function mod(uint256 a, uint256 b) internal pure returns (uint256) {require(b != 0, "SafeMath: modulo by zero");return a % b;}
}
interface IERC20 {function totalSupply() external view returns (uint256);function balanceOf(address account) external view returns (uint256);function transfer(address recipient, uint256 amount) external returns (bool);function allowance(address owner, address spender) external view returns (uint256);function approve(address spender, uint256 amount) external returns (bool);function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);event Transfer(address indexed from, address indexed to, uint256 value);event Approval(address indexed owner, address indexed spender, uint256 value);
}abstract contract ERC20Detailed is IERC20 {string private _name;string private _symbol;uint8 private _decimals;constructor (string memory tokenName, string memory tokenSymbol, uint8 tokenDecimals) {_name = tokenName;_symbol = tokenSymbol;_decimals = tokenDecimals;}function name() public view returns (string memory) {return _name;}function symbol() public view returns (string memory) {return _symbol;}function decimals() public view returns (uint8) {return _decimals;}
}contract ERC20 is IERC20 {using SafeMath for uint256;mapping (address => uint256) private _balances;mapping (address => mapping (address => uint256)) private _allowances;uint256 private _totalSupply;function totalSupply() public view returns (uint256) {return _totalSupply;}function balanceOf(address account) public view returns (uint256) {return _balances[account];}function transfer(address recipient, uint256 amount) public returns (bool) {_transfer(msg.sender, recipient, amount);return true;}function allowance(address owner, address spender) public view returns (uint256) {return _allowances[owner][spender];}function approve(address spender, uint256 value) public returns (bool) {_approve(msg.sender, spender, value);return true;}function transferFrom(address sender, address recipient, uint256 amount) public returns (bool) {_transfer(sender, recipient, amount);_approve(sender, msg.sender, _allowances[sender][msg.sender].sub(amount));return true;}function _transfer(address sender, address recipient, uint256 amount) internal {require(sender != address(0), "ERC20: transfer from the zero address");require(recipient != address(0), "ERC20: transfer to the zero address");_balances[sender] = _balances[sender].sub(amount);_balances[recipient] = _balances[recipient].add(amount);emit Transfer(sender, recipient, amount);}function _mint(address account, uint256 amount) internal {require(account != address(0), "ERC20: mint to the zero address");_totalSupply = _totalSupply.add(amount);_balances[account] = _balances[account].add(amount);emit Transfer(address(0), account, amount);}function _burn(address account, uint256 value) internal {require(account != address(0), "ERC20: burn from the zero address");_totalSupply = _totalSupply.sub(value);_balances[account] = _balances[account].sub(value);emit Transfer(account, address(0), value);}function _approve(address owner, address spender, uint256 value) internal {require(owner != address(0), "ERC20: approve from the zero address");require(spender != address(0), "ERC20: approve to the zero address");_allowances[owner][spender] = value;emit Approval(owner, spender, value);}function _burnFrom(address account, uint256 amount) internal {_burn(account, amount);_approve(account, msg.sender, _allowances[account][msg.sender].sub(amount));}
}
contract ERC20Template is ERC20, ERC20Detailed {constructor() ERC20Detailed("USDT", "USDT", 18) {_mint(msg.sender, 10000000000 * (10 ** uint256(decimals())));}
}
2、编译合约执行 npx hardhat compile
% npx hardhat compileCompiled 1 Solidity file successfully
3、在test目录下 编写测试案例 Token.js
//Chai,这是一个断言库
const { expect } = require("chai");describe("创建合约测试案例", function() {it("CreateContract", async function() {//ethers.js中的Signer 代表以太坊账户对象。 它用于将交易发送到合约和其他帐户。// 在这里,我们获得了所连接节点中的帐户列表,在本例中节点为Hardhat Network,并且仅保留第一个帐户const [owner, addr1, addr2] = await ethers.getSigners();//ethers.js中的ContractFactory是用于部署新智能合约的抽象,因此此处的Token是用来实例代币合约的工厂。const Token = await ethers.getContractFactory("ERC20Template");//在ContractFactory上调用deploy()将启动部署,并返回解析为Contract的Promise。 该对象包含了智能合约所有函数的方法。const hardhatToken = await Token.deploy();//当你调用deploy()时,将发送交易,但是直到该交易打包出块后,合约才真正部署。 调用deployed()将返回一个Promise,因此该代码将阻塞直到部署完成。await hardhatToken.deployed();//查询代币总量const balance = await hardhatToken.balanceOf(await owner.getAddress());console.log("代币总量="+balance)// 给钱包addr1转移100代币数量await hardhatToken.transfer(await addr1.getAddress(), 100);//查询地址addr1余额const balanceAddr1 = await hardhatToken.balanceOf(await addr1.getAddress());console.log("地址addr1余额="+balanceAddr1)// 钱包addr1给钱包addr2转移100代币数量await hardhatToken.connect(addr1).transfer(await addr2.getAddress(), 100);const balanceAddr11 = await hardhatToken.balanceOf(await addr1.getAddress());console.log("余额转移给addr2后地址addr1余额="+balanceAddr11)//查询地址addr2余额const balanceAddr2 = await hardhatToken.balanceOf(await addr2.getAddress());console.log("地址addr2余额="+balanceAddr2)//断言判断expect(await hardhatToken.balanceOf(await addr2.getAddress())).to.equal(100);});
});
执行 npx hardhat test 查看运行结果:
六、部署合约到正式网络网络
1、hardhat.config.js 在此文件里面配置 网络信息
require("@nomicfoundation/hardhat-toolbox");
require("@nomiclabs/hardhat-etherscan");module.exports = {networks: {bsc: {url: `https://bsc-dataseed1.ninicoin.io/`,accounts: [`部署合约钱包私钥`],},bscTest: {url: `https://data-seed-prebsc-2-s3.binance.org:8545/`,accounts: [`部署合约钱包私钥`]},hecoTest: {url: 'https://http-testnet.hecochain.com',accounts: [`部署合约钱包私钥`]}},etherscan: {apiKey: {bsc: '',hecoTestnet: '',}},solidity: "0.8.9"
};
2、在scripts目录下创建 TokenDeploy.js 文件
async function main() {const [deployer] = await ethers.getSigners();console.log("获取部署钱包地址:",await deployer.getAddress());console.log("获取部署钱包地址余额:", (await deployer.getBalance()).toString());//指定合约工程要部署的名称const Token = await ethers.getContractFactory("ERC20Template");const token = await Token.deploy();await token.deployed();console.log("部署后合约地址:", token.address);
}main().then(() => process.exit(0)).catch(error => {console.error(error);process.exit(1);});
执行部署命令:npx hardhat run scripts/TokenDeploy.js --network hecoTest
% npx hardhat run scripts/TokenDeploy.js --network hecoTest获取部署钱包地址: 0xc290436b3da897115493a1547B52783c50f0Bef3
获取部署钱包地址余额: 1138718537000000000
部署后合约地址: 0x9AdAaDb89C6968CF6C4Ef116C614EAedD314a6EE
HECO测试浏览器查看验证
七、合约源代码开源
注:需要申请浏览器 apiKey配置在 hardhat.config.js文件此处。
开源执行命令,成功后就可以在浏览器上查看了。
% npx hardhat verify 0x9adaadb89c6968cf6c4ef116c614eaedd314a6ee --network hecoTest
Hardhat以太坊智能合约开发框架基础教程相关推荐
- 以太坊智能合约编程简单教程(全)
有些人说以太坊太难对付,于是我们(译注:指Consensys, 下同)写了这篇文章来帮助大家学习如何利用以太坊编写智能合约和应用.这里所用到的工具,钱包,应用程序以及整个生态系统仍处于开发状态,它们将 ...
- 教程 | 以太坊智能合约编程之菜鸟教程
教程 | 以太坊智能合约编程之菜鸟教程 译注:原文首发于ConsenSys开发者博客,原作者为Eva以及ConsenSys的开发团队.如果您想要获取更多及时信息,可以访问ConsenSys首页点击左下 ...
- 以太坊智能合约编程之带菜鸟入门教程
手把手带你走上智能合约编程之路 译注:原文首发于ConsenSys开发者博客,原作者为Eva以及ConsenSys的开发团队.如果您想要获取更多及时信息,可以访问ConsenSys首页点击左下角New ...
- 以太坊智能合约编程之菜鸟教程
手把手带你走上智能合约编程之路 译注:原文首发于ConsenSys开发者博客,原作者为Eva以及ConsenSys的开发团队.如果您想要获取更多及时信息,可以访问ConsenSys首页点击左下角New ...
- truffle (ETH以太坊智能合约集成开发工具) 入门教程
truffle (ETH以太坊智能合约集成开发工具) 入门教程 前言 在你了解区块链开发之前,你有必要了解区块链的一些基础知识,什么是DApp,DApp与传统app的区别, 什么是以太坊,以太坊中的智 ...
- 使用hardhat开发以太坊智能合约-测试合约
Web3工具网站[点我访问] 现已上线,欢迎使用,如有好的意见和建议也欢迎反馈. 本系列课程: 第一节:使用hardhat开发以太坊智能合约-搭建环境 第二节:使用hardhat开发以太坊智能合约-测 ...
- 使用hardhat 开发以太坊智能合约-验证合约
Web3工具网站[点我访问] 现已上线,欢迎使用,如有好的意见和建议也欢迎反馈. 本系列课程: 第一节:使用hardhat开发以太坊智能合约-搭建环境 第二节:使用hardhat开发以太坊智能合约-测 ...
- 【以太坊智能合约】Embark Framework 开发基础篇
在之前的文章中,我们看到了使用Solidity开发以太坊智能合约的所有基本知识.我们使用了以太坊钱包,我们能够轻松设置小型产品开发环境.我们会发现开始的时候很不错,但是如果我们想要更深入的话呢?我们要 ...
- 区块链开发入门:基于以太坊智能合约构建 ICO DApp
写给前端开发者的第一本区块链开发入门指南,通过从 0 到 1 实战开发一个 ICO DApp 项目(基于 V 神的 DAICO 设计思想),深入掌握区块链及以太坊技术. 为什么要选择区块链开发? 未来 ...
- 一起学:以太坊智能合约开发
课程介绍 无论在科技圈还是金融圈,"区块链"俨然成了最热的词汇.2016年,区块链写入了国家的十三五规划中:2017年,央行基于区块链技术的数字票据交易平台测试成功:同年,工信部发 ...
最新文章
- 更快学习 JavaScript 的 6 个思维技巧
- python循环语句-python----循环语句及循环控制语句
- 基于deep learning的快速图像检索(Deep Learning of Binary Hash Codes for Fast Image Retrieval)
- java keeplive,java http长链接(keep-alive)导致的问题
- replace into mysql去重_上传 phpexcel 类 入库并入库前去重
- espflashdownloadtool连接串口失败_关于串口下载问题和超时
- 基于用例的工作量估计
- SAP Spartacus forms.scss的引用问题
- mysql between 查询不出来_mysql的语句优化
- LeetCode 337. 打家劫舍 III(记忆化+递归)
- SQL Server2005还原数据库攻略
- android tools add native support,使用NDK进行开发android
- 2020年前端如何适应大环境,发展的前途与趋势是怎么样的?
- Python数据结构实战——单向链表(LinkedList)
- LeetCode 445. Add Two Numbers II
- iOS底层探索之KVO(五)—FBKVOController分析
- Mac电脑的连接服务器功能如何使用?
- 使用AD13设计PCB的技巧总结
- 伟大程序员必须具备的7个好习惯
- 怎样找回win7密钥
热门文章
- 分片(primary shard replica shard)
- matlab 买什么电脑配置,要快速运行Matlab,电脑用什么配置和系统好
- mysql 删除临时表的语句_MySQL如何创建和删除临时表_MySQL
- Vue中三元运算符多种状态判断
- 计算机蓝牙快捷键,笔记本蓝牙快捷键是什么_怎么打开笔记本电脑蓝牙-win7之家...
- linux curl证书错误,curl – SSL证书错误
- 铁路标准 EN 50126
- 永恒之蓝漏洞复现及上传后门程序
- MySQL讲义第 45 讲——select 查询之查询练习(三)
- 心灵捕手~ 鸡汤悄悄话