Learning NFT Provenance by Example: Investigation Follow-Up

It's been nearly a year since I decided to verify the BAYC's provenance hash and made an interesting discovery. This post is a follow-up on what I've learned since then.

Learning NFT Provenance by Example: Investigation Follow-Up
Photo by Carlos Cram / Unsplash

It's been nearly a year since I decided to verify the Bored Ape Yacht Club's provenance hash out of boredom and made an interesting discovery. I wrote a blog post about it which you should read first before reading this. I also tweeted about it, and for someone with such a small Twitter following, it actually got the attention of some pretty prominent people in the NFT/bored ape space.

Every couple weeks, a big name in the space would find my tweet and it would go through another round of likes/retweets/replies. Still, no response from Yuga Labs or from anyone with real answers.

Then, out of nowhere, I got a reply that looked much different than the rest:

All the credit for this post and its findings go to @kittenpurrrrrr.

What Was Discovered?

This final tweet in @kittenpurrrrrr's thread was exactly the kind of information I was looking for.

The hash in question (5bb1c8a8390c284e9a4634c04eee34dfd08759d66d2b613b0631ab10e2f1f3d9) is actually the hash of an IPFS 429 error. A 429 essentially means that too many requests were coming in too quickly from the same address and the IPFS server decided to block it.

I reached out to @kittenpurrrrrr to see if something similar could explain the remaining hash in question (remember there were 32 hash mismatches, 31 of which were duplicate), and sure enough, they figured that out that this hash (d1d7cec7d41312780f1e5064fd2d199a7bef312ec84c8ceb367005bbb26f5d7a) was that of an IPFS 500 error:

A 500 error is vague and means that any number of things could have gone wrong during one particular asset request.

If you're curious as to how to verify this information for yourself, @kittenpurrrrrr was kind enough to describe his process in a separate thread:

What Does it All Mean?

So how is it possible for an HTTP error page to get hashed and end up in a provenance record? Well, as @kittenpurrrrrr describes, whatever script Yuga Labs was using to generate their provenance data was fetching the image assets from IPFS (as it should). However, their script failed to consider IPFS rate limits and/or failed to include any error handling when requesting assets.

This all comes off as extremely careless and leaves me questioning the legitimacy and integrity of other technical aspects of the Bored Ape Yacht Club. It also shows that no one felt the need to double check any of this information before making it live.

On the plus side, I think this discovery thoroughly answers all outstanding questions regarding the provenance records. Not only does this explain how the collection's provenance contains 32 incorrect hash values (including 31 duplicates), it also explains how that duplicate hash ended up in an entirely unrelated NFT collection. The same HTTP 429 error would produce the same hash even if coming from a script written by a different dev at a different time.

Now that I know this and have thought about it, it really is the only explanation for all of this and I feel silly for not coming to this conclusion myself.

In my (semi) professional opinion, I think @kittenpurrrrrr's findings absolve Yuga Labs of any potential malice solely in regards to their provenance records and hashes. They still have a lot of other shady stuff to answer for, don't get me wrong, and it certainly leaves me questioning the competency of some of the original devs.

Wrapping Up

I'm so thankful to finally put my mind at ease thanks to @kittenpurrrrrr's discovery. Again, this was entirely their finding and they deserve all the credit. I hope you enjoyed this investigative roller-coaster as much as I did and maybe even learned something along the way.

Thanks as always for reading.