前言
当我们购买一个NFT时,这个NFT对应的图片数据到底放在了哪里?为什么说NFT是不可修改的?
这里我以一些知名项目为例,看看这些项目将NFT存放在哪里?我抽了几个项目作为例子,进行简单的解释。
CryptoPunks(加密朋克)
在opensea中,搜索CryptoPunks,便可以找到这个NFT的早期项目,虽然早期,但很赚钱。
在NFT发展早期,比较多流程没有规范起来,CyrptoPunks作为早期项目,很多东西与当前的NFT项目会有较大差异,比如,其存放数据图像数据的地方。
严格来说,CryptoPunks的图像数据没有进行分布式存储,而是基于大家的共识约定着玩CryptoPunks,我们具体看看。
从opensea随便选一个CryptoPunks图,然后看到其Details中的contract address,即合约地址。
访问这个合约,然后找到imageHash
它记录着下面这张图的hash值(https://www.larvalabs.com/public/images/cryptopunks/punks.png)
而这张图,就是10000张CryptoPunk图片拼接起来的完整CryptoPunk,那怎么证明其中某个CryptoPunk图像属于某个人呢?
首先,CryptoPunk合约通过imagehash将完整CryptoPunk的图片的hash值记录在ETH上,确保imagehash不可变。至于某个用户是否用于其中一个CryptoPunk NFT,可以通过一个mapping结构将其存起来。
通过CryptoPunk合约提供的punksOfferedForSale方法可以找出某个CryptoPunk NFT属于哪个账户地址
这个地址,可以与opensea中记录的account address对应上。
一个有趣的想法是,对于拥有这些高知名度NFT项目的account address可以监控起来,因为他们有比较多的资金在圈子里,是重度玩家,这些玩家的一些操作,值得参考与借鉴。
对CryptoPunk而言,NFT的图像数据其实没有上链,它只是将image hash存了一下,仅此而已。
Bored Ape Yacht Club(BAYC,无聊猴)
在讨论BAYC时,简单提一下NFT规范是怎么变成当前这样的。
一开始,ERC721和ERC1155这些规范并没有规定NFT的数据规范,具体而言,就是没有规定metadata的格式,这让类似opensea这样的平台比较痛苦,他需要兼容不同的metadata格式,后续ERC721Metadata和ERC1155Metadata推出,规范化了metadata的格式,对于早期知名项目opensea做了单独的兼容,但如果现在要发NFT,就需要根据规范来玩,不然opensea是无法从的metadata中获取属性、图像位置等数据的。
在ERC721Metadata中给定义了一个外部方法:tokenURI,通过tokenURI,可以访问NFT相关的数据。
这里,你可能对什么是metadata不太清楚,没事,BAYC就很好的遵循,分析BAYC时,你就会很好的理解metadata和tokenURI。
随便在opensea找一个BAYC的NFT,依旧找到其Contract Address
然后直接找到tokenURI属性(其实也是一个mapping,tokenid 映射 token uri),传入token id,即上图的9611,获得如下内容:
即BAYC的tokenURI属性记录着ipfs地址,ipfs是一个分布式的文件系统,下一篇文章会介绍一下ipfs,这里先定性理解:ipfs上的热门数据是不会被删除的。
我们将ipfs的地址复制到浏览器中访问,我使用的chrome浏览器,它不支持直接访问ipfs,你需要先安装ipfs客户端并将其运行起来。
访问 ipfs://QmeSjSinHpPnmXmspMjwiXyN6zS4E9zccariGR3jxcaWtq/9611 时,会弹出提示。
最终得到如下内容:
这便是token id为9611的NFT的metadata。NFT的metadata其实就是一段JSON,用于记录当前NFT图片存放位置、NFT的属性:
{"image":"ipfs://QmZ73BEq4kYGztD9X6B4e71McCfnpaRSPDTsXdhcd4MWoB","attributes":[{"trait_type":"Earring","value":"SilverHoop"},{"trait_type":"Background","value":"Blue"},{"trait_type":"Eyes","value":"Closed"},{"trait_type":"Clothes","value":"TuxedoTee"},{"trait_type":"Mouth","value":"Discomfort"},{"trait_type":"Fur","value":"Brown"}]}
从metadata的image字段存放着NFT的图像的ipfs地址,访问一下,最终获得与opensea中一致的图像。
从BAYC来看,BAYC将metadata和image都存放了ipfs系统上,从而避免文件被随意修改。
Mutan Ape Yacht Club(变异猴)
同样在opensea中找到MAYC项目的任意一个NFT,然后访问它的合约。
查看tokenURI,发现里面存的是url
存url,而且这个url是他们官网的url,即中心化的形式,项目方可以轻松替换掉当前url返回的内容,从而改变当前NFT。
访问这个url,发现是metadata。
{"image":"ipfs://QmcPHJhQtn8i5HspxQ3Kd4wwgZequJgpdUdKhSKdvmzJp7","attributes":[{"trait_type":"Background","value":"M1ArmyGreen"},{"trait_type":"Fur","value":"M1DarkBrown"},{"trait_type":"Eyes","value":"M1Sunglasses"},{"trait_type":"Clothes","value":"M1Service"},{"trait_type":"Mouth","value":"M1BoredUnshaven"}]}
访问metadata中image字段对于的ipfs,就是图片了。
嗯,有点掩耳盗铃的意思。
Azuki
这是之前很火的项目,我看周围一些朋友的微信头像都换成了Azuki的头像,估计赚了不少。
老样子,直接访问合约的tokenURI,发现也是一个url。
但从url可知,这个url是pinata服务提供的,pinata是一个方便你上传NFT到IPFS的服务,通过API就可以快速上传了,不需要你本地搭建IPFS。
pinata的URL其实对应着ipfs的路径,当用户访问url时,本地不需要安装ipfs客户端,pinata服务内部帮我们做好了映射,我们访问pinata的url时,pinata会找到对于的ipfs并从中获取数据,然后再转发给我们。
但严格说,Azuki还是可变的,比如映射逻辑变了,那么此时tokenURI因为存的是pinata的url,所以Azuki NFT的内容也会改变。
尾
我们看了4个项目,简单总结一下:
CryptoPunks:ETH中存image hash,没有Metadata,图片数据基于HTTP协议获取(即中心化服务),但image hash不可被更改
BAYC:ETH中存储metadata的ipfs url,metadata数据存放在ipfs中,对应的图像也存放在ipfs,这种形式下,项目方无法修改BAYC的NFT
MAYC:ETH中存放http url,而且是项目方自己的http,可以轻易被修改,Metadata数据通过http获得,图像存放在ipfs中。
Azuki:ETH中存放http url,pinata服务的http url,这个url与ipfs有映射关系,但毕竟是pinata服务,映射关系是可以改动的,即Azuki也是可以被修改的,Metadata数据存放在ipfs中,图像也放在了ipfs中。
简单而言,最靠谱的便是BAYC的形式。
我是二两,下篇文章见。