hardhat
Version:
Hardhat is an extensible developer tool that helps smart contract developers increase productivity by reliably bringing together the tools they want.
145 lines (123 loc) • 3.93 kB
text/typescript
// This wrapper was created by extracting the parts of the solc-js package
// (https://github.com/ethereum/solc-js) that we need to perform compilation.
import { HardhatError } from "@nomicfoundation/hardhat-errors";
import * as semver from "semver";
interface Solc {
cwrap<T>(ident: string, returnType: string | null, argTypes: string[]): T;
// eslint-disable-next-line @typescript-eslint/naming-convention -- this is a C function
_solidity_reset?: Reset | null;
// eslint-disable-next-line @typescript-eslint/naming-convention -- this is a C function
_solidity_version?: Version | null;
_version?: Version | null;
_compileStandard?: Compile | null;
// eslint-disable-next-line @typescript-eslint/naming-convention -- this is a C function
_solidity_compile?: Compile | null;
}
type Reset = () => string;
type Version = () => string;
type Compile = (
input: string,
callbackPtr: number | null,
callbackContextPtr?: null,
) => string;
export interface SolcWrapper {
compile: CompileWrapper;
version: Version;
}
export type CompileWrapper = (input: string) => string;
export default function wrapper(solc: Solc): SolcWrapper {
const version = bindVersion(solc);
const semverVersion = versionToSemver(version());
const isVersion6OrNewer = semver.gte(semverVersion, "0.6.0");
const reset = bindReset(solc);
const compile = bindCompile(solc, isVersion6OrNewer);
if (compile === undefined) {
throw new HardhatError(
HardhatError.ERRORS.CORE.SOLIDITY.INVALID_SOLCJS_COMPILER,
{
version: version(),
},
);
}
return {
compile: compileWrapper(isVersion6OrNewer, compile, reset),
version,
};
}
function compileWrapper(
isVersion6OrNewer: boolean,
compile: Compile,
reset?: Reset,
): CompileWrapper {
return (input: string): string => {
const output = isVersion6OrNewer
? compile(input, null, null)
: compile(input, null);
if (reset !== undefined) {
// Explicitly free memory.
//
// NOTE: cwrap() of "compile" will copy the returned pointer into a
// Javascript string and it is not possible to call free() on it.
// reset() however will clear up all allocations.
reset();
}
return output;
};
}
function bindVersion(solc: Solc): Version {
if (solc._solidity_version === null || solc._solidity_version === undefined) {
return solc.cwrap("version", "string", []);
}
return solc.cwrap("solidity_version", "string", []);
}
function bindReset(solc: Solc): Reset | undefined {
if (solc._solidity_reset === null || solc._solidity_reset === undefined) {
return undefined;
}
return solc.cwrap("solidity_reset", null, []);
}
function bindCompile(
solc: Solc,
isVersion6OrNewer: boolean,
): CompileWrapper | undefined {
if (isVersion6OrNewer) {
if (
solc._solidity_compile !== null &&
solc._solidity_compile !== undefined
) {
return solc.cwrap("solidity_compile", "string", [
"string",
"number",
"number",
]);
}
} else {
if (
solc._solidity_compile !== null &&
solc._solidity_compile !== undefined
) {
return solc.cwrap("solidity_compile", "string", ["string", "number"]);
}
if (solc._compileStandard !== null && solc._compileStandard !== undefined) {
return solc.cwrap("compileStandard", "string", ["string", "number"]);
}
}
return undefined;
}
function versionToSemver(version: string): string {
// FIXME: parse more detail, but this is a good start
const parsed = version.match(
/^([0-9]+\.[0-9]+\.[0-9]+)-([0-9a-f]{8})[/*].*$/,
);
if (parsed !== null) {
return parsed[1] + "+commit." + parsed[2];
}
if (version.indexOf("0.1.3-0") !== -1) {
return "0.1.3";
}
if (version.indexOf("0.3.5-0") !== -1) {
return "0.3.5";
}
// assume it is already semver compatible
return version;
}