# LooksRare 合约代码解读(一) **Published by:** [xyyme.eth](https://paragraph.com/@xyyme/) **Published on:** 2022-06-23 **URL:** https://paragraph.com/@xyyme/looksrare ## Content 最近研究了 LooksRare 的合约代码,他们的代码写得比较简单易懂,同时文档内容也比较丰富。学习了几天,基本算是把整个合约代码都研究明白了,因此写篇文章来做做笔记,同时也希望能够帮助到有需要的朋友。系统架构名词解释ask 代表卖家卖出,bid 代表买家买入。maker 代表主动挂单的人,例如卖家主动挂单卖 NFT ,此时卖家为 maker。或者买家对某 NFT 出价,此时买家为 maker。taker 代表撮合完成订单的人,例如买家看到某 NFT 的价格合适,对其买入,此时买家为 taker。或者卖家看到某买家的出价合适,对其卖出,此时卖家为 taker。结合上面的描述,合约中一共有四个角色,分别是:makerAsk,挂单的卖家makerBid,出价的买家takerAsk,撮合完成订单的卖家takerBid,撮合完成订单的买家链下挂单(出价)行为是在链下完成的,即 maker 操作不上链,只是在链下签名。链上成单行为是在链上完成的,即 taker 操作上链。因此代码中只有成单,没有挂单的逻辑。合约架构LooksRareExchange,主合约,用户的所有操作都在这里管理合约CurrencyManager,管理协议支持的支付币种ExecutionManager,管理协议支持的交易策略RoyaltyFeeManager,管理 NFT 对应的版税信息TransferManager,均继承于 ITransferManagerNFTTransferManagerERC721,执行 ERC-721 的转移操作(使用 safeTransferFrom)TransferManagerERC1155,执行 ERC-1155 的转移操作TransferManagerNonCompliantERC721,执行 ERC-721 的转移操作(不使用 safeTransferFrom,而是 transferFrom)OrderTypes,包含 MakerOrder 与 TakerOrder 的订单数据结构TransferSelectorNFT,管理 NFT 对应的 TransferManager交易策略合约StrategyStandardSaleForFixedPrice,标准固定价格交易StrategyPrivateSale,卖家指定的买家才能购买StrategyDutchAuction,荷兰拍卖StrategyAnyItemFromCollectionForFixedPrice,买家出价购买一个 NFT 合集中任意一项。例如,买家想购买 BAYC,任意一个都可以StrategyAnyItemInASetForFixedPrice,买家出价购买一个 NFT 合集中某些特定 tokenId 中任意一项。例如,买家只想购买蓝色背景的 BAYCRoyaltyFeeRegistry,设置 NFT 的版税信息,存储版税信息RoyaltyFeeSetter,设置 NFT 的版税信息,该合约为入口,调用上面的合约看到这么多合约,是不是已经晕了。不用怕,我们要关心的只有 LooksRareExchange 合约,其他的合约都是为了它服务的。源码解读注:由于 Mirror 的排版原因,长代码的阅读性很差,因此为了统一起见,所有代码将会截图展示。同时,只着重于主要业务逻辑,对于例如 setter 等比较简单的部分,不再介绍。OrderTypes包含 MakerOrder 与 TakerOrder,分别为:订单数据结构LooksRareExchangenonce 数据结构取消订单我们知道,挂单是在通过签名在链下进行的,每个挂单都包含 nonce。但是如果要取消订单,必须要上链,为什么呢?因为在成单的时候,要用到挂单的签名信息,而一旦签名了,签名信息是一直存在的。即使链下再怎么操作,链上也可以把这份签名拿过来用。因此 maker 需要在链上将这个 nonce 的订单取消,让其在链上失效。这样即使有人拿着签名信息来用,那么在链上这个 nonce 的订单已经失效了。 对于上面两个函数,cancelAllOrdersForSender 属于一刀切,传入一个 nonce,该 nonce 以下的订单就全部失效。cancelMultipleMakerOrders 则是传入特定的 nonce 列表,只有这些 nonce 的订单失效。matchAskWithTakerBidUsingETHAndWETH买家发起撮合,使用 WETH 购买买家使用 WETH 购买matchAskWithTakerBid买家发起撮合,使用指定币种(makerAsk.currency)购买买家使用非 WETH 币种购买可以看到上面两个函数的逻辑大同小异,区别比较大的地方就是使用 WETH 购买的函数中,需要对 msg.value 以及 ETH 的转换进行处理。matchBidWithTakerAsk卖家发起撮合卖家卖出可以看到,与上一个方法也是大同小异,只是方向不同。 用户所有的操作就是这些,我们再来小结一下:cancelAllOrdersForSender → 取消指定 nonce 以下所有订单cancelMultipleMakerOrders → 批量取消指定订单matchAskWithTakerBidUsingETHAndWETH → 买家发起撮合,使用 WETH 购买matchAskWithTakerBid → 买家发起撮合,使用指定币种(makerAsk.currency)购买matchBidWithTakerAsk → 卖家发起撮合读懂这些逻辑,我们就已经掌握了 LooksRare 合约的核心内容。 接下来,我们看看几个重要的内部函数。_transferFeesAndFunds分发买家的款项(非 ETH 支付)分发买家的款项(非 ETH 支付)_transferFeesAndFundsWithWETH分发买家的款项(WETH 支付)分发买家的款项(WETH 支付)我们可以看到,上面两个函数的内容基本相同,主要逻辑都是对买家的款项进行了分发,计算了协议费用和版税费用,最后将剩余款项转给卖家。 还记得我们前面看到的 MakerOrder 中的 minPercentageToAsk 字段吗,当时看是不是有点迷茫,这个字段是什么意思?因为有版税和协议费用的存在,且它俩都是变量,可能卖家在挂单之后,各种费用的值被管理员修改了,那么在挂单的时候就需要设置一个最小可接受的值,如果最后盈利的数量小于该值,那么就不交易了,类似于 DEX 中滑点的概念。 注意到两个函数最大的区别就是转账这块,在非 ETH 函数中,使用的是 safeTransferFrom,而在 ETH 函数中,使用的是 safeTransfer。因为一个是 ERC20,一个是原生货币,后者在调用函数的同时就已经转入款项了。同时这也是为什么我们前面的入口函数那里,ETH 支付的函数需要对 msg.value 进行处理,而 ERC20 不需要这一步。_transferNonFungibleToken转账 NFT转账 NFT由于目前 NFT 流行的标准有 ERC-721 和 ERC-1155,两者的转账方法略有不同。因此,这里会根据 NFT 合集对应的标准,选取相应的转账管理器来进行转账。转账管理器的内部逻辑其实很简单,我们后面再介绍,这里先着重于主逻辑。_validateOrder校验订单信息校验订单信息这里,先校验订单的 nonce 是否有效,我们最开始看到的两个关于 nonce 的数据结构可以用来验证。然后再根据 maker 的签名和 makerOrder 的哈希值来判断其是否为正确的订单信息,这里利用了 EIP-712 的相关内容,不熟悉的朋友可以看看我之前的写的这篇文章。小结到这里,所有的主逻辑我们就已经看完了,是不是还算比较简单。 我们先休息一下,没有完全看懂的朋友可以再多看两遍消化一下。这篇文章就先介绍到这里,看完这篇我们基本上就已经对 LooksRare 的主要逻辑了解了个大概了。剩下的合约基本上都是辅助合约了,例如各种管理器合约,我们放在下篇文章介绍。LooksRare 代码系列文章LooksRare 合约代码解读(一)LooksRare 合约代码解读(二)关于我欢迎和我交流参考LooksRare Exchange v1 Overview | LooksRare DocsUnderstand the LooksRare blockchain architecture with the technical documentation for smart contracts of the exchange protocol.https://docs.looksrare.org ## Publication Information - [xyyme.eth](https://paragraph.com/@xyyme/): Publication homepage - [All Posts](https://paragraph.com/@xyyme/): More posts from this publication - [RSS Feed](https://api.paragraph.com/blogs/rss/@xyyme): Subscribe to updates - [Twitter](https://twitter.com/xyymeeth): Follow on Twitter