The following article is for educational purposes only. All project names or wallet addresses in it, with the exception of BUSD, are fictional. Any association to real ones is merely coincidental.
As an investor or a developer, you’ll find that keeping track of DeFi projects is not as simple as it may sound. There are many reasons to feel restless when you don’t know how they are behaving, so you decide that you need some sort of app for that. While you’ve mastered the ways of the chart and data analysis, you are having trouble getting data. If that’s the case, welcome to the first of four articles on Snapshots with C#.
The main goal for this series is to get you acquainted with the Nethereum library that we’ll be using for said purpose and then develop our very own snapshot tool. After reading this first article, you’ll be able to understand the intricacies of a snapshot. From there, you can pick any of our three articles which correspond to:
- Nethereum and Contract interaction
- Developing a snapshot unit
- Analyzing the snapshot data
Keeping track of everything
Networks like Ethereum can process thousands of transactions in a blink of an eye (well, 10 seconds to be exact). Since they don’t have any downtime, these networks are able to process around 1.15 million transactions per day! So even when we are sleeping, a lot can happen, so most of us try to predict what is going to happen. This sort of prediction results from applying charting patterns and statistical indicators to historical data. It’s not like there’s nothing out there. Exchanges and other trade market platforms have them. The issue here is not that they don’t have it but rather that they either have too much information or don’t track the projects you need and you have to use more than one of these platforms.
If you’re a developer, then you have more than enough reasons to track your projects’ transactions. It’s not unheard of misuse by users that are trying to “win against the system”, and advising them to avoid doing so. You could also be thinking about doing an airdrop and only contract participants are eligible to receive the tokens. Either way, you don’t have the tools you need. So, you are going to create a tool that allows you to do so without much hassle.
Technicalities aside, the real challenge here is getting data. You can’t just go to a network’s node and request information about a single project. They’re not built that way. You can extract records from block explorers like BscScan, or even use their API but, sometimes, it’s behind a paywall, and cheaper alternatives don’t update their data with each new block, or the data lacks the details needed for your analysis. In these cases, a snapshot is your best bet.
The expression sounds familiar, right? The word, by itself, already gives us an idea of what it does. It’s used by our operating systems to make an instant backup of the state of a machine. But the reason you’re so familiar with it might be because you follow some sort of social media related to crypto. The term “snapshot” shows up in news related to hard forks, where it’s used to identify the block height for a new chain, or in airdrops where its results can identify token holders.
The snapshot is not an action the network does, but a process resulting from your requests to the network’s nodes. The entire process implies deciding what your block range is, and requesting the data to the node, block by block. One thing to consider is the guarantee of response. Nodes can, and will, deny access to data when they have a high working load. This happens because the node’s primary responsibility is block validation and propagation.
The request uses two Remote Procedure Calls, “eth_getBlockByNumber” and “eth_getTransactionReceipt”. First, we execute eth_getBlockByNumber. Its result is all the data the block contains, including the transactions. This might be enough to get you started. If you need a transaction’s logs, then you’ll have to call eth_getTransactionReceipt. Getting transactions from swapped tokens is one example where you need the logs since the token’s address won’t show in the transaction.
Let’s use the following as an example. We have this token, let’s call it TKN, and we want to find our balance because TKN lacks the balanceOf method. We know our first purchase on a swap contract was on block #425 and the last one was on block #1278. From BscScan we know we executed seven transactions. This could be a situation where we could extract these specific seven blocks, but we are going through all the blocks.
The following figure would result from our extraction. Notice that we only kept seven blocks, each with one transaction.
Considering that you’ll have issues because of denial of response, you might wonder if setting up a node is a good idea. It might be if your system can handle it. Nodes take up lots of space in disk. For example, between 2021 and 2022’s New Year’s Eve, the network received 2,351,147 new blocks. That’s about 105.8 Gb with an average block size of 45,000 bytes. In comparison, BSC had over 10 million new blocks in the same span. Imagine how much storage you’ll need to keep up with just two networks. The snapshot, on the other hand, is catered to your needs, so you can throw out the transactions that you don’t want.
What can we do with the result of a snapshot?
With the data persisted in a proper database system, you can start filtering what you need to write your conclusions. Besides the block, you’ll have access to transactions and logs. We will use this information later to look for all the transactions related to a token, the list of token holders, and the list of wallets that transferred the token through the following articles. Let’s use our example to get the balance.
Each of those seven transactions has some sort of relationship to the token and our wallet. We still don’t know which operations these are, but we could deduce four common situations:
- The “from” address in the transaction is ours and the “to” address is a swap. That means that we either bought or sold tokens. The token’s address should be in the logs.
- The “from” address is ours and the “to” address is the token. We probably sent tokens to someone, whose address is in the logs.
- The “from” address is someone else’s and the “to” address is the token. We probably received tokens from someone, and our address should be in the logs.
- We’ve executed an operation on the contract that might have changed our balance. We’ll need to look at the logs to properly assess what to do.
From what we gather, all of them belong to the first situation. We can also conclude whether it’s a purchase or a sale by the transfer logs. We made trades to a pair on a swap. Here, we have a pair TKN/BUSD.
If the trade is a sale, the first transfer log has TKN’s address in the address field and the amount sent in the data field. The second transfer log has the pair’s other token (in this case BUSD) and the amount we are getting. If the trade is a purchase, it’s the other way around.
From this analysis, we can determine both the balance and the price at which we bought the token.
|Block||Operation||Amount (TKN)||Amount (BUSD)||Estimated Price||Balance (TKN)|
But these are not the only results we can draw from our data. We could know if our trades were profitable, which they were because we have access to the fees spent in each transaction. So, for simplicity’s sake, if we had feeless transactions and we were to sell all the TKN we have at the same price as the last purchase, then we would profit around 30 BUSD. Through this data, we can also build charts like the approximate price change and the volume during said transactions.
And there you have it. Now that you know what a snapshot is and how it works, perhaps you’ll want to build your own. If that’s the case, why not check out our next article on how to develop your own snapshot application?
One response to “Developing on the chain – Snapshots”
[…] or go back a bit and re-read our introduction to […]