anvil-zksync
This section provides instructions on setting up and using the In-Memory Node, anvil-zksync
, for local testing.
It covers installation, network forking, transaction details viewing, replaying transactions, and testing local bootloader and system contracts.
anvil-zksync
is still in its alpha stage,
some features might not be fully supported yet and may not work as fully intended.
It is open-sourced and contributions are welcomed.Understand anvil-zksync
anvil-zksync uses an in-memory database for storing state information and simplified hashmaps for tracking blocks and transactions. In fork mode, it retrieves missing storage data from a remote source when not available locally. Moreover it also uses the remote server (openchain) to resolve the ABI and topics to human readable names.
You can visit the anvil-zksync
repository to learn more.
Run actions with zksync-cli
You can setup anvil-zksync
quickly with zksync-cli dev start
.
If you don't have zksync-cli
setup, see the Overview guide.
Note: at the moment this method won't allow you to use additional features like forking networks or replaying transactions.
Install and set up anvil-zksync
- Download
anvil-zksync
from latest Release. - Extract the binary and mark as executable:
tar xz -f /path/to/downloaded/binary/anvil-zksync.tar.gz -C /usr/local/bin/ chmod +x /usr/local/bin/anvil-zksync
- Start the node:
anvil-zksync run
The expected output will be as follows:
_ _ _____ _ __
__ _ _ __ __ __(_)| | |__ /| |/ / ___ _ _ _ __ ___
/ _` || '_ \ \ \ / /| || | _____ / / | ' / / __|| | | || '_ \ / __|
| (_| || | | | \ V / | || ||_____| / /_ | . \ \__ \| |_| || | | || (__
\__,_||_| |_| \_/ |_||_| /____||_|\_\|___/ \__, ||_| |_| \___|
|___/
testing
18:02:50 INFO Version: 0.1.0-alpha.34
18:02:50 INFO Repository: https://github.com/matter-labs/anvil-zksync
18:02:50 INFO Rich Accounts
18:02:50 INFO ========================
18:02:50 INFO (0) 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 (10000 ETH)
18:02:50 INFO (1) 0x70997970C51812dc3A010C7d01b50e0d17dc79C8 (10000 ETH)
18:02:50 INFO (2) 0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC (10000 ETH)
18:02:50 INFO (3) 0x90F79bf6EB2c4f870365E785982E1f101E93b906 (10000 ETH)
18:02:50 INFO (4) 0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65 (10000 ETH)
18:02:50 INFO (5) 0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc (10000 ETH)
18:02:50 INFO (6) 0x976EA74026E726554dB657fA54763abd0C3a0aa9 (10000 ETH)
18:02:50 INFO (7) 0x14dC79964da2C08b23698B3D3cc7Ca32193d9955 (10000 ETH)
18:02:50 INFO (8) 0x23618e81E3f5cdF7f54C3d65f7FBc0aBf5B21E8f (10000 ETH)
18:02:50 INFO (9) 0xa0Ee7A142d267C1f36714E4a8F75612F20a79720 (10000 ETH)
...
...
12:34:56 [INFO]
12:34:56 [INFO] ========================================
12:34:56 [INFO] Node is ready at 127.0.0.1:8011
12:34:56 [INFO] ========================================
anvil-zksync
with MetaMask, it's essential to note that any restart of the node
will necessitate a reset of MetaMask's cached account data (nonce, etc).
In the MetaMask app, navigate to 'Settings', then 'Advanced', and finally, select 'Clear activity tab data'.Network details
The anvil-zksync
has the following default network configurations:
- L2 RPC:
http://localhost:8011
- Network Id: 260
These can be configured to your preference.
Pre-configured rich wallets
anvil-zksync includes pre-configured "rich" accounts for testing:
Debug Transactions & Smart Contracts
The default configuration of anvil-zksync
displays minimal data in the terminal to keep the output clean.
However, if you are having issues with your smart contracts and need more details why a transaction is failing, try enabling --debug-mode
(or just -d
).
anvil-zksync -d
This will:
- Show the full call stack and each call's output for transactions
- Show more details about the breakdown of gas cost per transaction
- Resolve known hashes into human-readable strings
Fork a network
To fork the mainnet, use the following command, replacing [network]
with either mainnet
or sepolia-testnet
:
anvil-zksync fork [network]
This command starts the node, forked at the current head of the selected network.
You also have the option to specify a custom http endpoint and a custom forking height:
anvil-zksync fork --fork-block-number 7000000 --fork-url mainnet http://172.17.0.3:3060
Replay remote transactions locally
If you wish to replay a remote transaction locally for deep debugging, use the following command:
anvil-zksync replay_tx sepolia-testnet 0x7119045573862797257e4441ff48bf5a3bc4d133a00d167c18dc955eda12cfac
For more detailed transaction information, such as call traces, add the --show-calls
flag.
If you want to see ABI names, add the --resolve-hashes
flag:
anvil-zksync --show-calls=user \
--resolve-hashes replay_tx sepolia-testnet \
0x7119045573862797257e4441ff48bf5a3bc4d133a00d167c18dc955eda12cfac
Alternatively (if your node is already running) you can use config_setShowCalls
and config_setResolveHashes
RPC endpoints
to configure these values:
# anvil-zksync already running...
# Set show-calls to User
curl --request POST \
--url http://localhost:8011/ \
--header 'content-type: application/json' \
--data '{"jsonrpc": "2.0","id": "1","method": "config_setShowCalls","params": ["user"]}'
# Enable resolve-hashes
curl --request POST \
--url http://localhost:8011/ \
--header 'content-type: application/json' \
--data '{"jsonrpc": "2.0","id": "1","method": "config_setResolveHashes","params": [true]}'
Here's an example of what you should expect to see when show-calls
and resolve-hashes
are configured:
Send network calls
You can send network calls against a running anvil-zksync
.
Launch the local anvil-zksync
node:
anvil-zksync fork sepolia-testnet
- Use curl to send a network call:
curl --request POST \ --url http://localhost:8011 \ --header 'Content-Type: application/json' \ --data '{ "jsonrpc": "2.0", "id": 1, "method": "eth_call", "params": [ { "to":"0xe1134444211593Cfda9fc9eCc7B43208615556E2", "data":"0x313ce567" }, "latest" ] }'
- Use foundry-zksync.
Make sure to install and configure
foundry-zksync
before proceeding (for installation instructions, please see Foundry with ZKsync Era):cast call 0xe1134444211593Cfda9fc9eCc7B43208615556E2 \ "name()(string)" \ --rpc-url http://localhost:8011
Retrieve the balance of a particular contract:cast call 0x40609141Db628BeEE3BfAB8034Fc2D8278D0Cc78 \ "balanceOf(address)(uint256)" \ 0x40609141Db628BeEE3BfAB8034Fc2D8278D0Cc78 \ --rpc-url http://localhost:8011
Deploy contracts
For the deployment of your contracts, you have the flexibility to choose between two preferred methods:
either by using Hardhat with the @matter-labs/hardhat-zksync
plugin, or via foundry-zksync
.
The following example will detail the process using foundry-zksync
.
Before proceeding, ensure that you've compiled your contracts using forge build --zksync
.
forge create contracts/Greeter.sol:Greeter \
--constructor-args "ZKsync and Foundry" \
--private-key 7726827caac94a7f9e1b160f7ea819f172f7b6f9d2a97f992c38edeab82d4110 \
--rpc-url http://localhost:8011 \
--chain 260 \
--zksync
Test bootloader and system contracts
anvil-zksync allows testing of the currently compiled bootloader and system contracts. This makes it possible to examine the effects of changes on already deployed contracts.
$ZKSYNC_HOME
in your shell profile file
(e.g. ~/.bash_profile, ~/.zshrc) to target your local copy of anvil-zksync
.
For instance,export ZKSYNC_HOME=/path/to/anvil-zksync
export PATH=$ZKSYNC_HOME/bin:$PATH
- Preprocess and compile the contracts:
cd etc/system-contracts yarn preprocess && yarn hardhat run ./scripts/compile-yul.ts
- To use the locally compiled bootloader and system contracts, run:
RUST_LOG=vm=trace anvil-zksync --dev-use-local-contracts fork sepolia-testnet
Writing and running tests locally
This section demonstrates how to author and execute tests locally against anvil-zksync
using the mocha
and chai
testing frameworks with Hardhat.
Project configuration
- Start by creating a new Hardhat project. If you need guidance, follow the getting started guide.
- To incorporate the test libraries, execute:
yarn add -D mocha chai @types/mocha @types/chai
- Add the following lines to your
package.json
in the root folder:package.json"scripts": { "test": "NODE_ENV=test hardhat test" }
This script makes it possible to run tests in a Hardhat environment with the NODE_ENV
env variable set as test
.
Configure tests
Adjust hardhat.config.ts
to use the local node for testing:
anvil-zksync
is running in another process before executing the test command.import "@matterlabs/hardhat-zksync";
module.exports = {
zksolc: {
version: "latest",
settings: {},
},
defaultNetwork: "zkSyncTestnet",
networks: {
hardhat: {
zksync: true,
},
zkSyncTestnet: {
url: "http://localhost:8011",
ethNetwork: "http://localhost:8545",
zksync: true,
},
},
solidity: {
version: "0.8.17",
},
};
Write test scripts
Construct a test/main.test.ts
file with the following code:
import { expect } from "chai";
import { Wallet, Provider, Contract } from "zksync-ethers";
import * as hre from "hardhat";
import { Deployer } from "@matterlabs/hardhat-zksync";
const RICH_WALLET_PK = "0x7726827caac94a7f9e1b160f7ea819f172f7b6f9d2a97f992c38edeab82d4110";
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 artifact = await deployer.loadArtifact("Greeter");
const greeter = await deployer.deploy(artifact, ["Hi"]);
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!");
});
});
To run the test file, execute:
npm test
Well done! You've successfully run your first local tests with ZKsync Era and anvil-zksync
.
Troubleshooting
If running anvil-zksync run
provides the following error:
“anvil-zksync” can’t be opened because Apple cannot check it for malicious software.
This software needs to be updated. Contact the developer for more information.
You may require the use of sudo
. On macOS, the binary may need to have its quarantine attribute cleared:
xattr -d com.apple.quarantine /usr/local/bin/anvil-zksync