×
Array
(
[fid] => 6980
[description] =>
[password] =>
[icon] =>
[redirect] =>
[attachextensions] =>
[creditspolicy] => Array
(
[post] => Array
(
[usecustom] => 1
[cycletype] => 1
[cycletime] => 0
[rewardnum] => 75
[extcredits1] => 0
[extcredits2] => 0
[extcredits3] => 0
[extcredits4] => 0
[extcredits5] => 0
[extcredits6] => 0
[extcredits7] => 0
[extcredits8] => 0
[rid] => 1
[fid] => 6980
[rulename] => 发表主题
[action] => post
[fids] => 32,52,67,447,1120,1151,1156,6750,6762,6763,6766,6769,6772,6773,6787,6796,6808,6809,6810,6813,6814,6820,6829,6830,6846,6856,6864,6865,6827,6930,6931,6776,6858,6880,6764,6932,6871,6758,6905,1116,6788,6812,6798,6736,6759,6842,6966,6767,6828,6924,6935,6936,6938,6940,6941,6826,6909,6803,6919,6911,6908,6881,6920,6912,6913,6921,6925,6922,6789,6818,6819,6872,6928,6969,6889,6888,6917,6939,6947,6961,6937,6943,6970,6869,6900,6902,6783,6817,1111,6870,6821,6951,6876,6952,6954,6960,6942,6910,6949,6962,6963,6964,6927,6926,6973,6728,6929,6874,6894,6896,6885,6857,6868,1113,6778,56,6844,6878,6802,6933,6811,6923,6877,6875,6918,6892,6757,6832,6833,6795,6793,6848,6837,6849,6850,6851,6852,6853,6854,6863,6882,6836,6790,6838,6794,6791,6873,555,6895,6934,6958,6944,6945,6907,6779,6886,6950,6904,6956,6862,6957,6855,6955,6959,6914,6965,6971,6972,6953,6975,6976,6799,6974,6824,6815,6891,6866,6979,6977,6765,6903,6948,6845,6879,1121,6980
)
[reply] => Array
(
[usecustom] => 1
[cycletype] => 4
[cycletime] => 0
[rewardnum] => 0
[extcredits1] => 0
[extcredits2] => 0
[extcredits3] => 0
[extcredits4] => 0
[extcredits5] => 0
[extcredits6] => 0
[extcredits7] => 0
[extcredits8] => 0
[rid] => 2
[fid] => 6980
[rulename] => 发表回复
[action] => reply
)
[digest] => Array
(
[usecustom] => 1
[cycletype] => 4
[cycletime] => 0
[rewardnum] => 0
[extcredits1] => 0
[extcredits2] => 0
[extcredits3] => 0
[extcredits4] => 0
[extcredits5] => 0
[extcredits6] => 0
[extcredits7] => 0
[extcredits8] => 0
[rid] => 3
[fid] => 6980
[rulename] => 加精华
[action] => digest
)
)
[formulaperm] => a:5:{i:0;s:0:"";i:1;s:0:"";s:7:"message";s:0:"";s:5:"medal";N;s:5:"users";s:0:"";}
[moderators] =>
[rules] =>
[threadtypes] => Array
(
[status] => 1
[required] => 0
[listable] => 0
[types] => Array
(
)
)
[threadsorts] => Array
(
)
[viewperm] =>
[postperm] =>
[replyperm] =>
[getattachperm] =>
[postattachperm] =>
[postimageperm] =>
[spviewperm] =>
[seotitle] =>
[keywords] =>
[seodescription] =>
[supe_pushsetting] =>
[modrecommend] => Array
(
[open] => 0
[num] => 10
[imagenum] => 0
[imagewidth] => 300
[imageheight] => 250
[maxlength] => 0
[cachelife] => 0
[dateline] => 0
)
[threadplugin] => Array
(
)
[replybg] =>
[extra] => a:2:{s:9:"namecolor";s:0:"";s:9:"iconwidth";s:0:"";}
[jointype] => 0
[gviewperm] => 0
[membernum] => 0
[dateline] => 0
[lastupdate] => 0
[activity] => 0
[founderuid] => 0
[foundername] =>
[banner] =>
[groupnum] => 0
[commentitem] =>
[relatedgroup] =>
[picstyle] => 0
[widthauto] => 0
[noantitheft] => 0
[noforumhidewater] => 0
[noforumrecommend] => 0
[livetid] => 0
[price] => 0
[fup] => 6974
[type] => sub
[name] => 币圈资讯
[status] => 1
[displayorder] => 0
[styleid] => 0
[threads] => 77195
[posts] => 77266
[todayposts] => 0
[yesterdayposts] => 0
[rank] => 57
[oldrank] => 56
[lastpost] => 2745792 鲍威尔回应特朗普攻击:将 100%专注美联储法定职责 1751383020 比推快讯
[domain] =>
[allowsmilies] => 1
[allowhtml] => 1
[allowbbcode] => 1
[allowimgcode] => 1
[allowmediacode] => 0
[allowanonymous] => 0
[allowpostspecial] => 1
[allowspecialonly] => 0
[allowappend] => 0
[alloweditrules] => 0
[allowfeed] => 0
[allowside] => 0
[recyclebin] => 1
[modnewposts] => 0
[jammer] => 0
[disablewatermark] => 0
[inheritedmod] => 0
[autoclose] => 0
[forumcolumns] => 0
[catforumcolumns] => 0
[threadcaches] => 0
[alloweditpost] => 1
[simple] => 16
[modworks] => 0
[allowglobalstick] => 1
[level] => 0
[commoncredits] => 0
[archive] => 0
[recommend] => 0
[favtimes] => 0
[sharetimes] => 0
[disablethumb] => 0
[disablecollect] => 0
[ismoderator] => 0
[threadtableid] => 0
[allowreply] =>
[allowpost] =>
[allowpostattach] =>
)
OpenSea 新协议 Seaport 源码解析
[复制链接]
|
当前离线
经验:
天策币:
活跃币:
策小分:
总在线: 分钟
本月在线: 分钟
|
|
一、Seaport 简介近期,NFT 市场 OpenSea 宣布推出全新 Web3 市场协议 Seaport 协议,用于安全高效地买卖 NFT。本文将深度分析其关键业务实现和接口实现。SeaPort官方文档 https://docs.opensea.io/v2.0/reference/seaport-overview , 可配合查阅,进一步加深理解。 Uniswap 用开源去中心化交易改变了加密货币交易的游戏规则,这是我们现在所知的 2020 年 DeFi Summer的开始,也带来了 DEX 和 DeFi 的大规模增长和创新 。OpenSea的新协议Seaport或许也有改变NFT交易游戏规则的潜力,这也是我们分析Seaport协议的原因。 Seaport 是一个市场合约,用于安全有效地创建和执行 ERC721 和 ERC1155 代币的订单。 每个订单包含任意数量的供应商愿意提供的物品(“报价(offer)”)以及任意数量的必须连同其各自的接收者一起接收的物品(“对价(consideration)”)。Seaport 协议的 6 大关键点,以及它对 NFT 领域的意义: (1)开源代码: 有了 Seaport 协议,任何人都可以使用该协议构建一个 NFT 市场,因为它是去中心化和开源的。在未来几年,我们应该会看到更多的 NFT 市场建立起来。更多的竞争=更好+更快的创新 (2)去中心化: OpenSea 说这个协议没有合约所有者,任何人都可以更新或生成代码。 (3)交易新范式: 与一些平台只能用加密货币换取 NFT 不同,Seaport 协议允许用户以一系列新方式获取 NFT,投标人(或报价者)可以捆绑不同的资产(如提供 ETH/ERC20/ERC721/ERC1155 资产)以换取 NFT。 (4)交易特定的 NFT: 当交易 NFT 时,你也可以设置 NFT 必须具备的特定“条件”。 (5)荷兰式拍卖列表: 在 Seaport 协议中,你可以设置一个开始和结束价格,表明你希望拍卖持续多长时间。该列表将降低(或提高)价格,直到找到买家(或拍卖时间到)。 (6)更高的安全性: OpenSea 正在进行为期两周的协议审计竞赛,奖金总额为 100 万美元。任何开发人员都可以审核代码,提交他们发现的评审和错误,并获得奖励。 二、关键业务实现1、NFT订单每一个订单都包含11个关键组件: offerer 订单的报价者提供了所有的供应代币并且必须亲自执行订单(即 msg.sender == offerer )或者通过签名(标准的65字节 ECDSA,64字节 EIP-2098 或 EIP-1291 isValidSignature 检查)或列举链上订单(即调用 validate )来批准订单。
zone 订单的区域是附加到订单的可选辅助帐户,具有两个额外的权限:
offer 报价包含可以从报价者帐户转移的一系列代币,其中每个代币由以下组件组成:
itemType 指定代币类型,有效类型包括 Ether(或者其他指定链的原生代币)、ERC20、ERC721、ERC1155、ERC721、有“条件(criteria)”的 ERC721 以及有“条件(criteria)”的 ERC1155。
token 指定代币合约的账户地址(空地址用于以太币或其他原生代币)。
identifierOrCriteria 表示 ERC721 或 ERC1155 代币标识符,或者在基于条件的代币类型的情况下,表示由代币的有效代币标识符集合组成的 merkle 根。对于 Ether 和 ERC20 类型 ,该值会被忽略,并且对于基于条件的代币类型,可以将值设置为 0 以允许任何标识符。
startAmount 表示如果在订单激活时完成订单所需要的相关代币的数量。
endAmount 表示如果在订单到期时执行订单所需要的相关代币的数量。如果此值与 startAmount 不同,则根据订单激活后经历的时间线性计算出实际的数量。
consideration 包含为完成订单而必须接收的代币数组。它包含所有与所提供代币相同的组件,并且还包括一个用于接收每个代币的 recipient 组件。该数组可以由执行者在订单执行时进行扩展,以支持“小费”(例如中继费或推荐费)。
orderType 订单类型,根据两个不同的偏好,指定订单的四种类型之一,:
startTime 表示订单激活时的区块链时间。
endTime 表示订单到期的区块链时间。该值与 startTime 与每个代币的 startAmount 和 endAmount 一起使用以得出它们的当前数量。
zoneHash 表示一个任意的 32 字节值,当执行受限订单时,该值将提供给区域,该区域在确定是否是授权订单时可以使用该值。
salt 表示订单的任意熵源。
conduitKey 是一个 bytes32 类型的值,表示在执行转移时应将哪个渠道(conduit)(如果有)用作代币批准的来源。默认情况下(即当 conduitKey 设置为零哈希时),报价方将直接向 Seaport 授予 ERC20、ERC721 和 ERC1155 代币批准,以便它可以在执行期间执行订单指定的任何转移。相反,选择使用渠道的报价者将授予与提供的渠道密钥相对应的渠道合约的代币批准,然后 Seaport 指示该渠道转移相应的代币。
nonce 表示必须与给定报价者的当前随机数匹配的值。
2、订单执行订单通过以下4种方式中的一种来执行: 调用两个“标准”函数 fulfillOrder 和 fulfillAdvancedOrder 中的一个,并且构造第二个隐含订单,同时其调用者作为报价者(offerer),已执行订单的对价(consideration)作为报价(offer),已执行订单的报价作为对价(使用“高级”订单包含应与一组“条件解析器”一起填写的部分,这些“条件解析器”为已执行订单上的每个基于条件的代币指定一个标识符和相应的包含证明)。所有报价代币将从订单报价者转移到执行者,然后所有对价代币将从执行者转移到指定的接收者。 调用"基本"函数 fulfillBasicOrder ,并提供六种基本路线类型(ETH_TO_ERC721 、ETH_TO_ERC1155 、ERC20_TO_ERC721 、ERC20_TO_ERC1155 、ERC721_TO_ERC20 以及 ERC1155_TO_ERC20 )中的一种,将从组件子集派生要执行的订单,假设相关订单符合以下条件: 该订单仅包含一个报价代币,并且包含至少一个对价(consideration)代币。 该订单仅包含一个 ERC721 或 ERC1155 代币,并且该代币不是基于条件的。 订单的报价者是第一个对价代币的接收者。 所有其他代币都具有相同的以太币(或其他原生代币)或 ERC20 项目类型和代币。 该订单不提供以以太币(或其他原生代币)作为其项目类型的项目。 每个项目上的 startAmount 必须与该项目的 endAmount 匹配(即项目不能有升序/降序数量)。 所有“忽略”的项目字段(即 token 和原生代币项目中的 identifierOrCriteria 以及 ERC20 项目中的 identifierOrCriteria )都设置为空地址或零。 如果订单中有 ERC721 项目,则该项目的数量为.1 如果订单有多个对价(consideration)项目,且除了第一个对价项目以外的所有对价项目与报价项目的项目类型相同,报价项目数量不小于除了第一个对价项目数量外的所有对价项目数量之和。
调用两个“可用执行”函数(fulfillAvailableOrders 和 fulfillAvailableAdvancedOrders )中的一个,并且提供一组订单与一组执行声明,其中的执行声明指定哪些报价项目可以聚合到不同的转移中,相应地哪些对价项目可以聚合在一起,以及其中已经取消的订单是因为时间无效,或者已经完全成交的订单将被跳过,而不会导致其余可用订单回滚。此外,一旦锁定 maximumFulfilled 可用订单,剩余的所有订单都将被跳过。与标准执行函数类似,所有报价项目将从各自的报价者转移到执行者,然后所有对价项目将从执行者转移到指定的接收者。 调用两个“匹配”函数(matchOrders 和 matchAdvancedOrders )中的一个,并且提供一组明确的订单以及一组执行,该执行指定了哪些报价项目应用于哪些对价项目(并且“高级”案例以类似的方式运行标准方法,但支持通过提供的分子 numerator 和分母 denominator 小数值以及可选的 extraData 参数进行部分填充,当执行受限订单类型时,这些参数将作为调用区域上的 isValidOrderIncludingExtraData 视图函数的一部分提供)。 请注意,以这种方式执行的订单没有明确的执行者; 相反,Seaport 将简单地确保每个订单的需求一致。
虽然标准方法在技术上可用于执行任何订单,但在某些情况下存在关键的效率限制: 与简单的“热路径(hot path)”的基本方法相比,它需要额外的调用数据。 它要求执行者批准每个对价项目,即使对价项目可以使用报价项目来执行(在执行为 ERC721 或 ERC1155 项目提供 ERC20 项目并且还包括具有相同的考虑对价的订单时通常是这种情况用于支付费用的 ERC20 项目类型)。 它可能导致不必要的转移,而在“匹配”情况下,这些转移可以减少到更小的集合。
3、检查余额和批准交易创建报价时,应检查以下要求以确保订单可以执行: 执行基本订单时,需要检查以下要求以确保订单可以执行: 需要执行上述检查以确保报价者仍有足够的余额和批准。 执行者应该对所有对价项目有足够的余额,除了那些项目类型与订单提供的项目类型相匹配的项目——例如,如果执行的订单提供 ERC20 项目,并且要求向报价者提供 ERC721 项目并且向另一个接受者提供相同的 ERC20 项目,那么执行者需要拥有 ERC721 项目,但不需要拥有 ERC20 项目,因为它将来自报价者。 如果执行者不选择使用渠道,他们需要为已执行订单上所有的 ERC20、ERC721 和 ERC1155 对价项目设置足够的 Seaport 合约批准,项目类型与订单提供的项目类型匹配的 ERC20 项目除外。 如果执行者确实选择使用渠道,则他们需要为已执行订单上的所有 ERC20、ERC721 和 ERC1155 对价项目为其各自的渠道设置足够的批准,项目类型与订单提供的项目类型匹配的 ERC20 项目除外. 如果已执行的订单将以太币(或其他原生代币)指定为对价项目,则执行者必须能够将这些项目的总金额提供为 msg.value
执行标准订单时,需要检查以下要求以确保订单可以执行: 需要执行上述检查以确保报价者有足够的余额和批准。 在收到所有的报价项目后,执行者应该对所有的报价项目有足够的余额——例如,如果执行的订单提供了 ERC20 项目,并且需要向报价者提供 ERC721 项目,并且向另一个接收者提供相同的 ERC20 项目,其数量小于或等于提供的数量,执行者不需要拥有 ERC20 项目,因为它将最先从报价者处接收到。 如果执行者不选择使用渠道,他们需要为已执行订单上的所有 ERC20、ERC721 和 ERC1155 对价项目的 Seaport 合约设置足够的批准。 如果执行者确实选择使用渠道,则他们需要为已执行订单上的所有 ERC20、ERC721 和 ERC1155 对价项目其各自的渠道设置足够的批准。 如果已执行的订单将以太币(或其他原生代币)指定为对价项目,则执行者必须能够将这些项目的总数量提供为 msg.value
在执行一组匹配订单时,需要检查以下要求以确保订单可以执行: 部分成交在构建订单时,报价者可以选择通过设置适当的订单类型来启用部分成交。然后,支持部分执行的订单可以在相应订单的某一部分中执行,从而允许后续执行绕过签名验证。总结一下部分填充的几个关键点: 当创建支持部分成交的订单或确定这些订单要成交的部分时,订单上的所有项目(报价和对价)数量必须能被提供的部分项目数量完全整除(即除法后没有余数)。 如果要填写的所需部分会导致要填写的订单数量超过全部订单金额,则该部分将减少为剩余要填写的数量。这适用于部分填充尝试和完全填充尝试。如果不需要这种行为(即填充应该是“全部或无”),则执行者可以使用“基本”订单方法(如果可用)(这需要填写全部订单数量),或使用“匹配” 订单方法,并明确提供一个要求收到全部所需金额的订单。 如果部分可成交订单上的任一项目指定了不同的 startAmount 和 endAmount (例如,它们是递增数量或递减数量的项目),则在确定当前价格之前,该分数将应用于这两个数量。这确保了在构建订单时可以选择完全可分的金额,而不依赖于最终完成订单的时间。 部分成交可以与基于条件的项目进行组合,以支持构建提供或接收多个项目的订单,否则这些项目将无法部分成交(例如 ERC721 项目)。
5、业务关键步骤5.1 执行订单当通过 fulfillOrder 或 fulfillAdvancedOrder 来执行订单时: 计算订单哈希值
计算报价项目和对价项目的哈希值 检索报价者的当前计数器 计算订单哈希值
执行初始化校验 检索并更新订单状态 确定每个项目的金额 应用条件解析器 触发 OrderFulfilled 事件 将报价项目(代币)由报价者转移到调用者 将对价项目(代币)有调用者转移到对应的接受者 5.2 匹配订单当通过 matchOrders 或者 matchAdvancedOrders 来匹配一组订单时,步骤 1 到 6 几乎完全相同,但针对每个提供的订单执行。从这里开始,执行与上面的标准执行不同: 应用执行
确保每次执行都涉及一个或多个报价项目和一个或多个对价项目,所有这些项目都具有相同的类型和代币,并且每个报价项目具有相同的批准源以及每个对价项目具有相同接受者 将每个报价项目和对价项目的金额减少到零,并跟踪其总减少金额 比较每个项目的总金额,并将剩余金额加回相应订单一侧(报价项目或对价项目)的第一个项目 为每个成交返回一个执行
扫描每个对价项目并确保没有一个对价项目仍然有非零的剩余金额 作为每次执行的一部分进行转账 三、关键接口Seaport 是一个通用的 ETH/ERC20/ERC721/ERC1155 市场。它最大限度地减少了外部调用,并为普通路由提供了轻量级的方法,以及更灵活的方法来组合高级订单。 ConsiderationInterface 包含 Seaport 的所有外部函数接口。 fulfillBasicOrder执行基本订单,仅支持Ether(或指定链的原生代币)与 ERC721 之间的交易。 实现逻辑提取订单类型和基本订单路由,并且对其进行校验 准备执行基本订单 (1)添加重入锁 (2)校验时间正确 (3)检验参数正确 (4)计算并校验订单的哈希值 (5)更新订单状态 若使用了渠道,则根据订单路由导出渠道 根据订单路由,执行原生代币以及ERC721代币的转账,完成订单 删除重入锁
fulfillOrder & fulfillAdvancedOrder实现逻辑添加重入锁 _validateOrderAndUpdateStatus :根据参数,验证订单,更新状态并计算订单哈希值 orderHash 、需要执行订单的分子 numerator 和分母 denominator (1)时间校验:startTime <= block.time <= endTime (2)分子与分母校验:
(3)对价项目长度校验以及计算订单哈希值 orderHash : (4)校验高级订单的有效性:订单类型为 2 或 3 要求 zone 或 offerer 是 caller 或 者 zone 批准。 (5)校验订单状态 orderStauts = _orderStatus[orderHash] ,保证订单没有被取消并且是可执行的 (6)校验订单签名,即若orderStatus.isValidated == false ,则调用 _verifySignature 函数 (7)计算需要执行订单的分子 fillNumerator 和分母 fillDenominator (8)更新状态变量 orderStatus _applyCriteriaResolvers :用条件解析器,对每个生成的订单类型以及条件解析器的绑定进行校验,确保提交的待执行订单是有效的
_applyFractionsAndTransferEach :以指定的分数值执行每个项目的转账
_emitOrderFulfilledEvent :发出一个表明订单已完成的事件。
删除重入锁
fulfillAvailableOrders & fulfillAvailableAdvancedOrders实现逻辑_validateOrdersAndPrepareToFulfill :校验订单(若有无效订单则跳过)、更新其状态、通过先前填充的分数减少金额、应用条件解析器并触发 OrderFulfilled 事件。 (1)添加重入锁 (2)声明并设置一个错误缓冲区变量,指明任何本地报价项目的状态。 (3)循环遍历每一个订单,校验订单,更新每一个订单中的参数:
_validateOrderAndUpdateStatus :根据参数,验证订单,更新状态并计算订单哈希值 orderHash 、需要执行订单的分子 numerator 和分母 denominator
循环遍历订单中的每一个报价项目,更新报价项目中的 startAmount 和 endAmount 循环遍历订单中的每一个对价项目,更新对价项目中的 startAmount 和 endAmount
(4)校验错误缓冲区变量 (5)_applyCriteriaResolvers :应用条件解析器,对每个生成的订单类型以及条件解析器的绑定进行校验,确保提交的待执行订单是有效的聚合已使用的报价和对价项目并执行转账 (6)触发 OrderFulfilled 事件 _executeAvailableFulfillments :完全或部分执行通过了校验的订单,每个订单具有任意数量的要约和考虑项目,并执行转移。 任何当前未激活、已完全成交或已取消的订单都将被忽略。 然后,剩余的报价和考虑项目将在可能的情况下聚合,如所提供的报价和考虑组件数组所示,并且聚合的项目将分别转移到履行者或每个预期的接收者。 请注意,失败的项目转移或订单格式问题将导致整个批次失败。 (1)为每一个订单的报价和对价项目的执行分配一个 Execution 结构,构造为一个 Execution 结构数组 executions ,任何当前未激活、已完全成交或已取消的无效订单都将被忽略。 (2)校验 executions 的长度 (3)对 executions 中的每一个 Execution 结构对象进行校验,过滤掉当前未激活、已完全成交或已取消的所有订单。 (4)_performFinalChecksAndExecuteOrders :对高级订单以及 executions 进行最后的校验,然后执行订单,完成执行转账,删除重入锁。
matchOrders & matchAdvancedOrders实现逻辑_validateOrdersAndPrepareToFulfill :校验订单(若有无效订单则回滚)、更新其状态、通过先前填充的分数减少金额、应用条件解析器并触发 OrderFulfilled 事件。若有无效订单,则回滚。
_fulfillAdvancedOrders :在验证、调整金额和应用条件解析器之后,执行高级订单 (1)为每一个订单的报价和对价项目的执行分配一个 Execution 结构,构造为一个 Execution 结构数组 executions (2)循环遍历参数 fulfillments ,将 executions 中的每一个元素对应到fulfillments 的每一个元素,若报价人者(offerer )和接受者(recipient )是相同的,则跳过。 (3)_performFinalChecksAndExecuteOrders :对高级订单以及 executions 进行最后的校验,然后执行订单,完成执行转账,删除重入锁。
来源:金色财经 |
|
|
|
|
|
|