@layerzerolabs/verify-contract 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,27 @@
1
+ {
2
+ "avalanche": "api.snowtrace.io",
3
+ "fuji": "api-testnet.snowtrace.io",
4
+ "bsc": "api.bscscan.com",
5
+ "bsc-testnet": "api-testnet.bscscan.com",
6
+ "ethereum": "api.etherscan.io",
7
+ "ethereum-goerli": "api-goerli.etherscan.io",
8
+ "fantom": "api.ftmscan.com",
9
+ "fantom-testnet": "api-testnet.ftmscan.com",
10
+ "arbitrum": "api.arbiscan.io",
11
+ "arbitrum-goerli": "api-goerli.arbiscan.io",
12
+ "polygon": "api.polygonscan.com",
13
+ "mumbai": "api-testnet.polygonscan.com",
14
+ "optimism": "api-optimistic.etherscan.io",
15
+ "optimism-goerli": "api-goerli-optimistic.etherscan.io",
16
+
17
+ "aptos": "",
18
+ "celo": "",
19
+ "dexalot": "",
20
+ "dfk": "",
21
+ "harmony": "",
22
+ "intain": "",
23
+ "klaytn": "",
24
+ "metis": "",
25
+ "moonbeam": "api-moonbeam.moonscan.io",
26
+ "swimmer": ""
27
+ }
package/index.js ADDED
@@ -0,0 +1,185 @@
1
+ const FileSystem = require("fs");
2
+ const https = require('https');
3
+ const querystring = require('querystring');
4
+ const BLOCK_EXPLORER_API_URL = require("./constants/blockExplorerApi.json")
5
+
6
+ const licenseTypes = {
7
+ "None": 1,
8
+ "Unlicense": 2,
9
+ "MIT": 3,
10
+ "GNU-GPLv2": 4,
11
+ 'GNU-GPLv3': 5,
12
+ 'GNU-LGPLv2.1': 6,
13
+ 'GNU-LGPLv3': 7,
14
+ 'BSD-2-Clause': 8,
15
+ "BSD-3-Clause": 9,
16
+ "MPL-2.0": 10,
17
+ "OSL-3.0": 11,
18
+ "Apache-2.0": 12,
19
+ "GNU-AGPLv3": 13,
20
+ "BUSL-1.1": 14
21
+ }
22
+
23
+ function getContractInheritance(baseContractString, remainingContracts, finalObj) {
24
+ let contractNamesInherited = baseContractString.match(/(import).*(;)/g)
25
+ // we have reached the end of the inheritance as the base contract contains no more imports
26
+ if (!contractNamesInherited) { return finalObj }
27
+
28
+ // extract import names
29
+ contractNamesInherited = contractNamesInherited.map(
30
+ x => {
31
+ if (x.includes('"')) {
32
+ return (x.split(`"`)[1])
33
+ .split(`/`).pop()
34
+ } else {
35
+ return (x.split(`'`)[1])
36
+ .split(`/`).pop()
37
+ }
38
+ }
39
+ )
40
+
41
+ // there are more parent contracts to check, push them into final object
42
+ let parentContracts = []
43
+ for (const contractName of contractNamesInherited) {
44
+ for (const contract of remainingContracts) {
45
+ if (contract[0].includes("/" + contractName)) {
46
+ parentContracts.push(contract)
47
+ }
48
+ }
49
+ }
50
+
51
+ // filter out contracts that we haven't added to the finalObj yet
52
+ let remainingContractsNew = remainingContracts.filter(([k, v]) => !Object.keys(Object.fromEntries(parentContracts)).includes(k))
53
+
54
+ // take existing contracts and the new verified parent contracts and merge into object
55
+ let resp = {...finalObj, ...Object.fromEntries(parentContracts)}
56
+
57
+ // go through each of the parent contracts and get inheritance
58
+ for (const [k, v] of parentContracts) {
59
+ resp = {...getContractInheritance(v["content"], remainingContractsNew, finalObj), ...resp}
60
+ }
61
+
62
+ return resp
63
+ }
64
+
65
+ function formatPutObj(baseContract, contractBuildInfo, contractDeployment, contract, network) {
66
+ let putObj= {
67
+ apikey: process.env[`SCAN_API_KEY_${network}`],
68
+ module: "contract",
69
+ action: "verifysourcecode",
70
+ sourceCode: JSON.stringify(contractBuildInfo["input"]),
71
+ contractaddress: contractDeployment["address"],
72
+ codeformat: "solidity-standard-json-input",
73
+ contractname: `${baseContract[0]}:${contract}`,
74
+ compilerversion: "v" + contractBuildInfo["solcLongVersion"],
75
+ licenseType: licenseTypes["None"] // default to none
76
+ }
77
+
78
+ // specify license type if one is found in the base contract
79
+ for (const [license, type] of Object.entries(licenseTypes)) {
80
+ if (baseContract[1]["content"].includes(`SPDX-License-Identifier: ${license}`)) {
81
+ putObj["licenseType"] = type
82
+ }
83
+ }
84
+
85
+ if (contractBuildInfo["input"]["settings"]["optimizer"]["enabled"]) {
86
+ putObj["optimizationUsed"] = 1
87
+ putObj["runs"] = contractBuildInfo["input"]["settings"]["optimizer"]["runs"]
88
+ } else {
89
+ putObj["optimizationUsed"] = 0
90
+ }
91
+
92
+ let constructorAbiEncoded
93
+ if (baseContract[1]["content"].includes("constructor(")) {
94
+ let constructorTypes = (contractDeployment["abi"].filter(x => x["type"] && x["type"] == "constructor")[0]["inputs"]).map(x => x["type"])
95
+ constructorAbiEncoded = ethers.utils.defaultAbiCoder.encode(constructorTypes, contractDeployment["args"])
96
+ }
97
+
98
+ if (constructorAbiEncoded) {
99
+ putObj["constructorArguements"] = constructorAbiEncoded.substring(2) // misspelled in etherscans api
100
+ }
101
+
102
+ return putObj
103
+ }
104
+
105
+ function getBaseAndRemainingContract(contractName, contractBuildInfo) {
106
+ const baseContract = Object.entries(contractBuildInfo["input"]["sources"]).filter(([k, v]) => k.includes(contractName))[0]
107
+ const remainingContracts = Object.entries(contractBuildInfo["input"]["sources"]).filter(([k, v]) => !k.includes(contractName))
108
+ return [baseContract, remainingContracts]
109
+ }
110
+
111
+
112
+ module.exports = async function (network, contract) {
113
+ if(!BLOCK_EXPLORER_API_URL[network]) {
114
+ throw `Unsupported block explorer network: ${network}`
115
+ }
116
+ if (!process.env[`SCAN_API_KEY_${network}`]) {
117
+ throw `Missing API key for network: ${network}`
118
+ }
119
+
120
+ const contractName = `/${contract}.sol`
121
+
122
+ // get the build files/artifacts
123
+ const contractDeployment = JSON.parse(FileSystem.readFileSync(`./deployments/${network}/${contract}.json`, "utf8"))
124
+ // iterate the build-info to find the correct build file
125
+ let contractBuildInfo
126
+ FileSystem.readdirSync(`./artifacts/build-info/`).forEach(fileName => {
127
+ const f = JSON.parse(FileSystem.readFileSync(`./artifacts/build-info/${fileName}`, "utf8"))
128
+
129
+ let test = Object.entries(f["input"]["sources"]).filter(([k, v]) => k.includes(contractName))
130
+ if (test[0] && test[0][0]) {
131
+ if (test[0][0].includes(contractName)) {
132
+ contractBuildInfo = f
133
+ }
134
+ }
135
+ })
136
+ if (!contractBuildInfo) throw `Could not find contract: ${contractName} inside of build-info!`
137
+
138
+ console.log(`\n\nVerifying... Network: ${network}, contractName: ${contractName}, address: ${contractDeployment["address"]}`)
139
+
140
+ // parse and filter out the extra build files, because the verifier freaks out if too many contracts to check
141
+ const [baseContract, remainingContracts] = getBaseAndRemainingContract(contractName, contractBuildInfo)
142
+ contractBuildInfo["input"]["sources"] = getContractInheritance(baseContract[1]["content"], remainingContracts, Object.fromEntries([baseContract]))
143
+
144
+ // format the put request
145
+ const putObj = formatPutObj(baseContract, contractBuildInfo, contractDeployment, contract, network)
146
+
147
+ const response = await makeRequest(`${BLOCK_EXPLORER_API_URL[network]}`, putObj)
148
+ console.log(JSON.parse(response))
149
+ }
150
+
151
+ async function makeRequest(url, data) {
152
+ const postData = querystring.stringify(data);
153
+
154
+ const options = {
155
+ hostname: url,
156
+ path: '/api',
157
+ method: 'POST',
158
+ headers: {
159
+ 'Content-Type': 'application/x-www-form-urlencoded',
160
+ 'Content-Length': Buffer.byteLength(postData)
161
+ }
162
+ };
163
+
164
+ return new Promise((resolve, reject) => {
165
+ const req = https.request(options, (res) => {
166
+ let data = '';
167
+ res.on('data', (chunk) => {
168
+ data += chunk;
169
+ });
170
+ res.on('end', () => {
171
+ resolve(data);
172
+ });
173
+ });
174
+
175
+ req.on('error', (error) => {
176
+ reject(error);
177
+ });
178
+
179
+ req.write(postData);
180
+ req.end();
181
+ });
182
+ }
183
+
184
+
185
+
package/package.json ADDED
@@ -0,0 +1,17 @@
1
+ {
2
+ "name": "@layerzerolabs/verify-contract",
3
+ "version": "1.0.0",
4
+ "description": "Verify Solidity contracts on supported block explorers",
5
+ "main": "index.js",
6
+ "scripts": {},
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/LayerZero-Labs/verify-contract.git"
10
+ },
11
+ "author": "Lz.Warlock",
12
+ "license": "MIT",
13
+ "bugs": {
14
+ "url": "https://github.com/LayerZero-Labs/verify-contract/issues"
15
+ },
16
+ "homepage": "https://github.com/LayerZero-Labs/verify-contract#readme"
17
+ }