Skip to content

Optimize ArtifactsManager#artifactExists#8122

Merged
alcuadrado merged 5 commits intomainfrom
optimize-read-artifacts
Apr 13, 2026
Merged

Optimize ArtifactsManager#artifactExists#8122
alcuadrado merged 5 commits intomainfrom
optimize-read-artifacts

Conversation

@alcuadrado
Copy link
Copy Markdown
Member

@alcuadrado alcuadrado commented Apr 10, 2026

ArtifactsManager#artifactExists use to try to read the artifact, and return false when the read threw. That was slow, because the error that readArtifact generates includes all the similar contract names, which is a heavy operation. This implementation checks for the existence directly, making it much faster.

@alcuadrado alcuadrado requested review from Copilot and schaable April 10, 2026 19:13
@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented Apr 10, 2026

🦋 Changeset detected

Latest commit: b432591

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
hardhat Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@alcuadrado alcuadrado added no changeset needed This PR doesn't require a changeset no docs needed This PR doesn't require links to documentation no peer bump needed labels Apr 10, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR optimizes ArtifactManagerImplementation#artifactExists by avoiding exception-based control flow and instead checking cached filesystem metadata (FsData) to determine whether an artifact is present.

Changes:

  • Reworked artifactExists to use cached sets/maps from #getFsData() rather than calling getArtifactPath() and catching errors.
  • Updated the ArtifactManager type documentation to remove the (now-incorrect) @throws note for non-unique names.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
packages/hardhat/src/types/artifacts.ts Aligns artifactExists docs with the intended behavior (no throw on non-unique names).
packages/hardhat/src/internal/builtin-plugins/artifacts/artifact-manager.ts Implements the optimized artifactExists using cached filesystem-derived indices.

Comment on lines 81 to 94
public async artifactExists(
contractNameOrFullyQualifiedName: string,
): Promise<boolean> {
try {
// This throw if the artifact doesn't exist
await this.getArtifactPath(contractNameOrFullyQualifiedName);

return true;
} catch (error) {
if (HardhatError.isHardhatError(error)) {
if (
error.number === HardhatError.ERRORS.CORE.ARTIFACTS.NOT_FOUND.number
) {
return false;
}
}
const { bareNameToFullyQualifiedNameMap, allFullyQualifiedNames } =
await this.#getFsData();

throw error;
if (this.#isFullyQualifiedName(contractNameOrFullyQualifiedName)) {
return allFullyQualifiedNames.has(contractNameOrFullyQualifiedName);
}

return bareNameToFullyQualifiedNameMap.has(
contractNameOrFullyQualifiedName,
);
}
Copy link

Copilot AI Apr 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

artifactExists behavior changed to return a boolean based on cached fs data (and no longer relies on getArtifactPath throwing). There are existing tests for ArtifactManagerImplementation in packages/hardhat/test/internal/builtin-plugins/artifacts/artifact-manager.ts, but none cover artifactExists—especially the non-unique bare-name case that this change is meant to handle. Add tests that assert: (1) returns true for an existing bare name, (2) returns true for an existing fully-qualified name, (3) returns false for a missing name, and (4) returns true (and does not throw) when multiple artifacts share the same bare name.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good point, done

@alcuadrado alcuadrado removed the no changeset needed This PR doesn't require a changeset label Apr 10, 2026
@alcuadrado alcuadrado requested review from ChristopherDedominici and removed request for schaable April 13, 2026 10:01
*
* @param contractNameOrFullyQualifiedName Contract or fully qualified name.
* @throws Throws an error if a non-unique contract name is used,
* indicating which fully qualified names can be used instead.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given that this function’s semantics have changed, it would be good to call it out here. When there are multiple contracts with the same name, artifactExists("Foo") returning true no longer guarantees that readArtifact("Foo") will succeed:

if (await hre.artifacts.artifactExists("Foo")) {
  const a = await hre.artifacts.readArtifact("Foo"); // MULTIPLE_FOUND error
}

This could be confusing for users who expect readArtifact not to throw if artifactExists returned true.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll add a comment. That's a good point.

Note that I don't think the intentional semantics changed. I did a bit of and this method didn't used to have the @throws. I made a mistake in this commit by adding every @throws possible, despite contradicting the description.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in b1e4fcb

Copy link
Copy Markdown
Member

@schaable schaable left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, left a comment regarding documentation but I'm pre-approving it.

Copilot AI review requested due to automatic review settings April 13, 2026 10:24
@alcuadrado alcuadrado enabled auto-merge April 13, 2026 10:24
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 9 out of 9 changed files in this pull request and generated 1 comment.

Comment thread packages/hardhat/src/types/artifacts.ts Outdated
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 9 out of 9 changed files in this pull request and generated no new comments.

@alcuadrado alcuadrado added this pull request to the merge queue Apr 13, 2026
Merged via the queue into main with commit 860decf Apr 13, 2026
226 checks passed
@alcuadrado alcuadrado deleted the optimize-read-artifacts branch April 13, 2026 10:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

no docs needed This PR doesn't require links to documentation no peer bump needed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants