@skybit/hardhat-yul
Version:
Compile Yul smart contracts in Hardhat
173 lines • 8.89 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.compileYulp = exports.compileYul = void 0;
const source_names_1 = require("hardhat/utils/source-names");
const path_1 = __importDefault(require("path"));
const solc_1 = __importDefault(require("solc"));
const yulp_1 = __importDefault(require("yulp"));
const fs = __importStar(require("fs"));
const util_1 = __importDefault(require("util"));
async function compileYul(config, artifacts) {
const files = await getYulSources(config.paths);
const allArtifacts = [];
for (const file of files) {
const cwdPath = path_1.default.relative(process.cwd(), file);
const hardhatConfigSolcVersion = config.solidity.compilers[0].version;
if (!solc_1.default.version().includes(hardhatConfigSolcVersion)) {
console.log(`Your hardhat config specifies solc version ${hardhatConfigSolcVersion} but it was not found as a package in your repository. It's required to compile yul files. Install it by running yarn add solc@${hardhatConfigSolcVersion}.`);
return;
}
console.log(`Compiling ${cwdPath} using solc version ${solc_1.default.version()}...`); // e.g. 0.8.24+commit.e11b9ed9.Emscripten.clang
const yulOutput = await _compileYul(cwdPath, file, config.solidity.compilers[0]);
const sourceName = await (0, source_names_1.localPathToSourceName)(config.paths.root, file);
const artifact = getArtifactFromYulOutput(sourceName, yulOutput);
await artifacts.saveArtifactAndDebugFile(artifact);
allArtifacts.push({ ...artifact, artifacts: [artifact.contractName] });
const artifactsImpl = artifacts;
artifactsImpl.addValidArtifacts(allArtifacts);
}
}
exports.compileYul = compileYul;
async function compileYulp(config, artifacts) {
const files = await getYulpSources(config.paths);
const allArtifacts = [];
for (const file of files) {
const cwdPath = path_1.default.relative(process.cwd(), file);
const hardhatConfigSolcVersion = config.solidity.compilers[0].version;
if (!solc_1.default.version().includes(hardhatConfigSolcVersion)) {
console.log(`Your hardhat config specifies solidity compiler version ${hardhatConfigSolcVersion} but it was not found as a package in your repository. To compile yul files the installed solc version must match the solidity compiler version specified in hardhat.config.js. You can either install the correct version of solc by running 'yarn add solc@${hardhatConfigSolcVersion}', or update the version specified in hardhat.config.js to match whatever solc version is installed in your repository.`);
return;
}
console.log(`Compiling ${cwdPath} using solc version ${solc_1.default.version()}...`); // e.g. 0.8.24+commit.e11b9ed9.Emscripten.clang
const yulOutput = await _compileYulp(cwdPath, file, config.solidity.compilers[0]);
const sourceName = await (0, source_names_1.localPathToSourceName)(config.paths.root, file);
const artifact = getArtifactFromYulOutput(sourceName, yulOutput);
await artifacts.saveArtifactAndDebugFile(artifact);
allArtifacts.push({ ...artifact, artifacts: [artifact.contractName] });
const artifactsImpl = artifacts;
artifactsImpl.addValidArtifacts(allArtifacts);
}
}
exports.compileYulp = compileYulp;
async function getYulSources(paths) {
const glob = await Promise.resolve().then(() => __importStar(require("glob")));
const yulFiles = glob.sync(path_1.default.join(paths.sources, "**", "*.yul").split(path_1.default.sep).join("/"));
return yulFiles;
}
async function getYulpSources(paths) {
const glob = await Promise.resolve().then(() => __importStar(require("glob")));
const yulpFiles = glob.sync(path_1.default.join(paths.sources, "**", "*.yulp").split(path_1.default.sep).join("/"));
return yulpFiles;
}
function pathToContractName(file) {
const sourceName = path_1.default.basename(file);
return sourceName.substring(0, sourceName.indexOf("."));
}
function getArtifactFromYulOutput(sourceName, output) {
const contractName = pathToContractName(sourceName);
return {
_format: "hh-sol-artifact-1", // sig"function add()" makes this work
contractName,
sourceName,
abi: [], // FIXME: create a proper abi which will work with typechain etc...
bytecode: output.bytecode,
deployedBytecode: output.bytecode_runtime,
linkReferences: {},
deployedLinkReferences: {},
};
}
async function _compileYul(filepath, filename, compiler) {
const data = fs.readFileSync(filepath, "utf8");
const solcInput = {
language: "Yul",
sources: { "Target.yul": { content: data } },
settings: {
outputSelection: { "*": { "*": ["*"], "": ["*"] } },
optimizer: {
enabled: true,
runs: 0,
details: { yul: true, },
},
},
};
solcInput.settings = { ...solcInput.settings, ...compiler.settings }; // merge with settings in user's hardhat.config.js
solcInput.settings.optimizer.details = { yul: true }; // make sure yul optimization is enabled in case it was overwritten
console.log(`solc settings: ${JSON.stringify(solcInput.settings)}`);
const output = JSON.parse(solc_1.default.compile(JSON.stringify(solcInput)));
if (output.errors && output.errors.length > 0) {
throw new Error(`hardhat-yul: error compiling ${filename}: ${util_1.default.inspect(output, false, null, true)}`);
}
const contractObjects = Object.keys(output.contracts["Target.yul"]);
const bytecode = "0x" +
output.contracts["Target.yul"][contractObjects[0]]["evm"]["bytecode"]["object"];
const contractCompiled = {
_format: "hh-sol-artifact-1",
sourceName: filename,
abi: [], // needs to be an empty array to not cause issues with typechain
bytecode: bytecode,
};
return contractCompiled;
}
async function _compileYulp(filepath, filename, compiler) {
const data = fs.readFileSync(filepath, "utf8");
const source = yulp_1.default.compile(data);
const solcInput = {
language: "Yul",
sources: { "Target.yul": { content: yulp_1.default.print(source.results) } },
settings: {
outputSelection: { "*": { "*": ["*"], "": ["*"] } },
optimizer: {
enabled: true,
runs: 0,
details: { yul: true, },
},
},
};
solcInput.settings = { ...solcInput.settings, ...compiler.settings }; // merge with settings in user's hardhat.config.js
solcInput.settings.optimizer.details = { yul: true }; // make sure yul optimization is enabled in case it was overwritten
console.log(`solc settings: ${JSON.stringify(solcInput.settings)}`);
const output = JSON.parse(solc_1.default.compile(JSON.stringify(solcInput)));
if (output.errors && output.errors.length > 0) {
throw new Error(`hardhat-yul: error compiling ${filename}: ${util_1.default.inspect(output, false, null, true)}`);
}
const contractObjects = Object.keys(output.contracts["Target.yul"]);
const bytecode = "0x" +
output.contracts["Target.yul"][contractObjects[0]]["evm"]["bytecode"]["object"];
const abi = source.signatures
.map((v) => v.abi.slice(4, -1))
.concat(source.topics.map((v) => v.abi.slice(6, -1)));
const contractCompiled = {
_format: "hh-sol-artifact-1",
sourceName: filename,
abi: abi,
bytecode: bytecode,
};
return contractCompiled;
}
//# sourceMappingURL=compilation.js.map