/
verify.js
145 lines (137 loc) · 5.21 KB
/
verify.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
'use strict';
const clc = require('cli-color');
const parser = require('solidity-parser-antlr');
const rp = require('request-promise');
const ethers = require('ethers');
const straightener = require('sol-straightener');
const map = require('../lib/mapping.json');
const solReleases = require('./solReleases');
const hasFallback = require('./../utils/hasFallback');
module.exports.verify = async (data, cli = false) => {
try{
const { key, path, contractAddress, network, contractName, cvalues, evmVersion } = data;
let { runs, licenseType, optimizationFlag } = data;
if(Object.keys(map.urls).indexOf(network) > -1){
let name;
let abiEncodedParams;
let parsedData;
const contractSource = await straightener.straighten(path);
const ast = parser.parse(contractSource);
const nodes = ast.children;
const compiler = await solReleases.getCompilerVersion(nodes, map);
const availableContracts = nodes.filter(e => (e.type == 'ContractDefinition' && e.kind == 'contract'));
if( availableContracts.length == 1){
name = availableContracts[0].name;
parsedData = availableContracts[0];
}else if(availableContracts.length > 1){
if(contractName){
name = contractName;
parsedData = availableContracts.filter(e => (e.name == contractName))[0];
}else
throw new Error('More Than One Contracts in File!!! Please Provide --contractName Option');
}
const constructorNode = parsedData.subNodes.filter(obj => (obj.type == 'FunctionDefinition' && obj.isConstructor == true)); // eslint-disable-line max-len
if(constructorNode.length > 0 && constructorNode[0].parameters.parameters.length > 0){
const cParamsArray = constructorNode[0].parameters.parameters;
if(cvalues){
parser.visit(ast, {
UserDefinedTypeName: function (node) {
const contract = nodes.filter(e => (e.type == 'ContractDefinition' && e.name == node.namePath))[0];
let stateMutability = null;
if (hasFallback(contract)) {
stateMutability = 'payable';
}
node.resolvedType = {
type: 'ElementaryTypeName',
name: 'address',
stateMutability: stateMutability,
};
},
});
const cparams = [];
for (const param of cParamsArray){
if(param.typeName.type == 'UserDefinedTypeName')
cparams.push(param.typeName.resolvedType.name);
else if(param.typeName.type == 'ArrayTypeName'){
if(param.typeName.length)
cparams.push(param.typeName.baseTypeName.name + '[' + param.typeName.length.number + ']');
else
cparams.push(param.typeName.baseTypeName.name + '[]');
}
else
cparams.push(param.typeName.name);
}
abiEncodedParams = new ethers.utils.AbiCoder().encode(cparams, cvalues);
abiEncodedParams = abiEncodedParams.slice(2, abiEncodedParams.length);
}else
throw new Error('Constructor Found!!! Please Provide --constructParams Option');
}
runs = runs ? runs : 200;
licenseType = licenseType ? licenseType : 1;
optimizationFlag = optimizationFlag ? 1 : 0;
const data = {
apikey: key,
module: 'contract',
action: 'verifysourcecode',
contractaddress: contractAddress,
sourceCode: contractSource,
codeformat: 'solidity-single-file',
contractname: name,
compilerversion: compiler,
optimizationUsed: optimizationFlag,
runs: runs,
evmVersion: evmVersion,
licenseType: licenseType,
constructorArguements: abiEncodedParams,
};
const options = {
method: 'POST',
uri: map.urls[network],
form: data,
json: true,
};
const result = await rp(options);
if(result.status == 0) {
throw new Error(result.result);
} else {
const dataObj = {
guid: result.result,
module: 'contract',
action: 'checkverifystatus',
};
const obj = {
method: 'GET',
uri: map.urls[network],
form: dataObj,
};
const ms = 3000;
let count = 0;
async function lookupGuid (obj, ms) {
await sleep(ms);
const data = await rp(obj);
if (count < 10) {
if(JSON.parse(data).result == 'Pending in queue'){
if (cli == true) {
console.log(clc.yellow('Pending in queue...'));
console.log(clc.yellow('Please wait...'));
}
count++;
return await lookupGuid(obj, ms);
} else {
return JSON.parse(data);
}
} else {
throw new Error('Contract Verification Timeout!!! Check Final Status on Etherscan');
}
}
return await lookupGuid(obj, ms);
}
}else
throw new Error('Invalid Network/Network Not Supported!!!');
}catch(error){
throw error;
}
};
function sleep (ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}