Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,9 @@ export async function getBuildInfo(
solcVersion: compilationJob.solcConfig.version,
solcLongVersion: compilationJob.solcLongVersion,
compilerType,
...(compilationJob.toolVersions !== undefined
? { versions: compilationJob.toolVersions }
: {}),
userSourceNameMap:
compilationJob.dependencyGraph.getRootsUserSourceNameMap(),
input: await compilationJob.getSolcInput(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import type {
CacheHitInfo,
} from "../../../../types/solidity/build-system.js";
import type {
ToolVersions,
CompilationJob,
Compiler,
CompilerOutput,
Expand Down Expand Up @@ -57,6 +58,7 @@ import debug from "debug";
import pMap from "p-map";

import { FileBuildResultType } from "../../../../types/solidity/build-system.js";
import { getHardhatVersion } from "../../../utils/package.js";
import { DEFAULT_BUILD_PROFILE } from "../build-profiles.js";
import { getSolcCompilerForConfig } from "../solidity-hooks.js";

Expand Down Expand Up @@ -436,6 +438,11 @@ export class SolidityBuildSystemImplementation implements SolidityBuildSystem {

log(`Using build profile ${buildProfileName}`);

let toolVersions: ToolVersions | undefined;
if (buildProfile.toolVersionsInBuildInfo === true) {
toolVersions = { hardhat: await getHardhatVersion() };
}

const solcConfigSelector = new SolcConfigSelector(
buildProfileName,
buildProfile,
Expand Down Expand Up @@ -533,6 +540,7 @@ export class SolidityBuildSystemImplementation implements SolidityBuildSystem {
longVersion,
this.#hooks,
sharedContentHashes,
toolVersions,
);

await individualJob.getBuildId(); // precompute
Expand Down Expand Up @@ -687,6 +695,7 @@ export class SolidityBuildSystemImplementation implements SolidityBuildSystem {
longVersion,
this.#hooks,
sharedContentHashes,
toolVersions,
);

for (const [userSourceName, root] of subgraph.getRoots().entries()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import type { HookManager } from "../../../../types/hooks.js";
import type { CompilationJob } from "../../../../types/solidity/compilation-job.js";
import type { CompilerInput } from "../../../../types/solidity/compiler-io.js";
import type { DependencyGraph } from "../../../../types/solidity/dependency-graph.js";
import type { ToolVersions } from "../../../../types/solidity/solidity-artifacts.js";

import { createHash } from "node:crypto";

Expand All @@ -24,6 +25,7 @@ export class CompilationJobImplementation implements CompilationJob {
public readonly dependencyGraph: DependencyGraph;
public readonly solcConfig: SolidityCompilerConfig;
public readonly solcLongVersion: string;
public readonly toolVersions?: ToolVersions;

readonly #hooks: HookManager;
// This map is shared across compilation jobs and is meant to store content hashes of source files
Expand All @@ -39,12 +41,14 @@ export class CompilationJobImplementation implements CompilationJob {
solcLongVersion: string,
hooks: HookManager,
sharedContentHashes: Map<string, string> = new Map(),
toolVersions?: ToolVersions,
) {
this.dependencyGraph = dependencyGraph;
this.solcConfig = solcConfig;
this.solcLongVersion = solcLongVersion;
this.#hooks = hooks;
this.#sharedContentHashes = sharedContentHashes;
this.toolVersions = toolVersions;
}

public async getSolcInput(): Promise<CompilerInput> {
Expand Down Expand Up @@ -253,6 +257,12 @@ export class CompilationJobImplementation implements CompilationJob {
preimageObject.compilerType = compilerType;
}

// Include tool versions in the preimage when present, so that
// different tool versions produce different build IDs.
if (this.toolVersions !== undefined) {
preimageObject.versions = this.toolVersions;
}

const preimage = JSON.stringify(preimageObject);

const jobHash = await createNonCryptographicHashId(preimage);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -164,13 +164,15 @@ const singleVersionBuildProfileUserConfigType = conditionalUnionType(
(!("type" in data) || data.type === undefined || data.type === "solc"),
solcSolidityCompilerUserConfigType.extend({
isolated: z.boolean().optional(),
toolVersionsInBuildInfo: z.boolean().optional(),
...incompatibleVersionFields,
}),
],
[
(data) => isObject(data) && "type" in data && data.type !== "solc",
otherSolidityCompilerUserConfigType.extend({
isolated: z.boolean().optional(),
toolVersionsInBuildInfo: z.boolean().optional(),
...incompatibleVersionFields,
}),
],
Expand All @@ -183,6 +185,7 @@ const multiVersionBuildProfileUserConfigType = z.object({
compilers: z.array(solidityCompilerUserConfigType).nonempty(),
overrides: z.record(z.string(), solidityCompilerUserConfigType).optional(),
isolated: z.boolean().optional(),
toolVersionsInBuildInfo: z.boolean().optional(),
...incompatibleCompilerFields,
});

Expand Down Expand Up @@ -458,6 +461,7 @@ function resolveSolidityConfig(
profiles[profileName] = resolveBuildProfileConfig(
profile,
profileName === "production",
profile.toolVersionsInBuildInfo,
);
}

Expand All @@ -484,13 +488,15 @@ function resolveBuildProfileConfig(
| SingleVersionSolidityUserConfig
| MultiVersionSolidityUserConfig,
production: boolean = false,
toolVersionsInBuildInfo?: boolean,
): SolidityBuildProfileConfig {
if ("version" in solidityConfig) {
return {
compilers: [resolveSolidityCompilerConfig(solidityConfig, production)],
overrides: {},
isolated: solidityConfig.isolated ?? production,
preferWasm: solidityConfig.preferWasm ?? false,
toolVersionsInBuildInfo: toolVersionsInBuildInfo ?? production,
};
Comment on lines 494 to 508

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 decided to add it to SingleVersionSolidityUserConfig and MultiVersionSolidityUserConfig.

}

Expand All @@ -508,6 +514,7 @@ function resolveBuildProfileConfig(
),
isolated: solidityConfig.isolated ?? production,
preferWasm: solidityConfig.preferWasm ?? false,
toolVersionsInBuildInfo: toolVersionsInBuildInfo ?? production,
};
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -173,15 +173,17 @@ declare module "../../../types/config.js" {
export type SingleVersionBuildProfileUserConfig =
SolidityCompilerUserConfig & {
isolated?: boolean;
toolVersionsInBuildInfo?: boolean;

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.

Note: We only add this setting to the profiles, and not to every top-level config, as that seems unneeded.

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.

this was a bad idea, I'm changing it to make it consistent with the other fields.

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.

done

};

/**
* The type of a multi-version build profile user config.
* Mostly defined in `MultiVersionSolcUserConfig` for backwards compatibility
*/
/* eslint-disable-next-line @typescript-eslint/no-empty-interface -- Defined
in `MultiVersionSolcUserConfig` for backwards compatibility. */
export interface MultiVersionBuildProfileUserConfig
extends MultiVersionSolcUserConfig {}
extends MultiVersionSolcUserConfig {
toolVersionsInBuildInfo?: boolean;
}

/**
* The type of the build profile version of the SolidityUserConfig.
Expand Down Expand Up @@ -259,6 +261,7 @@ declare module "../../../types/config.js" {
export interface SolidityBuildProfileConfig {
isolated: boolean;
preferWasm: boolean;
toolVersionsInBuildInfo?: boolean;

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.

Intentionally optional for backwards compatibility, I'll add a comment

compilers: SolidityCompilerConfig[];
overrides: Record<string, SolidityCompilerConfig>;
}
Expand Down
7 changes: 7 additions & 0 deletions packages/hardhat/src/types/solidity/compilation-job.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type { CompilerInput } from "./compiler-io.js";
import type { DependencyGraph } from "./dependency-graph.js";
import type { ToolVersions } from "./solidity-artifacts.js";
import type { SolidityCompilerConfig } from "../config.js";

/**
Expand All @@ -22,6 +23,12 @@ export interface CompilationJob {
*/
solcLongVersion: string;

/**
* The versions to include in the build info, if any.
* When present, these versions influence the build id.
*/
toolVersions?: ToolVersions;

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.

Added this to the CompilationJob because it influences the build info and the build id.


/**
* Returns the solc input to be used.
*/
Expand Down
16 changes: 16 additions & 0 deletions packages/hardhat/src/types/solidity/solidity-artifacts.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
import type { CompilerInput, CompilerOutput } from "./compiler-io.js";

/**
* A record with the versions of the different tools used to create a
* build info.
*/
export interface ToolVersions {
readonly hardhat: string;
}

/**
* A SolidityBuildInfo is a file that contains all the information of a solc
* run. It includes all the necessary information to recreate that exact same
Expand Down Expand Up @@ -43,6 +51,14 @@ export interface SolidityBuildInfo {
*/
readonly compilerType?: string;

/**
* Versions of the different tools used to create this build info.
*
* Not present if the build profile used to create this build info
* had `toolVersionsInBuildInfo` as `false`.
*/
readonly versions?: ToolVersions;

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.

Have you considered using toolVersions to match the type and other variables, and to make it more explicit?

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 guess it's a good point


/**
* A mapping from user source names to input source names, for the root
* files of the build (i.e. the files whose artifacts where being compiled).
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,41 @@ describe("CompilationJobImplementation", () => {
);
assert.notEqual(await jobA.getBuildId(), await jobB.getBuildId());
});

it("toolVersions is added", async () => {
const newCompilationJob = new CompilationJobImplementation(
dependencyGraph,
solcConfig,
solcLongVersion,
hooks,
new Map(),
{ hardhat: "3.0.0" },
);
assert.notEqual(
await compilationJob.getBuildId(),
await newCompilationJob.getBuildId(),
);
});

it("the hardhat version in toolVersions changes", async () => {
const jobA = new CompilationJobImplementation(
dependencyGraph,
solcConfig,
solcLongVersion,
hooks,
new Map(),
{ hardhat: "3.0.0" },
);
const jobB = new CompilationJobImplementation(
dependencyGraph,
solcConfig,
solcLongVersion,
hooks,
new Map(),
{ hardhat: "3.1.0" },
);
assert.notEqual(await jobA.getBuildId(), await jobB.getBuildId());
});
});

describe("should not change when", () => {
Expand Down Expand Up @@ -441,6 +476,24 @@ describe("CompilationJobImplementation", () => {
);
});

it("toolVersions is undefined (not passed vs explicitly undefined)", async () => {
const jobA = new CompilationJobImplementation(
dependencyGraph,
solcConfig,
solcLongVersion,
hooks,
);
const jobB = new CompilationJobImplementation(
dependencyGraph,
solcConfig,
solcLongVersion,
hooks,
new Map(),
undefined,
);
assert.equal(await jobA.getBuildId(), await jobB.getBuildId());
});

it("the compiler type is undefined vs 'solc'", async () => {
const jobUndefined = new CompilationJobImplementation(
dependencyGraph,
Expand Down
Loading
Loading