锐单电子商城 , 一站式电子元器件采购平台!
  • 电话:400-990-0325

NFT及OpenSea交易背后的技术分享

时间:2022-09-24 23:30:00 bf3v系列圆柱形光电传感器

前几天发现了一个人工智能学习网站,通俗易懂,幽默幽默,忍不住和大家分享。点击跳转到网站。


这段时间NFT市场火爆,原本准备和大家分享的去中心化存储项目改为本文NFT及OpenSea学习分享。

最近购入了NFT你可以看到你花了很多钱买的NFT背后是什么?OpenSea如何实现对NFT如果你做生意,这篇文章可以作为一个介绍。也许这篇文章是你成为货币圈所谓科学家的启蒙教程。

从我第一次买NFT的故事讲起

今年1月3日,我从推特上看到周杰伦发行他的消息。NFT PhantaBear,所以我们应该以粉丝的心态去理解。当时发现熊的地板价只有0.4ETH,所以马上花了2ETH买了四只熊。(后来被买了。 @BTCdayu 传授经验应该购买稀有属性,然后购买两只稀有熊)

两天后,我在推特上看到很多人说PhantaBear因为周杰伦发表了切割声明,项目不值得投资,所以我在推特上发表了自己的观点PhantaBear,同时公开打赌PhantaBear如果一年后年化收入不到300%(2)E,打赌时,小熊地板的价格是0.6E愿意多送一只熊。结果没想到过了两三天就打了自己的脸。关于我的观点和公开赌注,可以参考这条推特。https://twitter.com/nelsonie/status/1478618887537233922

一般来说,能在用户心目中占据第一位的项目都是比较好的目标。比特币是整个区块链行业的先驱,所以它是最值得投资的目标;以太坊在第二代区块链中排名第一,因此也值得投资(尽管我没有头寸);CryptoPunks是第一个NFT项目也值得投资。(18年有一个加密猫游戏,好像是我印象中的那个。NFT但现在似乎没有人提到祖先?)

而PhantaBear是华人圈第一个NFT同时,随着我的成长,这个项目也是天王带来的,所以它必须在理性和情感上赢得。

自己在很多时候crypto该行业的投资更关注该项目背后的故事及其意义utility token分析是否有用,是否解决了行业的痛点或问题。

自购入了人生中的第一个NFT之后,上周整周刷推特,混小熊。discord(修炼升级,偶尔有明星聊天),刷floor price,浪费原本安排写作的时间。

所以本周开始放弃各种刷刷social network,学习研究OpenSea平台上交易NFT并记录和分享技术细节。毕竟,在繁荣之后,我们仍然需要积累和沉淀一些东西。

这篇文章被鄙视会先说NFT的合约(ERC721)以及NFT在OpenSea以上是如何实现交易的,这两部分的内容比较偏技术,希望能耐心阅读。

前面废话太多,下面正式开始。

NFT与ERC721

NFT不要说名词的定义。网上有很多信息可以自己搜索。

对于NFT其实就是Ethereum协会定义的规范,即ERC它的作用是和Fungible Token的ERC20规范是一样的,接口是通过这个规范统一的。Token或者NFT各种各样的出各种各样的东西DAPP各种生态,比如Swap、贷款等等DAPP。

上面提到的可能有点抽象。以广告为例:为了学习写合同,我练习了一个分散的红包DAPP,其实就是把微信红包这个产品搬到区块链上,区别在于红包DAPP各种各样的人塞进红包里Token。这个红包DAPP支持一切的原因Token,正是因为它适应了一切Token都遵循的ERC20规范。

NFT的ERC721规范是从ERC衍生出来的方法有很多相同的方法,以下规范方法如下:

// 查询NFT中某个owner拥有的数量 balanceOf(owner)  // 查询NFT哪个人属于中号,例如查询某个编号的猴属于哪个owner ownerOf(tokenId)  // 返回NFT的名字 name()  // 返回NFT的符号 symbol()  // NFT总发行量 totalSupply()  // 返回某个NFT的URI,这个URI就是这个NFT所有描述信息 tokenURI(tokenId)  // 按index序号返回该owner的所有持有NFT的编号 tokenOfOwnerByIndex(owner, index)  // 按index序号返回NFT的编号 tokenByIndex(index)  // 允许to这个地址可以转移到他身上tokenId编号的NFT(攸关你的NFT安全!) approve(to, tokenId)  // 查询tokenId编号的NFT授权给谁(查询谁可以转让你NFT!) approve(to, tokenId)  // 查询tokenId编号的NFT授权给谁(查询谁可以转让你NFT!) getApproved(tokenId)  // 授权或取消授权operator这个地址转移给你Collection下的所有NFT(攸关你的NFT安全!) setApprovalForAll(operator, approved)  // 查询某个operator是否有权转让某个owner的这一Collection中的所有NFT(查询某个地址是否可以转让你Collection的所有NFT!) isApprovedForAll(owner, operator)  // 将from这个地址的tokenID编号的NFT转给to这个地址(需要授权) transferFrom(from, to, tokenId) 

以上是几个主要的ERC721规范的方法,虽然写了注释,但我猜大家还是一脸懵。

所以下面给大家通过例子来说明,从NFT的起源Mint开始。

Mint铸造

下面的代码是OpenZeppelin如何铸造最后一个简单的NFT的代码:

// 铸造NFT方法只需要传入铸造给谁,再加上这个NFT的tokenURI即可 function awardItem(address player, string memory tokenURI)     public     returns (uint256) {     _tokenIds.increment();     uint256 newTokenId = _tokenIds.current();      // 将这个新的tokenId与player绑定     _mint(player, newTokenId);      // 将tokenURI与这个newTokenId绑定     _setTokenURI(newTokenId, tokenURI);      return newItemId; } 

铸造NFT其实就是往NFT两条信息写在合同中:

  • tokenId及其owner
  • tokenId及其tokenURI

有人说NFT还有图片和各种属性。为什么这么简单就铸造出来?

是的,就这么简单!

接下来我们用CryptoApes这个NFT给大家举个例子,看看我们看到的各种眼花缭乱。NFT是怎么展示的?

Play with NFT contract

让我们来看看如何通过简单的几行代码查询CryptoApes NFT基本信息:

从截图中可以看到,通过方向CryptoApes上述合同调用ERC721规范的方法name(),symbol(),totalSupply(),你可以得到这个NFT名称、符号和总数分别为:CryptoApes,CRAP,6969

CryptoApes的合约地址以及NFT编号可以在OpenSea中的URL拿到,见以下截图:

可以看到OpenSea的NFT链接 https://opensea.io/assets/0x29714cafe792ef8b8c649451d13c89e21a0d7f5b/24 ,assets后面的第一个地址是NFT Collection的合约地址,合同地址后的数字是NFT编号

让我们通过几行简单代码调用合同,查询这个号码为24CryptoApes的信息:

我们可以通过ERC721规范中的 ownerOf() 方法,你可以找到这个CryptoApes拥有者(是的,是我自己)。

另外通过 balanceOf() 方法可以发现我总共有四个CryptoApes。

值得注意的是,截图中的截图 tokenURI() 这种方法可以通过它获得24号NFT的tokenURI。这个tokenURI非常重要!因为它存储了所有关于猴子的描述信息(Metadata)

24号猴的tokenURI是:ipfs://QmWGAFtzyzB6A6gYMnb6838hysHuT2rcV8B98Gmj4T4pyY/24.json,说明是存储的IPFS分布式存储json文件,我们继续这样做IPFS的网关地址(https://ipfs.io/ipfs/QmWGAFtzyzB6A6gYMnb6838hysHuT2rcV8B98Gmj4T4pyY/24.json) 访问内容:

上面的截图是这只24号猴子的所有信息,包括名字、图片、描述、编号、创建时间、背景颜色、头发颜色、嘴巴衣服等属性。(点击大图片就可以看到。

其中的图片信息又指向了另外一个IPFS地址:ipfs://QmZFnUm3bjSyEPrvxEa3fR9eUxnkfQeLmPTzDhAmCWtbMZ/24.png,通过这个地址(https://ipfs.io/ipfs/QmZFnUm3bjSyEPrvxEa3fR9eUxnkfQeLmPTzDhAmCWtbMZ/24.png) 就能看到24号猴的图片了,这也是OpenSea平台中给大家展示的图片样子。

大家可以看到NFT的所有关键信息都是存在tokenURI这个链接中的,这个链接中的数据包括了你NFT的编号、属性、图片或视频,所以tokenURI这个链下数据能不能正常访问,会不会被篡改非常重要!!!

这里CryptoApes的TokenURI用的是IPFS协议,IPFS协议可以保证不会被篡改。但如果是HTTP协议则有被篡改的可能,虽然使用HTTP协议可以通过checksum校验数据等方式验证,但这并不优雅,并且也不是ERC721的协议规范。

这里插一句,鄙人原本打算写一篇介绍去中心化存储的文章的,因为感觉这个领域的重要性被大家严重忽视了,它也是区块链生态的基础设施,重要性并不比被热捧的各类公链项目低。 使用IPFS协议存储内容虽然不会被篡改,但是IPFS还存在它自身的问题,这里就不展开了。

接着说,上面我们查到了编号24的猴的所有关键信息。那如果想把所有6969只CryptoApes的信息查找出来可以吗?

当然可以!使用上述ERC721规范中的“tokenByIndex()”方法进行遍历就行,有兴趣的朋友可以自行试试。

实际上OpenSea支持所有的ERC721的NFT的信息展示,就是通过上述方法去链上抓取数据,并在OpenSea自己的系统中来建立起来所有资源信息,最后通过Web的形式展现到大家面前,方便大家浏览。

这里需要吐槽的是OpenSea网站的robust及performance做得实在太烂了,经常动不动就挂掉,所以鄙人也正着手搞一个类似的产品,从blockchain上同步NFT数据,以及从OpenSea上同步交易数据,存储后按用户需求展示给用户,提供稳定、高效以及易用的浏览及查询服务。(做得好的话未来想象空间也很大,哈哈)

上面通过脚本调用合约给大家展示的都是“”方法,“”方法的话就是在代码中加载钱包,签名之后就可以了。(所以挺简单的吧,大家也别被所谓“科学家”这个名字唬住了。简单学习一下编程,再熟悉下合约的调用,就可以通过程序操作多个钱包,去薅羊毛还是干点别的事情就都可以了)

需要警惕的一些方法

ERC721规范中有两个方法需要大家警惕一下,如果不小心也许就会丢掉你的NFT

第一个需要警惕的方法是“approve(to, tokenId)”,这个方法是授权“to”这个地址有权利可以转走你这个“tokenId”的NFT。如果你在小狐狸中授权钓鱼网站调用了这个方法,最多会损失一个NFT。

这个方法ERC20规范中也有,ERC20是授权“to”地址最多可以使用多少数量的token。鄙人的去中心化红包项目,就是在你发红包之前要求你使用“approve”授权一下,好让红包合约可以扣你的token并装入红包中给大家去抢。各类Swap的DAPP也是一样,需要先“approve”才可以进行swap。

第二个需要警惕的方法是“setApprovalForAll(operator, approved)”,这个方法是授权“operator”这个地址可以转走你在这个Collection下所有的NFT。如果你在小狐狸中授权钓鱼网站调用了这个方法,则可能丢失这个Collection下的所有NFT。

在OpenSea平台中,如果我们“Sell”一个NFT,小狐狸就会弹出这个方法的授权,见下面截图。

注意红框里的内容,就是向CryptoApes的合约地址调用“setApprovalForAll(operator, approved)”这个方法。授权之后,如果有人出价购买,OpenSea的交易合约则可以把你的NFT直接转给买家,转给买家这个操作调用的是ERC721规范中的方法“transferFrom(from, to, tokenId)”,from是你自己,to是买家,tokenId是这个NFT的编号。

所以大家在小狐狸中进行授权的时候,一定有安全意识,看见approve或者setApprovalForAll方法时一定要注意是不是正规的网站,合约地址是不是正确的地址。如果不小心授权错了,你的NFT就可能被转走。

也许有人会问:我只卖出一个NFT,为什么不单独授权这一个出售的NFT(approve),而是要授权所有的NFT呢(setApproveForAll)?

答:OpenSea的解释是可以省gas费,一次授权后,再次卖出其余NFT的时就不需要因为再次授权而付更多的gas费用了。

也许有人会问:那我授权给了OpenSea所有NFT的转移权限,那OpenSea平台会不会悄悄转走我的NFT呢?

关于这个这个问题可以继续看后面。

OpenSea买卖流程的背后

卖出NFT的背后

下图是在你卖出NFT时候的弹窗截图:

在OpenSea上进行卖出操作时,会弹出窗口第一步让你先初始化钱包(这个是一次性操作),在你付了gas费之后,OpenSea的Registry合约会帮你创建一个钱包合约(实际上就是一个Proxy合约),大家如果在etherscan上查的话,可以看到一个RegisterProxy的操作,实际上调用的就是下面代码去创建了一个属于你个人钱包合约:

function registerProxy()
        public
        returns (OwnableDelegateProxy proxy)
    {
        require(proxies[msg.sender] == address(0));
        // 创建一个新的代理合约
        proxy = new OwnableDelegateProxy(msg.sender, delegateProxyImplementation, abi.encodeWithSignature("initialize(address,address)", msg.sender, address(this)));
        proxies[msg.sender] = proxy;
        return proxy;
    }

为什么需要创建这个合约呢?主要目的是为了安全,因为第二步“Approve this item for sale”时需要授权一个合约地址可以转移你的NFT(也就是上一段落说的setApprovalForAll方法),授权可以转移你NFT的地址,就是“Initialize your wallet”这一步所创建的钱包合约地址。

也就是说OpenSea不能直接转走你的NFT,只有你在OpenSea上初次创建的这个钱包地址才可以转走。

在创建完钱包以及授权NFT之后,如果你去挂出同个Collection下的NFT进行卖出时,不需要额外的手续费,OpenSea仅仅验证你的签名就可以挂出卖单了,这点就是被OpenSea宣传的“gas-free listing”。

所以讲到这里,也许有人又注意到了一个问题:为什么后续挂出卖单仅仅只需要签名,不需要 transaction呢?OpenSea的卖单信息只是存到它自己的中心化服务器上,没有存在链上吗?

答:是的,卖单信息只存在OpenSea的中心化服务器上,没有上链,具体可以参考这里OpenSea的解释。

On OpenSea, most actions are off-chain, meaning they generate orders that are stored in the our system and can be fulfilled by a matching order from another user.

When a user lists an item for sale, they simply sign their intent to swap the item for payment. This intent is stored in the OpenSea system as a sell order, and does not create a transaction.

关于很多评论说OpenSea太过中心化这个问题,之后鄙人也会简单谈谈自己观点。

买入NFT的背后

在OpenSea买入的时候,买卖的撮合其实是发生在OpenSea的中心化系统中,匹配好订单后让用户调用OpenSea交易合约地址的AtomicMatch方法完成交易,这个方法里完成了一系列复杂操作,这里就不展开讨论了。

也就是说成交之后,成交订单的信息会上链,毕竟这涉及到了Token和NFT的转移。

OpenSea使用的交易合约应该是Wyvern协议,实际上如果整个交易过程中只有最终交易数据才上链的话,可以不用这么复杂的合约,不过这应该是历史遗留包袱。

大家只需要知道这次买入交易成功的背后,会完成这两个步骤:

  • 把NFT转给买家
  • 把买家的钱转给卖家和OpenSea(平台手续费)

其它交易方式

关于Offer报价以及Auction拍卖的交易方式鄙人没有试过,不过我认为跟Listing交易一样,在offer或者bid之前approve一下你的WETH就行,而auction拍卖订单和Offer报价订单的创建与撮合也应该还是通过OpenSea的中心化系统完成。

关于OpenSea太过中心化的评论

鄙人在网络上看到很多声讨OpenSea太过中心化的评论,这段时间开始买NFT对OpenSea进行研究了之后才了解这些评论的根本原因,实际上OpenSea也是基于当时条件限制下的产物。

鄙人这里也为OpenSea的部分中心化技术方案辩驳几句:

  • 首先它降低了手续费,贵族链绝非浪得虚名的。如果所有数据信息上链那必然会导致交易的成本上升,更加提高了用户的交易门槛。(如果所有信息上链的话,我想唯一的好处就是鄙人不会每天收到批量offer的邮件通知了,毕竟每一次offer都需要燃烧gas)
  • 其次Etheruem的performance不足以承载大量的transaction,如果每次挂出卖单、修改卖单价格、每次Offer价格等所有信息都上链的话,那会更加进一步推高Ethereum的gas费用。
  • 最后关键信息上链也一定程度上确保了交易的安全和公开。比如你NFT和WETH的授权是给到你的钱包合约的,OpenSea不直接触碰。OpenSea也开放了它的API,所有未上链的订单数据可以通过API获取,好心人可以通过API拿到数据后和链上最终的交易数据进行比对验证。(不过我猜测不存在这样的好心人吧)

最近这一年公链的迅猛发展,gas费过高以及性能的问题以及得到了极大的缓解。如果OpenSea不思进取、不做改进的话绝对会被大多数用户抛弃,最后发展成为贵族NFT市场,比如前几天LooksRare平台也来空投抢用户了。当然这个问题也是Ethereum需要面对的。

关于OpenSea的交易背后本人有两个问题:
**

  1. 本人发现在OpenSea上Cancel一个Listing订单,也是需要写入区块链的。但我觉得直接在OpenSea的中心化系统中直接Cancel就好了,毕竟Listing的订单信息也没上链啊,为什么Cancel Listing订单的操作需要上链呢?这gas费不是白白浪费掉了吗?
  2. Listing订单价格的修改,只能往低了修改,不能改高了,如果需要报更高价格的话需要先Cancel Listing订单,然后再重新挂一个,而Cancel的时候又得上链浪费一笔gas费用。同样Listing订单数据没在链上,为什么List price都可以往低了改,而不能直接改高呢?

这两个问题本人没太想明白为什么OpenSea这样做,因为个人觉得在中心化系统上取消订单和随意修改订单价格不是很简单的事情吗?

个人不怀好意的猜测是OpenSea系统做得太烂,不愿意让用户随意取消订单和修改价格,因为这样会导致系统的不稳定。所以Cancel Listing这个操作硬要上链,让用户消耗gas,这样用户在挂卖单的时候就需要慎重考虑要不要挂,以及要挂的价格了。

也希望知道原因的朋友不吝赐教!**

上面两个问题的解答(2022-01-25更新)

昨天opensea出现了一个问题,很多人高价的NFT以特别低的价格被出售了,损失惨重。本人今天研究了下,顺便这个问题同步更新一下。

在OpenSea官网中有这么一篇文章教用户如何取消订单的,注意截图里的这段话:

大意是如果你挂出过你NFT的卖单,这时你又把你NFT转到另外一个钱包地址,这种情况不会自动取消你NFT的卖单,所以你应该在转走你NFT之前先把卖单取消掉。

而这次出现损失的用户大部分就是这个原因了。例如几个月前, 用户A把他的NFT挂出10ETH的价格出售,当时价格未成交,这时用户A未取消卖单就直接把NFT转到另外的钱包地址(可能是为了安全转到冷钱包)去了。

过了几个月后发现市场价格不错,就把NFT又转回到之前的钱包地址,准备挂单出售,但当刚转回成功的时候就发现NFT被以之前的卖单价格(10ETH)出售了,当前市场价可能是80ETH,造成了严重损失。

之所以可以被10ETH的卖单价格出售,就是因为之前的卖单信息被人盯上了,所以在转回NFT的时候被人立马以10ETH的低价购买成功。

合约分析

上面说过,opensea的卖单信息是中心化存储的,这个卖单信息中包括了你NFT的信息、价格以及签名,同时这个卖单信息可以通过opensea的API查询到。

科学家可以通过opensea的API找到一些价值比较高的NFT的卖单信息,同时监控该NFT是否又被转回到与该卖单信息一致的钱包地址,当发现转回时,科学家调用前文所述的atomicMatch这个方法即可完成交易。

截图中可以看到,atomicMatch方法里有个requireValidOrder内部方法,该方法会去校验这个卖单信息是否有效,签名是否正确等。这个卖单信息是存在opensea上并通过API开放出来的,任何人拿到这个卖单信息并且提供能与之匹配的买单,就能完成交易。

上面这个截图是购买时,requireValidOrder方法里判断卖单信息是否合法的实现,可以看到有一步是通过cancelledOrFinalized这个map类型变量来判断的。

而之前说的取消订单是一个上链操作,就是通过设置cancelledOrFinalized这个状态来控制卖单信息失效的。

总而言之,就是一个用户之前挂过低价卖单,后来NFT转走了就再也没管过这个卖单,而这个高价值NFT的低价卖单信息(包含签名)又被人盯上了,所以当NFT又转回来的时候就可以以之前的低价成交。

本人之所以有上一节的两个问题,完全是因为没看过opensea的API,没想到opensea这么open,把卖单的签名信息也开放出来了,任何第三方拿到这个卖单信息都可以自己下单进行NFT的购买。

如何避免损失?

对于opensea来说,现在这个交易合约是n年前的产物,我觉得可以重新设计一个,做好迁移过度相关的工作,但这个工作量会比较高,费时比较长。我猜opensea已经在计划了,因为opensea上polygon链的NFT已经不再是当前的交易方式。

另外对于opensea来说更简单粗暴的方式就是卖单信息中的签名别开放出去,为了安全更加中心化一些,防止不知情的用户造成损失。

对于用户来说,记得取消卖单,虽然费一些gas费吧。另外如果曾经挂过卖单且没取消过的钱包,就别把NFT往回转了, 就用新钱包直接卖吧。

最后的最后

最近因为PhantaBear的关系对NFT着迷了,鄙人着迷到什么程度呢?我媳妇告诉我,我小学2年级的孩子都在问她同学有没有爆炸头熊的NFT了。。。

着迷到已经有点动摇BTC Hodl决心,盘算着是不是拿点BTC去换一个CryptoPunks的程度,毕竟有NFT第一的故事加持,非常想搞一枚。

关于NFT的胡思乱想

社会的经济活动实际上就是钱和资产相互兑换的过程。比如用钱购买衣服、鞋、车、房就是用钱购买了资产。同样也可以变卖衣服、鞋、车、房将资产换取钱,这就是基本的经济活动。这个交易过程的顺利执行其实是通过合同保证的(买衣服、鞋这类小商品虽然没有实体合同,但实际上存在虚拟合同),而社会法律强制确保了合同可以按预期执行(你要是收了钱但没给我东西,我就可以起诉你)。

你会看到在区块链的世界中是一模一样的,BTC、ETH等各种币就是钱,而玲琅满目的NFT就是个各类资产。crypto可以购买NFT,NFT可以变卖换成crypto,这样就形成了未来元宇宙中的经济活动。交易通过智能合约来完成,而公链的共识机制又确保了智能合约能够以预期方式执行。

你会发现区块链行业的发展与现实社会极其相似,NFT的出现也许不是偶然吧。

不过比较有意思的是,人类社会最早的经济活动只是以物换物,例如我用羊去换你的牛,因为以物换物的不便才出现了货币作为交换的媒介。所以现实社会是先出现资产,再出现货币。但区块链行业中先出现的是各类加密货币,然后才出现了代表资产的NFT,与现实社会相反

文章原创链接:https://mirror.xyz/xing824.eth/O3hpbibMf9vLNz6p80YUriU8Bf3bEaJWvRL49FGAgAc

锐单商城拥有海量元器件数据手册IC替代型号,打造电子元器件IC百科大全!

相关文章