如何实现类似OpenSea的signed transactions签名交易功能
OpenSea NFT离线报价功能实现方案
功能核心原理
该功能本质是链下签名报价+链上触发结算的去中心化交易模式,目前OpenSea基于自研的Seaport协议实现该能力,全程仅在卖家接受报价时产生一次链上gas消耗,买家发起报价无需支付任何链上费用。
完整实现流程
1. 买家发起报价阶段(链下执行)
- 买家在OpenSea前端填写报价参数:NFT对应合约地址、Token ID、报价金额、报价有效期
- 前端将上述参数拼接为符合EIP-712标准的结构化消息,调起用户钱包完成签名
- 签名完成后,OpenSea将完整报价结构体、签名内容存入中心化数据库,不做任何链上广播
- 可选:买家可提前将报价对应的WETH额度授权给Seaport结算合约,避免报价被接受时因额度不足失败
2. 卖家接受报价阶段(链上执行,卖家支付gas)
- 卖家在OpenSea前端选中目标报价,选择接受
- 前端拉取对应报价的结构体、买家签名,拼接为结算交易,调起卖家钱包签名
- 卖家签名后广播交易到链上,Seaport结算合约依次完成以下校验:
- 校验买家的EIP-712签名合法,和报价结构体内容完全匹配
- 校验当前时间在报价有效期范围内,报价未被买家作废
- 校验卖家为NFT的当前合法持有者,且已将NFT转移权限授权给Seaport合约
- 校验买家有足够的资产(ETH/WETH/其他代币)完成支付
- 所有校验通过后,合约自动执行资产交割:将买家的报价资产划转至卖家地址,将卖家的NFT划转至买家地址,交易完成
核心代码实现示例
链上合约核心结构
// 资产类型枚举 enum ItemType { NATIVE, // 原生代币(ETH) ERC20, ERC721, ERC1155 } // 报价资产结构体(买家付出的资产) struct OfferItem { ItemType itemType; address token; // 资产合约地址 uint256 tokenId; // 若为NFT则为Token ID,同质化资产填0 uint256 amount; // 资产数量 } // 对价资产结构体(卖家付出的NFT) struct ConsiderationItem { ItemType itemType; address token; // NFT合约地址 uint256 tokenId; // NFT的Token ID uint256 amount; // 数量,ERC721固定为1 address recipient; // 收款地址(买家地址) } // 完整报价订单结构体 struct Order { address offerer; // 报价发起方(买家)地址 OfferItem[] offerItems; // 买家提供的报价资产列表 ConsiderationItem[] considerationItems; // 买家期望获得的资产列表 uint256 startTime; // 报价生效时间 uint256 endTime; // 报价过期时间 uint256 counter; // 报价作废计数器,用于批量作废旧报价 bytes signature; // 买家的EIP-712签名 } // 签名校验逻辑 function verifyOrder(Order calldata order) internal view returns (bool) { // 生成订单的EIP-712结构化哈希 bytes32 orderHash = _hashTypedDataV4(keccak256(abi.encode(order))); // 校验签名是否为报价发起方本人签署 return ECDSA.recover(orderHash, order.signature) == order.offerer; }
报价作废逻辑
买家可以随时调用Seaport合约的incrementCounter()方法,将自己账户的counter值+1,所有counter值低于当前值的未成交报价会自动失效,无需逐个取消报价,大幅降低作废成本。
关键特性说明
- 报价未被接受前不会产生任何链上记录,也不会冻结买家资产,买家可随时发起或作废报价
- 仅在卖家接受报价时产生一次链上gas消耗,由卖家支付,成交逻辑完全由链上合约保证,不可篡改
- 所有签名遵循EIP-712标准,钱包会展示清晰的报价参数,避免用户盲签风险
内容的提问来源于stack exchange,提问作者Владимир Владимирович
相关产品推荐
相关产品推荐

