Replace a Contract and Keep its History With Grafting
Reading time: 6 min
In this guide, you will learn how to build and deploy new subgraphs by grafting existing subgraphs.
Grafting reuses the data from an existing subgraph and starts indexing it at a later block. This is useful during development to get past simple errors in the mappings quickly or to temporarily get an existing subgraph working again after it has failed. Also, it can be used when adding a feature to a subgraph that takes long to index from scratch.
Il grafted subgraph può utilizzare uno schema GraphQL non identico a quello del subgraph di base, ma semplicemente compatibile con esso. Deve essere uno schema di subgraph valido di per sé, ma può discostarsi dallo schema del subgraph di base nei seguenti modi:
- Aggiunge o rimuove i tipi di entità
- Rimuove gli attributi dai tipi di entità
- Aggiunge attributi annullabili ai tipi di entità
- Trasforma gli attributi non nulli in attributi nulli
- Aggiunge valori agli enum
- Aggiunge o rimuove le interfacce
- Cambia per quali tipi di entità viene implementata un'interfaccia
For more information, you can check:
In this tutorial, we will be covering a basic usecase. We will replace an existing contract with an identical contract (with a new address, but the same code). Then, graft the existing subgraph onto the "base" subgraph that tracks the new contract.
Caution: It is recommended to not use grafting for subgraphs published to The Graph Network
Grafting is a powerful feature that allows you to "graft" one subgraph onto another, effectively transferring historical data from the existing subgraph to a new version. While this is an effective way to preserve data and save time on indexing, grafting may introduce complexities and potential issues when migrating from a hosted environment to the decentralized network. It is not possible to graft a subgraph from The Graph Network back to the hosted service or Subgraph Studio.
Initial Migration: when you first deploy your subgraph to the decentralized network, do so without grafting. Ensure that the subgraph is stable and functioning as expected.
Subsequent Updates: once your subgraph is live and stable on the decentralized network, you may use grafting for future versions to make the transition smoother and to preserve historical data.
By adhering to these guidelines, you minimize risks and ensure a smoother migration process.
Building subgraphs is an essential part of The Graph, described more in depth . To be able to build and deploy the existing subgraph used in this tutorial, the following repo is provided:
The subgraph manifest subgraph.yaml
identifies the data sources for the subgraph, the triggers of interest, and the functions that should be run in response to those triggers. See below for an example subgraph manifest that you will use:
specVersion: 0.0.4schema:file: ./schema.graphqldataSources:- kind: ethereumname: Locknetwork: sepoliasource:address: '0xb3aabe721794b85fe4e72134795c2f93b4eb7e63'abi: LockstartBlock: 5955690mapping:kind: ethereum/eventsapiVersion: 0.0.6language: wasm/assemblyscriptentities:- Withdrawalabis:- name: Lockfile: ./abis/Lock.jsoneventHandlers:- event: Withdrawal(uint256,uint256)handler: handleWithdrawalfile: ./src/lock.ts
- The
Lock
data source is the abi and contract address we will get when we compile and deploy the contract - The network should correspond to a indexed network being queried. Since we're running on Sepolia testnet, the network is
sepolia
- The
mapping
section defines the triggers of interest and the functions that should be run in response to those triggers. In this case, we are listening for theWithdrawal
event and calling thehandleWithdrawal
function when it is emitted.
Grafting requires adding two new items to the original subgraph manifest:
---features:- grafting # feature namegraft:base: Qm... # subgraph ID of base subgraphblock: 5956000 # block number
features:
is a list of all used .graft:
is a map of thebase
subgraph and the block to graft on to. Theblock
is the block number to start indexing from. The Graph will copy the data of the base subgraph up to and including the given block and then continue indexing the new subgraph from that block on.
The base
and block
values can be found by deploying two subgraphs: one for the base indexing and one with grafting
- Go to and create a subgraph on Sepolia testnet called
graft-example
- Follow the directions in the
AUTH & DEPLOY
section on your subgraph page in thegraft-example
folder from the repo - Once finished, verify the subgraph is indexing properly. If you run the following command in The Graph Playground
{withdrawals(first: 5) {idamountwhen}}
It returns something like this:
{"data": {"withdrawals": [{"id": "0xe8323d21c4f104607b10b0fff9fc24b9612b9488795dea8196b2d5f980d3dc1d0a000000","amount": "0","when": "1716394824"},{"id": "0xea1cee35036f2cacb72f2a336be3e54ab911f5bebd58f23400ebb8ecc5cfc45203000000","amount": "0","when": "1716394848"}]}}
Once you have verified the subgraph is indexing properly, you can quickly update the subgraph with grafting.
The graft replacement subgraph.yaml will have a new contract address. This could happen when you update your dapp, redeploy a contract, etc.
- Go to and create a subgraph on Sepolia testnet called
graft-replacement
- Create a new manifest. The
subgraph.yaml
forgraph-replacement
contains a different contract address and new information about how it should graft. These are theblock
of the you care about by the old contract and thebase
of the old subgraph. Thebase
subgraph ID is theDeployment ID
of your originalgraph-example
subgraph. You can find this in Subgraph Studio. - Follow the directions in the
AUTH & DEPLOY
section on your subgraph page in thegraft-replacement
folder from the repo - Once finished, verify the subgraph is indexing properly. If you run the following command in The Graph Playground
{withdrawals(first: 5) {idamountwhen}}
It should return the following:
{"data": {"withdrawals": [{"id": "0xe8323d21c4f104607b10b0fff9fc24b9612b9488795dea8196b2d5f980d3dc1d0a000000","amount": "0","when": "1716394824"},{"id": "0xea1cee35036f2cacb72f2a336be3e54ab911f5bebd58f23400ebb8ecc5cfc45203000000","amount": "0","when": "1716394848"},{"id": "0x2410475f76a44754bae66d293d14eac34f98ec03a3689cbbb56a716d20b209af06000000","amount": "0","when": "1716429732"}]}}
You can see that the graft-replacement
subgraph is indexing from older graph-example
data and newer data from the new contract address. The original contract emitted two Withdrawal
events, and . The new contract emitted one Withdrawal
after, . The two previously indexed transactions (Event 1 and 2) and the new transaction (Event 3) were combined together in the graft-replacement
subgraph.
Congrats! You have successfully grafted a subgraph onto another subgraph.
If you want more experience with grafting, here's a few examples for popular contracts:
To become even more of a Graph expert, consider learning about other ways to handle changes in underlying datasources. Alternatives like can achieve similar results