Skip to content

Commit

Permalink
feat: replacing the toolbox plugin with hardhat-zksync and introducin… (
Browse files Browse the repository at this point in the history
#970)

* feat: replacing the toolbox plugin with Hardhat-ZKSync and introducing new tasks for deploying, upgrading and verifying contracts

* fix: update tests to work

* fix: add initializer function as option, update readme and fix address for ethers-v5

* Revert "fix: add initializer function as option, update readme and fix address for ethers-v5"

This reverts commit b9cd5c6.

* fix: add initializer function as option, update readme and fix address for ethers-v5

* fix: rename task names, change readme files and update tasks with deployment type

* chore: update readme files

* fix: mock setDeploymentType function inside deployer

* fix: update task arguments

* fix: remove chai-matchers from the plugin list

* fix: dont compile when verify contracts

* chore: update readme files

* chore: update readme files

---------

Co-authored-by: Marko Arambasic <makiarambasic@gmail.com>
  • Loading branch information
kiriyaga-txfusion and kiriyaga authored Apr 3, 2024
1 parent 87504e8 commit 286c50d
Show file tree
Hide file tree
Showing 48 changed files with 1,593 additions and 232 deletions.
4 changes: 2 additions & 2 deletions .github/release-please/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@
"release-type": "node",
"component": "@matterlabs/hardhat-zksync-verify"
},
"packages/hardhat-zksync-toolbox": {
"packages/hardhat-zksync": {
"release-type": "node",
"component": "@matterlabs/hardhat-zksync-toolbox"
"component": "@matterlabs/hardhat-zksync"
},
"packages/hardhat-zksync-node": {
"release-type": "node",
Expand Down
2 changes: 1 addition & 1 deletion .github/release-please/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"packages/hardhat-zksync-deploy": "0.8.0",
"packages/hardhat-zksync-upgradable": "0.3.1",
"packages/hardhat-zksync-verify": "0.5.1",
"packages/hardhat-zksync-toolbox": "0.4.1",
"packages/hardhat-zksync": "0.0.1",
"packages/hardhat-zksync-node": "0.1.0",
"packages/hardhat-zksync-chai-matchers": "0.3.0"
}
2 changes: 1 addition & 1 deletion .github/workflows/npm-publish.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ on:
- hardhat-zksync-deploy
- hardhat-zksync-upgradable
- hardhat-zksync-verify
- hardhat-zksync-toolbox
- hardhat-zksync
- hardhat-zksync-node
- hardhat-zksync-chai-matchers

Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ Here is an overview of the plugins currently available:
| hardhat-zksync-verify-vyper | Specialized for automating the verification of Vyper contracts on the zkSync network. |
| hardhat-zksync-vyper | Streamlines the compilation of Vyper contracts for deployment on the zkSync network. |
| hardhat-zksync-chai-matchers | Extends chai with additional matchers, aiding in testing zkSync-specific features more effectively. |
| hardhat-zksync-toolbox | Offers a suite of zkSync-related Hardhat plugins in one package, enhancing accessibility and efficiency. |
| hardhat-zksync | Offers a suite of zkSync-related Hardhat plugins in one package, enhancing accessibility and efficiency. |
| hardhat-zksync-upgradeable | Enables easier deployment and upgrading of smart contracts on the zkSync network, improving contract lifecycle management. |
| hardhat-zksync-node | Convenient plugin to run the zkSync era-test-node locally. |
| hardhat-zksync-ethers | A zksync-ethers SDK wrapper providing additional methods for accelerated development on zkSync. |
Expand All @@ -32,7 +32,7 @@ You can find more detailed explanations on how to use hardhat zkSync plugins on
[hardhat-zksync-verify-vyper](https://era.zksync.io/docs/tools/hardhat/hardhat-zksync-verify-vyper.html)\
[hardhat-zksync-vyper](https://era.zksync.io/docs/tools/hardhat/hardhat-zksync-vyper.html)\
[hardhat-zksync-chai-matchers](https://era.zksync.io/docs/tools/hardhat/hardhat-zksync-chai-matchers.html)\
[hardhat-zksync-toolbox](https://era.zksync.io/docs/tools/hardhat/plugins.html)\
[hardhat-zksync](https://era.zksync.io/docs/tools/hardhat/plugins.html)\
[hardhat-zksync-upgradeable](https://era.zksync.io/docs/tools/hardhat/hardhat-zksync-upgradable.html)\
[hardhat-zksync-node](https://era.zksync.io/docs/tools/hardhat/hardhat-zksync-node.html)\
[hardhat-zksync-ethers](https://era.zksync.io/docs/tools/hardhat/hardhat-zksync-ethers.html)
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@
"wsrun": "^5.2.2"
},
"scripts": {
"build": "tsc --build packages/hardhat-zksync-deploy packages/hardhat-zksync-chai-matchers packages/hardhat-zksync-verify packages/hardhat-zksync-toolbox packages/hardhat-zksync-upgradable packages/hardhat-zksync-verify-vyper packages/hardhat-zksync-node",
"watch": "tsc --build --watch packages/hardhat-zksync-deploy packages/hardhat-zksync-chai-matchers packages/hardhat-zksync-verify packages/hardhat-zksync-toolbox packages/hardhat-zksync-upgradable packages/hardhat-zksync-verify-vyper packages/hardhat-zksync-node",
"build": "tsc --build packages/hardhat-zksync-deploy packages/hardhat-zksync-chai-matchers packages/hardhat-zksync-verify packages/hardhat-zksync-upgradable packages/hardhat-zksync-verify-vyper packages/hardhat-zksync-node packages/hardhat-zksync",
"watch": "tsc --build --watch packages/hardhat-zksync-deploy packages/hardhat-zksync-chai-matchers packages/hardhat-zksync-verify packages/hardhat-zksync-upgradable packages/hardhat-zksync-verify-vyper packages/hardhat-zksync-node packages/hardhat-zksync",
"clean": "wsrun --exclude-missing clean",
"lint": "wsrun --exclude-missing --stages lint",
"lint:fix": "wsrun --exclude-missing --stages lint:fix",
Expand Down
28 changes: 27 additions & 1 deletion packages/hardhat-zksync-deploy/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -452,7 +452,33 @@ To run a specific script, add the `--script` argument, e.g. `yarn hardhat deploy

To run a scripts with specific tags add the `--tags` argument, e.g `yarn hardhat deploy-zksync --tags all`. Run all scripts with tag `all`.

`yarn hardhat deploy-zksync:libraries --private-key-or-index <PRIVATE_KEY_OR_INDEX>` -- compilation and deployment of missing libraries (the list of all missing libraries is provided by the output of [matterlabs/hardhat-zksync-solc](https://www.npmjs.com/package/@matterlabs/hardhat-zksync-solc) plugin). Read more about how zkSync deals with libraries on this [link](https://era.zksync.io/docs/tools/hardhat/compiling-libraries.html).
`yarn hardhat deploy-zksync:libraries` -- compilation and deployment of missing libraries (the list of all missing libraries is provided by the output of [matterlabs/hardhat-zksync-solc](https://www.npmjs.com/package/@matterlabs/hardhat-zksync-solc) plugin). Read more about how zkSync deals with libraries on this [link](https://era.zksync.io/docs/tools/hardhat/compiling-libraries.html).
The account used for deployment will be the one specified by the `deployerAccount` configuration within the `hardhat.config.ts` file. If no such configuration is present, the account with index `0` will be used.

`yarn hardhat deploy-zksync:contract --contract-name <contract name or FQN>`

This command provides an easy and fast way to deploy one contract. If the provided command for deploying a single contract is insufficient and you require additional flexibility, such as incorporating additional dependencies or overrides, it would be advisable to utilize a script-based approach.
When executed, this command deploys the provided contract on the specified network, using the provided contract constructor arguments.

- To provide a contract name or FQN, required argument in the task, add a `--contract-name <contract name or FQN>` argument, e.g. `hardhat deploy-zksync:contract --contract-name SomeContract`.
- To provide a constructor arguments, specify them after a `--contract-name` argument, e.g. `hardhat deploy-zksync:contract --contract-name Greeter 'Hello'`.
- To provide a complex constructor argument list, you can write a separate javascript module to export it and provide module name with `--constructor-args <module name>` argument, e.g.
`hardhat deploy-zksync:contract --contract-name ComplexContract --constructor-args args.js`. Example of `args.js` :
```typescript
module.exports = [
"a string argument",
"0xabcdef",
"42",
{
property1: "one",
property2: 2,
},
];
```
- To allows the task to skip the compilation process, add `--no-compile` argument, e.g. `hardhat deploy-zksync:contract --contract-name Contract --no-compile`.
- To allows the task to specify which deployer smart contract function will be called, add `--deployment-type` argument. Permissible values for this parameter include `create`, `create2`, `createAccount`, and `create2Account`. If this parameter is omitted, the default value assumed will be `create`, e.g. `hardhat deploy-zksync:contract --contract-name Greeter 'Hello' --deployment-type create2`.

The account used for deployment will be the one specified by the `deployerAccount` configuration within the `hardhat.config.ts` file. If no such configuration is present, the account with index `0` will be used.

## 📝 Documentation

Expand Down
9 changes: 9 additions & 0 deletions packages/hardhat-zksync-deploy/src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,12 @@ export const SCRIPT_DEFAULT_PRIORITY = 0;
export const defaultAccountDeployerSettings: DeployerAccount = {
default: 0,
};

export const ENCODED_ARAGUMENTS_NOT_FOUND_ERROR = (constructorArgsModulePath: string) =>
`The module ${constructorArgsModulePath} doesn't export a list and does not start with "0x"\n` +
`Please export a list of constructor arguments or a single string starting with "0x".`;

export const CONSTRUCTOR_MODULE_IMPORTING_ERROR = (
errorMessage: string,
) => `Importing the module for the constructor arguments list failed.
Reason: ${errorMessage}`;
23 changes: 20 additions & 3 deletions packages/hardhat-zksync-deploy/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { extendConfig, extendEnvironment, task } from 'hardhat/config';
import { extendConfig, extendEnvironment, task, types } from 'hardhat/config';
import { HardhatRuntimeEnvironment } from 'hardhat/types';

import { string } from 'hardhat/internal/core/params/argumentTypes';
import { TASK_DEPLOY_ZKSYNC, TASK_DEPLOY_ZKSYNC_LIBRARIES } from './task-names';
import { TASK_DEPLOY_ZKSYNC, TASK_DEPLOY_ZKSYNC_CONTRACT, TASK_DEPLOY_ZKSYNC_LIBRARIES } from './task-names';
import './type-extensions';
import { zkSyncDeploy, zkSyncLibraryDeploy } from './task-actions';
import { deployZkSyncContract, zkSyncDeploy, zkSyncLibraryDeploy } from './task-actions';
import { DEFAULT_DEPLOY_SCRIPTS_PATH, defaultAccountDeployerSettings } from './constants';
import { DeployerExtension } from './deployer-extension';

Expand Down Expand Up @@ -53,3 +53,20 @@ task(TASK_DEPLOY_ZKSYNC_LIBRARIES, 'Runs the library deploy for zkSync network')
.addFlag('noAutoPopulateConfig', 'Flag to disable auto population of config file')
.addFlag('compileAllContracts', 'Flag to compile all contracts at the end of the process')
.setAction(zkSyncLibraryDeploy);

task(TASK_DEPLOY_ZKSYNC_CONTRACT, 'Runs the deploy scripts for zkSync network')
.addParam('contractName', 'A contract name or a FQN', '')
.addOptionalVariadicPositionalParam(
'constructorArgsParams',
'Contract constructor arguments. Cannot be used if the --constructor-args option is provided',
[],
)
.addOptionalParam(
'constructorArgs',
'Path to a Javascript module that exports the constructor arguments',
undefined,
types.inputFile,
)
.addOptionalParam('deploymentType', 'Type of deployment', undefined)
.addFlag('noCompile', 'Flag to disable auto compilation')
.setAction(deployZkSyncContract);
30 changes: 29 additions & 1 deletion packages/hardhat-zksync-deploy/src/plugin.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
import { HardhatRuntimeEnvironment } from 'hardhat/types';

import chalk from 'chalk';
import { Wallet } from 'zksync-ethers';
import { Contract, Wallet } from 'zksync-ethers';
import { TASK_COMPILE } from 'hardhat/builtin-tasks/task-names';
import { DeploymentType } from 'zksync-ethers/build/src/types';
import { ZkSyncDeployPluginError } from './errors';
import { Deployer } from './deployer';
import { ContractFullQualifiedName, ContractInfo, MissingLibrary } from './types';
import {
compileContracts,
fillLibrarySettings,
generateFullQuailfiedNameString,
getConstructorArguments,
getLibraryInfos,
getWalletsFromAccount,
isNumber,
Expand Down Expand Up @@ -176,3 +179,28 @@ export function getNetworkAccount(hre: HardhatRuntimeEnvironment): number {
const networkName = hre.network.name;
return hre.config.deployerAccounts[networkName] ?? hre.config.deployerAccounts.default ?? 0;
}

export async function deployContract(
hre: HardhatRuntimeEnvironment,
taskArgs: {
contractName: string;
constructorArgsParams: any[];
constructorArgs?: string;
deploymentType?: DeploymentType;
noCompile?: boolean;
},
): Promise<Contract> {
if (!taskArgs.noCompile) {
await hre.run(TASK_COMPILE);
}

const constructorArguments: any[] = await getConstructorArguments(
taskArgs.constructorArgsParams,
taskArgs.constructorArgs,
);

hre.deployer.setDeploymentType(taskArgs.deploymentType ?? 'create');
const contract: Contract = await hre.deployer.deploy(taskArgs.contractName, constructorArguments);
console.log(chalk.green(`Contract ${taskArgs.contractName} deployed at ${contract.address}`));
return contract;
}
7 changes: 6 additions & 1 deletion packages/hardhat-zksync-deploy/src/task-actions.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { HardhatRuntimeEnvironment, TaskArguments } from 'hardhat/types';
import { deployLibraries } from './plugin';
import { Contract } from 'zksync-ethers';
import { deployContract, deployLibraries } from './plugin';
import { ScriptManager } from './script-manager';

export async function zkSyncDeploy(taskArgs: TaskArguments, hre: HardhatRuntimeEnvironment) {
Expand All @@ -23,3 +24,7 @@ export async function zkSyncLibraryDeploy(taskArgs: TaskArguments, hre: HardhatR
taskArgs.compileAllContracts,
);
}

export async function deployZkSyncContract(taskArgs: TaskArguments, hre: HardhatRuntimeEnvironment): Promise<Contract> {
return await deployContract(hre, taskArgs);
}
1 change: 1 addition & 0 deletions packages/hardhat-zksync-deploy/src/task-names.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export const TASK_DEPLOY_ZKSYNC = 'deploy-zksync';
export const TASK_DEPLOY_ZKSYNC_LIBRARIES = 'deploy-zksync:libraries';
export const TASK_DEPLOY_ZKSYNC_CONTRACT = 'deploy-zksync:contract';
33 changes: 31 additions & 2 deletions packages/hardhat-zksync-deploy/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,14 @@ import {
HttpNetworkConfig,
NetworkConfig,
} from 'hardhat/types';
import { TASK_COMPILE } from 'hardhat/builtin-tasks/task-names';
import fs from 'fs';
import { Wallet } from 'zksync-ethers';
import path from 'path';
import { ContractFullQualifiedName, ContractInfo, MissingLibrary } from './types';
import { MorphTsBuilder } from './morph-ts-builder';
import { ZkSyncDeployPluginError } from './errors';
import { LOCAL_CHAIN_IDS } from './constants';
import { CONSTRUCTOR_MODULE_IMPORTING_ERROR, ENCODED_ARAGUMENTS_NOT_FOUND_ERROR, LOCAL_CHAIN_IDS } from './constants';
import { richWallets } from './rich-wallets';

export function isHttpNetworkConfig(networkConfig: NetworkConfig): networkConfig is HttpNetworkConfig {
Expand Down Expand Up @@ -91,7 +93,7 @@ export function removeLibraryInfoFile(hre: HardhatRuntimeEnvironment) {
export async function compileContracts(hre: HardhatRuntimeEnvironment, contracts: string[]) {
hre.config.zksolc.settings.contractsToCompile = contracts;

await hre.run('compile', { force: true });
await hre.run(TASK_COMPILE, { force: true });
}

function isHardhatNetworkHDAccountsConfig(object: any): object is HardhatNetworkHDAccountsConfig {
Expand Down Expand Up @@ -150,3 +152,30 @@ export async function retrieveContractBytecode(
}
return bytecodeString;
}

export async function getConstructorArguments(
constructorArgsParams: any[],
constructorArgsModule?: string,
): Promise<any> {
if (typeof constructorArgsModule !== 'string') {
return constructorArgsParams;
}

const constructorArgsModulePath = path.resolve(process.cwd(), constructorArgsModule);

try {
const constructorArguments = await extractModule(constructorArgsModulePath);

if (!Array.isArray(constructorArguments) && !constructorArguments.startsWith('0x')) {
throw new ZkSyncDeployPluginError(ENCODED_ARAGUMENTS_NOT_FOUND_ERROR(constructorArgsModulePath));
}
return constructorArguments;
} catch (error: any) {
throw new ZkSyncDeployPluginError(CONSTRUCTOR_MODULE_IMPORTING_ERROR(error.message), error);
}
}

export async function extractModule(constructorArgsModulePath: string) {
const constructorArguments = (await import(constructorArgsModulePath)).default;
return constructorArguments;
}
58 changes: 58 additions & 0 deletions packages/hardhat-zksync-deploy/test/tests/plugin.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import * as chai from 'chai';
import sinon from 'sinon';
import { HardhatRuntimeEnvironment } from 'hardhat/types';
import { expect } from 'chai';
import sinonChai from 'sinon-chai';
import { deployContract } from '../../src/plugin';

chai.use(sinonChai);

describe('deployWithContract', () => {
const sandbox = sinon.createSandbox();
let hre: HardhatRuntimeEnvironment;
const artifact = {
sourceName: 'contracts/MyContract.sol',
contractName: 'MyContract',
};

beforeEach(() => {
hre = {
deployer: {
loadArtifact: sandbox.stub().resolves(artifact),
deploy: sandbox.stub().resolves({
getAddress: async () => '0x1234567890123456789012345678901234567890',
abi: [],
}),
setDeploymentType: sandbox.stub().resolves(),
},
run: sandbox.stub(),
} as any;
});

afterEach(() => {
sandbox.restore();
});

const taskArgs = {
contractName: 'MyContract',
constructorArgsParams: [],
constructorArgs: undefined,
noCompile: false,
};

it('should deploy the contract with compile', async () => {
await deployContract(hre, taskArgs);

expect(hre.deployer.deploy).to.have.been.callCount(1);
expect(hre.deployer.setDeploymentType).to.have.been.callCount(1);
expect(hre.run).to.have.been.callCount(1);
});

it('should deploy the contract without compile', async () => {
taskArgs.noCompile = true;
await deployContract(hre, taskArgs);
expect(hre.run).to.have.been.callCount(0);
expect(hre.deployer.deploy).to.have.been.callCount(1);
expect(hre.deployer.setDeploymentType).to.have.been.callCount(1);
});
});
46 changes: 0 additions & 46 deletions packages/hardhat-zksync-toolbox/README.md

This file was deleted.

7 changes: 0 additions & 7 deletions packages/hardhat-zksync-toolbox/src/index.ts

This file was deleted.

Loading

0 comments on commit 286c50d

Please sign in to comment.