Skip to content
This repository has been archived by the owner on Jan 4, 2024. It is now read-only.

Show server response when Sourcify fails #199

Merged
merged 7 commits into from
Apr 24, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ export const RequestStatus = {
export enum VerificationStatus {
FAILED = 'Fail - Unable to verify',
SUCCESS = 'Pass - Verified',
PARTIAL = 'Pass - Partially Verified (with a metadata mismatch)',
PENDING = 'Pending in queue',
ALREADY_VERIFIED = 'Contract source code already verified',
AUTOMATICALLY_VERIFIED = 'Already Verified',
Expand Down
4 changes: 2 additions & 2 deletions src/verifier/AbstractVerifier.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@ export abstract class AbstractVerifier {
abstract name: string;

abstract getContractUrl(address: string): string | undefined;
abstract verifyContract(artifact: Artifact): Promise<VerificationStatus>;
abstract verifyContract(artifact: Artifact): Promise<string>;
abstract verifyProxyContract(
proxyArtifact: Artifact,
implementationName: string,
implementationAddress: string
): Promise<VerificationStatus>;
): Promise<string>;

logger: Logger;

Expand Down
2 changes: 1 addition & 1 deletion src/verifier/EtherscanVerifier.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export class EtherscanVerifier extends AbstractVerifier implements Verifier {
await super.verifyAll(contractNameAddressPairs);
}

async verifyContract(artifact: Artifact): Promise<VerificationStatus> {
async verifyContract(artifact: Artifact): Promise<string> {
this.checkBoundaries();

const res = await this.sendVerifyRequest(artifact);
Expand Down
85 changes: 49 additions & 36 deletions src/verifier/SourcifyVerifier.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,26 +22,65 @@ export class SourcifyVerifier extends AbstractVerifier implements Verifier {
await super.verifyAll(contractNameAddressPairs);
}

async verifyContract(artifact: Artifact): Promise<VerificationStatus> {
// Note that Sourcify may indicate failed verification in through errors, but also through 200 responses
// This is why we check both cases
async verifyContract(artifact: Artifact): Promise<string> {
await this.checkBoundaries();

const res = await this.sendVerifyRequest(artifact);
enforceOrThrow(res.data?.result?.length === 1, `Failed to connect to Sourcify API at url ${SOURCIFY_API_URL}`);
const inputJSON = await getInputJSON(artifact, this.options, this.logger);

const [contract] = res.data.result;
const files: { [path: string]: string } = {};
Object.keys(inputJSON.sources).forEach((path) => {
files[path.replace(/^.*[\\/]/, '')] = inputJSON.sources[path].content;
});
files['metadata.json'] = JSON.stringify(JSON.parse(artifact.metadata));

if (contract.storageTimestamp) {
return VerificationStatus.ALREADY_VERIFIED;
}
const postQueries = {
address: artifact.networks[`${this.options.networkId}`].address,
chain: `${this.options.chainId}`,
files,
};

try {
this.logger.debug('Sending verify request with POST arguments:');
logObject(this.logger, 'debug', postQueries, 2);
const res = await axios.post(SOURCIFY_API_URL, postQueries);

const [result] = res?.data?.result ?? [];
this.logger.debug('Received response:');
logObject(this.logger, 'debug', result, 2);

if (!result) {
// If no result was returned, there is likely an issue with the API connection
throw new Error(`Could not connect to Sourcify API at url ${SOURCIFY_API_URL}`);
}

if (result.storageTimestamp) return VerificationStatus.ALREADY_VERIFIED;
if (result.status === 'partial') return VerificationStatus.PARTIAL;
if (result.status === 'perfect') return VerificationStatus.SUCCESS;
return `${VerificationStatus.FAILED}: ${result?.message}`
} catch (error: any) {
const errorResponse = error?.response?.data;
const errorResponseMessage = errorResponse?.message ?? errorResponse?.error;

this.logger.debug(`Error: ${error?.message}`);
logObject(this.logger, 'debug', error?.response?.data, 2)

// If an error message is present in the checked response, this likely indicates a failed verification
if (errorResponseMessage) {
return `${VerificationStatus.FAILED}: ${errorResponseMessage}`
}

return VerificationStatus.SUCCESS;
// If no message was passed in the response, this likely indicates a failed connection
throw new Error(`Could not connect to Sourcify API at url ${SOURCIFY_API_URL}`);
}
}

async verifyProxyContract(
proxyArtifact: Artifact,
implementationName: string,
implementationAddress: string
): Promise<VerificationStatus> {
): Promise<string> {
await this.checkBoundaries();

if (this.options.customProxy) {
Expand All @@ -63,32 +102,6 @@ export class SourcifyVerifier extends AbstractVerifier implements Verifier {
return status;
}

private async sendVerifyRequest(artifact: Artifact) {
const inputJSON = await getInputJSON(artifact, this.options, this.logger);

const files: { [path: string]: string } = {};
Object.keys(inputJSON.sources).forEach((path) => {
files[path.replace(/^.*[\\/]/, '')] = inputJSON.sources[path].content;
});
files['metadata.json'] = JSON.stringify(JSON.parse(artifact.metadata));

const postQueries = {
address: artifact.networks[`${this.options.networkId}`].address,
chain: `${this.options.chainId}`,
files,
};

try {
this.logger.debug('Sending verify request with POST arguments:');
logObject(this.logger, 'debug', postQueries, 2);
return await axios.post(SOURCIFY_API_URL, postQueries);
} catch (error: any) {
this.logger.debug(error.message);
this.logger.debug(error.response.data.message);
throw new Error(`Failed to connect to Sourcify API at url ${SOURCIFY_API_URL}`);
}
}

private async checkBoundaries() {
enforceOrThrow(
await this.isSupportedChain(this.options.chainId),
Expand All @@ -103,7 +116,7 @@ export class SourcifyVerifier extends AbstractVerifier implements Verifier {

private async getSupportedChains() {
if (this.supportedChainIds) return this.supportedChainIds;
const chainsUrl = `${SOURCIFY_API_URL}chains`
const chainsUrl = `${SOURCIFY_API_URL}chains`;

try {
this.logger.debug(`Fetching supported chains from ${chainsUrl}`);
Expand Down
4 changes: 2 additions & 2 deletions src/verifier/Verifier.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ export interface Verifier {
name: string;
options: Options;
getContractUrl(address: string): string | undefined;
verifyContract(artifact: Artifact): Promise<VerificationStatus>;
verifyContract(artifact: Artifact): Promise<string>;
verifyProxyContract(
proxyArtifact: Artifact,
implementationName: string,
implementationAddress: string
): Promise<VerificationStatus>;
): Promise<string>;
verifyAll(contractNameAddressPairs: string[]): Promise<void>;
}