Skip to content

Commit

Permalink
fix: get valid minimal context for verification BE request (#1063)
Browse files Browse the repository at this point in the history
* fix: get valid minimal context for verification BE request

---------

Co-authored-by: Marko Arambasic <[email protected]>
  • Loading branch information
kiriyaga-txfusion and kiriyaga authored May 14, 2024
1 parent 8ed148f commit 0cf6e79
Show file tree
Hide file tree
Showing 5 changed files with 141 additions and 30 deletions.
4 changes: 4 additions & 0 deletions packages/hardhat-zksync-verify/src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,4 +122,8 @@ export const COMPILATION_ERRORS = [
error: 'MissingContract',
pattern: /^Backend verification error: Contract with .* name is missing in sources$/,
},
{
error: 'DeployedBytecodeMismatch',
pattern: /^Backend verification error: Deployed bytecode is not equal to generated one from given source$/,
},
];
26 changes: 24 additions & 2 deletions packages/hardhat-zksync-verify/src/plugin.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
import { TASK_FLATTEN_GET_FLATTENED_SOURCE } from 'hardhat/builtin-tasks/task-names';
import { Artifacts, CompilerInput, HardhatRuntimeEnvironment, ResolvedFile } from 'hardhat/types';
import {
TASK_COMPILE_SOLIDITY_GET_DEPENDENCY_GRAPH,
TASK_COMPILE_SOLIDITY_GET_SOURCE_NAMES,
TASK_COMPILE_SOLIDITY_GET_SOURCE_PATHS,
TASK_FLATTEN_GET_FLATTENED_SOURCE,
} from 'hardhat/builtin-tasks/task-names';
import { Artifacts, CompilerInput, DependencyGraph, HardhatRuntimeEnvironment, ResolvedFile } from 'hardhat/types';
import { isFullyQualifiedName, parseFullyQualifiedName } from 'hardhat/utils/contract-names';
import path from 'path';
import chalk from 'chalk';
Expand Down Expand Up @@ -69,6 +74,23 @@ Instead, this name was received: ${contractFQN}`,
}
}

export async function getMinimalResolvedFiles(
hre: HardhatRuntimeEnvironment,
sourceName: string,
): Promise<ResolvedFile[]> {
hre.config.zksolc.settings.contractsToCompile = [sourceName];
const sourcePaths = await hre.run(TASK_COMPILE_SOLIDITY_GET_SOURCE_PATHS, { sourcePath: hre.config.paths.sources });
const sourceNames = await hre.run(TASK_COMPILE_SOLIDITY_GET_SOURCE_NAMES, {
rootPath: hre.config.paths.root,
sourcePaths,
});
const dependencyGraph: DependencyGraph = await hre.run(TASK_COMPILE_SOLIDITY_GET_DEPENDENCY_GRAPH, {
sourceNames,
});

return dependencyGraph.getResolvedFiles();
}

export function getSolidityStandardJsonInput(
hre: HardhatRuntimeEnvironment,
resolvedFiles: ResolvedFile[],
Expand Down
17 changes: 9 additions & 8 deletions packages/hardhat-zksync-verify/src/task-actions.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import { DependencyGraph, HardhatRuntimeEnvironment, RunSuperFunction, TaskArguments } from 'hardhat/types';
import { HardhatRuntimeEnvironment, RunSuperFunction, TaskArguments } from 'hardhat/types';

import { parseFullyQualifiedName } from 'hardhat/utils/contract-names';
import chalk from 'chalk';
import path from 'path';
import { TASK_COMPILE_SOLIDITY_GET_DEPENDENCY_GRAPH } from 'hardhat/builtin-tasks/task-names';
import { getSupportedCompilerVersions, verifyContractRequest } from './zksync-block-explorer/service';

import {
Expand Down Expand Up @@ -33,7 +32,13 @@ import { ZkSyncVerifyPluginError } from './errors';
import { Bytecode, extractMatchingContractInformation } from './solc/bytecode';

import { ContractInformation } from './solc/types';
import { checkContractName, getLibraries, getSolidityStandardJsonInput, inferContractArtifacts } from './plugin';
import {
checkContractName,
getLibraries,
getMinimalResolvedFiles,
getSolidityStandardJsonInput,
inferContractArtifacts,
} from './plugin';
import {
SolcMultiUserConfigExtractor,
SolcSoloUserConfigExtractor,
Expand Down Expand Up @@ -203,15 +208,11 @@ export async function verifyContract(

contractInformation.contractName = `${contractInformation.sourceName}:${contractInformation.contractName}`;

const dependencyGraph: DependencyGraph = await hre.run(TASK_COMPILE_SOLIDITY_GET_DEPENDENCY_GRAPH, {
sourceNames: [contractInformation.sourceName],
});

const request = {
contractAddress: address,
sourceCode: getSolidityStandardJsonInput(
hre,
dependencyGraph.getResolvedFiles(),
await getMinimalResolvedFiles(hre, contractInformation.sourceName),
contractInformation.compilerInput,
),
codeFormat: JSON_INPUT_CODE_FORMAT,
Expand Down
15 changes: 13 additions & 2 deletions packages/hardhat-zksync-verify/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,20 @@ export async function encodeArguments(abi: any, constructorArgs: any[]) {
return deployArgumentsEncoded;
}

export function nextAttemptDelay(currentAttempt: number, baseDelay: number, baseNumberOfAttempts: number): number {
if (currentAttempt < baseNumberOfAttempts) {
return baseDelay;
}

return baseDelay * 2 ** (currentAttempt - baseNumberOfAttempts);
}

export async function executeVeificationWithRetry(
requestId: number,
verifyURL: string,
maxRetries = 5,
delayInMs = 1500,
maxRetries = 11,
baseRetries = 5,
baseDelayInMs = 2000,
): Promise<VerificationStatusResponse | undefined> {
let retries = 0;

Expand All @@ -63,6 +72,8 @@ export async function executeVeificationWithRetry(
console.info(chalk.cyan(PENDING_CONTRACT_INFORMATION_MESSAGE(requestId)));
return;
}

const delayInMs = nextAttemptDelay(retries, baseDelayInMs, baseRetries);
await delay(delayInMs);
}
}
Expand Down
109 changes: 91 additions & 18 deletions packages/hardhat-zksync-verify/test/tests/task-actions.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
import { expect } from 'chai';
import sinon from 'sinon';
import { fail } from 'assert';
import { TASK_COMPILE, TASK_COMPILE_SOLIDITY_GET_DEPENDENCY_GRAPH } from 'hardhat/builtin-tasks/task-names';
import {
TASK_COMPILE,
TASK_COMPILE_SOLIDITY_GET_DEPENDENCY_GRAPH,
TASK_COMPILE_SOLIDITY_GET_SOURCE_NAMES,
TASK_COMPILE_SOLIDITY_GET_SOURCE_PATHS,
} from 'hardhat/builtin-tasks/task-names';
import {
getCompilerVersions,
getConstructorArguments,
Expand Down Expand Up @@ -121,6 +126,17 @@ describe('verifyContract', async function () {

const runSuperStub = sinon.stub().resolves(0);
const hre = {
config: {
paths: {
sources: 'contracts',
root: 'root',
},
zksolc: {
settings: {
contractsToCompile: [],
},
},
},
network: {
config: {
url: 'http://localhost:3000',
Expand Down Expand Up @@ -178,6 +194,10 @@ describe('verifyContract', async function () {
solcVersion: '0.8.0',
})
.onCall(3)
.resolves(['contracts/'])
.onCall(4)
.resolves(['contracts/Contract.sol'])
.onCall(5)
.resolves({
getResolvedFiles: sinon.stub().resolves(),
}),
Expand All @@ -188,8 +208,10 @@ describe('verifyContract', async function () {
expect(hre.run.firstCall.args[0]).to.equal(TASK_VERIFY_GET_COMPILER_VERSIONS);
expect(hre.run.secondCall.args[0]).to.equal(TASK_COMPILE);
expect(hre.run.thirdCall.args[0]).to.equal(TASK_VERIFY_GET_CONTRACT_INFORMATION);
expect(hre.run.getCall(3).args[0]).to.equal(TASK_COMPILE_SOLIDITY_GET_DEPENDENCY_GRAPH);
expect(hre.run.getCall(4).args[0]).to.equal(TASK_CHECK_VERIFICATION_STATUS);
expect(hre.run.getCall(3).args[0]).to.equal(TASK_COMPILE_SOLIDITY_GET_SOURCE_PATHS);
expect(hre.run.getCall(4).args[0]).to.equal(TASK_COMPILE_SOLIDITY_GET_SOURCE_NAMES);
expect(hre.run.getCall(5).args[0]).to.equal(TASK_COMPILE_SOLIDITY_GET_DEPENDENCY_GRAPH);
expect(hre.run.getCall(6).args[0]).to.equal(TASK_CHECK_VERIFICATION_STATUS);
});

it('should call fallback request sent if there is compilation error', async function () {
Expand All @@ -209,6 +231,17 @@ describe('verifyContract', async function () {

const runSuperStub = sinon.stub().resolves(0);
const hre = {
config: {
paths: {
sources: 'contracts',
root: 'root',
},
zksolc: {
settings: {
contractsToCompile: [],
},
},
},
network: {
config: {
url: 'http://localhost:3000',
Expand Down Expand Up @@ -266,12 +299,16 @@ describe('verifyContract', async function () {
solcVersion: '0.8.0',
})
.onCall(3)
.resolves(['contracts/'])
.onCall(4)
.resolves(['contracts/Contract.sol'])
.onCall(5)
.resolves({
getResolvedFiles: sinon.stub().resolves(),
})
.onCall(4)
.onCall(6)
.throwsException(new ZkSyncVerifyPluginError(errorMessage))
.onCall(5)
.onCall(7)
.resolves(true),
};

Expand All @@ -280,9 +317,11 @@ describe('verifyContract', async function () {
expect(hre.run.firstCall.args[0]).to.equal(TASK_VERIFY_GET_COMPILER_VERSIONS);
expect(hre.run.secondCall.args[0]).to.equal(TASK_COMPILE);
expect(hre.run.thirdCall.args[0]).to.equal(TASK_VERIFY_GET_CONTRACT_INFORMATION);
expect(hre.run.getCall(3).args[0]).to.equal(TASK_COMPILE_SOLIDITY_GET_DEPENDENCY_GRAPH);
expect(hre.run.getCall(4).args[0]).to.equal(TASK_CHECK_VERIFICATION_STATUS);
expect(hre.run.getCall(5).args[0]).to.equal(TASK_CHECK_VERIFICATION_STATUS);
expect(hre.run.getCall(3).args[0]).to.equal(TASK_COMPILE_SOLIDITY_GET_SOURCE_PATHS);
expect(hre.run.getCall(4).args[0]).to.equal(TASK_COMPILE_SOLIDITY_GET_SOURCE_NAMES);
expect(hre.run.getCall(5).args[0]).to.equal(TASK_COMPILE_SOLIDITY_GET_DEPENDENCY_GRAPH);
expect(hre.run.getCall(6).args[0]).to.equal(TASK_CHECK_VERIFICATION_STATUS);
expect(hre.run.getCall(7).args[0]).to.equal(TASK_CHECK_VERIFICATION_STATUS);
});

it('should call fallback request sent if there is missing source file', async function () {
Expand All @@ -301,6 +340,17 @@ describe('verifyContract', async function () {

const runSuperStub = sinon.stub().resolves(0);
const hre = {
config: {
paths: {
sources: 'contracts',
root: 'root',
},
zksolc: {
settings: {
contractsToCompile: [],
},
},
},
network: {
config: {
url: 'http://localhost:3000',
Expand Down Expand Up @@ -358,12 +408,16 @@ describe('verifyContract', async function () {
solcVersion: '0.8.0',
})
.onCall(3)
.resolves(['contracts/'])
.onCall(4)
.resolves(['contracts/Contract.sol'])
.onCall(5)
.resolves({
getResolvedFiles: sinon.stub().resolves(),
})
.onCall(4)
.onCall(6)
.throwsException(new ZkSyncVerifyPluginError(errorMessage))
.onCall(5)
.onCall(7)
.resolves(true),
};

Expand All @@ -372,9 +426,11 @@ describe('verifyContract', async function () {
expect(hre.run.firstCall.args[0]).to.equal(TASK_VERIFY_GET_COMPILER_VERSIONS);
expect(hre.run.secondCall.args[0]).to.equal(TASK_COMPILE);
expect(hre.run.thirdCall.args[0]).to.equal(TASK_VERIFY_GET_CONTRACT_INFORMATION);
expect(hre.run.getCall(3).args[0]).to.equal(TASK_COMPILE_SOLIDITY_GET_DEPENDENCY_GRAPH);
expect(hre.run.getCall(4).args[0]).to.equal(TASK_CHECK_VERIFICATION_STATUS);
expect(hre.run.getCall(5).args[0]).to.equal(TASK_CHECK_VERIFICATION_STATUS);
expect(hre.run.getCall(3).args[0]).to.equal(TASK_COMPILE_SOLIDITY_GET_SOURCE_PATHS);
expect(hre.run.getCall(4).args[0]).to.equal(TASK_COMPILE_SOLIDITY_GET_SOURCE_NAMES);
expect(hre.run.getCall(5).args[0]).to.equal(TASK_COMPILE_SOLIDITY_GET_DEPENDENCY_GRAPH);
expect(hre.run.getCall(6).args[0]).to.equal(TASK_CHECK_VERIFICATION_STATUS);
expect(hre.run.getCall(7).args[0]).to.equal(TASK_CHECK_VERIFICATION_STATUS);
});

it('should call fallback request sent if there is missing contract file', async function () {
Expand All @@ -394,6 +450,17 @@ describe('verifyContract', async function () {

const runSuperStub = sinon.stub().resolves(0);
const hre = {
config: {
paths: {
sources: 'contracts',
root: 'root',
},
zksolc: {
settings: {
contractsToCompile: [],
},
},
},
network: {
config: {
url: 'http://localhost:3000',
Expand Down Expand Up @@ -451,12 +518,16 @@ describe('verifyContract', async function () {
solcVersion: '0.8.0',
})
.onCall(3)
.resolves(['contracts/'])
.onCall(4)
.resolves(['contracts/Contract.sol'])
.onCall(5)
.resolves({
getResolvedFiles: sinon.stub().resolves(),
})
.onCall(4)
.onCall(6)
.throwsException(new ZkSyncVerifyPluginError(errorMessage))
.onCall(5)
.onCall(7)
.resolves(true),
};

Expand All @@ -466,9 +537,11 @@ describe('verifyContract', async function () {
expect(hre.run.firstCall.args[0]).to.equal(TASK_VERIFY_GET_COMPILER_VERSIONS);
expect(hre.run.secondCall.args[0]).to.equal(TASK_COMPILE);
expect(hre.run.thirdCall.args[0]).to.equal(TASK_VERIFY_GET_CONTRACT_INFORMATION);
expect(hre.run.getCall(3).args[0]).to.equal(TASK_COMPILE_SOLIDITY_GET_DEPENDENCY_GRAPH);
expect(hre.run.getCall(4).args[0]).to.equal(TASK_CHECK_VERIFICATION_STATUS);
expect(hre.run.getCall(5).args[0]).to.equal(TASK_CHECK_VERIFICATION_STATUS);
expect(hre.run.getCall(3).args[0]).to.equal(TASK_COMPILE_SOLIDITY_GET_SOURCE_PATHS);
expect(hre.run.getCall(4).args[0]).to.equal(TASK_COMPILE_SOLIDITY_GET_SOURCE_NAMES);
expect(hre.run.getCall(5).args[0]).to.equal(TASK_COMPILE_SOLIDITY_GET_DEPENDENCY_GRAPH);
expect(hre.run.getCall(6).args[0]).to.equal(TASK_CHECK_VERIFICATION_STATUS);
expect(hre.run.getCall(7).args[0]).to.equal(TASK_CHECK_VERIFICATION_STATUS);
});
});
describe('getCompilerVersions', async function () {
Expand Down

0 comments on commit 0cf6e79

Please sign in to comment.