2020-09-15 15:24:50 +00:00
import { exit } from 'process' ;
2020-09-24 15:48:29 +00:00
import fs from 'fs' ;
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 fatalErrors = [
` The address provided as argument contains a contract, but its bytecode ` ,
` Daily limit of 100 source code submissions reached ` ,
2020-11-10 12:11:33 +00:00
` has no bytecode. Is the contract deployed to this network ` ,
` The constructor for ` ,
2020-10-22 09:17:21 +00:00
] ;
2020-11-10 12:11:33 +00:00
const okErrors = [ ` Contract source code already verified ` ] ;
2020-08-20 15:35:05 +00:00
2020-11-10 12:11:33 +00:00
const unableVerifyError = 'Fail - Unable to verify' ;
2020-08-20 15:35:05 +00:00
2020-11-10 12:11:33 +00:00
export const SUPPORTED_ETHERSCAN_NETWORKS = [ 'main' , 'ropsten' , 'kovan' ] ;
2020-08-20 15:35:05 +00:00
function delay ( ms : number ) {
return new Promise ( ( resolve ) = > setTimeout ( resolve , ms ) ) ;
}
export const verifyContract = async (
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 ( ) } `
) ;
}
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 = {
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-11-10 12:11:33 +00:00
if ( okErrors . some ( ( okReason ) = > error . message . includes ( okReason ) ) ) {
console . info ( '[ETHERSCAN][INFO] Skipping due OK response: ' , error . message ) ;
return ;
}
2020-10-22 09:17:21 +00:00
if ( fatalErrors . some ( ( fatalError ) = > error . message . includes ( fatalError ) ) ) {
console . error (
2020-11-10 12:11:33 +00:00
'[ETHERSCAN][ERROR] Fatal error detected, skip retries and resume deployment.' ,
error . message
2020-10-22 09:17:21 +00:00
) ;
return ;
}
2020-11-10 12:11:33 +00:00
console . error ( '[ETHERSCAN][ERROR]' , error . message ) ;
console . log ( ) ;
console . info ( ` [ETHERSCAN][[INFO] Retrying attemps: ${ counter } . ` ) ;
if ( error . message . includes ( unableVerifyError ) ) {
console . log ( '[ETHERSCAN][WARNING] Trying to verify via uploading all sources.' ) ;
delete params . relatedSources ;
}
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
}
} ;