如此精简优美的 NFT 协议+NFT 交易市场,仅仅使用 230 行代码就在 2017 年实现,并且演变为目前世界上最有价值的蓝筹 NFT 之一,是值得研究的产品。
作者:十四君
封面:Larva Labs
CryptoPunk 加密朋克不仅是一个顶级蓝筹 NFT 项目(地板价为 70ETH 约 15W 刀),更是后续 ERC721 标准协议的灵感来源。
NFT 交易市场,是目前整个区块链行业中除了以太坊本身之外最高收入的赛道,而 OpenSea,x2y2,LooksRare 是目前 Top3 平台,其合计交易量占 99% 以上。
今天咱们将解读 CryptoPunk 的区区 230 行源码,其对订单模型与交易流程的实现,探索其内置的专用 NFT 交易市场的优势缺点,也为后续逐步源码分析 3 大 NFT 交易市场合约模型做基础铺垫。
想知道大蛋糕未来鹿死谁手,不妨和我一起源码入手吧。
CryptoPunk 内置的交易市场
如果细心的同学可以发现,在 OpenSea 上如果想购买 Punk 在其属性页面会发现,对其所用标准的描述并非 ERC721 或者 1155,而是绝无仅有的 cryptoPunks,他作为 2017 年推出堪称史上最早的 NFT 协议(成为后续以太坊基金会推出的 721 标准的灵感来源),不仅实现了如今 721 标准的多数功能甚至还在其中内置了一个完全去中心化的交易服务市场,实现 3 种交易拍卖模式!
拓展阅读:【源码解读】你买的 NFT 到底是什么?
其实对于 NFT 最底层而言,交易流动是个最最基础的功能了,无非是要求双方都使用 tansfer,卖方给买方 NFT,买方给卖方 ETH,一手交钱一手交货,但是当面交易尚且担忧对方不给钱呢。因此原子性,是达成信任的必备因素,链上成交基于不可更改的特性正是最佳解决方案
1、Punk 优美的订单模型
回想一下,咱们在现实中是如何买卖商品的,大概有三类
- 卖家报价,买家支付→等于超市选购
- 买家报价,卖家同意→等于菜市口砍价
- 线下议价,链上成交→等于线下公证拍卖
无论哪种,最终达成成交则需要执行交换,既要防止卖家不给货,也要防止买家不给钱。
区块链技术虽然完美的解决了万一不给钱的问题,但是也带来了议价困难的痛点,毕竟 “砍一刀价格” 都是要上链的,肯定不能用拼多多那样的砍小数点后 6 位(- 。-)
Punk 的 market 同时支持这 3 大类交易形式,既可以卖家报价,也可以买家报价,也可以议价后由合约帮你成交,全程无任何版税扣取,且 230 行简短的代码也杜绝了后门的可能
他的订单结构非常简单分两种:卖家报价单 Offer 和买家投标单 Bid
1.1、卖家报价单 Offer
与标准 NFT 一样,每个 Punk 都有一个唯一 ID,因此每个 punk 都有一个独占的 Offer 订单簿,这个独占指的是,如果我重新报价无论是涨价还是降价,都将会替换掉前一个
这里通过 isForSale
标注是否在售,通过 onlySellTo
标注指定买家,则是用于链下议价链上执行成交功能
struct Offer {
bool isForSale; // 此 Punk 是否被卖家设置了报价卖出
uint punkIndex; // 此 Punk 的 ID
address seller; // 此 Punk 的当前持有者
uint minValue; // 卖家设定最小卖价
address onlySellTo;} // 是否指定只能由谁购买
咱们可以显著感受到,订单模型非常的简单,甚至连常见的订单有效期都没有,只要挂单卖家不主动取消的话,就总是有可能被买家以此价格购走
特别说明:这点虽然和 opensea 长时间的授权卖单类似,但不会出现异常价成交的情况,因为 Punk 在转移的时候会取消掉历史的报价单记录
1.2、买家投标单 Bid
投标单也非常简约,基本等于(我,想买,这个,给多少钱)四元组了。
除了卖家标价等待购买的形式,任何人均可以通过提交投标单,来声明哪个 punk 我愿意用 x 的金额购买,这里同样提供了 hasBid
变量用于体现当前这个投标单是否有效
买方随时可以取消之前的投标单,但是如果没有更高的价格覆盖的话,则原始的投标价格会保留(虽然已经无效),这是用于辅助其他买家定价出价的信息共享的设计
struct Bid {
bool hasBid; // 投标是否有效,用于买家不想买取消用
uint punkIndex; // 指定想投标的 PunkID
address bidder; // 投标者
uint value; } // 投标价
投标时,钱在哪里??其实已经打到 Punk 合约里了
买家要提交投标单 Bid
是通过其 Punk 合约的 enterBidForPunk
方法进入的,要传入 punkID 参数以及当前交易的 Value 值,这就意味着,买家报价的时候,就已经将要购买的资金转入到 Punk 的合约中
1.3、小结
看懂其核心的订单簿结构后就是抓住了老鼠尾巴,其实他对应的各种方法,都是在进行对当前交易是否合理合法的审核,确定合法后,再对订单数据做增删查改
比如卖家成交后,会执行修改 balanceOf
中记录的用户累计持有的 Punk 总量,也会修改最核心 punkIndexToAddress
这个记录哪个 PunkID 所有者是哪个的信息
对于标准协议的底层数据意义可拓展阅读
NFT 租赁提案 EIP-5006 步入最后审核!让海外大型游戏的链改成为可能
总之订单是为交易模式服务的,而 Punk 内置了 3 种交易方法
2、Punk 支持三种交易模式
2.1、卖家先报价,买家再竞标
如果我作为持有 Punk 的尊贵用户之一,想要卖出 Punk,需 3 步
卖家报价-> 买家提交买单-> 卖家提取收益
展开看看
卖家报价:卖家执行 offerPunkForSale
设置愿意以某价格卖掉某 nft,而后订单簿如下
bool: isForSale true
uint256: punkIndex 3
address: seller 0x5B38Da6a701c568545dCfcB03FcB875f56beddC4
uint256: minValue 100
address: onlySellTo 0x0000000000000000000000000000000000000000
买家购买:执行 buyPunk
方法在交易的 value 值传入超过于卖家的 minValue 即可购买成功。**
卖家需要再次调用 withdraw
提走自己本次收益(即买家 buy 时存入合约的 value)
如果卖家突然不想卖了:则调用 punkNoLongerForSale
来报价单
还有什么流程能比这更简单的?
或许只有在买家购买的同时也将收益打入卖家账户了吧。而 Punk 系统不这么设计的原因或许是激励更高频的场内交易,等需要外部用再提取走吧
2.2、买家先竞标,卖家先确认
如果我并未持有 Punk 但对某个 ID 情有独钟,也能先出价分 3 步:
买家报竞标单 Bid-> 卖家接受-> 卖家提取收益
展开看看
买家报价:调用 enterBidForPunk
,并将 eth 作为 value,此时钱存于 punk 合约内
卖家接受:调用 acceptBidForPunk
,要明确按买家报价的价格接受此交易,执行后买方已经得到了此朋克 NFTID
卖方提取收益:需要再次执行 withdraw
提走所有可提额度
如果买家不想买了:则调用 withdrawBidForPunk
取消竞标单,同时提走预存金额
2.3、链下议价链上执行
最后一种更简单了,就是完全已经谈妥了价格,由卖家通过
offerPunkForSaleToAddress
对订单簿不仅设置价格,还设置一个唯一买家地址 onlySellTo
,只有此地址可以来完成这个订单
这样一来虽然链上依旧是 3 次交易(卖家报,买家买,卖家提取收益)但是可以实现低价交易的应用场景,例如定向质押,防止被人监听截胡低价单用
如何评价 Punk 的交易市场?
乍一看,是一个很标准的最小 NFT 交易模型,确实可以准确稳定可靠的实现交易的核心环节,但有得有失,他优势如何,而又少了什么呢
3.1、GAS 成本低
由于链上只存储了 offer
和 Bid
两种简约的订单簿,且只保留最新最高价的部分(对存储的新增需要高 gas,但对修改则 gas 低)详情可见下文文末对以太坊黄皮书中定义 gas 计算的解析:【源码解读】你买的 NFT 到底是什么?
所以 Punk 市场的整体 gas 消耗并不高,笔者核算了下完成买卖提取全环节,大致消耗为 30W 的 gas(含买卖双方合计支出)
按成交 GAS 排序: Punk < opensea < GEM < Genie < X2Y2 < Looksrare
3.2、无需手续费
目前链上可见 Punk 累计有 21W 交易,如果 5 笔交易可成交一单的话,则以及有 4W 次转移,对于这样数十亿市值的顶级蓝筹而言,不收版税简直是暴遣天物啊
当然,拿这样内置交易服务对比专职交易市场来比着实有些不公平,但也正是因为 punk 这样内置完成交易的功能是远远到不了完善的功能体系的,所以才有了各种广泛市场的可乘之机
而按手续费排序:Punk(0%) < X2Y2(0.5%) < Looksrare(2%) < OS(2.5%)
3.3、对机制的缺点评价
结论 1:买卖机制不利于流动性池
NFT 而言流动性是至关重要的,而每次报价都要上链显然是盆冷水,卖家不缺钱则不乐意动,买家难成交也缺乏动机,所以对报价者即收费且要求锁定资产到 Punk 此举虽然不会出现扣款失败的情况,但是也导致买家资产的时间的价值的损失
这点,后来 Os 等平台均采用签名的方式,来链下撮合购买意愿,报价近乎无需 gas 仅成单的时候需要链上登记订单结果来执行转移
这一击是中心化与去中心化在效率上的争夺,显然现在的市场还是需要效率
结论 2:订单模型不利于批量操作
Punk 订单模型的简约堪称是交易模型的典范,然而面对批量成交的诉求呢?
- 卖家:得每个 id 每个报单,确定成交
- 买家:得每个 id 每个竞价,等待成交
虽然收益的资金有可以累计后批量提取的设计,但不是重点
而批量报价成交,是现在 NFT 市场的必争之地
x2y2 和 Looksrare 都在这点发力作为针对 os 的包围战,甚至拉上 Gem 等聚合器打通流量池的局限性,而 os 最新的 SeaPort 协议也实现了捆绑交易的新订单模型,从而可以任意资产组合对应任意资产组合直接实现市场交易
然而 Punk 的源码太过于超前,缺乏了代扣授权的功能,再也无缘批量成交
结论 3:单一拍卖流程不利于撮合成交与定价
成交是需要妥协的,而 NFT 当前的价值也需要通过成交来博弈,如何为 NFT 定价一直都是巨大的难题
由此常见有四大拍卖机制:
- 英式拍卖。公开竞标往上拾价,最高出价者得
- 荷式拍卖。价格由高往低降,首个出价者得
- 第一价格拍卖。对拍品进行单独密封报价竞品,不知道其他竞买人的出价
- 第二价格拍卖。与上类似,不同的是最后出价最高者获胜,但只需按第二高价格支付
而这些拍卖机制(英拍荷拍)是 Opensea 的基础功能,利于促进成交与定价
英拍:限定时间竞拍,即不占用高价值蓝筹的资金成本,也有时间缓冲来拟合各群体的博弈结果
荷拍:更有效的减少过高报价流动性低而无成交的问题,让价值总要依据市场而变化
最终
虽然我吐槽了一堆,但是如此精简优美的 NFT 协议+NFT 交易市场,仅仅使用 230 行代码就在 2017 年实现,并且演变为目前世界上最有价值的蓝筹 NFT 之一,是值得研究的产品
未来未必只有交易市场一头独大,更多垂类会在自己 NFT 内也内置交易功能如 StepN、Axie Infinity、NBA Top Shot,而在 Seaport 开源开放后内置市场就未必是功能浓缩版的代言词了
后续笔者将继续研究 OpenSea,X2Y2,Looksrare,Gem 等头部 NFT 市场平台,从合约出发,看其优势与局限性,有兴趣的看官,速速点赞关注,后续跟进吧~
免责声明:作为区块链信息平台,本站所发布文章仅代表作者及嘉宾个人观点,与 Web3Caff 立场无关。本文内容仅用于信息分享,均不构成任何投资建议及要约,并请您遵守所在国家或地区的相关法律法规。