基础命令
Hardhat是一个非常流行的以太坊智能合约开发框架,提供了一系列工具和插件来帮助开发、测试和部署智能合约。下面是一些基本的Hardhat命令和它们的用途:
基本命令
-
初始化一个新项目:
npx hardhat这个命令会启动一个新项目的创建过程,包括建立项目结构和安装必要的依赖。
-
编译智能合约:
npx hardhat compile该命令编译项目中的智能合约。编译后的合约会生成相应的工件(artifacts),这些文件包含了ABI和字节码。
-
运行测试:
npx hardhat test这个命令运行项目中的测试脚本。Hardhat支持使用Mocha和Chai来编写测试。
-
部署合约:
npx hardhat run scripts/deploy.js使用此命令运行部署脚本以部署智能合约。
deploy.js是你的部署脚本文件。 -
启动本地开发网络:
npx hardhat node这个命令启动了一个本地的以太坊网络,用于开发和测试。它会模拟真实的区块链环境。
-
运行任务或脚本:
npx hardhat run --network <network-name> scripts/your-script.js运行特定的脚本或任务,并可以指定网络(比如localhost、testnet或mainnet)。
-
交互式控制台:
npx hardhat console启动一个交互式JavaScript控制台,允许与Hardhat环境和部署的合约进行交互。
-
清理工件:
npx hardhat clean清除编译生成的工件和缓存,有助于解决某些构建问题。
配置和自定义
Hardhat的行为可以通过在项目根目录中编辑hardhat.config.js文件来自定义。你可以在这个文件中配置网络、编译器版本、插件等。
插件
Hardhat社区提供了许多插件,用于扩展功能,如Gas报告器、代码覆盖率分析和更高级的部署机制。你可以通过NPM安装这些插件,并在hardhat.config.js中进行配置。
有关合约命令
-
账户列表:
npx hardhat accounts列出可用的以太坊账户地址。
-
检查Gas使用:
npx hardhat gas-reporter生成Gas使用报告(需要安装相关插件)。
-
Flatten合约:
npx hardhat flatten > output.sol代码扁平 将合约和其依赖合并到一个文件(需要安装相关插件)。
-
验证合约:
npx hardhat verify --network [网络名] [合约地址] [合约构造函数参数]在Etherscan等公共区块链浏览器上验证智能合约代码(需要配置API密钥)
hardhat.config.js.ts
这里是一个整合了常用配置和自定义任务的 hardhat.config.js 文件的例子,包含了详细的注释以解释每个部分的作用:
require("@nomiclabs/hardhat-waffle");
require("@nomiclabs/hardhat-ethers");
require("@nomiclabs/hardhat-etherscan");
require("dotenv").config();
module.exports = {
// Solidity编译器配置
solidity: {
version: "0.8.4", // 指定Solidity版本
settings: {
optimizer: {
enabled: true, // 启用优化器
runs: 200 // 指定优化器运行次数
}
}
},
// 网络配置
networks: {
hardhat: {
// 用于本地开发的Hardhat网络设置
},
rinkeby: {
url: process.env.RINKEBY_URL, // 连接到Rinkeby测试网的URL
accounts: [process.env.PRIVATE_KEY] // 用于部署的账户私钥
},
// 你可以添加更多网络配置
},
// Etherscan插件配置
etherscan: {
apiKey: process.env.ETHERSCAN_API_KEY // Etherscan API密钥,用于合约验证
},
// 自定义任务 npx hardhat accounts .....
tasks: {
accounts: async (_, { ethers }) => { // 自定义任务:列出所有账户
const accounts = await ethers.getSigners();
accounts.forEach((account) => {
console.log(account.address);
});
},
greet: task("greet", "Prints a greeting") // 自定义任务:打印问候语
.addParam("name", "The name to greet") // 定义参数
.setAction(async (taskArgs, hre) => { // 定义任务动作
console.log(`Hello, ${taskArgs.name}!`);
})
},
// 配置文件路径
paths: {
sources: "./contracts", // 指定Solidity源文件路径
tests: "./test", // 指定测试文件路径
cache: "./cache", // 编译缓存路径
artifacts: "./artifacts" // 编译合约的输出路径
},
// Mocha测试框架配置
mocha: {
timeout: 20000 // 测试运行的超时时间(毫秒)
},
// 默认网络配置
defaultNetwork: "hardhat",
// Hardhat运行时环境扩展
extendEnvironment: (hre) => {
hre.myHelper = async () => { /* 自定义扩展内容 */ };
}
};
在这个配置文件中,我们包含了如下几个主要部分:
- Solidity编译器配置:用于设定Solidity版本和编译器优化设置。
- 网络配置:定义连接到不同以太坊网络(如Hardhat本地网络、Rinkeby测试网)的参数。
- Etherscan插件配置:用于配置与Etherscan的集成,便于合约验证。
- 自定义任务:定义一些自定义的Hardhat任务,比如列出账户地址和打印问候语。
- 文件路径配置:设定Solidity源代码、测试代码、编译产物的存放路径。
- Mocha测试配置:配置Mocha测试框架的行为,例如设置超时时间。
- 默认网络:当不显式指定网络时使用的默认网络。
- 环境扩展:向Hardhat运行时环境添加自定义的功能或属性。
通过这个配置文件,你可以根据项目需求调整Hardhat的行为,包括编译设置、网络连接、自定义任务等,使之更贴合你的项目开发流程。
hardhat-abi-exporterABI导出
安装插件:
npm install --save-dev hardhat-abi-exporter
在hardhat.config.js文件中配置插件:
require('hardhat-abi-exporter');
module.exports = {
// ...其他配置
abiExporter: {
path: './data/abi',
clear: true,
flat: true,
// 只导出外部和公共方法的ABI
only: [':ERC20$'],
spacing: 2,
pretty: true,
},
};
问题
管理不同环境下的 部署隔离问题
1. 使用环境变量
通过 .env 文件和 dotenv 库来设置环境变量。首先,需要在项目根目录下创建一个 .env 文件,并设置合约参数:
# .env 文件
CONTRACT_PARAM1=Value1
CONTRACT_PARAM2=Value2
然后,在 deploy.js 脚本中使用这些环境变量:
// scripts/deploy.js
require("dotenv").config();
const hre = require("hardhat");
async function main() {
const MyContract = await hre.ethers.getContractFactory("MyContract");
const param1 = process.env.CONTRACT_PARAM1;
const param2 = process.env.CONTRACT_PARAM2;
const myContract = await MyContract.deploy(param1, param2);
await myContract.deployed();
console.log("MyContract deployed to:", myContract.address);
}
2. 使用命令行参数(并不推荐)
使用命令行参数传递合约参数。这可以通过修改 deploy.js 来实现,使其能够读取命令行参数:
// scripts/deploy.js
const hre = require("hardhat");
async function main() {
const MyContract = await hre.ethers.getContractFactory("MyContract");
// 从命令行读取参数
const param1 = process.argv[2];
const param2 = process.argv[3];
const myContract = await MyContract.deploy(param1, param2);
await myContract.deployed();
console.log("MyContract deployed to:", myContract.address);
}
然后,通过命令行运行部署脚本,并传递参数:
npx hardhat run scripts/deploy.js --network [网络名] Value1 Value2
3. 使用外部配置文件(推荐)
创建一个配置文件,比如 config.json,并在部署脚本中导入这个文件:
// config.json
{
"param1": "Value1",
"param2": "Value2"
}
然后在 deploy.js 中引用这些配置:
// scripts/deploy.js
const hre = require("hardhat");
const config = require("../config.json");
async function main() {
const MyContract = await hre.ethers.getContractFactory("MyContract");
const param1 = config.param1;
const param2 = config.param2;
const myContract = await MyContract.deploy(param1, param2);
await myContract.deployed();
console.log("MyContract deployed to:", myContract.address);
}
总结
这些方法使你能够在部署脚本之外灵活地指定智能合约的参数,既提高了代码的可维护性,也增加了部署过程的灵活性。选择哪种方法取决于你的具体需求和项目结构。