---
description: Learn how to setup a local in-memory era_test_node.
---

# In-Memory Node

***

This section provides instructions on setting up and using the In-Memory Node, `era_test_node`, for local testing. It covers installation, network forking, transaction details viewing, replaying transactions, and testing local bootloader and system contracts.

Please keep in mind that `era-test-node` 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](https://github.com/matter-labs/era-test-node) and contributions are welcomed.

### Understand the In-Memory Node <a href="#understand-the-in-memory-node" id="understand-the-in-memory-node"></a>

The In-Memory Node 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 `era-test-node` repository [to learn more](https://github.com/matter-labs/era-test-node).

### Run actions with `zksync-cli` <a href="#run-actions-with-zksync-cli" id="run-actions-with-zksync-cli"></a>

You can setup the In-Memory Node quickly with `zksync-cli dev start`. If you don't have `zksync-cli` setup, see the [Overview](../cli/getting-started) 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 `era_test_node` <a href="#install-and-set-up-era_test_node" id="install-and-set-up-era_test_node"></a>

1. Download `era_test_node` from latest [Release](https://github.com/matter-labs/era-test-node/releases/latest).
2.  Extract the binary and mark as executable:

    ```shell
    tar xz -f /path/to/downloaded/binary/era_test_node.tar.gz -C /usr/local/bin/
    chmod +x /usr/local/bin/era_test_node
    ```
3.  Start the node:

    ```sh
    era_test_node run
    ```

The expected output will be as follows:

```
12:34:56 [INFO] Starting network with chain id: L2ChainId(260)
12:34:56 [INFO] Rich Accounts
12:34:56 [INFO] =============
12:34:56 [INFO] Account #0: 0x36615Cf349d7F6344891B1e7CA7C72883F5dc049 (1_000_000_000_000 ETH)
12:34:56 [INFO] Private Key: 0x7726827caac94a7f9e1b160f7ea819f172f7b6f9d2a97f992c38edeab82d4110
12:34:56 [INFO]
12:34:56 [INFO] Account #1: 0xa61464658AfeAf65CccaaFD3a512b69A83B77618 (1_000_000_000_000 ETH)
12:34:56 [INFO] Private Key: 0xac1e735be8536c6534bb4f17f06f6afc73b2b5ba84ac2cfb12f7461b20c0bbe3

...

12:34:56 [INFO] Account #9: 0xE90E12261CCb0F3F7976Ae611A29e84a6A85f424 (1_000_000_000_000 ETH)
12:34:56 [INFO] Private Key: 0x3eb15da85647edd9a1159a4a13b9e7c56877c4eb33f614546d4db06a51868b1c
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] ========================================
```

When utilizing `era_test_node` with MetaMask, it's essential to note that any restart of the in-memory 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 <a href="#network-details" id="network-details"></a>

The `era_test_node` has the following default network configurations:

* **L2 RPC:** `http://localhost:8011`
* **Network Id:** 260

These can be configured to your preference.

Please note that the existing implementation does not facilitate communication with Layer 1. As a result, an L1 RPC is not available.

#### Pre-configured rich wallets <a href="#pre-configured-rich-wallets" id="pre-configured-rich-wallets"></a>

In-Memory node includes pre-configured "rich" accounts for testing:

Rich walletsSame mnemonic rich wallets

***

### Debug Transactions & Smart Contracts <a href="#debug-transactions-smart-contracts" id="debug-transactions-smart-contracts"></a>

The default configuration of `era_test_node` 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`).

```bash
era_test_node -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 <a href="#fork-a-network" id="fork-a-network"></a>

To fork the mainnet, use the following command, replacing `[network]` with either `mainnet` or `sepolia-testnet`:

```bash
era_test_node fork [network]
```

Expected output

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:

```bash
era_test_node fork --fork-at 7000000 mainnet http://172.17.0.3:3060
```

***

### Replay remote transactions locally <a href="#replay-remote-transactions-locally" id="replay-remote-transactions-locally"></a>

If you wish to replay a remote transaction locally for deep debugging, use the following command:

{% code overflow="wrap" %}
```bash
era_test_node replay_tx sepolia-testnet 0x7119045573862797257e4441ff48bf5a3bc4d133a00d167c18dc955eda12cfac
```
{% endcode %}

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:

```bash
era_test_node --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:

```bash
# era_test_node 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:

Expected output

***

### Send network calls <a href="#send-network-calls" id="send-network-calls"></a>

You can send network calls against a running `era_test_node`.

Launch the local in-memory node:

```bash
era_test_node fork sepolia-testnet
```

*   Use curl to send a network call:curlexpected output

    ```bash
    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](https://github.com/matter-labs/foundry-zksync). Make sure to install and configure `foundry-zksync` before proceeding (for installation instructions, please see [Foundry with ZKsync Era](https://github.com/matter-labs/foundry-zksync?tab=readme-ov-file#-installation)):foundry-zksyncexpected output

    ```bash
    cast call 0xe1134444211593Cfda9fc9eCc7B43208615556E2 \
      "name()(string)" \
      --rpc-url http://localhost:8011
    ```

    \
    Retrieve the balance of a particular contract:foundry-zksyncexpected output

    ```bash
    cast call 0x40609141Db628BeEE3BfAB8034Fc2D8278D0Cc78 \
      "balanceOf(address)(uint256)"  \
      0x40609141Db628BeEE3BfAB8034Fc2D8278D0Cc78  \
      --rpc-url http://localhost:8011
    ```

***

### Deploy contracts <a href="#deploy-contracts" id="deploy-contracts"></a>

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`](https://github.com/matter-labs/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`.

foundry-zksync

```bash
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 <a href="#test-bootloader-and-system-contracts" id="test-bootloader-and-system-contracts"></a>

In-memory node allows testing of the currently compiled bootloader and system contracts. This makes it possible to examine the effects of changes on already deployed contracts.

These commands assume you have set `$ZKSYNC_HOME` in your shell profile file (e.g. \~/.bash\_profile, \~/.zshrc) to target your local copy of `era_test_node`. For instance,

```bash
export ZKSYNC_HOME=/path/to/era_test_node

export PATH=$ZKSYNC_HOME/bin:$PATH
```

1.  Preprocess and compile the contracts:

    ```bash
    cd etc/system-contracts
    yarn preprocess && yarn hardhat run ./scripts/compile-yul.ts
    ```
2.  To use the locally compiled bootloader and system contracts, run:

    ```bash
    RUST_LOG=vm=trace era_test_node --dev-use-local-contracts fork sepolia-testnet
    ```

### Writing and running tests locally <a href="#writing-and-running-tests-locally" id="writing-and-running-tests-locally"></a>

This section demonstrates how to author and execute tests locally against `era_test_node` using the `mocha` and `chai` testing frameworks with Hardhat.

#### Project configuration <a href="#project-configuration" id="project-configuration"></a>

1. Start by creating a new Hardhat project. If you need guidance, follow the [getting started guide](../tooling/hardhat-validium/guides/getting-started).
2.  To incorporate the test libraries, execute:yarnnpmbun

    ```bash
      yarn add -D mocha chai @types/mocha @types/chai
    ```
3.  Add the following lines to your `package.json` in the root folder:package.json

    ```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 <a href="#configure-tests" id="configure-tests"></a>

Adjust `hardhat.config.ts` to use the local node for testing:

Ensure `era_test_node` is running in another process before executing the test command.hardhat.config.ts

```typescript
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 <a href="#write-test-scripts" id="write-test-scripts"></a>

Construct a `test/main.test.ts` file with the following code:

test/main.test.ts

```typescript
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:

npmyarnpnpmbun

```bash
  npm test
```

Well done! You've successfully run your first local tests with Validium and `era_test_node`.

***

### Troubleshooting <a href="#troubleshooting" id="troubleshooting"></a>

If running `era_test_node run` provides the following error:

```bash
“era_test_node” 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:

```bash
xattr -d com.apple.quarantine /usr/local/bin/era_test_node
```
