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

Posted sanqima

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了解决“hardhat unresolved libraries or missing links“问题相关的知识,希望对你有一定的参考价值。

    今天在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) 测试库合约的链接

以上是关于解决“hardhat unresolved libraries or missing links“问题的主要内容,如果未能解决你的问题,请参考以下文章

vs2008解决方案资源管理器不显示解决方案

什么是 沙盒解决方案

解决PowerShell乱码问题

如何解决解决方案中现有项目的c#CS0006错误

关于问题解决与事件解决的思考

「解决方案架构」解决方案架构概述