Skip to content

Commit

Permalink
feat: introducing ethers extension in hre (#1283)
Browse files Browse the repository at this point in the history
* feat: introducing ethers extension in hre

* fix: replace ...args with typed arguments and fix logic for providing signer accounts

* fix: replace test signer address

* fix: update zksync-ethers version, refactor code and fix signer to support impersonated signers

* fix: implement signing methods for both impersionated and normal accounts

---------

Co-authored-by: Marko Arambasic <[email protected]>
  • Loading branch information
kiriyaga-txfusion and kiriyaga authored Sep 16, 2024
1 parent 187722e commit 8e471bc
Show file tree
Hide file tree
Showing 29 changed files with 1,227 additions and 285 deletions.
2 changes: 1 addition & 1 deletion examples/basic-example/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
"chalk": "^4.1.2",
"hardhat": "^2.22.5",
"ethers": "^6.12.2",
"zksync-ethers": "^6.8.0",
"zksync-ethers": "^6.11.2",
"@matterlabs/zksync-contracts": "^0.6.1",
"@openzeppelin/contracts": "^4.9.2",
"@openzeppelin/contracts-upgradeable": "^4.9.2"
Expand Down
2 changes: 1 addition & 1 deletion examples/deploy-example/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
"chalk": "^4.1.2",
"hardhat": "^2.22.5",
"ethers": "^6.12.2",
"zksync-ethers": "^6.8.0"
"zksync-ethers": "^6.11.2"
},
"prettier": {
"tabWidth": 4,
Expand Down
2 changes: 1 addition & 1 deletion examples/download-with-compiler-origin/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
"chalk": "^4.1.2",
"hardhat": "^2.22.5",
"ethers": "^6.12.2",
"zksync-ethers": "^6.8.0"
"zksync-ethers": "^6.11.2"
},
"prettier": {
"tabWidth": 4,
Expand Down
2 changes: 1 addition & 1 deletion examples/node-example/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
"chalk": "^4.1.2",
"hardhat": "^2.22.5",
"ethers": "^6.12.2",
"zksync-ethers": "^6.8.0",
"zksync-ethers": "^6.11.2",
"@matterlabs/zksync-contracts": "^0.6.1",
"@openzeppelin/contracts": "^4.9.2",
"@openzeppelin/contracts-upgradeable": "^4.9.2"
Expand Down
2 changes: 1 addition & 1 deletion examples/noninline-libraries-example/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
"chalk": "^4.1.2",
"hardhat": "^2.22.5",
"ethers": "^6.12.2",
"zksync-ethers": "^6.8.0",
"zksync-ethers": "^6.11.2",
"@matterlabs/zksync-contracts": "^0.6.1",
"@openzeppelin/contracts": "^4.9.2",
"@openzeppelin/contracts-upgradeable": "^4.9.2"
Expand Down
2 changes: 1 addition & 1 deletion examples/upgradable-example/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
},
"dependencies": {
"ethers": "^6.12.2",
"zksync-ethers": "^6.8.0",
"zksync-ethers": "^6.11.2",
"hardhat": "^2.22.5",
"@matterlabs/hardhat-zksync-deploy": "workspace:^",
"@matterlabs/hardhat-zksync-solc": "workspace:^",
Expand Down
2 changes: 1 addition & 1 deletion examples/verify-example/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
"chalk": "^4.1.2",
"hardhat": "^2.22.5",
"ethers": "^6.12.2",
"zksync-ethers": "^6.8.0"
"zksync-ethers": "^6.11.2"
},
"prettier": {
"tabWidth": 4,
Expand Down
2 changes: 1 addition & 1 deletion examples/vyper-example/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
"@nomiclabs/hardhat-vyper": "^3.0.5",
"chalk": "^4.1.2",
"ethers": "^6.12.2",
"zksync-ethers": "^6.8.0"
"zksync-ethers": "^6.11.2"
},
"prettier": {
"tabWidth": 4,
Expand Down
102 changes: 102 additions & 0 deletions examples/zksync-ethers-example/deploy/002_deploy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
import { HardhatRuntimeEnvironment } from 'hardhat/types';
import chalk from 'chalk';
import { Signer } from 'ethers';

export default async function (hre: HardhatRuntimeEnvironment) {
console.info(chalk.yellow(`Running deploy script 002_deploy.ts`));

//Deploy Greeter contract with provided signer and name
const signer = await hre.ethers.getSigner('0x36615Cf349d7F6344891B1e7CA7C72883F5dc049');
const greets = await hre.ethers.deployContract('Greeter', ['Hello, world with loadArtifact!'], signer);
await greets.waitForDeployment();
const greetsRunner = greets.runner as Signer;
console.info(chalk.green(`Greeter deployed to: ${await greets.getAddress()}`));
console.info(chalk.green(`Greeter greeting set to: ${await greets.greet()}`));
const tx1 = await greets.setGreeting('Hello, world again with loadArtifact!');
await tx1.wait();
console.info(chalk.green(`Greeter greeting set to: ${await greets.greet()}`));
console.info(chalk.green(`Greeter greeting set to: ${await greetsRunner.getAddress()}`));

console.log('----------------------------------')

console.log('Greeter contract deployed with name factory');
const greeterFactory1 = await hre.ethers.getContractFactory('Greeter', signer,);
const greets2 = await greeterFactory1.deploy('Hello, world with name!');
await greets2.waitForDeployment();
const greets2Runner = greets2.runner as Signer;
console.info(chalk.green(`Greeter deployed to: ${await greets2.getAddress()}`));
console.info(chalk.green(`Greeter greeting set to: ${await greets2.greet()}`));
console.info(chalk.green(`Greeter greeting set to: ${await greets2Runner.getAddress()}`));

console.log('----------------------------------')

console.log('Greeter contract deployed with abi and bytecode');
const artifact = await hre.artifacts.readArtifact('Greeter');
const greeterFactory2 = await hre.ethers.getContractFactory(artifact.abi, artifact.bytecode);
const greets3 = await greeterFactory2.deploy('Hello, world with abi and bytecode!');
await greets3.waitForDeployment();
const greets3Runner = greets3.runner as Signer;
console.info(chalk.green(`Greeter deployed to: ${await greets3.getAddress()}`));
console.info(chalk.green(`Greeter greeting set to: ${await greets3.greet()}`));
const tx = await greets3.setGreeting('Hello, world again with abi and bytecode!');
await tx.wait();
console.info(chalk.green(`Greeter greeting set to: ${await greets3.greet()}`));
console.info(chalk.green(`Greeter greeting set to: ${await greets3Runner.getAddress()}`));

console.log('----------------------------------')

console.log('Greeter contract deployed with artifact');
const greeterFactory3 = await hre.ethers.getContractFactoryFromArtifact(artifact);
const greets4 = await greeterFactory3.deploy('Hello, world with artifact!');
await greets4.waitForDeployment();
const greets4Runner = greets4.runner as Signer;
console.info(chalk.green(`Greeter deployed to: ${await greets4.getAddress()}`));
console.info(chalk.green(`Greeter greeting set to: ${await greets4.greet()}`));
const tx2 = await greets4.setGreeting('Hello, world again with artifact!');
await tx2.wait();
console.info(chalk.green(`Greeter greeting set to: ${await greets4.greet()}`));
console.info(chalk.green(`Greeter greeting set to: ${await greets4Runner.getAddress()}`));

console.log('----------------------------------')

console.log('Greeter contract deployed with factory and signer2');
const [,,signer2] = await hre.ethers.getSigners();
const greeterFactory4 = await hre.ethers.getContractFactory(
'Greeter',
signer2
);
const greets5 = await greeterFactory4.deploy('Hello, world with name!');
await greets5.waitForDeployment();
const greets5Runner = greets5.runner as Signer;
console.info(chalk.green(`Greeter deployed to: ${await greets5.getAddress()}`));
console.info(chalk.green(`Greeter greeting set to: ${await greets5.greet()}`));
const tx3 = await greets5.setGreeting('Hello, world again with name!');
await tx3.wait();
console.info(chalk.green(`Greeter greeting set to: ${await greets5.greet()}`));
console.info(chalk.green(`Greeter greeting set to: ${await greets5Runner.getAddress()}`));

console.log('----------------------------------')

console.log('Greeter get contract with name');
const signer3 = await hre.ethers.provider.getSigner('0x36615Cf349d7F6344891B1e7CA7C72883F5dc049');
const contract1 = await hre.ethers.getContractAt('Greeter', await greets2.getAddress(), signer3);
const contract1Runner = contract1.runner as Signer;
console.info(chalk.green(`Greeter from getContractAt set to: ${await contract1.greet()}`));
console.info(chalk.green('Runner from getContractAt set to: ', await contract1Runner.getAddress()));

console.log('----------------------------------')

console.log('Greeter get contract with abi');
const contract2 = await hre.ethers.getContractAt(artifact.abi, await greets3.getAddress());
console.info(chalk.green(`Greeter from getContractAt set to: ${await contract2.greet()}`));
const contract2Runner = contract2.runner as Signer;
console.info(chalk.green('Runner from getContractAt set to: ', await contract2Runner.getAddress()));

console.log('----------------------------------')

console.log('Greeter get contract with artifact');
const contract3 = await hre.ethers.getContractAtFromArtifact(artifact, await greets4.getAddress());
console.info(chalk.green(`Greeter from getContractAt set to: ${await contract3.greet()}`));
const contract3Runner = contract3.runner as Signer;
console.info(chalk.green('Runner from getContractAt set to: ', await contract3Runner.getAddress()));
}
2 changes: 1 addition & 1 deletion examples/zksync-ethers-example/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
"chalk": "^4.1.2",
"hardhat": "^2.22.5",
"ethers": "^6.12.2",
"zksync-ethers": "^6.8.0"
"zksync-ethers": "^6.11.2"
},
"prettier": {
"tabWidth": 4,
Expand Down
4 changes: 2 additions & 2 deletions packages/hardhat-zksync-deploy/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@
"eslint-plugin-no-only-tests": "^3.1.0",
"eslint-plugin-prettier": "^5.0.1",
"ethers": "^6.12.2",
"zksync-ethers": "^6.8.0",
"zksync-ethers": "^6.11.2",
"hardhat": "^2.22.5",
"ts-node": "^10.9.2",
"prettier": "^3.3.0",
Expand All @@ -68,7 +68,7 @@
"peerDependencies": {
"hardhat": "^2.22.5",
"ethers": "^6.12.2",
"zksync-ethers": "^6.8.0"
"zksync-ethers": "^6.11.2"
},
"prettier": {
"tabWidth": 4,
Expand Down
7 changes: 4 additions & 3 deletions packages/hardhat-zksync-ethers/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@
"hardhat": "^2.22.5",
"chai": "^4.3.4",
"@matterlabs/hardhat-zksync-solc": "workspace:^",
"@matterlabs/hardhat-zksync-deploy": "workspace:^"
"@matterlabs/hardhat-zksync-deploy": "workspace:^",
"@nomicfoundation/hardhat-ethers": "^3.0.6"
},
"devDependencies": {
"@types/chai": "^4.3.16",
Expand All @@ -61,13 +62,13 @@
"ts-node": "^10.9.2",
"typescript": "^5.3.0",
"ethers": "^6.12.2",
"zksync-ethers": "^6.8.0",
"zksync-ethers": "^6.11.2",
"rlp": "3.0.0",
"c8": "^8.0.1"
},
"peerDependencies": {
"ethers": "^6.12.2",
"zksync-ethers": "^6.8.0"
"zksync-ethers": "^6.11.2"
},
"prettier": {
"tabWidth": 4,
Expand Down
13 changes: 9 additions & 4 deletions packages/hardhat-zksync-ethers/src/constants.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
export const PLUGIN_NAME = '@matterlabs/hardhat-zksync-ethers';

export const LOCAL_CHAIN_IDS = [
'0x104', // era-node
'0x10e', // local-setup
];
// eslint-disable-next-line @typescript-eslint/naming-convention
export enum LOCAL_CHAIN_IDS_ENUM {
ERA_NODE = '0x104', // era-node
LOCAL_SETUP = '0x10e', // local-setup
}

export const LOCAL_CHAIN_IDS = [LOCAL_CHAIN_IDS_ENUM.ERA_NODE, LOCAL_CHAIN_IDS_ENUM.LOCAL_SETUP];

export const LOCAL_CHAINS_WITH_IMPERSONATION = [LOCAL_CHAIN_IDS_ENUM.ERA_NODE];

export const ZKSOLC_ARTIFACT_FORMAT_VERSION = 'hh-zksolc-artifact-1';
export const ZKVYPER_ARTIFACT_FORMAT_VERSION = 'hh-zkvyper-artifact-1';
Expand Down
75 changes: 75 additions & 0 deletions packages/hardhat-zksync-ethers/src/extension-generator.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import { HardhatRuntimeEnvironment } from 'hardhat/types';
import { Address, DeploymentType } from 'zksync-ethers/build/types';
import { lazyObject } from 'hardhat/plugins';
import { Overrides, BytesLike } from 'ethers';
import { createProviders } from './utils';
import {
deployContract,
extractFactoryDeps,
getContractAtFromArtifact,
getContractFactoryFromArtifact,
getImpersonatedSigner,
getSigner,
getSigners,
getWallet,
getWallets,
loadArtifact,
makeContractAt,
makeGetContractFactory,
} from './helpers';
import { HardhatZksyncSignerOrWallet, HardhatZksyncSignerOrWalletOrFactoryOptions, ZkSyncArtifact } from './types';
import { Generator } from './generator';

export class ZkSyncGenerator implements Generator {
constructor(private _hre: HardhatRuntimeEnvironment) {}

public populateExtension(): any {
return lazyObject(() => {
const { zksyncEthers } = require('zksync-ethers');
const { ethWeb3Provider, zkWeb3Provider } = createProviders(this._hre);
const { ethers } = require('ethers');

return {
...ethers,
...zksyncEthers,
providerL1: ethWeb3Provider,
providerL2: zkWeb3Provider,
provider: zkWeb3Provider,
getSigners: () => getSigners(this._hre),
getSigner: (address: string) => getSigner(this._hre, address),
getWallet: (privateKeyOrIndex?: string | number) => getWallet(this._hre, privateKeyOrIndex),
getWallets: () => getWallets(this._hre),
getImpersonatedSigner: (address: string) => getImpersonatedSigner(this._hre, address),
getContractFactory: makeGetContractFactory(this._hre),
getContractFactoryFromArtifact: (
artifact: ZkSyncArtifact,
walletOrSignerOrOptions?: HardhatZksyncSignerOrWalletOrFactoryOptions,
deploymentType?: DeploymentType,
) => getContractFactoryFromArtifact(this._hre, artifact, walletOrSignerOrOptions, deploymentType),
getContractAt: makeContractAt(this._hre),
getContractAtFromArtifact: (
artifact: ZkSyncArtifact,
address: string | Address,
walletOrSigner?: HardhatZksyncSignerOrWallet,
) => getContractAtFromArtifact(this._hre, artifact, address, walletOrSigner),
extractFactoryDeps: (artifact: ZkSyncArtifact) => extractFactoryDeps(this._hre, artifact),
loadArtifact: (name: string) => loadArtifact(this._hre, name),
deployContract: (
artifact: ZkSyncArtifact,
constructorArguments: any[],
walletOrSigner?: HardhatZksyncSignerOrWallet,
overrides?: Overrides,
additionalFactoryDeps?: BytesLike[],
) =>
deployContract(
this._hre,
artifact,
constructorArguments,
walletOrSigner,
overrides,
additionalFactoryDeps,
),
};
});
}
}
21 changes: 21 additions & 0 deletions packages/hardhat-zksync-ethers/src/generator.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { HardhatRuntimeEnvironment } from 'hardhat/types';
import { ZkSyncGenerator } from './extension-generator';
import { EthersGenerator } from './hardhat-ethers/extension-generator';

export class ExtensionGenerator {
constructor(private _hre: HardhatRuntimeEnvironment) {}

public populatedExtension(): any {
if (this._hre.network.zksync) {
const zkSyncGenerator = new ZkSyncGenerator(this._hre);
return zkSyncGenerator.populateExtension();
}

const ethersGenerators = new EthersGenerator(this._hre);
return ethersGenerators.populateExtension();
}
}

export interface Generator {
populateExtension(): any;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { FactoryOptions } from '@nomicfoundation/hardhat-ethers/types';
import { Addressable, Signer } from 'ethers';
import { lazyObject } from 'hardhat/plugins';
import { Artifact, HardhatRuntimeEnvironment } from 'hardhat/types';
import { Generator } from '../generator';

export class EthersGenerator implements Generator {
constructor(private _hre: HardhatRuntimeEnvironment) {}

public populateExtension(): any {
return lazyObject(() => {
const hardhatEthersHelpers = require('@nomicfoundation/hardhat-ethers/internal/helpers');
const {
HardhatEthersProvider,
} = require('@nomicfoundation/hardhat-ethers/internal/hardhat-ethers-provider');
const { ethers } = require('ethers');
const provider = new HardhatEthersProvider(this._hre.network.provider, this._hre.network.name);
return {
...ethers,
provider,
getSigner: (address: string) => hardhatEthersHelpers.getSigner(this._hre, address),
getSigners: () => hardhatEthersHelpers.getSigners(this._hre),
getImpersonatedSigner: (address: string) =>
hardhatEthersHelpers.getImpersonatedSigner(this._hre, address),
getContractFactory: hardhatEthersHelpers.getContractFactory.bind(null, this._hre) as any,
getContractFactoryFromArtifact: (artifact: Artifact, signerOrOptions?: Signer | FactoryOptions) =>
hardhatEthersHelpers.getContractFactoryFromArtifact(this._hre, artifact, signerOrOptions),
getContractAt: (nameOrAbi: string | any[], address: string | Addressable, signer?: Signer) =>
hardhatEthersHelpers.getContractAt(this._hre, nameOrAbi, address, signer),
getContractAtFromArtifact: (artifact: Artifact, address: string | Addressable, signer?: Signer) =>
hardhatEthersHelpers.getContractAtFromArtifact(this._hre, artifact, address, signer),
deployContract: hardhatEthersHelpers.deployContract.bind(null, this._hre) as any,
};
});
}
}
Loading

0 comments on commit 8e471bc

Please sign in to comment.