Skip to main content
Flow 是一份描述多步骤 DeFi 操作的不可变 JSON 文档。每个 Flow 都由三部分组成:版本头、声明的 inputs,以及一个有序的 op calls 列表(也称为节点(nodes))。 Flow 中所有的 nameid 字段(输入名称、节点 id、flow 自身的 id)都是用户自定义的。你在编写时挑选它们;编译器仅用它们来将输出与下游绑定关联起来。请选择简短、有意义的名称,例如 amountInswapzap。当你调试线格式 JSON 时,读到的就是它们。

顶层形态

chainId 是此 Flow 中每个 call 所针对的 EVM 链;资源位于不同链上的输入会在构建时被拒绝。inputs 声明 flow 所消费的具名值;nodes 是有序的 op call 列表。关于每个键逐字段的参考,参见 Flow Schema

Inputs

每个输入要么是一个 resource input(一个代币,采用线性消费),要么是一个 handle input(一个类型化标量,如 uint256address,采用复制模式)。 Resource input 在整个 flow 中携带一份余额。默认情况下,恰好有一个下游 call 消费它。复制模式绑定可以在不消费的情况下读取某个资源 —— 例如 core.approve 会引用某个资源以授权某个 spender,同时把余额留给之后的消费型绑定使用。同一资源的复制模式读取可以与一个消费型绑定共存。op manifest 的 port 元数据决定哪个绑定消费、哪个仅读取。 Handle input 是非线性的:一个表示截止时间或滑点容差的 uint256 可以被接入到每个需要它的 op 中。

Calls(nodes)

一个 Call 是单次 op 调用。nodes 的顺序就是编译器降级它们的顺序。每个 call 都有一个用户自定义的 id(被下游 call 以 <id>.<port> 形式引用)、一个来自 manifest 的 op 名称、一个将其输入 port 接入到 refs 或字面值的 bind 映射、op 特定的 config,以及可选的、用于强制不变量的 guards 关于 ref 语法,参见 References;关于 guards 的作用,参见 Guards

Ports 与 handles

Op 在 manifest 中声明类型化的输入和输出 ports。每个 port 都有一个类型(resource 或 handle)、resource port 的一个模式(消费型还是只读),以及一个可用性(输入还是输出)。SDK 会为这些 port 交给你 handlesbuilder.inputs.amountIn,或某个之前 op 调用返回的对象),并在序列化 Flow 时将它们转换为线格式的 $ref 字符串。校验器会拒绝 handle 类型或模式与 port 不匹配的绑定。 关于作用域规则、保留前缀和 handle 到 ref 的转换,参见 References

组合到一起

swap-and-zap quickstart 生成的 Flow,在 builder.build() 之后大致如下:
Inputs 和节点绑定携带 resources(代币余额)和 handles(类型化标量)。下一页 Resource Model 介绍它们在运行时如何表现。

另请参阅

  • Flow Schema —— 每个键逐字段的参考。
  • Resource Model —— resources 和 handles 在运行时如何表现。
  • References —— input.*context.*<nodeId>.<port> refs 如何解析。
  • Execution Model —— 一个 Flow 如何变成 calldata。