UNPKG

@nomicfoundation/hardhat-verify

Version:
116 lines (99 loc) 3.96 kB
import type { ArtifactManager, BuildInfo } from "hardhat/types/artifacts"; import type { CompilerInput, SolidityBuildInfoOutput, SolidityBuildSystem, } from "hardhat/types/solidity"; import path from "node:path"; import { assertHardhatInvariant } from "@nomicfoundation/hardhat-errors"; import { readJsonFile } from "@nomicfoundation/hardhat-utils/fs"; export interface BuildInfoAndOutput { buildInfo: BuildInfo; buildInfoOutput: SolidityBuildInfoOutput; } // TODO: reading build info from disk on each call is inefficient. // We should consider caching the results in memory. // TODO2: getBuildInfoId and readJsonFile can throw errors, we should // wrap them in a try-catch block and return undefined if an error occurs // while also logging the error. // TODO3: the information contained in the output can be read from the // artifact: // artifact field | output field // abi | contracts.[sourceName][contractName].abi // linkReferences | contracts.[sourceName][contractName].evm.bytecode.linkReferences // deployedLinkReferences | contracts.[sourceName][contractName].evm.deployedBytecode.linkReferences // deployedBytecode | contracts.[sourceName][contractName].evm.deployedBytecode.object // immutableReferences | contracts.[sourceName][contractName].evm.deployedBytecode.immutableReferences // TODO4: consider returning only the fields needed from the build info: solcVersion, solcLongVersion, input /** * Retrieves the saved build information and output for a given contract. * * @param artifacts The artifact manager instance to use for retrieving build info. * @param contract The fully qualified contract name (e.g., "contracts/Token.sol:Token"). * @returns The `BuildInfo` object if it exists on disk, or `undefined` if no * build info is found. */ export async function getBuildInfoAndOutput( artifacts: ArtifactManager, contract: string, ): Promise<BuildInfoAndOutput | undefined> { const buildInfoId = await artifacts.getBuildInfoId(contract); if (buildInfoId === undefined) { // TODO: maybe we should throw an error here indicating that the // contract wasn't compiled with Hardhat 3's build system return undefined; } const buildInfoPath = await artifacts.getBuildInfoPath(buildInfoId); if (buildInfoPath === undefined) { return undefined; } const buildInfoOutputPath = await artifacts.getBuildInfoOutputPath(buildInfoId); if (buildInfoOutputPath === undefined) { return undefined; } const buildInfo: BuildInfo = await readJsonFile(buildInfoPath); const buildInfoOutput: SolidityBuildInfoOutput = await readJsonFile(buildInfoOutputPath); return { buildInfo, buildInfoOutput, }; } // TODO: consider moving this to the solidity build system as a helper function export async function getCompilerInput( solidity: SolidityBuildSystem, root: string, sourceName: string, isNpmModule: boolean, buildProfileName: string, ): Promise<CompilerInput> { const rootFilePath = isNpmModule ? `npm:${sourceName}` : path.join(root, sourceName); const getCompilationJobsResult = await solidity.getCompilationJobs( [rootFilePath], { buildProfile: buildProfileName, quiet: true, force: true, }, ); assertHardhatInvariant( getCompilationJobsResult.success, "getCompilationJobs should not error", ); const compilationJob = getCompilationJobsResult.compilationJobsPerFile; // TODO: should this be an error instead? assertHardhatInvariant( compilationJob instanceof Map && compilationJob.size === 1, "The compilation job for the contract source was not found.", ); const compilerInput = await compilationJob.get(rootFilePath)?.getSolcInput(); // TODO: should this be an error instead? assertHardhatInvariant( compilerInput !== undefined, "The compiler input for the contract source was not found.", ); return compilerInput; }