解决“hardhat unresolved libraries or missing links“问题

31 篇文章 2 订阅
17 篇文章 0 订阅
本文介绍了如何处理在Hardhat测试中遇到的`unresolved libraries`问题,原因在于未正确链接自定义库合约。解决方法包括:先部署库合约,获取其地址,然后在部署业务合约时,将库合约地址放入`libraries`列表。文章通过一个具体例子展示了创建、部署合约及编写测试脚本的完整过程。
摘要由CSDN通过智能技术生成

    今天在Hardhat测试合约,发现"unresolved libraries"问题,如图(1)所示:

图(1) 报"库合约没有链接"

    出现这种现象的原因是:若library是自定义的库文件,在部署合约时,需要手动link到合约里。
    解决方法:先部署库合约,得到库合约地址,将这个地址放到业务合约的libraries列表即可。这个库合约必须要有public函数可供外部调用,不能使用函数全为internal的库合约(因为internal的库合约无法导出)。

        // 1) 部署LibMath库合约
        libFactory = await ethers.getContractFactory("LibMath");
        libObj = await libFactory.deploy()


        // 2)部署CountOne合约
        // 将CountOne所引用的库合约,全部放到libraries列表里
        contractFactory = await ethers.getContractFactory("CountOne",{
            libraries: {
                LibMath: libObj.address
            }
        });

    这里以CountOne.sol引用LibMath.sol库文件为例,进行说明。

1、创建LinkLib工程

1.1 创建文件夹

## 1)创建工程目录
mkdir LinkLib
cd LinkLib
npm init -y

## 2)创建合约文件夹、测试文件夹
mkdir contracts test

1.2 设置依赖包

    在package.json里添加dependencies、devDependencies这2个字段:

{
  "name": "LinkLib",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@nomiclabs/hardhat-ethers": "^2.0.2",
    "@nomiclabs/hardhat-waffle": "^2.0.1",
    "chai": "^4.3.4",
    "ethereum-waffle": "^3.4.0",
    "ethereumjs-abi": "^0.6.8",
    "ethers": "^5.4.7",
    "ts-node": "^10.0.0",
    "typescript": "^4.3.5",
    "hardhat": "^2.4.1"
  }
}

    然后,安装这些依赖包

npm install

1.3 设置hardhat

    hardhat.config.js是hardhat的配置文件,其设置如下:
    //hardhat.config.js

 require("@nomiclabs/hardhat-waffle");

 module.exports = {
    solidity: {
        compilers: [
            {version: "0.5.16"},
            {version: "0.5.12"},
            {version: "0.6.6"},
        ]
      }
 };
 
 

1.4 创建业务合约

    在contracts目录里,创建一个业务合约CountOne.sol,用于设置count的增减。
    // CountOne.sol

// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;

import "./LibMath.sol";

contract CountOne {
    using LibMath for uint256;

    uint    public count;
    address public owner;

    constructor() public {
        count = 0;
        owner = msg.sender;
    }

    function getCount() public view returns(uint) {
        return count;
    }

    function getOwner() public view returns(address) {
        return owner;
    }

    function increaseCount() public {
       count = count.add(1);
    }

    function decreaseCount() public {
        count = count.sub(1);
    }

    function clearCount() public onlyOwner {
        count = 0;
    }

    modifier onlyOwner() {
        require(owner == msg.sender,"info: caller is not owner");
        _;
    }
}


1.4 创建库合约

    在contracts目录里,创建减加乘除的库合约: LibMath.sol,库合约里必须要有public公开的函数接口,否则无法链接到业务合约。
    //LibMath.sol

// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;

library LibMath {

    function add(uint256 a, uint256 b) public pure returns (uint256) {
        uint256 c = a + b;
        require(c >= a, "SafeMath: addition overflow");
        return c;
    }

    function sub(uint256 a, uint256 b) public pure returns (uint256) {
        return sub(a, b, "SafeMath: subtraction overflow");
    }

    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b <= a, errorMessage);
        uint256 c = a - b;
        return c;
    }

    function mul(uint256 a, uint256 b) public 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) public pure returns (uint256) {
        return div(a, b, "SafeMath: division by zero");
    }

    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        // Solidity only automatically asserts when dividing by 0
        require(b > 0, errorMessage);
        uint256 c = a / b;
        return c;
    }

    function mod(uint256 a, uint256 b) public pure returns (uint256) {
        return mod(a, b, "SafeMath: modulo by zero");
    }

    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b != 0, errorMessage);
        return a % b;
    }
}

1.6 工程目录结构

    LinkLib工程的目录结构如下:

图(2) LinkLib的目录结构

2 编写测试脚本

    在LinkLib/test目录里,创建用于测试CountOne.sol合约的脚本: CountOne_test.js
    //CountOne_test.js

const { expect } = require("chai")
const { ethers } = require("hardhat")
const { utils } = require("ethers");

describe("CountOne Test", function() {
    let contractFactory;
    let contractObj;
    let libFactory;
    let libObj;
    let owner,addr1,addr2,addr3,addrs;

    before(async function() {
        // 1) 部署LibMath库合约
        libFactory = await ethers.getContractFactory("LibMath");
        libObj = await libFactory.deploy();
        console.log("libObj addr",libObj.address);

        [owner,addr1,addr2,addr3,...addrs] = await ethers.getSigners();

        // 2)部署CountOne合约
        // 将CountOne所引用的库合约,全部放到libraries列表里
        contractFactory = await ethers.getContractFactory("CountOne",{
            libraries: {
                LibMath: libObj.address
            }
        });
        contractObj = await contractFactory.deploy();

        
    });

    describe("Deployment", function() {
        it("Check owner", async ()=> {
            expect(owner.address).to.equal(await contractObj.getOwner());
        });

        it("Check increaseCount() func", async ()=> {
            await contractObj.increaseCount();
            let num = await contractObj.getCount()
            expect(num).to.equal(1);            
        })

        it("Check decreaseCount() func", async ()=> {
            await contractObj.decreaseCount();
            let num = await contractObj.getCount()
            expect(num).to.equal(0);            
        })
    });

})

3、进行测试

    在命令行窗口,输入如下命令:

npx hardhat test test\CountOne_test.js

    效果如下:

图(3) 测试库合约的链接
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

sanqima

一键三连,多多益善

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值