For some purpose. I use web3.js 0.20 to deploy contracts.(eg. press button to deploy contracts automatically, not through remix IDE). When I deploy contracts, etherscan need to verify solidity. Is there a method that verifies contracts automatically through Web3? Thanks a lot.
Nothing about Etherscan (a proprietary, third-party app) is built in to web3.js, but Etherscan does have an API for verifying contract source code: https://etherscan.io/apis#contracts.
There you go (relying on web3 v1.0.0-beta.34 and truffle-flattener v1.2.10)...
Create a file named verify.js
with the contents below, and place it next to package.json
:
const WORK_DIR = "./PROJ_DIR"; // your contracts folder should be under this path
const NODE_DIR = "../node_modules";
const INPUT_FILE = process.argv[2];
const fs = require("fs");
const path = require("path");
const request = require("request");
const spawnSync = require("child_process").spawnSync;
const input = JSON.parse(fs.readFileSync(INPUT_FILE, {encoding: "utf8"}));
// input example:
// {
// "network" : "api", // use "api" for mainnet or "api-<testnet>" for testnet
// "apiKey" : "", // generate this value at https://etherscan.io/myapikey
// "compilerVersion": "v0.4.24+commit.e67f0147",
// "optimization" : {"used": 1, "runs": 6000},
// "contracts" : {
// "Contract1": {"addr": "0x0000000000000000000000000000000000000001", "args": "<abi-encoded constructor arguments>"},
// "Contract2": {"addr": "0x0000000000000000000000000000000000000002", "args": "<abi-encoded constructor arguments>"},
// "Contract3": {"addr": "0x0000000000000000000000000000000000000003", "args": "<abi-encoded constructor arguments>"}
// }
// }
function run() {
for (const pathName of getPathNames("contracts")) {
const contractName = path.basename(pathName, ".sol");
if (input.contracts.hasOwnProperty(contractName))
post(contractName, getSourceCode(pathName));
}
}
function getPathNames(dirName) {
let pathNames = [];
for (const fileName of fs.readdirSync(WORK_DIR + "/" + dirName)) {
if (fs.statSync(WORK_DIR + "/" + dirName + "/" + fileName).isDirectory())
pathNames = pathNames.concat(getPathNames(dirName + "/" + fileName));
else if (fileName.endsWith(".sol"))
pathNames.push(dirName + "/" + fileName);
}
return pathNames;
}
function getSourceCode(pathName) {
const result = spawnSync("node", [NODE_DIR + "/truffle-flattener/index.js", pathName], {cwd: WORK_DIR});
return result.output.toString().slice(1, -1);
}
function post(contractName, sourceCode) {
console.log(contractName + ": sending verification request...");
request.post({
url: "https://" + input.network + ".etherscan.io/api",
form: {
module : "contract",
action : "verifysourcecode",
sourceCode : sourceCode,
contractname : contractName,
apikey : input.apiKey,
compilerversion : input.compilerVersion,
optimizationUsed : input.optimization.used,
runs : input.optimization.runs,
contractaddress : input.contracts[contractName].addr,
constructorArguements: input.contracts[contractName].args,
}
},
function(error, response, body) {
if (error) {
console.log(contractName + ": " + error);
}
else {
body = JSON.parse(body);
if (body.status == "1")
get(contractName, body.result);
else
console.log(contractName + ": " + body.result);
}
}
);
}
function get(contractName, guid) {
console.log(contractName + ": checking verification status...");
request.get(
"https://" + input.network + ".etherscan.io/api?module=contract&action=checkverifystatus&guid=" + guid,
function(error, response, body) {
if (error) {
console.log(contractName + ": " + error);
}
else {
body = JSON.parse(body);
if (body.result == "Pending in queue")
get(contractName, guid);
else
console.log(contractName + ": " + body.result);
}
}
);
}
run();
In package.json
, add:
"scripts": {
"verify": "node verify.js"
},
"devDependencies": {
"truffle-flattener": "1.2.10",
"web3": "1.0.0-beta.34"
}
After running npm install
, you can verify your set of contracts by running npm verify input.txt
from a command line. You'll need to create input.txt
according to the input example at the top of verify.js
.
I created truffle-plugin-verify
to automate Truffle contract verification on Etherscan.
- Install the plugin with npm
npm install truffle-plugin-verify
- Add the plugin to your
truffle.js
ortruffle-config.js
file
module.exports = {
/* ... rest of truffle-config */
plugins: [
'truffle-plugin-verify'
]
}
- Generate an API Key on your Etherscan account (see the Etherscan website)
- Add your Etherscan API key to your truffle config
module.exports = {
/* ... rest of truffle-config */
api_keys: {
etherscan: 'MY_API_KEY'
}
}
After migrating your contract to to a public network, you are able to verify it on Etherscan by running:
truffle run verify ContractName [--network networkName]
More information can be found on the repository or in my article Automatically verify Truffle smart contracts on Etherscan.