What are NFTs and why do they have people so excited?
A Non-fungible Token (NFT) is a digital asset which cannot be copied, substituted, or subdivided, meaning it is wholly unique. This is in contrast to the assets you use on a daily basis which tend to be
fungible. For instance, a pound coin is worth exactly the same as any other and can be freely swapped around without you losing any wealth.
Despite the memes, NFT’s can be used as a variety of items with real world applications, such as: Deeds to a property/piece of land; A domain name (for those old enough to remember the dot com boom); Or, for the focus of this analysis, unique digital artworks. As an example, below is the first NFT, “Quantum”, created by Kevin McCoy.
NFT’s are stored on blockchain systems, notably Ethereum, with the
owner of an NFT being whomever has access to the
wallet it is stored within. Selling a house certainly becomes a lot less of a headache when all you need to do is send the deed to the buyer’s wallet instead of involving lawyers and estate agents.
Quantum NFT, image via Portion, provided by Sotheby’s
Anyone, including robots , can make, buy and sell NFTs. This is usually done via cryptocurrencies on marketplaces like OpenSea (an Ebay for NFTs) or directly from person to person.
Since Quantum many NFT artworks have arisen including Cryptokitties and Cryptopunks. This culminated in a boom in 2021 which included the arrival of the Bored Ape Yacht Club, with NFTS reaching a global market valued of $15.7 Billion.
Set your tokens to spun
With such large amounts moving around in a seemingly unregulated market this has naturally attracted criminals looking to get in on the action. For instance, a recent crime report from Chainalysis revealed that 262 users have been participating in wash-trading their NFTs.
A wash-trade occurs when the buyer and seller within a transaction are the same person or group of people. This is normally done to mislead potential buyers into thinking the asset is worth more, by pumping up the price with each trade, or to make them believe it has very high liquidity, i.e., if they buy it, it can be quickly sold at any point in the future. In reality when they do buy it, they find they cannot sell it to anyone for remotely close to the price they purchased it for.
The authorities have been hot on the heels of NFT crime, where just last month a former NFT marketplace employee was charged with the first case of digital asset insider trading. This won’t stop criminals from attempting to make money off NFT’s, but it will force them to attempt to better obscure their activities.
This got us thinking. Network of transactions… occurring over time… complex patterns hidden in large volumes of data… if only we had a tool to let us investigate further ! Fortunately, Raphtory was at hand to let us dive into the problem.
What are we digging into?
With the above premise in mind, we set out to see what sort of patterns we could find within the network of trades, specifically focusing on
cycles. This is when a NFT has been sold by a wallet, but eventually ends up being owned by it again. This can involve a chain of any number of other wallets, take any amount of time, and increase or decrease the price by any amount.
Below we can see an example of such a cycle where
Wallet A sold an NFT to
Wallet B for
$50 on Monday, but its back in their position by Thursday, costing them
$750. They either have serious sellers remorse or, more likely, the same person owns all these wallets and is trying to pump up the price of the given NFT.
Example NFT cycle across 5 wallets over the course of a week
This example opens many initial questions about the network which we will explore, such as:
- Do users regularly cycle NFTs between each other? And if so, is cycling localised to a small number of wallets or is the practice widespread?
- What is the timespan over which these normally take place?
- Can we actually see typical washing practices like
We have our tools, where’s the data?
To answer these questions we used open data from the “Mapping the NFT revolution: market trends, trade networks, and visual features” paper. This dataset contains 4.7 million NFTs that in total were traded across 6.1 million transactions between June 23, 2017, and April 27, 2021.
The data is pre-classified and contains transaction details for NFT sales including the buyers, sellers, type of NFT, price and time. The sales are spread across various tokens and cryptocurrencies, however, in some cases the price data in USD was unavailable. To handle this, we filtered the data to those traded with Ethereum where we could obtain the average $ Dollar \rightarrow Ether$ price for the day of the trade. This left us with 2.3 million trades across 3,384 NFTs, an example row of which can be seen below.
| Smart_contract | ID_token | Transaction_hash | Seller_address | Seller_username | Buyer_address | Buyer_username | Price_Crypto | Crypto | Price_USD | Collection | Market | Datetime_updated_seconds | Collection_cleaned | Category | | 0xd73be.. | 66733 | 0xcdb2c.. | 0xd0c23.. | GorillaNixon | 0xf6362.. | iMott | 0.008 | ETH | 15.4833 | Blockchaincuties | OpenSea | 2021-04-01 00:05:09 | Block | Collectible |
Modelling the data
Prior research has analysed this data as a network of wallets, however, we took a different approach.
We created a
bipartite graph, meaning a graph with two types of nodes, corresponding to wallets (addresses) and NFTs. Directed edges $Wallet\rightarrow NFT$ in this network indicate a purchase.
From the perspective of an individual NFT within this model we can see all the wallets which have purchased it, when these occurred and for how much. With this information it is trivial to rebuild cycles of any length.
Below is an example of a bipartite graph. On the left we have Ethereum wallets, the right NFTs, and the edges indicating who has purchased what. Some of these transactions (in green) appear to be innocuous, whereas others (in red) are part of a cycle to pump the value of
Digging into this we can see that there is a wallet cycle $A\rightarrow B\rightarrow C\rightarrow A$ over the course of 4 blocks, pumping the price from 0.8ETH to 2.6ETH.
Example of an NFT Bipartite Graph. Red arrows indicate the transaction is part of a cycle, green arrows indicate the transaction is not.
Click me if you want a deeper dive into the model and algorithm!
Why do we model the data like this?
Cycle detection is a notoriously hard algorithm to run on large networks because you need to track the entire path you have traversed so far. This explodes exponentially with the size of the cycle you are looking for, quickly becoming impossible to calculate. This would be the case if we had to
follow each NFT along the transaction edges in a network of wallets.
By instead splitting the NFT's into their own set of nodes (as above) we have all the information on the transactions each has been involved in within the edge lists of the NFT vertex. With Raphtory's time-focused API's we can easily order all the edges chronologically and then loop through them to find all cycles. This means even if there are cycles involving thousands of transactions/wallets, they are just as easy to detect as triangles.
Let's get the data into Raphtory
Now we understand our data and know how we are going to model it we can create our
Graph Builder. In Raphtory, Graph Builders are responsible for turning data into graphs, a little bit like a loose schema. They do not track previously seen nodes and edges as all of this is handled internally by Raphtory. All they require is a parsing function which says, for each row, what is converted into vertices and what is converted into edges.
In our data, each row contains a transaction. This transaction states the buyer, seller, NFT, time and the financial cost. We, therefore, want to tell the Graph Builder that for each row we will take this information and parse it in the following way:
- The Buyer Node $\rightarrow$ Generate an
addVertexupdate to say we have seen the wallet at the given timestamp.
- NFT $\rightarrow$ Generate an
addVertexmessage to say we have seen the NFT at the given timestamp.
- Purchase Transaction $\rightarrow$ Generate an
addEdgemessage to say the buyer wallet purchased the NFT at the given time for the converted dollar price.
Note here that the seller is not required as we have all the buyers (who are going to be the next seller if there is one). The code for this Graph Builder can be found here.
What does the algorithm look like?
Now we have converted our data into a graph, we can do some analysis using built-in Raphtory algorithms or write our own. Let's write a cycle detection algorithm.
Our cycle is defined as follows:
- Alice owns an NFT(cat)
- Alice sells her NFT(cat) to someone else
- After some time, Alice repurchases her NFT(cat) at a higher price than she sold it.
appreciatedin value through the cycle.
To find these cycles, we:
- Select each NFT and get all of its edges in chronological order.
- List the buyers of these transactions and loop through them in order.
- Track all unique buyers as we loop and if we see one repeated go back through the list to build up the cycle.
- Record this cycle for output and continue where we left off.
This process ensures we only have to pass over the data once ($O(n)$) and do not need to record anything until we find a cycle, minimising memory overhead. The code can be seen on github here.
What did we find!
After running this algorithm, we identified 16,673 cycles whereby the user had purchased the NFT at a higher price than they originally sold it at, which we denote as an
appreciation. Of these over 90% appreciated less than $80, but there is some very strange patterns in the outliers.
Below we have two plots comparing the cycle duration to both the length of the cycle (unique involved wallets) and appreciated price for the traded NFT. What is really startling here is that the cycles involving the most wallets overwhelmingly finished in the shortest amount of time whilst generating the greatest appreciation! This was deeply fishy and needed to be probed further !
Left: A plot of the duration of cycles in days against the number of unique wallets involved (cycle length). Right: The duration of cycles against the appreciation in USD since the original purchase.
Are large cycles always suspicious?
Not at all, there are many instances where this is totally legitimate behaviour and makes sense when you have a niche community trading amongst themselves. For example the longest cycle found involved an NFT from the Major League Baseball collectible game, traded over 206 times. This specific NFT started with the buyer (0xe7387) originally purchasing the figure for ~22.68 USD (0.1296 Ether) then repurchasing it after 44 days for ~26.24 USD (0.1296 Ether).
Given the large amount of time between their first and last purchase, and the low profit, this is much more likely someone just repurchasing a collectable they wanted back.
But some certainly are!
In contract to the above, one cycle identified is of a user who purchased Cryptopunk 8033 for 25 ETH (48,490 USD), held it for about 22 days before selling it for 45 ETH (79,459 USD) and then purchased it back after 6 days for 54 ETH (95,912 USD). These transactions and the Cryptopunk in question can be seen in the figure below. I certainly would have kept the tidy $30,000 profit instead!
Purchases and sales of Cryptopunk 8033 by the same wallet
Thar She Blows!
Whilst an individual cycle may or may not be suspicious, if we see the same repeating patterns involving the same wallets, the evidence can compound. The next question is, therefore, are there certain groups or individuals conducting the majority of these cycles?
From the total 352 traders we find that the vast majority (322 traders (~91.48%)) had been involved in 4 or less cycles. A small contingent in the middle (10 traders (~2.84%)) conducted between 4 and 14 cycles. Leaving a small subset of
Whales (20 traders (~5.68%)) to conduct between 528 and 617 cycles each!!
Lets go whale watching
Picking out one of these whales from our dataset we found that trader 0x8acc was involved in 617 cycles, gaining a total appreciation of ~1,389 USD (averaging $2.25 per trade). By looking further into these cycles, we find that they traded 32 NFTs belonging to Etheremon, Cryptokitties and Mlbchampion between 20 wallets across 12,874 transactions. A selection of these NFT’s can be seen below.
Three of the 32 NFT traded by wallet 0x8acc
By exploring the inter-purchase times of each transaction within the cycles we further identified that over 88% of transactions executed in 3.4 hours to 4.6 hours increments. For example below we’ve simplified the transaction time deltas of Ethermon #34508 being traded between these wallets.
First Buy - 0x2c14a11af2efcd71ecbf6e391f423d8d82a719d12cd38a78cb6cfcb8911647e8 Delta 3.9h - 0x578603b33e4ab6d6402a87e9c096d0b9c6ba345caf168ae580fab88f487844c2 Delta 4.0h - 0x8ca90485db647c962d65be927b7235efd06b1f50c3766cd99f8b36fa7d1cadd5 Delta 3.9h - 0x6bd619cd1568f54c2c8567fcd4d2095e4ae0d1d6825c85cdcb252e9712f6cd71 Delta 3.9h - 0xf5b233b07db48da23f4d52e34b6128dd45d81db3fc4581cd126edf234ade931a Delta 3.9h - 0x2002b28210f7ac948a4154e76a6fe6f48d23c6527476554c8d165cea90543b49 Delta 4.0h - 0xc7526f495bde6bfa21dd89bc091043ffdeaa77d39e43d737d189ac5c7d714598 Delta 3.9h - 0x5b6089495d305313d193bf4805ac68cf53bfa770c443ed3565656cde51722673 Delta 4.0h - 0x97484bbaa9c47a9b62b4d221248c1ccbd5902bca58176bf1df3cac57bb99e1c4
Repeating this analysis on the rest of our whale pod we discovered that these too followed the same pattern, purchasing and trading NFTs between the same groups of wallets, with the same 3-4 hour time window.
The dataset we used did not take into account transaction fees. Due to the small price changes on these NFT’s across the cycles (probably less than the total fees paid for the transactions) these accounts could be a number of points. These could be accounts owned by the same entity or group performing wash-trades, a veteran NFT trader trading within their close knit community or a case of NFT creators employing automated Market Maker bots to generate liquidity for their tokens. This is useful in someways as it kick starts the community and allows first adopters to easily make purchases, but can veer towards misleading if overused.
Conclusions and Future Works
This was a very brief run through a dataset ripe with many interesting questions and research avenues to dive into. In our next blog on this topic, we will look into processes for detecting victims of a pump and dump and allocating risk scores to NFT’s based upon many different network metrics including the cycles discussed here.
We are also in the process of acquiring a much more up to date version of the same data, including both the Bored Ape Yacht Club explosion and recent NFT market crash. Both of which we can look at under the same lens!
Interested in giving it a go yourself?
The basic version of this algorithm is available for free as part of the Raphtory Open Source Project. This can be run on any data you like as long as it fits the bipartite model described above.
If this is your first step into the world of temporal graphs, consider checking out the Introduction to Raphtory which will lead you into our Getting started guide. If you run into any issues you can get assistance from the wonderful Raphtory community on Slack.
If you would like to run these algorithms at scale in a production environment, drop the team at Pometry a message, and they will be more than happy to help.
The original data from this project was from here:
- Nadini, M., Alessandretti, L., Di Giacinto, F. et al. Mapping the NFT revolution: market trends, trade networks, and visual features. Sci Rep 11, 20902 (2021). https://doi.org/10.1038/s41598-021-00053-8