Skip to main content
Rainier Wu

EVM Trackooor: Tracking Anything and Everything on EVM Chains

Zellic is proud to announce the EVM trackooor, a framework for tracking and processing arbitrary data on blockchains
Article heading

Zellic is proud to announce the EVM trackooor, a framework for tracking and processing arbitrary data on blockchains.

With the amount of data that blockchains contain, it’s difficult to query and process anything that isn’t indexed event fields.

This is why we built the EVM trackooor — a modular tool for monitoring arbitrary actions on chain.

What Is the EVM Trackooor?

The EVM trackooor is a framework for tracking any kind of data on a blockchain. It allows users to easily request and handle blockchain data, including event logs, transactions, and blocks mined.

It essentially allows you to register what data you want from a blockchain, whether they’re events emitted from a certain contract or transactions by a specific account. Then, you can define what happens when you receive the data, such as processing it and recording it in a database or sending an alert through a webhook.

The EVM trackooor features the following:

  • Real-time data monitoring, including event logs, transactions, and blocks mined
  • The ability to request historical data, such as past events or transactions that occured within a block range
  • A modular approach to request and process data for any purpose
  • Event and function-ABI fetching to automatically decode event logs and transaction calldata

You can request real-time data to monitor for certain activities, or historical data, providing a block range to process data from a specific time period.

Why Did We Make It?

Blockchains have a lot of data. There are RPC calls to query this data, but creating a new project every time you wanted to query and filter data for specific purposes is troublesome.

The EVM trackooor simplifies this process by being a generic framework for querying and filtering data — all you need to do is tell it what data you’re looking for, and it provides the data directly to you.

For example, let’s say there’s an address 0xcafe... holding native ETH and some ERC-20 tokens, and we want to be alerted when it moves those funds.

On an RPC level, this would look something like

  • (for native ETH) listening for new blocks mined with eth_subscribe("newHeads"), iterating through all transactions in the block to look for transactions by 0xcafe..., and then checking the value of the transaction.
  • (for ERC-20 tokens) listening to Transfer event logs emitted by ERC-20 token contracts, such as the USDT token contract, with eth_subscribe("logs"), decoding the log and checking the from address and value.

This is quite tedious, especially if we want to track multiple different events, as for each event we must have its ABI to decode it.

The EVM trackooor handles all of this — it handles the whole process of retrieving and filtering data and implements a simple method to provide event ABI for decoding event logs.

All we need to do is provide the address we want to monitor for transactions or the contract we want to monitor for event logs as well as a callback function that the EVM trackooor will call with our requested data for us to process. Then in the callback function, we can implement checking the value and sending alerts.

Now, we can easily query for and process data from blockchains, allowing us to create complex modules from graphing funding paths to monitoring contract proxy upgrades and ownership transfers.

Example Code

Here’s example code for the above use case.

package actions

import (
"evm-trackooor/shared"
"evm-trackooor/utils"
"fmt"
"math/big"
"slices"

"github.com/ethereum/go-ethereum/common"
)

var monitoredAddresses []common.Address

func (p action) InitMonitorTransfers() {
// monitor addresses for transactions
monitoredAddresses = p.o.Addresses
for _, addr := range monitoredAddresses {
addTxAddressAction(addr, handleAddressTx)
}
// monitor erc20 token for transfer events
for _, addrInterface := range p.o.CustomOptions["erc20-tokens"].([]interface{}) {
erc20TokenAddress := common.HexToAddress(addrInterface.(string))
addAddressEventSigAction(erc20TokenAddress, "Transfer(address,address,uint256)", handleTokenTransfer)
}
}

// called when a tx is from/to monitored address
func handleAddressTx(p ActionTxData) {
from := *p.From
value := p.Transaction.Value()
// tx is from monitored address (since it can be either from/to)
// and value of tx > 0
if slices.Contains(monitoredAddresses, from) &&
value.Cmp(big.NewInt(0)) > 0 {
// alert
fmt.Printf("Native ETH Transfer by %v with value %v\n", from, utils.FormatDecimals(value, 18))
}
}

// called when erc20 token we're tracking emits Transfer event
func handleTokenTransfer(p ActionEventData) {
from := p.DecodedTopics["from"].(common.Address)
value := p.DecodedData["value"].(*big.Int)

// erc20 transfer is from an address we're monitoring
if slices.Contains(monitoredAddresses, from) {
// get erc20 token info (to format value decimals + symbol)
token := p.EventLog.Address
tokenInfo := shared.RetrieveERC20Info(token)
decimals := tokenInfo.Decimals
symbol := tokenInfo.Symbol

// alert
fmt.Printf("ERC20 Transfer by %v with value %v %v\n", from, utils.FormatDecimals(value, decimals), symbol)
}
}

The EVM trackooor takes a JSON config file, where we can specify the addresses and ERC-20 tokens to track. Here we are tracking the Binance 18 EOA for native ETH transfers and USDT transfers.

{
"rpcurl": "wss://...",
"actions": {
"MonitorTransfers": {
"addresses":{
"0x9696f59E4d72E237BE84fFD425DCaD154Bf96976":{}
},
"options":{
"erc20-tokens":[
"0xdAC17F958D2ee523a2206206994597C13D831ec7"
]
}
}
}
}

An example of the module running is shown below:

How Is This Useful?

The EVM trackooor allows us to process and monitor arbitrary data on any EVM chain.

We’ve already used the EVM trackooor to

  • graph funding paths to visualize movements of funds, including native ETH and ERC-20 tokens

  • listen for ownership transfers and proxy upgrades for high-value contracts

and more!

How Can I Use It?

The EVM trackooor is a command-line tool, and you can access it on GitHub. There, you can access its documentation with more info on usage, including how to use preexisting modules or create your own module.

About Us

Zellic specializes in securing emerging technologies. Our security researchers have uncovered vulnerabilities in the most valuable targets, from Fortune 500s to DeFi giants.

Developers, founders, and investors trust our security assessments to ship quickly, confidently, and without critical vulnerabilities. With our background in real-world offensive security research, we find what others miss.

Contact us for an audit that’s better than the rest. Real audits, not rubber stamps.