Skip to main content

Scenario

某用户持有 WETH,希望在 Ethereum 主网上获得带收益的 Aave USDC(aEthUSDC)。这需要两个操作:一次将 WETH 转换为 USDC 的交换,以及一次将该 USDC 存入 Aave 的 zap。compose 栈将其表达为一个双节点 Flow,其中交换的 amountOut 句柄被直接接入 zap 的 amountIn 绑定,无需手动记账,也无需中间转移。 这个 recipe 是链式 swap → zap flow 的标准结构:先由路由提供方执行交换,再执行协议专属的 zap,两者都由后端降级(lower)为 VM 指令。

What this recipe demonstrates

  • 将某个 op 的类型化输出句柄接入下游 op 的输入(swapOutputs.amountOutzap.amountIn)。
  • 运行不带滑点 guard 的 lifi.swap(该交换的 amountOut port 携带 providesMinimum,因此滑点由提供方强制执行)。
  • lifi.zap 输出上附加一个 slippage guard(参见 guards 概念页)。
  • 使用 materialisers.directDeposit 以固定金额为 flow 提供资金,并使用 sweepTo: builder.context.sender 返还任何残余代币。

Full example

改编自 composer-sdk-examples 仓库中的 swapAndZap.ts

What to observe

  • Inputs. 一个资源输入(amountIn: WETH)。directDeposit materialiser 精确地将 10^18 wei(1 WETH)转入 VM;不执行任何余额读取。
  • Nodes. 恰好两个:flow.nodes[0].op === 'lifi.swap'flow.nodes[1].op === 'lifi.zap'
  • Handle threading. zap 的 bind.amountIn 是引用 swap.amountOut,没有中间资源或转移。
  • Guards. 只有 zap 携带滑点 guard(port: 'amountOut'bps: 100,即 1%)。交换没有 guard,因为其 amountOut port 已经提供了一个最小值。
  • Terminal resource. zap 产生的 Aave aEthUSDC 是终端资源,并被清扫给发送方。
  • producedResources[<name>].simulated?.amountOut.ComposeCompileResult 上,producedResources 包含该 zap 的输出,其模拟得到的 aEthUSDC 金额位于 .simulated?.amountOut