Files
openzeppelin-contracts/scripts/get-contracts-metadata.js

56 lines
2.3 KiB
JavaScript

const fs = require('fs');
const glob = require('glob');
const match = require('micromatch');
const path = require('path');
const { findAll } = require('solidity-ast/utils');
module.exports = function (
pattern = 'contracts/**/*.sol',
skipPatterns = ['contracts/mocks/**/*.sol'],
artifacts = [],
) {
// Use available hardhat artifacts. They reliably identify pragmas and the contracts, libraries and interfaces
// definitions with minimal IO operations.
const metadata = Object.fromEntries(
artifacts.flatMap(artifact => {
const { output: solcOutput } = require(path.resolve(__dirname, '..', artifact));
return Object.keys(solcOutput.contracts)
.filter(source => match.all(source, pattern) && !match.any(source, skipPatterns))
.map(source => [
source,
{
pragma: Array.from(findAll('PragmaDirective', solcOutput.sources[source].ast))
.find(({ literals }) => literals.at(0) == 'solidity')
.literals.slice(1)
.join(''),
sources: Array.from(findAll('ImportDirective', solcOutput.sources[source].ast)).map(
({ absolutePath }) => absolutePath,
),
interface: Array.from(findAll('ContractDefinition', solcOutput.sources[source].ast)).every(
({ contractKind }) => contractKind === 'interface',
),
},
]);
}),
);
// Artifacts are missing files that only include imports. We have a few of these in contracts/interfaces
// We add the missing metadata entries using the foundry artifacts
glob
.sync(pattern)
.filter(file => !match.any(file, skipPatterns) && !Object.hasOwn(metadata, file))
.forEach(file => {
const entries = glob.sync(`out/${path.basename(file)}/*`);
metadata[file] = {
pragma: fs.readFileSync(file, 'utf-8').match(/pragma solidity (?<pragma>[<>=^]*[0-9]+\.[0-9]+\.[0-9]+);/)
?.groups.pragma,
sources: entries
.flatMap(entry => Object.keys(JSON.parse(fs.readFileSync(entry)).metadata.sources))
.filter(source => source !== file && match.all(source, pattern) && !match.any(source, skipPatterns)),
interface: entries.every(entry => path.basename(entry).match(/^I[A-Z]/)),
};
});
return metadata;
};