@ -21,7 +21,7 @@ interface EtherscanRpcResponse {
interface EtherscanCheckStatusResponse {
interface EtherscanCheckStatusResponse {
status : '0' | '1'
status : '0' | '1'
message : string
message : string
result : 'Pending in queue' | 'Pass - Verified' | 'Fail - Unable to verify' | 'Unknown UID'
result : 'Pending in queue' | 'Pass - Verified' | 'Fail - Unable to verify' | 'Already Verified' | ' Unknown UID'
}
}
export class EtherscanVerifier extends AbstractVerifier {
export class EtherscanVerifier extends AbstractVerifier {
@ -32,18 +32,14 @@ export class EtherscanVerifier extends AbstractVerifier {
async verify ( submittedContract : SubmittedContract , compilerAbstract : CompilerAbstract ) : Promise < VerificationResponse > {
async verify ( submittedContract : SubmittedContract , compilerAbstract : CompilerAbstract ) : Promise < VerificationResponse > {
// TODO: Handle version Vyper contracts. This relies on Solidity metadata.
// TODO: Handle version Vyper contracts. This relies on Solidity metadata.
const metadata = JSON . parse ( compilerAbstract . data . contracts [ submittedContract . filePath ] [ submittedContract . contractName ] . metadata )
const metadata = JSON . parse ( compilerAbstract . data . contracts [ submittedContract . filePath ] [ submittedContract . contractName ] . metadata )
const body : EtherscanVerificationRequest = {
const formData = new FormData ( )
chainId : submittedContract.chainId ,
formData . append ( 'chainId' , submittedContract . chainId )
codeformat : 'solidity-standard-json-input' ,
formData . append ( 'codeformat' , 'solidity-standard-json-input' )
sourceCode : JSON.stringify ( compilerAbstract . input ) ,
formData . append ( 'sourceCode' , compilerAbstract . input . toString ( ) )
contractaddress : submittedContract.address ,
formData . append ( 'contractaddress' , submittedContract . address )
contractname : submittedContract.filePath + ':' + submittedContract . contractName ,
formData . append ( 'contractname' , submittedContract . filePath + ':' + submittedContract . contractName )
compilerversion : metadata.compiler.version ,
formData . append ( 'compilerversion' , ` v ${ metadata . compiler . version } ` )
}
formData . append ( 'constructorArguements' , submittedContract . abiEncodedConstructorArgs ? ? '' )
if ( submittedContract . abiEncodedConstructorArgs ) {
body . constructorArguements = submittedContract . abiEncodedConstructorArgs
}
const url = new URL ( this . apiUrl + '/api' )
const url = new URL ( this . apiUrl + '/api' )
url . searchParams . append ( 'module' , 'contract' )
url . searchParams . append ( 'module' , 'contract' )
@ -54,10 +50,7 @@ export class EtherscanVerifier extends AbstractVerifier {
const response = await fetch ( url . href , {
const response = await fetch ( url . href , {
method : 'POST' ,
method : 'POST' ,
headers : {
body : formData ,
'Content-Type' : 'application/json' ,
} ,
body : JSON.stringify ( body ) ,
} )
} )
if ( ! response . ok ) {
if ( ! response . ok ) {
@ -76,7 +69,7 @@ export class EtherscanVerifier extends AbstractVerifier {
return { status : 'pending' , receiptId : verificationResponse.result }
return { status : 'pending' , receiptId : verificationResponse.result }
}
}
async checkVerificationStatus ( receiptId : string ) : Promise < VerificationStatus > {
async checkVerificationStatus ( receiptId : string ) : Promise < VerificationResponse > {
const url = new URL ( this . apiUrl + '/api' )
const url = new URL ( this . apiUrl + '/api' )
url . searchParams . append ( 'module' , 'contract' )
url . searchParams . append ( 'module' , 'contract' )
url . searchParams . append ( 'action' , 'checkverifystatus' )
url . searchParams . append ( 'action' , 'checkverifystatus' )
@ -95,28 +88,26 @@ export class EtherscanVerifier extends AbstractVerifier {
const checkStatusResponse : EtherscanCheckStatusResponse = await response . json ( )
const checkStatusResponse : EtherscanCheckStatusResponse = await response . json ( )
if ( checkStatusResponse . status !== '1' || ! checkStatusResponse . message . startsWith ( 'OK' ) ) {
if ( checkStatusResponse . result === 'Fail - Unable to verify' ) {
console . error ( 'Error on Etherscan API check verification status at ' + this . apiUrl + '\nStatus: ' + checkStatusResponse . status + '\nMessage: ' + checkStatusResponse . message + '\nResult: ' + checkStatusResponse . result )
return { status : 'failed' , receiptId , message : checkStatusResponse.result }
throw new Error ( checkStatusResponse . result )
}
if ( checkStatusResponse . result === 'Pending in queue' ) {
return { status : 'pending' , receiptId }
}
if ( checkStatusResponse . result === 'Pass - Verified' || checkStatusResponse . result === 'Already Verified' ) {
return { status : 'verified' , receiptId }
}
}
if ( checkStatusResponse . result === 'Unknown UID' ) {
if ( checkStatusResponse . result === 'Unknown UID' ) {
console . error ( 'Error on Etherscan API check verification status at ' + this . apiUrl + '\nStatus: ' + checkStatusResponse . status + '\nMessage: ' + checkStatusResponse . message + '\nResult: ' + checkStatusResponse . result )
console . error ( 'Error on Etherscan API check verification status at ' + this . apiUrl + '\nStatus: ' + checkStatusResponse . status + '\nMessage: ' + checkStatusResponse . message + '\nResult: ' + checkStatusResponse . result )
throw new Error ( checkStatusResponse . result )
return { status : 'failed' , receiptId , message : checkStatusResponse.result }
}
}
let status : VerificationStatus = 'unknown'
if ( checkStatusResponse . status !== '1' || ! checkStatusResponse . message . startsWith ( 'OK' ) ) {
if ( checkStatusResponse . result === 'Fail - Unable to verify' ) {
console . error ( 'Error on Etherscan API check verification status at ' + this . apiUrl + '\nStatus: ' + checkStatusResponse . status + '\nMessage: ' + checkStatusResponse . message + '\nResult: ' + checkStatusResponse . result )
status = 'failed'
throw new Error ( checkStatusResponse . result )
}
if ( checkStatusResponse . result === 'Pending in queue' ) {
status = 'pending'
}
if ( checkStatusResponse . result === 'Pass - Verified' ) {
status = 'verified'
}
}
return status
return { status : 'unknown' , receiptId }
}
}
async lookup ( contractAddress : string , chainId : string ) : Promise < LookupResponse > {
async lookup ( contractAddress : string , chainId : string ) : Promise < LookupResponse > {