UNPKG

@truffle/compile-solidity

Version:
139 lines 6.82 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.compileWithPragmaAnalysis = void 0; const compilerSupplier_1 = require("./compilerSupplier"); const config_1 = __importDefault(require("@truffle/config")); const semver_1 = __importDefault(require("semver")); const profiler_1 = require("./profiler"); const run_1 = require("./run"); const reportSources_1 = require("./reportSources"); const os_1 = __importDefault(require("os")); const cloneDeep_1 = __importDefault(require("lodash/cloneDeep")); const getSemverExpression = source => { const result = source.match(/pragma solidity(.*);/); return result && result[1] ? result[1].trim() : undefined; }; const getSemverExpressions = sources => { return sources .map(source => getSemverExpression(source)) .filter(expression => expression); }; const validateSemverExpressions = semverExpressions => { for (const expression of semverExpressions) { if (semver_1.default.validRange(expression) === null) { const message = `Invalid semver expression (${expression}) found in ` + `one of your contract's imports.`; throw new Error(message); } } }; // takes an array of versions and an array of semver expressions // returns a version of the compiler or undefined if none can be found const findNewestSatisfyingVersion = ({ solcReleases, semverExpressions }) => { // releases are ordered from newest to oldest return solcReleases.find(version => { return semverExpressions.every(expression => semver_1.default.satisfies(version, expression)); }); }; const throwCompilerVersionNotFound = ({ path, semverExpressions }) => { const message = `Could not find a single version of the Solidity compiler that ` + `satisfies the following semver expressions obtained from your source ` + `files' pragma statements: ${semverExpressions.join(" - ")}. ` + `${os_1.default.EOL}Please check the pragma statements for ${path} and its imports.`; throw new Error(message); }; const compileWithPragmaAnalysis = ({ paths, options }) => __awaiter(void 0, void 0, void 0, function* () { //don't compile if there's yul const yulPath = paths.find(path => path.endsWith(".yul")); if (yulPath !== undefined) { throw new Error(`Paths to compile includes Yul source ${yulPath}. ` + `Pragma analysis is not supported when compiling Yul.`); } const filteredPaths = paths.filter(path => path.endsWith(".sol") || path.endsWith(".json")); if (filteredPaths.length === 0) { return { compilations: [] }; } // construct supplier options for fetching list of solc versions; // enforce no Docker because listing Docker versions is slow (Docker Hub API // paginates responses, with >500 pages at time of writing) const supplierOptions = { events: options.events, solcConfig: Object.assign(Object.assign({}, options.compilers.solc), { docker: false }) }; const compilerSupplier = new compilerSupplier_1.CompilerSupplier(supplierOptions); const { releases } = yield compilerSupplier.list(); // collect sources by the version of the Solidity compiler that they require const versionsAndSources = {}; for (const path of filteredPaths) { const source = (yield options.resolver.resolve(path)).body; const parserVersion = findNewestSatisfyingVersion({ solcReleases: releases, semverExpressions: [getSemverExpression(source)] }); if (!parserVersion) { const m = `Could not find a valid pragma expression in ${path}. To use the ` + `"pragma" compiler setting your contracts must contain a pragma ` + `expression.`; throw new Error(m); } // allSources is of the format { [filename]: string } const { allSources } = yield profiler_1.Profiler.requiredSourcesForSingleFile(options.with({ path, base_path: options.contracts_directory, resolver: options.resolver, compiler: { name: "solc", version: parserVersion }, compilers: { solc: { version: parserVersion } } })); // get an array of all the semver expressions in the sources const semverExpressions = yield getSemverExpressions(Object.values(allSources)); // this really just validates the expressions from the contracts' imports // as it has already determined the parser version for each contract validateSemverExpressions(semverExpressions); const newestSatisfyingVersion = findNewestSatisfyingVersion({ solcReleases: releases, semverExpressions }); if (!newestSatisfyingVersion) { throwCompilerVersionNotFound({ path, semverExpressions }); } versionsAndSources[newestSatisfyingVersion] = Object.assign(Object.assign({}, versionsAndSources[newestSatisfyingVersion]), allSources); } (0, reportSources_1.reportSources)({ paths: filteredPaths, options }); const compilations = []; for (const compilerVersion in versionsAndSources) { const compilationOptions = { compilers: (0, cloneDeep_1.default)(options.compilers) }; compilationOptions.compilers.solc.version = compilerVersion; const config = config_1.default.default().with(compilationOptions); const compilation = yield (0, run_1.run)(versionsAndSources[compilerVersion], config); if (compilation && Object.keys(compilation.contracts).length > 0) { compilations.push(compilation); } } return { compilations }; }); exports.compileWithPragmaAnalysis = compileWithPragmaAnalysis; //# sourceMappingURL=compileWithPragmaAnalysis.js.map