Skip to content

Latest commit

 

History

15 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

📸 ERC20 Snapshot

Capture every holder of any ERC20 token at any block — one command, zero fuss.

Version License Node.js TypeScript viem Last commit

📚 Table of contents

✨ Features

  • 🔍 Full holder discovery — scans every Transfer event since the token's deployment.
  • ⛓️ Any block — snapshot on an exact block number or a tag (latest, safe, finalized, …).
  • ⚡ Multicall balances — resolves all balanceOf calls in batched multicalls, not one-by-one.
  • 🚦 Rate-limit friendly — configurable batch size and sleep timeout between batches.
  • 📊 Ready-to-use reports — JSON + CSV output, plus a details file of the parameters used.

🧠 How it works

flowchart LR
    A["🔎 Scan Transfer events<br/>deployment → snapshot block"] --> B["🧾 Collect unique addresses"]
    B --> C["⚡ Multicall balanceOf<br/>at snapshot block"]
    C --> D["💾 Write JSON + CSV<br/>to ./output"]
Loading
  1. Scans all Transfer events of the token contract, from its deployment block up to the snapshot block, in configurable batches.
  2. Collects every address that ever sent or received the token.
  3. Resolves each address's balance at the snapshot block via a single multicall of balanceOf.
  4. Writes the results to ./output as JSON and CSV, plus a details file with the parameters used.

📋 Requirements

  • Node.js 18 or higher
  • An RPC endpoint (HTTP or WebSocket) for the chain the token lives on
    • 🗄️ An archive node is required when snapshotting on a historical block

🚀 Getting started

git clone https://github.com/JoeyKhd/erc20-snapshot.git
cd erc20-snapshot
npm install
cp .env.skel .env

Then fill in .env:

Variable Description
RPC_URL RPC endpoint of the chain node (https:// or wss://).
DEPLOYMENT_BLOCK Block at which the token contract was deployed.
SNAPSHOT_BLOCK Block to snapshot on: a block number or a tag (latest, earliest, pending, safe, finalized).
BLOCKS_PER_BATCH Amount of blocks scanned per batch when collecting Transfer events.
SLEEP_TIMEOUT Delay in milliseconds between batches to avoid rate limiting.
CONTRACTADDRESS Address of the ERC20 token contract.

▶️ Usage

npm start

Sit back — progress and the remaining time estimate are logged per batch. ⏱️

📂 Output

Reports are written to ./output:

File Contents
report-snapshot-<block>.json Array of { address, balance } records
report-snapshot-<block>.csv Same data in CSV format
report-details-<block>.json The parameters the snapshot was taken with

JSON example

[
  {
    "address": "0x1234567890abcdef1234567890abcdef12345678",
    "balance": "1000000000000000000"
  }
]

CSV example

Address,Balance,Snapshot Block
0x1234567890abcdef1234567890abcdef12345678,1000000000000000000,19000000

⚠️ Good to know

  • 💰 Balances are raw uint256 amounts — they are not adjusted for the token's decimals.
  • 🧹 Addresses that ever held the token are included, even if their balance at the snapshot block is 0.
  • 🗄️ Historical snapshots require an archive node; most free RPC tiers only serve recent state.

📄 License

ISC © JoeyKhd

About

A proper snapshot for ERC20's for various EVM chains

Topics

Resources

Stars

1 star

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages