Local testing
Local testing
Sometimes there is a need to test contracts in a local environment for network latency or fee reasons.
zkSync team provides a dockerized local setup for this purpose.
Prerequisites
It is required that you have Docker
and docker-compose
installed on your computer. Find the installation guide here
This guide assumes that you're familiar with the zkSync Hardhat plugins. If you are newly developing on zkSync with Hardhat, please check the getting started section here.
Installing the testing environment
Download the dockerized project with the following command:
git clone https://github.com/matter-labs/local-setup.git
Start the local nodes
To run zkSync locally, run the start.sh
script:
cd local-setup
./start.sh
This command will start three docker containers:
- Postgres (used as the database for zkSync).
- Local Geth node (used as L1 for zkSync).
- zkSync node itself.
By default, the HTTP JSON-RPC API will run on port 3050
, while WS API will run on port 3051
.
Note
Note, that it is important that the first start.sh
script invocation goes uninterrupted. If you face any issues after the bootstrapping process unexpectedly stopped, you should reset the local zkSync state and try again.
Connect wallet to local nodes
You can connect your wallet to both L1 and L2 nodes using the following details:
Local L1 network
- Network Name:
L1 local
- RPC URL:
http://localhost:8545/
- Chain ID:
9
- Currency Symbol:
ETH
Local zkSync network
- Network Name:
L2 local zkSync
- RPC URL:
http://localhost:3050/
- Chain ID:
270
- Currency Symbol:
ETH
Reset the zkSync state
To reset the zkSync state, run the ./clear.sh
script:
./clear.sh
Note, that you may receive a "permission denied" error when running this command. In this case, you should run it with the root privileges:
sudo ./clear.sh
Rich wallets
The local zkSync setup comes with some "rich" wallets with large amounts of ETH on both L1 and L2.
The full list of the addresses of these accounts with the corresponding private keys can be found here.
ERC20 tokens
Rich wallets only have ETH. If you need to test with ERC20 tokens, you should deploy them yourself.
If you'd like the local node to come with pre-deployed tokens again, please let us know on our Discord, so we can prioritize accordingly.
Using custom database or Ethereum node
To use a custom Postgres database or Layer 1 node, you should change the environment parameters in the docker-compose file:
environment:
- DATABASE_URL=postgres://postgres@postgres/zksync_local
- ETH_CLIENT_WEB3_URL=http://geth:8545
DATABASE_URL
is the URL to the Postgres database.ETH_CLIENT_WEB3_URL
is the URL to the HTTP JSON-RPC interface of the L1 node.
mocha
+ chai
Testing with Since the zkSync node URL is provided in the hardhat.config.ts
, the best way to use different URLs for deployment and local testing is to use environment variables. The standard way is to set the NODE_ENV=test
environment variable before invoking the tests.
Project setup
Create a new Hardhat project following the getting started guide as a reference.
To install the test libraries, run the following command:
yarn add -D mocha chai @types/mocha @types/chai
- Add the following lines to your
package.json
in the root folder:
"scripts": {
"test": "NODE_ENV=test hardhat test"
}
This will enable running tests in a Hardhat environment with the NODE_ENV
env variable set as a test
.
Configuration
- Modify
hardhat.config.ts
to use the local node for testing:
import "@matterlabs/hardhat-zksync-deploy";
import "@matterlabs/hardhat-zksync-solc";
// dynamically changes endpoints for local tests
const zkSyncTestnet =
process.env.NODE_ENV == "test"
? {
url: "http://localhost:3050",
ethNetwork: "http://localhost:8545",
zksync: true,
}
: {
url: "https://zksync2-testnet.zksync.dev",
ethNetwork: "goerli",
zksync: true,
};
module.exports = {
zksolc: {
version: "1.3.5",
compilerSource: "binary",
settings: {},
},
// defaults to zkSync network
defaultNetwork: "zkSyncTestnet",
networks: {
hardhat: {
zksync: true,
},
// load test network details
zkSyncTestnet,
},
solidity: {
version: "0.8.16",
},
};
Create a test
folder, where the tests will reside.
Writing test files
- Now you can write your first test! Create a
test/main.test.ts
file with the following code:
import { expect } from "chai";
import { Wallet, Provider, Contract } from "zksync-web3";
import * as hre from "hardhat";
import { Deployer } from "@matterlabs/hardhat-zksync-deploy";
const RICH_WALLET_PK = "0x7726827caac94a7f9e1b160f7ea819f172f7b6f9d2a97f992c38edeab82d4110";
async function deployGreeter(deployer: Deployer): Promise<Contract> {
const artifact = await deployer.loadArtifact("Greeter");
return await deployer.deploy(artifact, ["Hi"]);
}
describe("Greeter", function () {
it("Should return the new greeting once it's changed", async function () {
const provider = Provider.getDefaultProvider();
const wallet = new Wallet(RICH_WALLET_PK, provider);
const deployer = new Deployer(hre, wallet);
const greeter = await deployGreeter(deployer);
expect(await greeter.greet()).to.eq("Hi");
const setGreetingTx = await greeter.setGreeting("Hola, mundo!");
// wait until the transaction is mined
await setGreetingTx.wait();
expect(await greeter.greet()).to.equal("Hola, mundo!");
});
});
This script deploys the Greeter
contract created in the getting started guide and test that it returns a correct message when calling the greet()
method, and that the message can be updated with the setGreeting()
method.
You can now run the test file with the following command:
yarn test
Congratulations! You've ran your first tests locally with zkSync 🎉
Full example
The full example with tests can be found here
Chai Matchers
The zkSync team provides the hardhat-zksync-chai-matchers plugin to make it easier to write and maintain tests for your projects, in addition to offering a local testing environment. This plugin includes a set of Chai matchers specifically designed for use with zkSync, which can help you write more comprehensive and understandable tests for your contracts. By using these matchers, you can ensure that your contracts are working as intended and reduce the likelihood of encountering bugs or other issues during development.