Tutorial for The Graph on Scroll Alpha Testnet

Gaurang (GT) Torvekar
Published in
10 min readMar 8, 2023


How to create a local Graph node and a subgraph for your DAPP

The Graph is arguably one of the most important infrastructure layers that prop up almost all EVM networks. Recently, they have also started supporting other networks like Arweave, Near, and Cosmos, amongst others! Having said that, the Graph doesn’t natively support a lot of testnets, especially amongst newer entrants like Scroll zkEVM’s Alpha testnet.

This tutorial is divided into three parts. In the first part, you will learn how to deploy your local Graph node that supports the Scroll Alpha Testnet. In the second part, you will create a Hardhat project and deploy a Smart contract on the testnet, which we will index using our subgraph. In the third part, you will learn how to create a simple subgraph connected to this local Graph node, thus indexing your Smart Contract on the Scroll testnet. Once you have this subgraph, you can use it in your DAPP for multiple purposes, such as a stats dashboard.

Graph on Scroll

Part 1 — How to create your local Graph node

There are two ways in which you can create a local Graph node. The first is to compile their source code, or the second (and recommended) way is to use Docker!

Before you begin, please make sure that you have the following installed on your machine —

  • NodeJS
  • Docker
  • Docker Compose

Let’s start by cloning the graph-node repo provided by the Graph team.

git clone https://github.com/graphprotocol/graph-node

cd graph-node/docker

After that, you must install the setup file at ./setup.sh. This will load all the docker images and the required information in the docker-compose.yml file.


Once this is done, you need to edit the docker-compose.yml file and change the value of ethereumin that file. The default value expects you to be running a local Ethereum network node on port 8545 (like ganache or geth), but in the case of Scroll Alpha Testnet, you can just connect to their RPC URL — https://alpha-rpc.scroll.io/l2

Hence, the value for “ethereum” should be ‘scrollAlpha:https://alpha-rpc.scroll.io/l2’.

Note — please make sure that you put a memorable name like ‘scrollAlpha’ for your network because that’s the name we will be using in Part 2 while creating a subGraph

The docker-compose.yml file should now look like this

version: '3'
image: graphprotocol/graph-node
- '8000:8000'
- '8001:8001'
- '8020:8020'
- '8030:8030'
- '8040:8040'
- ipfs
- postgres
- host.docker.internal:host-gateway
postgres_host: postgres
postgres_user: graph-node
postgres_pass: let-me-in
postgres_db: graph-node
ipfs: 'ipfs:5001'
ethereum: 'scrollAlpha:https://alpha-rpc.scroll.io/l2'
image: ipfs/go-ipfs:v0.10.0
- '5001:5001'
- ./data/ipfs:/data/ipfs
image: postgres
- '5432:5432'
POSTGRES_USER: graph-node
POSTGRES_DB: graph-node
# FIXME: remove this env. var. which we shouldn't need. Introduced by
# <https://github.com/graphprotocol/graph-node/pull/3511>, maybe as a
# workaround for https://github.com/docker/for-mac/issues/6270?
PGDATA: "/var/lib/postgresql/data"
- ./data/postgres:/var/lib/postgresql/data

Once this is done, you can start your Docker containers by running

docker-compose up

This will start the Docker containers and sync your local node to the existing blockchain from the RPC URL. It might take a while for your node to catch up with all the blocks already mined. You should see something like this —

After syncing

You can check whether your node has synced by looking at the latest blocks on https://blockscout.scroll.io/.

Restarting/resyncing the node

All the data about the blockchain is stored in a local /data folder. If you have to restart your node, this folder will be out of sync and might cause some issues. Hence it is usually best to remove the whole folder and re-sync the whole blockchain from the beginning.

rm -rf /data

docker-compose up

Exposing this node to the internet

Once you know how to create a local node, you could very well replicate this whole process on, let’s say, an Amazon EC2 instance or a Google Cloud server. You could expose the required ports through a proxy like Nginx and make your Graph node available for the community! I won’t be covering this portion in this tutorial because there are several high-quality tutorials out there which can help you do that!

Part 2 [optional] — Creating a subgraph connected to the Scroll graph node

This part assumes that you already have Hardhat installed on your machine. If not, then please first complete these steps from their website.

Note — If you already have a Smart Contract (AND it’s ABI) that you have deployed on the testnet, then you can skip this part and go to Part 3 directly. Make sure to use that ABI in subgraph.yaml while creating the subgraph.

Suppose you are familiar with Smart Contract development using Hardhat and don’t want to follow along. In that case, the complete code for this tutorial can be found in my Github repo here.

After creating the local Graph node in Part 1, we now need to create a new Hardhat project and init a subgraph within this project.

cd ../..

mkdir scroll-example-subgraph

npx hardhat

Accept all the options for now. Once hardhat finishes the installation, your terminal should look like this —

`npx hardhat` output

You can open this project in your favourite code editor, for example, Visual Studio Code. The file structure should look like this —

Project structure

Next, create a .env file at the root of your folder. In that file, you need to add values for these two variables —

ACCOUNT_KEY=XXXX <Private key of an Ethereum account used to deploy the contract>

We also need to install a few npm packages. Run this command —

npm i dotenv @nomiclabs/hardhat-ethers ethers

Once you install these packages, we need to update the hardhat.config.js file to add the Scroll Alpha testnet network. Replace the code in that file with this —

require("dotenv").config({ path: ".env" });

/** @type import('hardhat/config').HardhatUserConfig */
module.exports = {
solidity: "0.8.17",
networks: {
scrollAlpha: {
url: process.env.SCROLL_RPC_URL,
accounts: [process.env.ACCOUNT_KEY],

Let’s write a Smart Contract to deploy on the Scroll Alpha testnet. We will be indexing this Smart Contract from the subgraph that we will create in Part 3 of this tutorial.

For this tutorial, I have written a simple Smart Contract called NaiveWallet.sol. It has three main functions — deposit, withdraw and transfer. Using these functions, anyone can add native cryptocurrency like ETH, remove it and transfer it to another address.

Delete the Lock.sol file from the /contracts folder, create a new file called NaiveWallet.sol and add this code to that file —

// SPDX-License-Identifier: GPL-3.0
pragma solidity >0.8.0;

// Dev Notes - This is a potentially insecure, naive wallet implementation just for the purposes of demonstration and for this tutorial.
// It is NOT AT ALL recommended to be used in Production or to store any real assets.
contract NaiveWallet {
mapping(address => uint) public balances;

event Deposit(address indexed from, uint256 indexed amount);
event Transfer(address indexed from, address indexed to, uint256 indexed amount);
event Withdraw(address indexed from, uint256 indexed amount);

function deposit() public payable {
require(msg.value > 0, "Deposit must be more than 0");
balances[msg.sender] += msg.value;
emit Deposit(msg.sender, msg.value);

function withdraw(uint256 _amount) public {
require(_amount > 0, "Cannot withdraw an amount less than 0");
require(balances[msg.sender] >= _amount, "Cannot withdraw more than you own");
balances[msg.sender] -= _amount;
(bool sent,) = payable(msg.sender).call{value: _amount}("");
require(sent, "Failed to send Ether");
emit Withdraw(msg.sender, _amount);

function transfer(address _to, uint256 _amount) public {
require(_amount > 0, "Cannot transfer less than 0");
require(balances[msg.sender] >= _amount, "Cannot transfer more than you own");
balances[msg.sender] -= _amount;
balances[_to] += _amount;
emit Transfer(msg.sender, _to, _amount);

function getBalance(address _from) view public returns(uint){
return balances[_from];

After writing the Smart Contract, we need to update the deploy script so that Hardhat can deploy our contract to the testnet. Delete all the code from scripts/deploy.js and replace it with the following code. Here, we create an instance of the Naive Wallet contract using the ABI that Hardhat generates after compiling the contract, and then we deploy it using the Private Key mentioned in the .env file.

// We require the Hardhat Runtime Environment explicitly here. This is optional
// but useful for running the script in a standalone fashion through `node <script>`.
// You can also run a script with `npx hardhat run <script>`. If you do that, Hardhat
// will compile your contracts, add the Hardhat Runtime Environment's members to the
// global scope, and execute the script.
const { ethers } = require("hardhat");

async function main() {
const walletContract = await ethers.getContractFactory("NaiveWallet");
const deployedWalletContract = await walletContract.deploy();

await deployedWalletContract.deployed();
console.log("Wallet contract address:", deployedWalletContract.address);

// We recommend this pattern to be able to use async/await everywhere
// and properly handle errors.
main().catch((error) => {
process.exitCode = 1;

Now that we have the Smart Contract and the deploy script ready, we can deploy the contract to the Scroll Alpha testnet. Run this command in your terminal —

npx hardhat run scripts/deploy.js --network scrollAlpha

The output should look like this (your contract address will be different)

Deploying a Smart Contract

Make sure to save the address of this Smart contract because we will need that in the next few steps.

Part 3 — Creating a subgraph on the Scroll Alpha testnet

To get started, you must first install the graph CLI on your machine. To do so, run the following command in your terminal —

npm install -g @graphprotocol/graph-cli

This command will install the graph CLI globally on your machine. Once that is done, we can init the subgraph in our project directory. Make sure that you are in the root directory of your project, scroll-subgraph-tutorial and run the following command —

graph init --node http://localhost:8020 scroll-subgraph

In the above command, http://localhost:8020 is the URL to connect to our local graph node in Docker. This command will ask you for some command line options. For this tutorial, you can enter these values (before the ‘||=>’).

✔ Protocol · ethereum
✔ Subgraph name · gaurangtorvekar/scroll-subgraph ||=> (Note - format is <username>/<subgraph-name>)
✔ Directory to create the subgraph in · scroll-subgraph
✔ Ethereum network · mainnet ||=> (Note - keep this as mainnet for now, we will change it later)
✔ Contract address · 0xfA205A82715F144096B75Ccc4C543A8a2D4CcfaF ||=> (Note - this is the contract you deployed in Part 2 above)
✔ ABI file (path) · artifacts/contracts/NaiveWallet.sol/NaiveWallet.json
✔ Start Block · 213915 ||=> (Note - this is the block number when your contract was deployed)
✔ Contract Name · NaiveWallet
✔ Index contract events as entities (Y/n) · true
✔ Add another contract? (y/n): n ||=> (Note - You can add another contract if you like)

If you enter these values, your terminal output should look something like this —

Graph init

Now, let’s cd into the subgraph directory and make a few changes to the subgraph.yaml file.

cd scroll-subgraph/

Open the file subgraph.yaml in your favourite code editor, and change the value of network from mainnet to scrollAlpha. The file should now look like this —

specVersion: 0.0.5
file: ./schema.graphql
- kind: ethereum
name: NaiveWallet
network: scrollAlpha
address: "0xfA205A82715F144096B75Ccc4C543A8a2D4CcfaF"
abi: NaiveWallet
startBlock: 213915
kind: ethereum/events
apiVersion: 0.0.7
language: wasm/assemblyscript
- Deposit
- Transfer
- Withdraw
- name: NaiveWallet
file: ./abis/NaiveWallet.json
- event: Deposit(indexed address,indexed uint256)
handler: handleDeposit
- event: Transfer(indexed address,indexed address,indexed uint256)
handler: handleTransfer
- event: Withdraw(indexed address,indexed uint256)
handler: handleWithdraw
file: ./src/naive-wallet.ts

Once you make this change to the yaml file, look at the schema.graphql file. In this file, the graph CLI has auto-generated a few GraphQL schemas for you based on the events defined in your Smart Contract.

There is also a corresponding mappings file that can be found in src/naive-wallet.ts. In this file, you can find some code that will be used to populate and sync the subgraph with the appropriate values from the blockchain. That way, you are exposing an API which any DAPP can directly query.

Once you familiarize yourself with the files in your new subgraph and you have made the necessary changes, we need to run a few more commands to create the subgraph on the local node and deploy it.

Run these commands on your terminal —

graph codegen

graph build

graph create <username>/scroll-subgraph --node http://localhost:8020

graph deploy <username>/scroll-subgraph --ipfs http://localhost:5001 --node http://localhost:8020

Once you have successfully deployed the subgraph, your terminal output should look something like this —

Deploying the subgraph

Now that you have deployed the subgraph, any DAPP that you build can query it at the URL http://localhost:8000/subgraphs/name/gaurangtorvekar/scroll-subgraph

Exposing the subgraph to the internet

Like the local graph node, you could deploy this subgraph on a cloud server like Amazon or Google. Using Nginx, you can expose port 8000 to the internet, thus making your subgraph available to the community. However, that is out of the scope of this tutorial.

If you are looking for expert advice for your next blockchain project, or Smart Contract consultants, check out my website.

New to trading? Try crypto trading bots or copy trading on best crypto exchanges

Join Coinmonks Telegram Channel and Youtube Channel get daily Crypto News

Also, Read