Skip to content

Inject gas setting into ABIs and move tasks from hardhat.config to tasks/ #50

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Mar 24, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 3 additions & 55 deletions hardhat.config.ts
Original file line number Diff line number Diff line change
@@ -1,41 +1,13 @@
require("dotenv").config();
const replace = require("replace-in-file");

let changedFiles;

import { HardhatUserConfig, internalTask } from "hardhat/config";
import { TASK_COMPILE_SOLIDITY_COMPILE, TASK_TEST_SETUP_TEST_ENVIRONMENT } from "hardhat/builtin-tasks/task-names";
import { execSync } from "child_process";
import { HardhatUserConfig } from "hardhat/config";
import { privateKeys } from "./utils/wallets";

import "@nomiclabs/hardhat-waffle";
import "hardhat-typechain";
import "solidity-coverage";
import "hardhat-deploy";

internalTask(TASK_COMPILE_SOLIDITY_COMPILE).setAction(setupNativeSolc);
internalTask(TASK_TEST_SETUP_TEST_ENVIRONMENT).setAction(async function setupNativeSolc({ input }, { config }, runSuper) {
// Fix gas to be string instead of number in typechain files
const options = {
// Glob(s)
files: [
"./typechain/**/*.ts",
],

// Replacement to make (string or regex)
from: /gas\: [0-9]+,/g,
to: (match: string) => match.replace(/gas: ([0-9]+),/g, 'gas: "$1",'),
};

try {
changedFiles = replace.sync(options);
console.log("Fixing gas cost type from number to string...")
;
}
catch (error) {
console.error("Error occurred:", error);
}
});
import "./tasks";

const config: HardhatUserConfig = {
solidity: {
Expand Down Expand Up @@ -83,7 +55,7 @@ const config: HardhatUserConfig = {
},
mocha: {
timeout: 100000,
}
},
};

function getHardhatPrivateKeys() {
Expand All @@ -96,28 +68,4 @@ function getHardhatPrivateKeys() {
});
}

// @ts-ignore
async function setupNativeSolc({ input }, { config }, runSuper) {
let solcVersionOutput = "";
try {
solcVersionOutput = execSync(`solc --version`).toString();
} catch (error) {
// Probably failed because solc wasn"t installed. We do nothing here.
}

console.log("Output", solcVersionOutput);

if (!solcVersionOutput.includes(config.solidity.version)) {
console.log(`Using solcjs`);
return runSuper();
}

console.log(`Using native solc`);
const output = execSync(`solc --standard-json`, {
input: JSON.stringify(input, undefined, 2),
});

return JSON.parse(output.toString(`utf8`));
}

export default config;
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@
"chain": "npx hardhat node --no-deploy",
"clean": "rm -f coverage.json; rm -rf .coverage_cache; rm -rf .coverage_contracts; rm -rf cache; rm -rf coverage; rm -rf typechain; rm -rf artifacts",
"compile": "npx hardhat compile",
"coverage": "yarn clean && yarn build && npx hardhat coverage --temp artifacts",
"coverage": "yarn clean && yarn build && yarn cov:command",
"cov:command": "COVERAGE=true node --max-old-space-size=4096 ./node_modules/.bin/hardhat coverage",
"etherscan:verify": "hardhat --network kovan etherscan-verify --solc-input --license 'None'",
"fix-typechain": "node scripts/fix-typechain.js && yarn rename-extensions",
"flatten": "npx waffle flatten",
Expand Down
1 change: 1 addition & 0 deletions tasks/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./subtasks";
43 changes: 43 additions & 0 deletions tasks/subtasks.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import {
TASK_COMPILE_SOLIDITY_COMPILE,
TASK_TEST_SETUP_TEST_ENVIRONMENT,
TASK_COMPILE_SOLIDITY_GET_ARTIFACT_FROM_COMPILATION_OUTPUT,
} from "hardhat/builtin-tasks/task-names";

import { subtask, internalTask } from "hardhat/config";
import { addGasToAbiMethods, setupNativeSolc } from "../utils/tasks";

// Injects network block limit (minus 1 million) in the abi so
// ethers uses it instead of running gas estimation.
subtask(TASK_COMPILE_SOLIDITY_GET_ARTIFACT_FROM_COMPILATION_OUTPUT)
.setAction(async (_, { network }, runSuper) => {
const artifact = await runSuper();
artifact.abi = addGasToAbiMethods(network.config, artifact.abi);
return artifact;
}
);

// Use native solc if available locally at config specified version
internalTask(TASK_COMPILE_SOLIDITY_COMPILE).setAction(setupNativeSolc);

// Fix gas to be string instead of number in typechain files
internalTask(TASK_TEST_SETUP_TEST_ENVIRONMENT)
.setAction(async function setupNativeSolc({ input }, { config }, runSuper) {
const replace = require("replace-in-file");

const options = {
files: [ "./typechain/**/*.ts" ],
from: /gas\: [0-9]+,/g,
to: (match: string) => match.replace(/gas: ([0-9]+),/g, 'gas: "$1",'),
};

try {
replace.sync(options);
console.log("Fixing gas cost type from number to string...");
} catch (error) {
console.error("Error occurred:", error);
}
});


export {};
8 changes: 7 additions & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,13 @@
"@typechain/*": ["typechain/*"],
}
},
"include": ["./test/**/*.ts", "./utils/**/*.ts", "./deploy/**/*.ts", "./typechain/**/*.ts"],
"include": [
"./test/**/*.ts",
"./utils/**/*.ts",
"./deploy/**/*.ts",
"./typechain/**/*.ts",
"./tasks/**/*.ts"
],
"files": [
"hardhat.config.ts",
]
Expand Down
42 changes: 42 additions & 0 deletions utils/tasks/artifactUtils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import type { ethers } from "ethers";
import { NetworkConfig } from "hardhat/types";


// Adds a `gas` field to the ABI function elements so that ethers doesn't
// automatically estimate gas limits on every call. Halves execution time.
// (Borrowed from hardhat-ethers/src/internal/helpers.ts)
export function addGasToAbiMethods(
networkConfig: NetworkConfig,
abi: any[]
): any[] {
const { BigNumber } = require("ethers") as typeof ethers;

// Stay well under network limit b/c ethers adds a margin
// Also need special setting logic for coverage b/c it compiles
// before configuring the network with higher gas values.
let gas: number;
if (process.env.COVERAGE === "true") {
const CoverageAPI: any = require("solidity-coverage/api");
gas = new CoverageAPI().gasLimit as number;
} else {
gas = networkConfig.gas as number;
}

const gasLimit = BigNumber.from(gas).sub(1000000).toHexString();

const modifiedAbi: any[] = [];

for (const abiElement of abi) {
if (abiElement.type !== "function") {
modifiedAbi.push(abiElement);
continue;
}

modifiedAbi.push({
...abiElement,
gas: gasLimit,
});
}

return modifiedAbi;
}
2 changes: 2 additions & 0 deletions utils/tasks/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from "./artifactUtils";
export * from "./setupNativeSolc";
30 changes: 30 additions & 0 deletions utils/tasks/setupNativeSolc.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { execSync } from "child_process";

let isFirstRun = true;

// @ts-ignore
export async function setupNativeSolc({ input }, { config }, runSuper) {
let solcVersionOutput = "";
try {
solcVersionOutput = execSync(`solc --version`).toString();
} catch (error) {
// Probably failed because solc wasn"t installed. We do nothing here.
}

isFirstRun && console.log("Local native solc version: ", solcVersionOutput);

if (!solcVersionOutput.includes(config.solidity.version)) {
isFirstRun && console.log(`Using solcjs`);
isFirstRun = false;
return runSuper();
}

isFirstRun && console.log(`Using native solc`);
isFirstRun = false;

const output = execSync(`solc --standard-json`, {
input: JSON.stringify(input, undefined, 2),
});

return JSON.parse(output.toString(`utf8`));
}