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

Commit 2d6a4ef

Browse files
kuzdoganrkalis
andauthored
Show server response when Sourcify fails (#199)
Co-authored-by: Kaan Uzdoğan <[email protected]> Co-authored-by: Rosco Kalis <[email protected]>
1 parent 33c7655 commit 2d6a4ef

File tree

5 files changed

+55
-41
lines changed

5 files changed

+55
-41
lines changed

src/constants.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ export const RequestStatus = {
8181
export enum VerificationStatus {
8282
FAILED = 'Fail - Unable to verify',
8383
SUCCESS = 'Pass - Verified',
84+
PARTIAL = 'Pass - Partially Verified (with a metadata mismatch)',
8485
PENDING = 'Pending in queue',
8586
ALREADY_VERIFIED = 'Contract source code already verified',
8687
AUTOMATICALLY_VERIFIED = 'Already Verified',

src/verifier/AbstractVerifier.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,12 @@ export abstract class AbstractVerifier {
88
abstract name: string;
99

1010
abstract getContractUrl(address: string): string | undefined;
11-
abstract verifyContract(artifact: Artifact): Promise<VerificationStatus>;
11+
abstract verifyContract(artifact: Artifact): Promise<string>;
1212
abstract verifyProxyContract(
1313
proxyArtifact: Artifact,
1414
implementationName: string,
1515
implementationAddress: string
16-
): Promise<VerificationStatus>;
16+
): Promise<string>;
1717

1818
logger: Logger;
1919

src/verifier/EtherscanVerifier.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ export class EtherscanVerifier extends AbstractVerifier implements Verifier {
3232
await super.verifyAll(contractNameAddressPairs);
3333
}
3434

35-
async verifyContract(artifact: Artifact): Promise<VerificationStatus> {
35+
async verifyContract(artifact: Artifact): Promise<string> {
3636
this.checkBoundaries();
3737

3838
const res = await this.sendVerifyRequest(artifact);

src/verifier/SourcifyVerifier.ts

Lines changed: 49 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -22,26 +22,65 @@ export class SourcifyVerifier extends AbstractVerifier implements Verifier {
2222
await super.verifyAll(contractNameAddressPairs);
2323
}
2424

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

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

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

33-
if (contract.storageTimestamp) {
34-
return VerificationStatus.ALREADY_VERIFIED;
35-
}
38+
const postQueries = {
39+
address: artifact.networks[`${this.options.networkId}`].address,
40+
chain: `${this.options.chainId}`,
41+
files,
42+
};
43+
44+
try {
45+
this.logger.debug('Sending verify request with POST arguments:');
46+
logObject(this.logger, 'debug', postQueries, 2);
47+
const res = await axios.post(SOURCIFY_API_URL, postQueries);
48+
49+
const [result] = res?.data?.result ?? [];
50+
this.logger.debug('Received response:');
51+
logObject(this.logger, 'debug', result, 2);
52+
53+
if (!result) {
54+
// If no result was returned, there is likely an issue with the API connection
55+
throw new Error(`Could not connect to Sourcify API at url ${SOURCIFY_API_URL}`);
56+
}
57+
58+
if (result.storageTimestamp) return VerificationStatus.ALREADY_VERIFIED;
59+
if (result.status === 'partial') return VerificationStatus.PARTIAL;
60+
if (result.status === 'perfect') return VerificationStatus.SUCCESS;
61+
return `${VerificationStatus.FAILED}: ${result?.message}`
62+
} catch (error: any) {
63+
const errorResponse = error?.response?.data;
64+
const errorResponseMessage = errorResponse?.message ?? errorResponse?.error;
65+
66+
this.logger.debug(`Error: ${error?.message}`);
67+
logObject(this.logger, 'debug', error?.response?.data, 2)
68+
69+
// If an error message is present in the checked response, this likely indicates a failed verification
70+
if (errorResponseMessage) {
71+
return `${VerificationStatus.FAILED}: ${errorResponseMessage}`
72+
}
3673

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

4079
async verifyProxyContract(
4180
proxyArtifact: Artifact,
4281
implementationName: string,
4382
implementationAddress: string
44-
): Promise<VerificationStatus> {
83+
): Promise<string> {
4584
await this.checkBoundaries();
4685

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

66-
private async sendVerifyRequest(artifact: Artifact) {
67-
const inputJSON = await getInputJSON(artifact, this.options, this.logger);
68-
69-
const files: { [path: string]: string } = {};
70-
Object.keys(inputJSON.sources).forEach((path) => {
71-
files[path.replace(/^.*[\\/]/, '')] = inputJSON.sources[path].content;
72-
});
73-
files['metadata.json'] = JSON.stringify(JSON.parse(artifact.metadata));
74-
75-
const postQueries = {
76-
address: artifact.networks[`${this.options.networkId}`].address,
77-
chain: `${this.options.chainId}`,
78-
files,
79-
};
80-
81-
try {
82-
this.logger.debug('Sending verify request with POST arguments:');
83-
logObject(this.logger, 'debug', postQueries, 2);
84-
return await axios.post(SOURCIFY_API_URL, postQueries);
85-
} catch (error: any) {
86-
this.logger.debug(error.message);
87-
this.logger.debug(error.response.data.message);
88-
throw new Error(`Failed to connect to Sourcify API at url ${SOURCIFY_API_URL}`);
89-
}
90-
}
91-
92105
private async checkBoundaries() {
93106
enforceOrThrow(
94107
await this.isSupportedChain(this.options.chainId),
@@ -103,7 +116,7 @@ export class SourcifyVerifier extends AbstractVerifier implements Verifier {
103116

104117
private async getSupportedChains() {
105118
if (this.supportedChainIds) return this.supportedChainIds;
106-
const chainsUrl = `${SOURCIFY_API_URL}chains`
119+
const chainsUrl = `${SOURCIFY_API_URL}chains`;
107120

108121
try {
109122
this.logger.debug(`Fetching supported chains from ${chainsUrl}`);

src/verifier/Verifier.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@ export interface Verifier {
55
name: string;
66
options: Options;
77
getContractUrl(address: string): string | undefined;
8-
verifyContract(artifact: Artifact): Promise<VerificationStatus>;
8+
verifyContract(artifact: Artifact): Promise<string>;
99
verifyProxyContract(
1010
proxyArtifact: Artifact,
1111
implementationName: string,
1212
implementationAddress: string
13-
): Promise<VerificationStatus>;
13+
): Promise<string>;
1414
verifyAll(contractNameAddressPairs: string[]): Promise<void>;
1515
}

0 commit comments

Comments
 (0)