IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    使用hardhat部署智能合约

    haofly发表于 2022-09-06 14:40:00
    love 0
    • 能够非常方便地编写、测试并部署智能合约到以太坊
    • 内置了Hardhat Network,不用部署到真是的以太坊网络也能进行测试

    安装配置

    1
    2
    3
    4
    5
    6
    7
    npm install -g hardhat
    npx hardhat# 直接初始化项目,会生成一个hardhat.config.js配置文件,选最长的那个最全面了

    # 也可以在现有项目中初始化
    npm install --save hardhat
    npm install --save-dev @nomiclabs/hardhat-ethers ethers @nomiclabs/hardhat-waffle ethereum-waffle chai# 安装一些测试需要用到的依赖
    npx hardhat# 初始化hardhat项目,可以选择只生成配置文件

    配置文件hardhat.config.js

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    {
    require("@nomiclabs/hardhat-waffle");// 注意这里一定要引入,否则测试会报错,默认的配置文件中没有这个

    /**
    * @type import('hardhat/config').HardhatUserConfig
    */
    module.exports = {
    solidity: "0.7.3",
    networks: {
    reposten: {// 如果要部署到其他网络需要在这里定义
    url: `https://eth-ropsten.alchemyapi.io/v2/${ALCHEMY_API_KEY}`,
    accounts: [`0x${ROPSTEN_PRIVATE_KEY}`],
    httpHeaders: {
    Authorization: `Bearer 自定义http header`,
    },
    },
    private: {
    url: 'http://127.0.0.1:8545',
    accounts: ['0x111111111']
    }
    },
    path: {
    sources: './contracts',
    tests: './test',
    cache: './cache',
    artifacts: './artifacts',
    },
    mocha: {
    timeout: 20000
    }
    };
    }

    目录结构

    1
    2
    3
    4
    5
    6
    7
    8
    9
    .
    ├── artifacts# 生成的build文件夹
    ├── contracts# 存放智能合约源代码的目录
    │   └── token.sol
    ├── scripts# 存放部署脚本的目录
    │   └── deploy.js
    ├── test# 存放测试文件的目录
    │   └── token.js
    └──hardhat.config.js

    使用hardhat

    常用命令

    • 编译目录artifacts中的信息与大多数的合约编译工具的输出是兼容的,例如Truffle
    1
    2
    3
    4
    npx hardhat compile# 编译合约,编译会编译到artifacts目录。默认只会编译更改后的
    npx hardhat compile --force # 强制重新编译所有合约

    npx hardhat test# 运行测试

    测试

    • 默认是Jest测试

    • 一个测试用例./test/token.js

    • 智能合约的工具都互相兼容,如果是truffle语法写的测试用例,仍然可以用npx hardhat test来测试,需要先安装插件npm install --save-dev @nomiclabs/hardhat-truffle5 @nomiclabs/hardhat-web3 web3,并在hardhat.config.js中引入require("@nomiclabs/hardhat-truffle5");

    • 测试的各种操作默认都是owner,如果要切换为其他的用户,可以使用connect方法contract.connect(singer).getBalance(),当然,得是getSigners里面的用户才可以,不然没有私钥基本上也操作不了

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    const { expect } = require("chai");// import { expect } from 'chai';
    import { ethers } from 'hardhat';

    describe("Token contract", function() {
    let Token;

    // 代替beforeAll,这里面不能使用beforeAll,可以每个it里面都调用,只会执行一次
    async function deployTokenFixture() {
    Token = await ethers.getContractFactory("Token");
    const [owner, addr1, addr2] = await ethers.getSigners();

    const hardhatToken = await Token.deploy();

    await hardhatToken.deployed();

    // Fixtures can return anything you consider useful for your tests
    return { Token, hardhatToken, owner, addr1, addr2 };
    }

    it("Test total supply to the owner", async function() {
    await loadFixture(deployTokenFixture);

    const [owner] = await ethers.getSigners();// 这里只取了默认账户列表中的第一个账户,它也是默认的智能合约的owner

    const Token = await ethers.getContractFactory("Token");// ContractFactory就是一个部署智能合约的工厂方法,这里并没有实际部署

    const myContract = await Token.deploy(60, "abc");// 部署智能合约到hardhat本地的测试网络,可以将参数传递给构造函数

    const ownerBalance = await myContract.balanceOf(owner.address);
    expect(await myContract.totalSupply()).to.equal(ownerBalance);
    });
    });

    部署

    • 部署到指定的以太坊网络
    • 如果发现部署的时候卡住了,一直没有响应,检查下是不是没有miner在挖矿
    • example: ./scripts/deploy.js
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    async function main() {

    const [deployer] = await ethers.getSigners();// 这里取测试网络的第一个,当然也可以自己给一个地址

    console.log("Account balance:", (await deployer.getBalance()).toString());

    const Token = await ethers.getContractFactory("Token");
    const token = await Token.deploy();

    const MyContract2 = await ethers.getContractFactory('MyContract');
    const contract2 = await MyContract2.attach('0xxxxxx');// 直接使用已经部署的合约的地址来调用其方法

    console.log("Token address:", token.address);
    }

    main()
    .then(() => process.exit(0))
    .catch(error => {
    console.error(error);
    process.exit(1);
    });

    编写完成后执行命令进行部署

    1
    2
    npx hardhat run scripts/deploy.js# 默认部署到hardhat本地的测试网络,当然成功后就没了
    npx hardhat run scripts/deploy.js --network networkName# 部署到指定的网络,这里的networkName是在hardhat.config.js中定义的

    调用合约

    • 根据我的使用,artifacts目录下的东西是编译后的东西,感觉有必要放到git repo中去,这样就不用存储abi到数据库了,而且代码也方便调用。每次部署相同的合约会得到一个不同地址,但编译后的合约肯定是一样的。放到backend repo里面既可以用代码来部署也可以直接返回最新的给前端
    • 最好存储一下abi信息到数据库,这样后面即使不用hardhat也能比较方便地调用合约方法
    1
    2
    3
    4
    5
    6
    7
    8
    // import '@nomiclabs/hardhat-waffle';
    const hre = require("hardhat");// 以代码来执行deploy或者使用都是这个前缀

    await hre.artifacts.getArtifactPaths()// 获取工件文件的路径
    await hre.artifacts.readArtifacts("contracts/Auction.sol:Auction")// 获取指定合约的工件的内容

    deployedContract = await hre.ethers.getContractAt("Auction", '0xaaaaaaa')// 直接通过地址获取到部署的智能合约
    deployedContract.customFunc()// 直接调用合约的方法

    参考文章

    • Hardhat新手教程: 里面包含代币的完整测试用例


沪ICP备19023445号-2号
友情链接