0

I'm attempting to deploy a contract using Buidler (via scaffold-eth), but am getting the following error:

Error: Factory contains unresolved libraries. You must deploy and link the following libraries before you can deploy a new version of Factory: $c63268ab2b467de325495e38718facdea1$

The contract in question (Factory.sol) imports three contracts, and one of them is called library (Library_Token.sol). I receive this error even if I deploy it first, though.

What is causing this error, and how can it be fixed?

Update: I see Truffle has a function for linking libraries: https://www.trufflesuite.com/docs/truffle/getting-started/running-migrations#deployer-link-library-destinations-

I assume that Buidler should have something similar, and that's what needs to happen here. As such, I'm guessing the question should be rephrased as 'how do I link a library to a contract using Buidler', but I guess I won't know until that's figured out and we see if it works.

0

First things first, let's dive into the issue a bit more.

A linked library isn't just another contract deployed in the same ecosystem, it needs to be actively linked to the contract that uses it, as the link above (to the Truffle code for doing so) demonstrates.

Buidler does not currently (mid-July 2020) have a native shortcut for doing this. An issue has been opened on GitHub, which also has the following workaround in it, also copied and pasted below.

The workaround is preceded by the devs saying that there should be a more direct and simple way to link contracts soon, so it may be worth verifying if they've implemented something for this before using the code below.

const { ethers, config } = require("@nomiclabs/buidler");
const { readArtifact } = require("@nomiclabs/buidler/plugins");

async function main() {
  const Library = await ethers.getContractFactory("Library");
  const library = await Library.deploy();
  await library.deployed();

  const cArtifact = await readArtifact(config.paths.artifacts, "Contract");
  const linkedBytecode = linkBytecode(cArtifact, { Library: library.address });
  const Contract = await ethers.getContractFactory(
    cArtifact.abi,
    linkedBytecode
  );

  const contract = await Contract.deploy();
  await contract.deployed();

  console.log("Contract address:", contract.address);
}

function linkBytecode(artifact, libraries) {
  let bytecode = artifact.bytecode;

  for (const [fileName, fileReferences] of Object.entries(
    artifact.linkReferences
  )) {
    for (const [libName, fixups] of Object.entries(fileReferences)) {
      const addr = libraries[libName];
      if (addr === undefined) {
        continue;
      }

      for (const fixup of fixups) {
        bytecode =
          bytecode.substr(0, 2 + fixup.start * 2) +
          addr.substr(2) +
          bytecode.substr(2 + (fixup.start + fixup.length) * 2);
      }
    }
  }

  return bytecode;
}

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

If my understanding of the code is correct, you would most likely use this inside /scripts/deploy.js, which should contain the script for deploying the contracts in your project.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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