Skip to main content
订单服务器是一个有用的中介,允许用户提交意图(订单)并将这些意图广播给解算器。它充当一个中心枢纽,负责:
  1. 从各种来源收集用户意图。
  2. 实时向已连接的解算器广播这些意图。
  3. 跟踪所有交易的链上状态。
虽然订单服务器凭借其内置的安全辅助功能是推荐的集成接口,但需要注意的是——对于链上订单——订单服务器完全是可选的。然而,并非所有意图都在链上发出,lintent.org 并不在链上发出意图。在链上发出的意图需要经过填充并进行非常彻底的验证。

订单订阅

有 2 种方式可以收集订单:通过 websocket 订阅(订单会被推送),或通过 GET 端点。建议通过 websocket 订阅获取推送的订单。这两种方式都可以在 lintent.org 演示实现中找到。 如果您过于频繁地使用 GET 端点,您可能会被限流或暂时超时。您可以在 https://order-dev.li.fi/docs 上找到关于 api 接口的 swagger 文档。
您可能会通过 WebSocket 接口多次收到同一个订单。每当从一个真实来源摄取意图时,都可能发生这种情况。二次发出可能包含额外的上下文。在消费 WebSocket 意图时,请使用 orderId 来识别意图。

订单服务器事件

连接到订单服务器后,订单服务器将持续发送 ping 消息,客户端应使用 pong 进行响应。这用于断开行为异常的客户端,并用于调试目的。您可以在此处找到示例实现 对于订单收集,重要的事件是 user:vm-order-submit。返回的数据与提交时的格式类似。

订单验证

LI.FI Intents 允许高度可定制的订单。因此,您应添加进一步的验证,以确保您支持转发给您的订单。正确验证订单非常重要。 下文中,术语”白名单”是指由信任并验证过的。当某个代币_必须_被列入白名单时,意味着信任该代币。如果某个验证层被列入白名单,意味着信任该验证层,以此类推。白名单并不意味着由某个中心化实体授权;它意味着由信任。 以下尝试列出解算器必须实现的验证的详尽清单。虽然该清单可能看起来过多,但您很可能已经为其中大部分实现了检查。

通用验证

  1. fillDeadline:确保您有足够的时间填充订单:
    • 在目标链上填充的时间,包括潜在的源链最终性。
  2. expiry:确保您有足够的时间填充、转发和领取订单:
    • 在目标链上填充的时间,包括潜在的源链最终性。
    • 将消息验证证明发送到输入链的时间。
    • 验证送达后领取订单的时间。
  3. 验证层:确保您支持向验证层提交证明(如果不是自动的,还需转发)。此外,inputOracleoutput.oracle 必须属于同一个验证层。
  4. 确保您已将每个 input 代币列入白名单。如果某个输入代币是恶意的,订单可能无法领取。此外,对于像 USDC 这样可被列入黑名单的代币,请确保您不在黑名单上。
    • 如果订单的输入或输出中包含 0 数量的某个您未列入白名单的代币,该订单可能无法填充。在填充包含不熟悉代币的订单时请务必小心。
  5. 对于每个输出:
    1. output.chainId 已列入白名单。
    2. output.oracleinputOracleoriginChainIdoutput.chainId 而言配置正确。链上配置是不可变的,因此这对每个链对只需做一次。
    3. output.settler 已列入白名单。
    4. output.context 可解码,且订单类型受支持并与 output.settler 兼容。
    5. output.token 已列入白名单。此外,对于像 USDC 这样可被列入黑名单的代币,请确保您和接收方都不在黑名单上。
      • 如果订单的输入或输出中包含 0 数量的某个您未列入白名单的代币,该订单可能无法填充。在填充包含不熟悉代币的订单时请务必小心。
    6. 您有足够的代币用于 output.amount
    7. 如果输出包含 calldata,请确保您能够原子性地执行它以及其他输出。对于不同链上的输出,如果存在 calldata,您可能必须将接收方列入白名单。
      • 在 OP 链上,CrossL2Inbox 需要在整个调用树中被列入黑名单。如果其他链上存在类似的合约,它们也需要被列入黑名单。
    8. call.lengthcontext.length 都不超过 65’535 字节长。
    9. 根据订单类型验证上下文。具体针对 Bitcoin,请确保编码的乘数是相对于 Bitcoin 值的。
  6. 如果订单有多个输出,请确保您能够填充所有输出,且第一个输出设置为您的解算器标识符。如果所有输出都在同一条链上,可以使用 fillBatch 作为一种保护措施。
  7. 如果 InputSettler 有任何费用,请检查是否有即将发生的费用变更。
代币输入以 uint256 提供。这是资源锁和跨链地址的标准格式。对于 EVM,前 12 字节代表一个潜在的 lock tag,地址是最后 20 字节。同样的 20-byte-in-bytes32 规则也适用于 Tron——base58 的 0x41 版本字节从不出现在链上(参见 Tron vs EVM)。

Escrow 验证

  1. 确保没有任何输入代币是转账时收费(fee on transfer)的。
  2. 确保每个 inputs 代币的高 12 字节中没有设置任何位。
  3. 确保订单已经被打开,可以通过 event Openfunction orderStatus,或者您在填充订单之前通过 function openFor 打开订单。

Compact 验证

  1. 确保每个 input 代币使用相同的 AllocatorId。如果 lockId 不同,则应检查每个 lockId 的锁过期时间。或者,检查是否所有 lockId 都相等。
  2. 确保资源锁的潜在 reset period 延伸到 expiry 之后,并且没有活跃的提款。
  3. 确保 allocatorID 已列入白名单。分配器可以阻止领取的处理(通过撤回签名或重用 nonce)。
    • allocatorID 是 inputslock tag(前 12 字节)的一部分。
    • 可选地,确保用户有足够的代币。不过这应该已经由分配器验证过了。
  4. 确保用户提供了 ECDSA 签名或者他们注册了列入白名单的 emissary或者您在填充领取之前在链上注册了该领取。
    • 注意:如果采取了这些操作中的任何一个,则可以假定签名是可信的。
    • emissary 签名无法在链上注册。必须信任 emissary 不会撤回签名。
  5. 验证 allocatorData。您可能需要进行链上调用。
  6. 验证分配器 nonce 之前未被任何用户使用过。订单 nonce 不是用户 nonce。

签名验证

StandardOrder 将用于对接输入链上的所有函数。此外,一旦填充了签名,它就允许人们验证订单的有效性。 StandardOrder 结构体将被签名并作为见证存储在相应的锁/领取结构中。对于 TheCompact,这是:
要验证订单,请确保 sponsor 和 allocator 的签名对于这个 EIP-712 签名结构是有效的。

链上订单广播

当意图在链上注册时,可以通过输入结算合约上的 IntentRegistered 事件进行广播:
在收集无需许可的订单时,请确保它们经过正确验证和共同签名。订单服务器有助于验证,但在链上,可能会发出潜在的欺诈性消息。