Skip to content

Commit 19da230

Browse files
authored
build: add script to verify contracts from address-book in Etherscan (#236)
* build: add script to verify contracts from address-book in Etherscan * build: ignore if contract address is not defined
1 parent cbfd87a commit 19da230

File tree

9 files changed

+133
-11
lines changed

9 files changed

+133
-11
lines changed

.env.example

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
MNEMONIC=
2+
ETHERSCAN_API_KEY=
3+
INFURA_KEY=

buidler.config.ts

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
11
import * as dotenv from 'dotenv'
22
import { Wallet } from 'ethers'
3-
import { BuidlerConfig, task, usePlugin, types } from '@nomiclabs/buidler/config'
3+
import { BuidlerConfig, task, usePlugin } from '@nomiclabs/buidler/config'
44

55
import { cliOpts } from './scripts/cli/constants'
66
import { migrate } from './scripts/cli/commands/migrate'
7+
import { verify } from './scripts/cli/commands/verify'
78

89
dotenv.config()
910

1011
// Plugins
1112

13+
usePlugin('@nomiclabs/buidler-etherscan')
1214
usePlugin('@nomiclabs/buidler-waffle')
1315
usePlugin('solidity-coverage')
1416

@@ -26,7 +28,6 @@ function getInfuraProviderURL(network: string) {
2628

2729
task('accounts', 'Prints the list of accounts', async (taskArgs, bre) => {
2830
const accounts = await bre.ethers.getSigners()
29-
3031
for (const account of accounts) {
3132
console.log(await account.getAddress())
3233
}
@@ -41,6 +42,13 @@ task('migrate', 'Migrate contracts')
4142
await migrate(accounts[0] as Wallet, taskArgs.addressBook, taskArgs.graphConfig, taskArgs.force)
4243
})
4344

45+
task('verify', 'Verify contracts in Etherscan')
46+
.addParam('addressBook', cliOpts.addressBook.description, cliOpts.addressBook.default)
47+
.setAction(async (taskArgs, bre) => {
48+
const accounts = await bre.ethers.getSigners()
49+
await verify(accounts[0] as Wallet, taskArgs.addressBook)
50+
})
51+
4452
// Config - Go to https://buidler.dev/config/ to learn more
4553

4654
const config: BuidlerConfig = {
@@ -120,7 +128,11 @@ const config: BuidlerConfig = {
120128
mnemonic: getAccountMnemonic(),
121129
},
122130
},
123-
}
131+
},
132+
etherscan: {
133+
url: 'https://api-kovan.etherscan.io/api',
134+
apiKey: process.env.ETHERSCAN_API_KEY,
135+
},
124136
}
125137

126138
export default config

package-lock.json

Lines changed: 38 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
"@graphprotocol/common-ts": "0.0.32",
1818
"@nomiclabs/buidler": "^1.3.7",
1919
"@nomiclabs/buidler-ethers": "^2.0.0-alpha.1",
20+
"@nomiclabs/buidler-etherscan": "^1.3.3",
2021
"@nomiclabs/buidler-waffle": "^2.0.0-alpha.1",
2122
"@openzeppelin/contracts": "3.0.1",
2223
"@types/bs58": "^4.0.1",
@@ -69,7 +70,7 @@
6970
"migrate": "buidler migrate",
7071
"test": "npm run typechain && buidler test",
7172
"coverage": "SOLIDITY_COVERAGE=true npm run evm:test",
72-
"evm:test": "scripts/evm.sh",
73+
"evm:test": "scripts/evm",
7374
"lint": "npm run lint:ts && npm run lint:sol",
7475
"lint:fix": "npm run lint:ts:fix && npm run lint:sol:fix",
7576
"lint:ts": "eslint '*/**/*.{js,ts}'",
@@ -79,9 +80,10 @@
7980
"prettier": "npm run prettier:ts && npm run prettier:sol",
8081
"prettier:ts": "prettier --write 'test/**/*.ts'",
8182
"prettier:sol": "prettier --write 'contracts/*.sol'",
82-
"flatten": "scripts/flatten.sh",
83+
"flatten": "scripts/flatten",
8384
"abi:extract": "truffle-abi -d ./build/contracts -o ./build/abis/ -v",
84-
"typechain": "typechain --target abarmat-ethers-v5 --outDir build/typechain/contracts 'build/abis/*.json'"
85+
"typechain": "typechain --target abarmat-ethers-v5 --outDir build/typechain/contracts 'build/abis/*.json'",
86+
"verify": "buidler verify"
8587
},
8688
"lint-staged": {
8789
"contracts/*.sol": [

scripts/cli/cli.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,14 @@
33
import yargs from 'yargs'
44

55
import { migrateCommand } from './commands/migrate'
6+
import { verifyCommand } from './commands/verify'
7+
import { cliOpts } from './constants'
68

79
yargs
10+
.option('a', cliOpts.addressBook)
11+
.option('m', cliOpts.mnemonic)
12+
.option('p', cliOpts.ethProvider)
813
.command(migrateCommand)
14+
.command(verifyCommand)
915
.demandCommand(1, 'Choose a command from the above list')
1016
.help().argv

scripts/cli/commands/migrate.ts

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -97,11 +97,7 @@ export const migrateCommand = {
9797
command: 'migrate',
9898
describe: 'Migrate contracts',
9999
builder: (yargs: Argv) => {
100-
return yargs
101-
.option('a', cliOpts.addressBook)
102-
.option('c', cliOpts.graphConfig)
103-
.option('m', cliOpts.mnemonic)
104-
.option('p', cliOpts.ethProvider)
100+
return yargs.option('c', cliOpts.graphConfig)
105101
},
106102
handler: async (argv: { [key: string]: any } & Argv['argv']) => {
107103
await migrate(

scripts/cli/commands/verify.ts

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import { Wallet, constants, utils, ContractTransaction } from 'ethers'
2+
3+
import { Argv } from 'yargs'
4+
5+
import { getAddressBook } from '../address-book'
6+
import { getProvider } from '../utils'
7+
import { spawn, execSync, spawnSync } from 'child_process'
8+
9+
const coreContracts = [
10+
'EpochManager',
11+
'GNS',
12+
'GraphToken',
13+
'ServiceRegistry',
14+
'Curation',
15+
'RewardsManager',
16+
'Staking',
17+
'DisputeManager',
18+
'IndexerCTDT',
19+
'IndexerSingleAssetInterpreter',
20+
'IndexerMultiAssetInterpreter',
21+
'IndexerWithdrawInterpreter',
22+
'MinimumViableMultisig',
23+
]
24+
25+
export const verify = async (wallet: Wallet, addressBookPath: string): Promise<void> => {
26+
const chainId = (await wallet.provider.getNetwork()).chainId
27+
const addressBook = getAddressBook(addressBookPath, chainId.toString())
28+
console.log(
29+
`* Verifying contracts for chainId (${chainId}) using address-book (${addressBookPath})`,
30+
)
31+
32+
for (const contractName of coreContracts) {
33+
const contract = addressBook.getEntry(contractName)
34+
if (!contract) {
35+
console.log(
36+
`- ERROR: Contract ${contractName} not found in address-book for network ${chainId}`,
37+
)
38+
continue
39+
}
40+
41+
const address = contract.address
42+
const args = contract.constructorArgs ? contract.constructorArgs.map(e => e.value) : []
43+
const argsList = args.map(e => `"${e}"`).join(' ')
44+
const cmd = `buidler verify-contract --contract-name ${contractName} --address ${address} ${argsList}`
45+
46+
try {
47+
console.log(`> Verifying contract ${contractName}::${address} ...`)
48+
await execSync(cmd)
49+
console.log(`+ Contract ${contractName}::${address} verified`)
50+
} catch (err) {
51+
console.log(`- ERROR: ${contractName}::${address}`)
52+
}
53+
}
54+
}
55+
56+
export const verifyCommand = {
57+
command: 'verify',
58+
describe: 'Verify contracts',
59+
handler: async (argv: { [key: string]: any } & Argv['argv']) => {
60+
await verify(
61+
Wallet.fromMnemonic(argv.mnemonic).connect(getProvider(argv.ethProvider)),
62+
argv.addressBook,
63+
)
64+
},
65+
}
File renamed without changes.
File renamed without changes.

0 commit comments

Comments
 (0)