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.
Updated Answer
I'll keep the original answer for posterity (not sure why, just kind of feels like the right thing to do), Hardhat (formerly known as Buidler) at this point has an implementation for linking libraries on deploy (code snippet taken from their docs here). Note: This uses the ethers
Hardhat plugin (see link above):
const contractFactory = await this.env.ethers.getContractFactory("Example", {
libraries: {
ExampleLib: "0x...",
},
});
Old Answer
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.