Skip to content

Commit

Permalink
fix: fqn resolution of artifacts
Browse files Browse the repository at this point in the history
In the artifact resolver detect whether a FQN is being used to refer to the
contract and use Hardhat's own build info resolution method as we can rely on
the fqn.

This is now covered with an additional integration test for repos with multiple
contracts with the same name in different files and an Ignition module where
those contracts are referred to by FQNs.

Fixes #778.
  • Loading branch information
kanej committed Oct 11, 2024
1 parent 774c465 commit 09f5434
Show file tree
Hide file tree
Showing 5 changed files with 87 additions and 0 deletions.
21 changes: 21 additions & 0 deletions packages/hardhat-plugin/src/hardhat-artifact-resolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,17 @@ export class HardhatArtifactResolver implements ArtifactResolver {
public async getBuildInfo(
contractName: string
): Promise<BuildInfo | undefined> {
// If a fully qualified name is used, we can can
// leverage the artifact manager directly to load the build
// info.
if (this._isFullyQualifiedName(contractName)) {
return this._hre.artifacts.getBuildInfo(contractName);
}

// Otherwise we have only the contract name, and need to
// resolve the artifact for the contract ourselves.
// We can build on the assumption that the contract name
// is unique based on Module validation.
const artifactPath = await this._resolvePath(contractName);

if (artifactPath === undefined) {
Expand Down Expand Up @@ -51,4 +62,14 @@ export class HardhatArtifactResolver implements ArtifactResolver {
public loadArtifact(contractName: string): Promise<Artifact> {
return this._hre.artifacts.readArtifact(contractName);
}

/**
* Returns true if a name is fully qualified, and not just a bare contract name.
*
* This is based on Hardhat's own test for fully qualified names, taken
* from `contract-names.ts` in `hardhat-core` utils.
*/
private _isFullyQualifiedName(contractName: string): boolean {
return contractName.includes(":");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;

// This contract name is the same as in `./Rocket2.sol`
contract Rocket {
string public name;

constructor(string memory _name) {
name = _name;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;

// This contract name is the same as in `./Rocket1.sol`
contract Rocket {
string public name;

constructor(string memory _name) {
name = _name;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
require("../../../src/index");

module.exports = {
solidity: "0.8.19",
};
39 changes: 39 additions & 0 deletions packages/hardhat-plugin/test/module-api/fully-qualified-names.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { buildModule } from "@nomicfoundation/ignition-core";
import { assert } from "chai";

import { useFileIgnitionProject } from "../test-helpers/use-ignition-project";

describe("fully qualified names", () => {
describe("where there are multiple contracts with the same name in the project", () => {
useFileIgnitionProject(
"multiple-contracts-with-same-name",
"contract-deploy"
);

it("should deploy contracts by referring using fully qualified names", async function () {
const LaunchModule = buildModule("Apollo", (m) => {
const rocket1 = m.contract(
"contracts/Rocket1.sol:Rocket",
["Rocket 1"],
{
id: "Rocket1",
}
);
const rocket2 = m.contract(
"contracts/Rocket2.sol:Rocket",
["Rocket 2"],
{
id: "Rocket2",
}
);

return { rocket1, rocket2 };
});

const result = await this.hre.ignition.deploy(LaunchModule);

assert.equal(await result.rocket1.read.name(), "Rocket 1");
assert.equal(await result.rocket2.read.name(), "Rocket 2");
});
});
});

0 comments on commit 09f5434

Please sign in to comment.