Guards 解释了最小值如何在模拟期间被产生。本页解释它们如何被报告,以及在 flow 结束时 proxy 仍持有的任何代币如何一并处理。Flow 描述资源如何在程序中流动。在执行结束时,proxy 仍持有的任何余额都需要一个明确的去向;否则代币会被搁浅。Sweeping 就是这一机制。Amount preparation(数量准备) 则是填入那些依赖链上状态的值。 本页两者都涵盖。它们位于编译流水线的两端(完整序列参见 Execution Model)。
终端资源
当 flow 中没有任何 op 消费某个资源时,该资源就是终端的。有两种到达此状态的方式:- 产出型 op 的输出没有其他东西绑定。 从
lifi.zap存入某个 vault 得到的凭证代币,如果没有后续节点消费它,就是终端的。 - 悬空的 split 输出。 当
core.split产生{ a, b }而只有a被下游绑定时,b就是终端的。关于这被有意为之的典型情形,参见dust-sweeprecipe。
producedResources 中,并有资格被 sweep。关于资源生命周期,参见 Resource Model。
sweepTo 策略
run.sweepTo 字段告诉后端在执行结束时将终端资源发送到哪里。有三种形式:
builder.context.sender。 Sweep 到交易签名者。大多数 flow 使用这种方式。在线格式上,它序列化为{ "$ref": "context.sender" }。- 一个字面地址(例如
'0xRecipientAddress')。Sweep 到一个特定地址。当 flow 的目的是把代币交付给签名者以外的某人时使用。 - 省略。 不 sweep。终端资源留在每个签名者独立的执行 proxy 上。这种情况很少见,主要用于那些有意在多次提交之间于 proxy 上累积余额的 flow。
sweepTo 时,编译器会为每个终端资源追加转账指令。这些转账在所有 op 调用之后、并在任何附加的 guard 断言完其不变量之后运行。
什么会被 sweep,什么不会
- 会: 所有终端资源,包括悬空的 split 输出,以及产出型 op 中无人消费的输出。
- 不会: 被另一个 op 消费的资源(它们是那个 op 的输入,不是残余)。Handles(类型化标量)。它们不是余额,永远不会被 sweep。
dust-sweep 起作用的原因:core.split 对一个输入进行分区,只有一个分区被消费,而未被绑定的分区自然变成了终端资源。
不可转移的终端资源
sweepTo 是一个兜底项:一旦设置,它会尝试把每一份残余的 proxy 余额转移到目标地址。大多数代币可以自由移动,但某些终端资源是被绑定的,无法被转出 —— 最常见的是支撑一笔未平仓债务的 aToken(或其他抵押品凭证)。如果移动该 aToken 会使仓位处于抵押不足状态,Aave 的 finalizeTransfer 就会回滚,因此对这样的余额进行一次一刀切的 sweepTo 会使整笔交易回滚。
当一个 flow 有意在 proxy 上保留一个仓位时 —— 例如一个保持抵押品在位的借款、杠杆或债务迁移 flow —— 不要设置一刀切的 sweepTo。把抵押品留在持久化的、每个签名者独立的 proxy 上,只对那些真正松散的代币发出显式转账:用 core.balanceOf(owner 默认为 proxy)读取每一份,再用 core.transfer 移动它。
数量准备
大多数数量在构建时是已知的。directDeposit({ amount: '1000000000000000000' }) 供应一个字面值。有些数量只能通过在执行时读取链上状态才能得知:
balanceOfmaterialiser。 在消费某个代币之前,读取 proxy 当前对该代币的余额。callmaterialiser。 调用一个 view 函数,并将其返回值用作输入数量。- Vault 份额价格读取。 当某个下游 op 需要知道”该存入产生了多少份额代币”时,服务会在生成 calldata 之前,从当前链上状态解析该数量。
preparation_error(HTTP 422)的形式暴露,通常是因为链上读取返回了 0 或发生了回滚。
响应上的模拟数量
模拟之后,每个终端资源都有一个已知的模拟数量。编译器将它们作为ComposeCompileResult 上的 producedResources 返回:
kind、token、chainId、owner、availability)以及一个 simulated 块:
simulated.amountOut。 在当前链状态(最新区块)下的确切模拟数量。在你的 UI 中把它显示为”你将收到 ≈ X”。simulated.amountOutMin。 给定附加到该资源输出 port 上的滑点 / 最小输出 guard,得到的最坏情况数量。把它显示为”你将至少收到 X”。当没有附加最小输出 guard 时(例如没有滑点保护的 split 产生的粉尘),amountOutMin可能等于amountOut;请检查响应,而不要假定它被省略。- 多个 guard。 当多个 guard 针对同一个 port 时,最紧的最小值胜出(最大的
simulated.amountOutMin)。
amountOutMin 如何从某个 guard 的容差推导而来,参见 Guards。
另请参阅
- Dust Sweep recipe —— 由
sweepTo回收的有意未消费的输入。 - Execution Model —— 数量准备和 sweeping 在编译流水线中的位置。
- Build a Flow → Wire runtime values ——
directDeposit、balanceOf和callmaterialisers。

