2020-09-15 15:24:50 +00:00
import { exit } from 'process' ;
2020-09-24 15:48:29 +00:00
import fs from 'fs' ;
2020-10-22 09:17:21 +00:00
import globby from 'globby' ;
2020-09-24 15:48:29 +00:00
import { file } from 'tmp-promise' ;
2020-11-05 12:44:20 +00:00
import { DRE } from './misc-utils' ;
2020-08-20 15:35:05 +00:00
2020-10-22 09:17:21 +00:00
const listSolidityFiles = ( dir : string ) = > globby ( ` ${ dir } /**/*.sol ` ) ;
const fatalErrors = [
` The address provided as argument contains a contract, but its bytecode ` ,
` Daily limit of 100 source code submissions reached ` ,
] ;
2020-08-20 15:35:05 +00:00
export const SUPPORTED_ETHERSCAN_NETWORKS = [ 'main' , 'ropsten' , 'kovan' ] ;
export const getEtherscanPath = async ( contractName : string ) = > {
2020-11-05 12:44:20 +00:00
const paths = await listSolidityFiles ( DRE . config . paths . sources ) ;
2020-08-20 15:35:05 +00:00
const path = paths . find ( ( p ) = > p . includes ( contractName ) ) ;
if ( ! path ) {
throw new Error (
` Contract path not found for ${ contractName } . Check if smart contract file is equal to contractName input. `
) ;
}
return ` ${ path } : ${ contractName } ` ;
} ;
function delay ( ms : number ) {
return new Promise ( ( resolve ) = > setTimeout ( resolve , ms ) ) ;
}
export const verifyContract = async (
contractName : string ,
address : string ,
2020-08-21 11:07:32 +00:00
constructorArguments : ( string | string [ ] ) [ ] ,
2020-08-20 15:35:05 +00:00
libraries? : string
) = > {
2020-11-05 12:44:20 +00:00
const currentNetwork = DRE . network . name ;
2020-08-20 15:35:05 +00:00
if ( ! process . env . ETHERSCAN_KEY ) {
throw Error ( 'Missing process.env.ETHERSCAN_KEY.' ) ;
}
if ( ! SUPPORTED_ETHERSCAN_NETWORKS . includes ( currentNetwork ) ) {
throw Error (
` Current network ${ currentNetwork } not supported. Please change to one of the next networks: ${ SUPPORTED_ETHERSCAN_NETWORKS . toString ( ) } `
) ;
}
const etherscanPath = await getEtherscanPath ( contractName ) ;
try {
console . log (
'[ETHERSCAN][WARNING] Delaying Etherscan verification due their API can not find newly deployed contracts'
) ;
const msDelay = 3000 ;
2020-11-09 17:55:09 +00:00
const times = 4 ;
2020-09-24 15:48:29 +00:00
// Write a temporal file to host complex parameters for buidler-etherscan https://github.com/nomiclabs/buidler/tree/development/packages/buidler-etherscan#complex-arguments
const { fd , path , cleanup } = await file ( {
prefix : 'verify-params-' ,
postfix : '.js' ,
} ) ;
fs . writeSync ( fd , ` module.exports = ${ JSON . stringify ( [ . . . constructorArguments ] ) } ; ` ) ;
const params = {
contractName : etherscanPath ,
address : address ,
libraries ,
constructorArgs : path ,
2020-11-09 17:55:09 +00:00
relatedSources : true ,
2020-09-24 15:48:29 +00:00
} ;
await runTaskWithRetry ( 'verify' , params , times , msDelay , cleanup ) ;
2020-08-20 15:35:05 +00:00
} catch ( error ) { }
} ;
export const runTaskWithRetry = async (
task : string ,
params : any ,
times : number ,
2020-09-24 15:48:29 +00:00
msDelay : number ,
cleanup : ( ) = > void
2020-08-20 15:35:05 +00:00
) = > {
let counter = times ;
await delay ( msDelay ) ;
try {
2020-11-09 17:55:09 +00:00
if ( times > 1 ) {
await DRE . run ( task , params ) ;
cleanup ( ) ;
} else if ( times === 1 ) {
console . log ( '[ETHERSCAN][WARNING] Trying to verify via uploading all sources.' ) ;
delete params . relatedSources ;
2020-11-05 12:44:20 +00:00
await DRE . run ( task , params ) ;
2020-09-24 15:48:29 +00:00
cleanup ( ) ;
2020-08-20 15:35:05 +00:00
} else {
2020-09-24 15:48:29 +00:00
cleanup ( ) ;
2020-10-22 09:17:21 +00:00
console . error (
'[ETHERSCAN][ERROR] Errors after all the retries, check the logs for more information.'
) ;
2020-08-20 15:35:05 +00:00
}
} catch ( error ) {
counter -- ;
2020-10-22 09:17:21 +00:00
console . info ( ` [ETHERSCAN][[INFO] Retrying attemps: ${ counter } . ` ) ;
console . error ( '[ETHERSCAN][[ERROR]' , error . message ) ;
if ( fatalErrors . some ( ( fatalError ) = > error . message . includes ( fatalError ) ) ) {
console . error (
'[ETHERSCAN][[ERROR] Fatal error detected, skip retries and resume deployment.'
) ;
return ;
}
2020-09-24 15:48:29 +00:00
await runTaskWithRetry ( task , params , counter , msDelay , cleanup ) ;
2020-08-20 15:35:05 +00:00
}
} ;
export const checkVerification = ( ) = > {
2020-11-05 12:44:20 +00:00
const currentNetwork = DRE . network . name ;
2020-08-20 15:35:05 +00:00
if ( ! process . env . ETHERSCAN_KEY ) {
2020-09-15 15:24:50 +00:00
console . error ( 'Missing process.env.ETHERSCAN_KEY.' ) ;
exit ( 3 ) ;
2020-08-20 15:35:05 +00:00
}
if ( ! SUPPORTED_ETHERSCAN_NETWORKS . includes ( currentNetwork ) ) {
2020-09-15 15:24:50 +00:00
console . error (
2020-08-20 15:35:05 +00:00
` Current network ${ currentNetwork } not supported. Please change to one of the next networks: ${ SUPPORTED_ETHERSCAN_NETWORKS . toString ( ) } `
) ;
2020-09-15 15:24:50 +00:00
exit ( 5 ) ;
2020-08-20 15:35:05 +00:00
}
} ;