资金流的处理是NFT交易平台的核心逻辑,我详细描述一下整个流程。 卖家的操作流程: 第一步:NFT授权 卖家想要出售NFT,首先需要授权我们的Exchange合约可以转移他的NFT。这是通过调用NFT合约的 setApprovalForAll或approve函数实现的。 setApprovalForAll函数会授权Exchange合约可以转移卖家的所有NFT(该合约下的),这是一次性授权,之后卖 家可以出售任意数量的NFT而不需要重复授权。approve函数只授权单个NFT,每次出售都需要重新授权。 大多数用户选择setApprovalForAll,因为更方便。这个授权操作需要支付Gas费,在Polygon上通常不到0.1美元。 第二步:创建订单 授权完成后,卖家在前端填写出售信息: NFT合约地址和TokenID 出售价格(可以选择ETH、USDT等支付代币) 订单有效期(比如7天) 版税设置(如果是首次出售) 前端会将这些信息组织成一个结构化的订单对象,然后调用钱包的签名功能,让卖家对订单进行签名。签名过程不 需要Gas费,也不会上链,只是用私钥对订单数据进行加密签名,证明这个订单确实是卖家创建的。 签名完成后,前端将订单和签名提交到我们的后端服务器,后端验证签名有效后,将订单存储在数据库中,并在前 端展示。 第三步:等待买家购买
订单创建后,卖家不需要做任何操作,只需要等待买家购买。在等待期间,卖家可以随时取消订单,或者修改价格 (实际上是取消旧订单,创建新订单)。 如果订单在有效期内没有成交,会自动过期失效。卖家也可以通过incrementNonce函数批量取消所有旧订单。 买家的操作流程: 第一步:浏览和选择NFT 买家在平台上浏览NFT,可以通过搜索、筛选、排序等功能找到感兴趣的NFT。点击NFT可以查看详细信息,包括 属性、历史交易记录、当前价格、版税比例等。 第二步:发起购买 买家点击"购买"按钮后,前端会进行一系列检查: 买家钱包余额是否足够(包括NFT价格和预估的Gas费) 买家是否已授权Exchange合约可以转移支付代币(如果用USDT等ERC20代币支付) NFT是否仍然属于卖家,订单是否仍然有效 如果买家使用ERC20代币(如USDT)支付,且还没有授权,前端会先引导买家授权。授权是调用ERC20合约的 approve函数,允许Exchange合约从买家账户转移指定数量的代币。这需要一次链上交易和Gas费。 第三步:调用合约撮合 所有检查通过后,前端会调用Exchange合约的matchOrder函数,传入以下参数: 卖家的签名订单(包括所有订单信息和签名) 买家的支付信息(支付金额、支付代币类型等) 这是一次链上交易,买家需要支付Gas费。在Polygon上,这笔交易的Gas费通常在0.1-0.3美元之间。 合约内部的资金处理流程: 当Exchange合约的matchOrder函数被调用时,合约会执行以下步骤: 第一步:验证订单有效性 合约首先验证卖家的签名,使用ecrecover函数从签名中恢复签名者地址,确认确实是卖家签名的。 然后检查订单状态: 订单是否已过期(当前时间 > 有效期) 订单是否已被取消(检查取消订单映射) 订单的nonce是否有效(检查是否小于卖家当前nonce) 订单是否已被执行(检查订单ID映射) 如果任何一项检查失败,交易会revert,买家支付的Gas费会被消耗,但资金不会转移。 第二步:验证资产状态 合约检查NFT和资金状态: 卖家是否仍然拥有这个NFT(调用NFT合约的ownerOf函数) 卖家是否已授权Exchange合约转移NFT(调用NFT合约的isApprovedForAll或getApproved函数) 买家是否有足够的资金支付(查询买家的余额) 如果是ERC20支付,买家是否已授权Exchange合约转移代币(调用ERC20合约的allowance函数)
这些检查确保交易能够成功执行,避免执行到一半失败。 第三步:计算资金分配 合约根据订单信息计算资金如何分配: 假设NFT价格是10 ETH,平台手续费2.5%,版税5%,计算如下: 总金额:10 ETH 平台手续费:10 × 2.5% = 0.25 ETH 版税:10 × 5% = 0.5 ETH 卖家收入:10 - 0.25 - 0.5 = 9.25 ETH 如果有多个版税接收地址,合约会按比例分配版税。比如版税总共5%,其中3%给创作者A,2%给创作者B: 创作者A:10 × 3% = 0.3 ETH 创作者B:10 × 2% = 0.2 ETH 第四步:更新合约状态 在执行资金转移之前,合约先更新状态,这是防止重入攻击的关键: 标记订单为已完成(将订单ID存入已完成映射) 记录交易信息(买家、卖家、价格、时间等) 这样即使后续的外部调用触发了重入,合约状态已经更新,不会被重复利用。 第五步:执行资金转移 合约按照计算好的分配方案,依次执行资金转移: 如果是ETH支付: 平台手续费:call{value: 0.25 ETH}(platformFeeRecipient) 版税给创作者A:call{value: 0.3 ETH}(creatorA) 版税给创作者B:call{value: 0.2 ETH}(creatorB) 卖家收入:call{value: 9.25 ETH}(seller) 如果是ERC20代币支付: 使用transferFrom函数从买家账户转移代币 分别转给平台、创作者、卖家 所有转账操作都检查返回值,如果任何一笔转账失败,整个交易revert。 第六步:转移NFT 资金转移完成后,合约调用NFT合约的transferFrom函数,将NFT从卖家转移给买家: 这是整个交易的最后一步,如果NFT转移失败(比如卖家在交易执行过程中转移了NFT),整个交易会revert,前 面的资金转移也会回滚。 第七步:触发事件 交易成功完成后,合约触发OrderMatched事件,包含所有交易详情: IERC721(nftContract).transferFrom(seller, buyer, tokenId);