Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: introducing ethers extension in hre #1399

Merged
Merged
Show file tree
Hide file tree
Changes from all 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
4 changes: 4 additions & 0 deletions .github/release-please/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@
"release-type": "node",
"component": "@matterlabs/hardhat-zksync-upgradable"
},
"packages/hardhat-zksync-ethers": {
"release-type": "node",
"component": "@matterlabs/hardhat-zksync-ethers"
},
"packages/hardhat-zksync": {
"release-type": "node",
"component": "@matterlabs/hardhat-zksync"
Expand Down
1 change: 1 addition & 0 deletions .github/release-please/manifest.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"packages/hardhat-zksync-deploy": "0.11.0",
"packages/hardhat-zksync-upgradable": "0.5.2",
"packages/hardhat-zksync-ethers": "0.1.0",
"packages/hardhat-zksync": "0.2.0"
}
43 changes: 42 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,18 @@ jobs:
pnpm hardhat run scripts/upgrade-factory-beacon.ts
pnpm hardhat run scripts/upgrade-factory-uups.ts
pnpm hardhat run scripts/upgrade-factory.ts

- name: Test zksync-ethers example
run: |
cd examples/zksync-ethers-example
pnpm hardhat compile
pnpm hardhat deploy-zksync

- name: Show logs
if: always()
run: |
cat server.log


upgradable:
runs-on: ubuntu-latest
Expand Down Expand Up @@ -143,4 +151,37 @@ jobs:
- name: Show logs
if: always()
run: |
cat server.log
cat server.log
zksync-ethers:
runs-on: ubuntu-latest
name: zksync-ethers
steps:
- uses: actions/checkout@v3

- uses: actions/checkout@v3
with:
repository: matter-labs/local-setup
path: local-setup

- name: Run server
run: |
cd local-setup
./start.sh &>../server.log &
- uses: pnpm/action-setup@v3

- uses: actions/setup-node@v3
with:
node-version: "18"
cache: pnpm

- name: Setup environment
run: |
pnpm install
pnpm build
- name: Wait until server is up
run: |
while ! curl -s -X POST -d '{"jsonrpc":"2.0","method":"net_version","id":1}' -H 'Content-Type: application/json' 0.0.0.0:3050; do sleep 1; done
- name: Test zksync ethers plugin
run: |
cd packages/hardhat-zksync-ethers
pnpm test
1 change: 1 addition & 0 deletions .github/workflows/npm-publish.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ on:
options:
- hardhat-zksync-deploy
- hardhat-zksync-upgradable
- hardhat-zksync-ethers
- hardhat-zksync

jobs:
Expand Down
7 changes: 7 additions & 0 deletions examples/zksync-ethers-example/.eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
module.exports = {
extends: [`${__dirname}/../../config/eslint/eslintrc.cjs`],
parserOptions: {
project: `${__dirname}/tsconfig.json`,
sourceType: "module",
},
};
3 changes: 3 additions & 0 deletions examples/zksync-ethers-example/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
cache
artifacts
contracts/tmp
61 changes: 61 additions & 0 deletions examples/zksync-ethers-example/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# ZKsync Era zksync-ethers environment example

This project demonstrates how to compile and deploy your contracts in ZKsync Era using the Hardhat plugins.

## Prerequisites

- node.js 14.x or later.
- yarn.

## Configuration

Plugin configuration is located in [`hardhat.config.ts`](./hardhat.config.ts).
You should only change the ZKsync network configuration.

`hardhat.config.ts` example with ZKsync network configured with the name `zkTestnet` and `sepolia` used as the underlying layer 1 network:
```ts
import "@matterlabs/hardhat-zksync-deploy";
import { HardhatUserConfig } from 'hardhat/types';

const config: HardhatUserConfig = {
networks: {
sepolia: {
url: 'https://sepolia.infura.io/v3/<API_KEY>' // you can use either the URL of the Ethereum Web3 RPC, or the identifier of the network (e.g. `mainnet` or `rinkeby`)
},
zkTestnet: {
url: 'https://sepolia.era.zksync.dev', // you should use the URL of the ZkSync network RPC
ethNetwork: 'sepolia',
zksync: true
},
}
};

export default config;
```

## Usage

Before using plugins, you need to build them first

```sh
# Run the following in the *root* of the repo.
yarn
yarn build
```

After that you should be able to run plugins:

```sh
# Run the following in `examples/ethers-example` folder.
yarn
yarn hardhat compile
yarn hardhat deploy-zksync
```

- `yarn hardhat compile`: compiles all the contracts in the `contracts` folder.
- `yarn hardhat deploy-zksync`: runs all the deploy scripts in the `deploy` folder.
- To run a specific script, add the `--script` argument, e.g. `--script 001_deploy.ts`.
- To run on a specific ZKsync network, use standard hardhat `--network` argument, e.g. `--network zkTestnet`
(with `zkTestnet` network specified in the `hardhat.config` networks section, with the `zksync` flag set to `true` and `ethNetwork` specified).

If you don't specify ZKsync network (`--network`), `local-setup` with <http://localhost:8545> (Ethereum RPC URL) and <http://localhost:3050> (ZKsync RPC URL) will be used.
19 changes: 19 additions & 0 deletions examples/zksync-ethers-example/contracts/Greeter.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;
pragma abicoder v2;

contract Greeter {
string greeting;
constructor(string memory _greeting) {
greeting = _greeting;
}

function greet() public view returns (string memory) {
return greeting;
}

function setGreeting(string memory _greeting) public {
greeting = _greeting;
}
}
49 changes: 49 additions & 0 deletions examples/zksync-ethers-example/deploy/001_deploy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { HardhatRuntimeEnvironment } from 'hardhat/types';
import chalk from 'chalk';
import { Wallet } from 'zksync-ethers';

export default async function (hre: HardhatRuntimeEnvironment) {
console.info(chalk.yellow(`Running deploy`));
const wallet = await hre.zksyncEthers.getWallet(4);

// console.info(chalk.yellow(`Depositing to wallet: ${await wallet.getAddress()}`));
// const depositHandle = await wallet.deposit({
// to: wallet.address,
// token: utils.ETH_ADDRESS,
// amount: ethers.parseEther('0.001'),
// });
// await depositHandle.wait();

const artifact = await hre.zksyncEthers.loadArtifact('Greeter');
const greets = await hre.zksyncEthers.deployContract(artifact, ['Hello, world with loadArtifact!'], wallet);
const wallet1 = greets.signer as Wallet;
console.info(chalk.yellow(`Deploying Greeter with wallet: ${await wallet1.getAddress()}`));
console.info(chalk.green(`Greeter deployed to: ${greets.address}`));
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()}`));

const greeterFactory = await hre.zksyncEthers.getContractFactory(artifact.abi, artifact.bytecode);
const greeter = await greeterFactory.deploy('Hello, world with abi and bytecode!');
const wallet2 = greeter.signer as Wallet;
console.info(chalk.yellow(`Deploying Greeter with wallet: ${await wallet2.getAddress()}`));
console.info(chalk.green(`Greeter deployed to: ${greeter.address}`));
console.info(chalk.green(`Greeter greeting set to: ${await greeter.greet()}`));
const tx = await greeter.setGreeting('Hello, world again with abi and bytecode!');
await tx.wait();
console.info(chalk.green(`Greeter greeting set to: ${await greeter.greet()}`));

const greeterFactoryFromName = await hre.zksyncEthers.getContractFactory(
'Greeter',
await hre.zksyncEthers.getWallet('0xbe79721778b48bcc679b78edac0ce48306a8578186ffcb9f2ee455ae6efeace1'),
);
const greeterFromName = await greeterFactoryFromName.deploy('Hello, world with name!');
const wallet3 = greeterFromName.signer as Wallet;
console.info(chalk.yellow(`Deploying Greeter with wallet: ${await wallet3.getAddress()}`));
console.info(chalk.green(`Greeter deployed to: ${greeterFromName.address}`));
console.info(chalk.green(`Greeter greeting set to: ${await greeterFromName.greet()}`));
const tx2 = await greeter.setGreeting('Hello, world again with name!');
await tx2.wait();
console.info(chalk.green(`Greeter greeting set to: ${await greeter.greet()}`));
}
99 changes: 99 additions & 0 deletions examples/zksync-ethers-example/deploy/002_deploy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
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.deployed();
const greetsRunner = greets.signer as Signer;
console.info(chalk.green(`Greeter deployed to: ${greets.address}`));
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.deployed();
const greets2Runner = greets2.signer as Signer;
console.info(chalk.green(`Greeter deployed to: ${greets2.address}`));
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.deployed();
const greets3Runner = greets3.signer as Signer;
console.info(chalk.green(`Greeter deployed to: ${greets3.address}`));
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.deployed();
const greets4Runner = greets4.signer as Signer;
console.info(chalk.green(`Greeter deployed to: ${greets4.address}`));
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.deployed();
const greets5Runner = greets5.signer as Signer;
console.info(chalk.green(`Greeter deployed to: ${greets5.address}`));
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 = hre.ethers.provider.getSigner('0x36615Cf349d7F6344891B1e7CA7C72883F5dc049');
const contract1 = await hre.ethers.getContractAt('Greeter', greets2.address, signer3);
const contract1Runner = contract1.signer 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, greets3.address);
console.info(chalk.green(`Greeter from getContractAt set to: ${await contract2.greet()}`));
const contract2Runner = contract2.signer 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, greets4.address);
console.info(chalk.green(`Greeter from getContractAt set to: ${await contract3.greet()}`));
const contract3Runner = contract3.signer as Signer;
console.info(chalk.green('Runner from getContractAt set to: ', await contract3Runner.getAddress()));
}
32 changes: 32 additions & 0 deletions examples/zksync-ethers-example/hardhat.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import '@matterlabs/hardhat-zksync-deploy';
import '@matterlabs/hardhat-zksync-solc';
import '@matterlabs/hardhat-zksync-ethers';

import { HardhatUserConfig } from 'hardhat/config';

const config: HardhatUserConfig = {
zksolc: {
compilerSource: 'binary',
settings: {
enableEraVMExtensions: true,
optimizer: {
enabled: true,
},
}
},
defaultNetwork: 'zkSyncLocal',
networks: {
zkSyncLocal: {
zksync: true,
url: "http://0.0.0.0:3050",
ethNetwork: 'http://0.0.0.0:8545',
},
},
// Docker image only works for solidity ^0.8.0.
// For earlier versions you need to use binary releases of zksolc.
solidity: {
version: '0.8.17',
},
};

export default config;
Loading
Loading