Skip to content

Commit

Permalink
fixes #15
Browse files Browse the repository at this point in the history
  • Loading branch information
Aniket-Engg committed Apr 3, 2019
1 parent 7a193da commit 500bace
Show file tree
Hide file tree
Showing 9 changed files with 667 additions and 659 deletions.
72 changes: 46 additions & 26 deletions bin/sol-verifier.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,49 +4,69 @@
const clc = require('cli-color');
const program = require('commander');
const { verify } = require('../lib/verify');
const { getNetwork } = require('../utils/network');

program
.version(require('../package.json').version, '-v, --version')
.option('-k, --key <etherscan-api-key>', 'Add Etherscan API Key (required)')
.option('-c, --contract <path-to-solidity-contract-file>', 'Add Contract File Path (required)')
.option('-a, --address <contract-address>', 'Add Address of Deployed Contract (required)')
.option('-n, --network <network>', 'Add Ethereum Network on Which Contract is deployed (required)')
.option('-n, --network <network>', 'Add Ethereum Network on Which Contract is deployed (if applicable)')
.option('-N, --contractName <contract-name>', 'Add Contract Name if Passed File Contains More Than One Contract (if applicable)') // eslint-disable-line max-len
.option('-p, --constructParams [param1, param2,...]', 'Add Constructor Parameter Values Same as in Deployment (if applicable)') // eslint-disable-line max-len
.option('-o, --optimize', 'Add This Flag to Optimize The Contract (optional)')
.parse(process.argv);

if(!program.key || !program.contract || !program.address || !program.network)
{
console.log(clc.red('Error: Required parameter not passed'));
program.outputHelp();
}
else{
if(program.constructParams)
program.constructParams = program.constructParams.slice(1, (program.constructParams.length -1)).split(',');

const data = {
key : program.key,
path : program.contract,
contractAddress : program.address,
network : program.network,
contractName : program.contractName,
cvalues : program.constructParams,
optimizationFlag: program.optimize,
};
verify(data)
.then(function (res){
(async function formalize (){
let network;

if(!program.key || !program.contract || !program.address)
{
console.log(clc.red('Error: Required Parameter Not Passed'));
program.outputHelp();
}
else{
if(program.constructParams)
program.constructParams = program.constructParams.slice(1, (program.constructParams.length -1)).split(',');

if(program.network)
network = program.network;
else {
const availableNets = await getNetwork(program.address);
if(availableNets.length == 1){
network = availableNets[0];
console.log(clc.green(`Contract Address Found on ${network} Network!!! Verifying ...`));
}
else{
console.log(clc.red(`Contract Address Found on ${availableNets} Networks. Please Provide --network Option.`));
program.outputHelp();
process.exit();
}
}

const data = {
key : program.key,
path : program.contract,
contractAddress : program.address,
network : network,
contractName : program.contractName,
cvalues : program.constructParams,
optimizationFlag: program.optimize,
};

try{
const res = await verify(data);
if(res.status == '1'){
console.log(clc.green('Contract has been successfully verified. Your GUID receipt : ' + res.result));
}
else if(res.status == '0'){
console.log(clc.red('Error: ' + res.result));
}
})
.catch(function (error){
console.log(clc.red('Error: ' + error.message));
});
}
}catch(error){
throw error;
}
}
})();



Expand Down
4 changes: 2 additions & 2 deletions lib/mapping.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
{
"urls" : {
"mainnet" : "https://api.etherscan.io/api",
"ropsten" : "https://api-ropsten.etherscan.io/api",
"kovan" : "https://api-kovan.etherscan.io/api",
"rinkeby" : "https://api-rinkeby.etherscan.io/api",
"mainnet" : "https://api.etherscan.io/api"
"rinkeby" : "https://api-rinkeby.etherscan.io/api"
},

"compilers" : {
Expand Down
42 changes: 18 additions & 24 deletions lib/solReleases.js
Original file line number Diff line number Diff line change
@@ -1,38 +1,32 @@
'use strict';
const rp = require('request-promise');

function getCompilerVersion (parsedData, map) {
module.exports.getCompilerVersion = async (parsedData, map) => {
let compiler;
return new Promise(function (resolve, reject){
try{
if(parsedData[0].type != 'PragmaStatement') {
reject(new Error('No Pragma Specified !!!'));
} else {
throw new Error('No Pragma Specified!!!');
}else {
const pragmaVersion = parsedData[0].start_version.version;
if(Object.keys(map.compilers).indexOf(parsedData[0].start_version.version) > -1){
compiler = map.compilers[parsedData[0].start_version.version];
resolve(compiler);
} else {
return compiler;
}else {
const options = {
method: 'GET',
uri: 'https://raw.githubusercontent.com/ethereum/solc-bin/gh-pages/bin/list.json',
};

rp(options)
.then(function (result) {
const data = JSON.parse(result);
if(!data.releases.hasOwnProperty(pragmaVersion)) {
reject(new Error('Unsupported Compiler Version'));
} else {
const commit = data.releases[pragmaVersion];
resolve(commit.slice(8, 30));
}
})
.catch(function (err) {
reject(err);
});
const result = await rp(options);
const data = JSON.parse(result);
if(!data.releases.hasOwnProperty(pragmaVersion)) {
throw new Error('Unsupported Compiler Version!!!');
}else {
const commit = data.releases[pragmaVersion];
return commit.slice(8, 30);
}
}
}
});
}

module.exports.getCompilerVersion = getCompilerVersion;
}catch(err) {
throw err;
};
};
123 changes: 53 additions & 70 deletions lib/verify.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
'use strict';

const parser = require('solparse');
const fs = require('fs');
const rp = require('request-promise');
const map = require('../lib/mapping.json');
const Web3 = require('web3');
Expand All @@ -10,84 +9,68 @@ const solReleases = require('./solReleases');
const { getPragma, processFile } = require('./../utils/import');


module.exports.verify = (data) => {

const { key, path, contractAddress, network, contractName, cvalues, optimizationFlag } = data;
return new Promise(async function (resolve, reject){
module.exports.verify = async (data) => {
try{
const { key, path, contractAddress, network, contractName, cvalues, optimizationFlag } = data;

if(Object.keys(map.urls).indexOf(network) > -1){
let oFlag = 0;
let compiler;
let name;
let abiEncodedParams;
const pragma = await getPragma(path);
const contractSource = await processFile(path, true);
let parsedData = parser.parse(pragma + '\n\n' + contractSource).body;
solReleases.getCompilerVersion(parsedData, map)
.then(result => {
compiler = result;
const noOfContracts = parsedData.filter(e => e.type == 'ContractStatement').length;
if( noOfContracts == 1){
name = parsedData[1].name;
parsedData = parsedData[1];
}else if(noOfContracts > 1){
if(contractName){
name = contractName;
parsedData = parsedData.filter(e => (e.type == 'ContractStatement' && e.name == contractName))[0];
}
else
reject(new Error('More Than One Contracts in File, Pass the Contract Name'));
}

const cParamsArray = parsedData.body.filter(obj => obj.type == 'ConstructorDeclaration');
if(cParamsArray.length > 0 && cParamsArray[0].params && cParamsArray[0].params.length > 0){
if(cvalues){
const cparams = [];
cParamsArray[0].params.forEach(param => cparams.push(param.literal.literal));
abiEncodedParams = web3.eth.abi.encodeParameters(cparams, cvalues);
abiEncodedParams = abiEncodedParams.slice(2, abiEncodedParams.length);
}
else
reject(new Error('Constructor Found, Pass the Constructor Parameter Values'));
}
else
abiEncodedParams = '';
const compiler = await solReleases.getCompilerVersion(parsedData, map);
const noOfContracts = parsedData.filter(e => e.type == 'ContractStatement').length;
if( noOfContracts == 1){
name = parsedData[1].name;
parsedData = parsedData[1];
}else if(noOfContracts > 1){
if(contractName){
name = contractName;
parsedData = parsedData.filter(e => (e.type == 'ContractStatement' && e.name == contractName))[0];
}else
throw new Error('More Than One Contracts in File!!! Please Provide --contractName Option');
}

const cParamsArray = parsedData.body.filter(obj => obj.type == 'ConstructorDeclaration');
if(cParamsArray.length > 0 && cParamsArray[0].params && cParamsArray[0].params.length > 0){
if(cvalues){
const cparams = [];
cParamsArray[0].params.forEach(param => cparams.push(param.literal.literal));
abiEncodedParams = web3.eth.abi.encodeParameters(cparams, cvalues);
abiEncodedParams = abiEncodedParams.slice(2, abiEncodedParams.length);
}else
throw new Error('Constructor Found!!! Please Provide --constructParams Option');
}
else
abiEncodedParams = '';

if(optimizationFlag)
oFlag = 1;
const data = {
apikey: key,
module: 'contract',
action: 'verifysourcecode',
contractaddress: contractAddress,
sourceCode: contractSource,
contractname: name,
compilerversion: compiler,
optimizationUsed: oFlag,
runs: '200',
constructorArguements: abiEncodedParams,
};
if(optimizationFlag)
oFlag = 1;
const data = {
apikey: key,
module: 'contract',
action: 'verifysourcecode',
contractaddress: contractAddress,
sourceCode: contractSource,
contractname: name,
compilerversion: compiler,
optimizationUsed: oFlag,
runs: '200',
constructorArguements: abiEncodedParams,
};

const options = {
method: 'POST',
uri: map.urls[network],
form: data,
json: true,
};
rp(options)
.then(function (result) {
resolve(result);
})
.catch(function (err) {
reject(err);
});
})
.catch(error => {
reject(error);
});
}
else
reject(new Error('Invalid Network Passed'));
});
const options = {
method: 'POST',
uri: map.urls[network],
form: data,
json: true,
};
return await rp(options);
}else
throw new Error('Invalid Network/Network Not Supported!!!');
}catch(error){
throw error;
}
};
Loading

0 comments on commit 500bace

Please sign in to comment.