3

Suppose I have a contract named MetaCoin.sol

// SPDX-License-Identifier: MIT
// Tells the Solidity compiler to compile only from v0.8.13 to v0.9.0
pragma solidity ^0.8.13;

import "./ConvertLib.sol";

// This is just a simple example of a coin-like contract.
// It is not ERC20 compatible and cannot be expected to talk to other
// coin/token contracts.

contract MetaCoin {


    mapping (address => uint) balances;

    event Transfer(address indexed _from, address indexed _to, uint256 _value);

    constructor() {
        balances[tx.origin] = 10000;
    }

    function sendCoin(address receiver, uint amount) public returns(bool sufficient) {
        if (balances[msg.sender] < amount) return false;
        balances[msg.sender] -= amount;
        balances[receiver] += amount;
        emit Transfer(msg.sender, receiver, amount);
        return true;
    }

    function getBalanceInEth(address addr) public view returns(uint){
        return ConvertLib.convert(getBalance(addr),2);
    }

    function getBalance(address addr) public view returns(uint) {
        return balances[addr];
    }
}

which uses convert function from library ConverLib.sol

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

library ConvertLib{
    function convert(uint amount, uint conversionRate) public pure returns (uint convertedAmount)
    {
        return amount * conversionRate;
    }
}

Here is my question: Suppose I have to link the library with the smart contract while deploying the contract using hardhat; how can I do this using hardhat?

Truffle uses link function to link library to contract

const ConvertLib = artifacts.require("ConvertLib");
const MetaCoin = artifacts.require("MetaCoin");

module.exports = function(deployer) {
  deployer.deploy(ConvertLib);
  deployer.link(ConvertLib, MetaCoin);
  deployer.deploy(MetaCoin);
};

2 Answers 2

2

You have to deploy the Solidity Library that has either a public or an external function to use it from a smart contract. This library would then sit on a separate address and your smart contract make calls to this address.

In Hardhat, you can pass the addresses of the library to the getContractFactory function with an object like this:

const MetaCoin = await this.env.ethers.getContractFactory("MetaCoin", {
  libraries: {
    ConvertLib: "0x...",
  },
});
const metaCoin = await MetaCoin.deploy();

Link to the official documentation of library linking.

There is a better solution, as long as you can edit the library and change the function's visibility from public to internal.

i.e.: function convert(uint amount, uint conversionRate) internal ....

Libraries that have internal functions only, don't have to be deployed separately since the compiler directly includes the functions in the bytecode of the smart contract.

You can use the internal function from the library the same way in solidity.

import "path/to/ConvertLib.sol";

....

ConvertLib.convert(getBalance(addr),2);

2

I found a solution; you have to first deploy the library and then pass the address of deployed library to the contract factory of contract.

async function main() {


  const signers = await ethers.getSigners();

  // Library deployment
  const lib = await hre.ethers.getContractFactory("ConvertLib", { signer: signers[0] });
  const libInstance = await lib.deploy();
  await libInstance.deployed();
  console.log("Library Address--->" + libInstance.address)

  // Contract deployment
  const MetaCoin= await hre.ethers.getContractFactory("MetaCoin", { signer: signers[0], libraries: { DoMath: libInstance.address } });
  const metaCoin= await MetaCoin.deploy();

  await metaCoin.deployed();

  console.log(
    `Lock with 1 ETH and unlock timestamp ${unlockTime} deployed to ${metaCoin.address}`
  );
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.