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.
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.
Install and set up anvil-zksync
The Foundry-ZKsync suite installs anvil-zksync
alongside forge
, and cast
. If you haven’t installed Foundry-ZKsync yet, see Foundry-ZKsync installation.
If you want to install it separately, follow the instructions below:
- 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
To start the anvil-zksync
node, run
anvil-zksync
The expected output will be as follows:
_ _ _____ _ __
__ _ _ __ __ __(_)| | |__ /| |/ / ___ _ _ _ __ ___
/ _` || '_ \ \ \ / /| || | _____ / / | ' / / __|| | | || '_ \ / __|
| (_| || | | | \ V / | || ||_____| / /_ | . \ \__ \| |_| || | | || (__
\__,_||_| |_| \_/ |_||_| /____||_|\_\|___/ \__, ||_| |_| \___|
|___/
Version: 0.4.0
Repository: https://github.com/matter-labs/anvil-zksync
Rich Accounts
========================
(0) 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 (10000 ETH)
(1) 0x70997970C51812dc3A010C7d01b50e0d17dc79C8 (10000 ETH)
(2) 0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC (10000 ETH)
(3) 0x90F79bf6EB2c4f870365E785982E1f101E93b906 (10000 ETH)
(4) 0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65 (10000 ETH)
(5) 0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc (10000 ETH)
(6) 0x976EA74026E726554dB657fA54763abd0C3a0aa9 (10000 ETH)
(7) 0x14dC79964da2C08b23698B3D3cc7Ca32193d9955 (10000 ETH)
(8) 0x23618e81E3f5cdF7f54C3d65f7FBc0aBf5B21E8f (10000 ETH)
(9) 0xa0Ee7A142d267C1f36714E4a8F75612F20a79720 (10000 ETH)
...
...
========================================
Listening on 0.0.0.0:8011
========================================
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,
start with verbose VM tracing:
anvil-zksync -vv
This will:
- Show the full call stack and each call's output for transactions
- Resolve known hashes into human-readable strings
Fork a network
To fork the mainnet, use the following command, replacing [network]
with either mainnet
, sepolia-testnet
, abstract
or abstract-testnet
:
anvil-zksync fork --fork-url [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 --fork-url sepolia-testnet 0x7119045573862797257e4441ff48bf5a3bc4d133a00d167c18dc955eda12cfac
For more detailed transaction information, such as call traces, add verbose flags -vv
for user, -vvv
for system,
and -vvvv
to include precompiles.
anvil-zksync -vv \
replay_tx --fork-url sepolia-testnet \
0x7119045573862797257e4441ff48bf5a3bc4d133a00d167c18dc955eda12cfac
Here's an example of what you should expect to see when -vv
is used:
L1–L2 Communication
anvil-zksync
supports L1-L2 communication by either spawning a new Anvil L1 node or using an existing one.
Spawn a Local L1 Node
Use the --spawn-l1
flag to launch an Anvil L1 node on a specified port (defaults to 8012
if no port is provided):
anvil-zksync --spawn-l1
# or specify a different port:
anvil-zksync --spawn-l1 9000
This command relies on Anvil being installed. To install Anvil, please refer to documentation here.
Connect to an External L1 Node
If you already have an Anvil L1 node running, ensure it was started with the --no-request-size-limit
option:
anvil --no-request-size-limit
Then, provide its JSON-RPC endpoint to anvil-zksync
via:
anvil-zksync --external-l1 http://localhost:8545
Note: The
--spawn-l1
and--external-l1
flags cannot be used together because they are mutually exclusive.
Send network calls
You can send network calls against a running anvil-zksync
.
Launch the local anvil-zksync
node:
anvil-zksync fork --fork-url 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