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 6 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 - Verified (with a metadata mismatch)',
rkalis marked this conversation as resolved.
Show resolved Hide resolved
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>;
}