Update pragma check: validate by actually running the compiler (#5730)
Co-authored-by: Arr00 <13561405+arr00@users.noreply.github.com>
This commit is contained in:
@ -1,49 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
const path = require('path');
|
||||
const semver = require('semver');
|
||||
const match = require('micromatch');
|
||||
const { findAll } = require('solidity-ast/utils');
|
||||
const { _: artifacts } = require('yargs').argv;
|
||||
|
||||
// files to skip
|
||||
const skipPatterns = ['contracts-exposed/**', 'contracts/mocks/WithInit.sol'];
|
||||
|
||||
for (const artifact of artifacts) {
|
||||
const { output: solcOutput } = require(path.resolve(__dirname, '../..', artifact));
|
||||
|
||||
const pragma = {};
|
||||
|
||||
// Extract pragma directive for all files
|
||||
for (const source in solcOutput.contracts) {
|
||||
if (match.any(source, skipPatterns)) continue;
|
||||
for (const { literals } of findAll('PragmaDirective', solcOutput.sources[source].ast)) {
|
||||
// There should only be one.
|
||||
const [first, ...rest] = literals;
|
||||
if (first === 'solidity') pragma[source] = rest.join('');
|
||||
}
|
||||
}
|
||||
|
||||
// Compare the pragma directive of the file, to that of the files it imports
|
||||
for (const source in solcOutput.contracts) {
|
||||
if (match.any(source, skipPatterns)) continue;
|
||||
// minimum version of the compiler that matches source's pragma
|
||||
const minVersion = semver.minVersion(pragma[source]);
|
||||
// loop over all imports in source
|
||||
for (const { absolutePath } of findAll('ImportDirective', solcOutput.sources[source].ast)) {
|
||||
// So files that only import without declaring anything cause issues, because they don't shop in "pragma"
|
||||
if (!pragma[absolutePath]) continue;
|
||||
// Check that the minVersion for source satisfies the requirements of the imported files
|
||||
if (!semver.satisfies(minVersion, pragma[absolutePath])) {
|
||||
console.log(
|
||||
`- ${source} uses ${pragma[source]} but depends on ${absolutePath} that requires ${pragma[absolutePath]}`,
|
||||
);
|
||||
process.exitCode = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!process.exitCode) {
|
||||
console.log('Pragma directives are consistent.');
|
||||
}
|
||||
45
scripts/checks/pragma-validity.js
Executable file
45
scripts/checks/pragma-validity.js
Executable file
@ -0,0 +1,45 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
const semver = require('semver');
|
||||
const pLimit = require('p-limit').default;
|
||||
|
||||
const { hideBin } = require('yargs/helpers');
|
||||
const yargs = require('yargs/yargs');
|
||||
|
||||
const getContractsMetadata = require('../get-contracts-metadata');
|
||||
const { compile } = require('../solc-versions');
|
||||
|
||||
const {
|
||||
argv: { pattern, skipPatterns, verbose, concurrency, _: artifacts },
|
||||
} = yargs(hideBin(process.argv))
|
||||
.env('')
|
||||
.options({
|
||||
pattern: { alias: 'p', type: 'string', default: 'contracts/**/*.sol' },
|
||||
skipPatterns: { alias: 's', type: 'string', default: 'contracts/mocks/**/*.sol' },
|
||||
concurrency: { alias: 'c', type: 'number', default: 8 },
|
||||
verbose: { alias: 'v', type: 'count' },
|
||||
});
|
||||
|
||||
const limit = pLimit(concurrency);
|
||||
Promise.all(
|
||||
Object.entries(getContractsMetadata(pattern, skipPatterns, artifacts)).map(([source, { pragma }]) =>
|
||||
limit(
|
||||
(file, version) =>
|
||||
compile(file, version).then(
|
||||
() => {
|
||||
verbose && console.log(`Compile ${file} using solc ${version}: ok`);
|
||||
},
|
||||
error => {
|
||||
console.error(`Failed to compile ${file} using solc ${version}\n${error}`);
|
||||
process.exitCode = 1;
|
||||
},
|
||||
),
|
||||
source,
|
||||
semver.minVersion(pragma),
|
||||
),
|
||||
),
|
||||
).finally(() => {
|
||||
if (!process.exitCode) {
|
||||
console.log('All files can be compiled with the specified pragma.');
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user