shaneson.eth

Posted on Feb 18, 2022Read on Mirror.xyz

Smart Order Router V2 -- SOR Algorithm

斯人若彩虹 遇上方知有

Summary

SOR v2 可以跨不同和任意类型的池优化选择交易路线。这是使 Balancer 成为现有最灵活的 AMM 协议的主要功能。对于交易者而言,完全不受各种交易池的影响,只需从金库中获取流动性收益。

SOR v1 不能用于 Balancer v2 的原因是 SOR v1 线性化了矿池的 spotPriceAfterSwap 函数。这种线性化不适用于稳定池或其他任意池。 SOR v2 与池一起工作的唯一先决条件是它具有第一和第二(数值或分析)可微分的 spotPriceAfterSwap 函数。

SOR 的最终目标是为用户找到最大化回报的交易。实现这一点的一个要求是,如果有多种路由方案,使用的每条路径/路线最终都具有相同的现货价格。这意味着交易后不可能套利(至少在使用池子的情况下)。

Glossary

  • tokenIn: 用户的输入Token
  • tokenOut: 用户的通过算法得到的Token
  • swapType < 'swapExactIn' , 'swapExactOut'>
  • targetAmountSwap:
  • pools: is a dictionary that is loaded from subgraph with all the pools available on Balancer
  • paths: paths是一系列池,使交易 tokenIn 到 tokenOut 发生。 路径可以包含一跳(直接交易)或两跳。 例如,DAI 与 BAL 的交易可以与包含 DAI 和 BAL 以及多跳路径的池进行直接交易,例如 DAI→WETH→BAL 或 DAI→USDC→BAL。
  • pairType < 'token->token' , 'token->BPT' ,'BPT->token' >: 这是 SOR v2 的新内容。 SOR 将具有单个代币的加入/退出池视为交换,就像池中两个基础代币之间的交换一样。 如果有一个带有 <DAI, USDT, USDC> 的大型稳定池(例如池 A)和另一个带有 <BPTA, GUSD> 的稳定池,BPTA 是 池 A。因此,如果一跳涉及加入池,即 BPTA 的 DAI,则此 pairType 将是 'token->BPT'
  • returnToken: 交换量未知且 SOR 正在计算的代币。 简单地说,如果swapType 是'swapExactIn',用户正在输入他们想要出售的数量(targetAmountSwap 在tokenIn 中),并且将从SOR 中获得returnAmount,即他们将在tokenOut 中得到多少。 相反,如果swapType 是'swapExactOut',那么用户正在输入他们想要购买的数量(targetAmountSwap 在tokenOut 中),并且将从SOR 获得returnAmount,这是他们必须在tokenIn 中支付的金额。
  • costReturnToken: 就 returnToken 而言,额外的交换会增加多少 gas 成本。 例如,对于 DAI 与 BAL 的“swapExactIn”交换,costReturnToken 可能是 0.1 BAL(BAL 是 returnToken)。 这可以通过以下方式简单计算:

Basic algorithm

  1. 检查我们需要能够交易targetAmountSwap的最具流动性池的数量(initalNumPaths)。b = initialNumPaths
  2. 找出最佳b个路径和 targetAmountSwap 的最佳分布,这是一个名为 swapAmounts 的列表,其中 b 数量要在每个 b 路径中交换。 swapAmounts 中所有金额的总和始终为 targetAmountSwap。
  3. 考虑到添加额外路径的额外成本 (costReturnToken * nSwapsInPath),比较上一步的 returnAmount 与 bestReturnAmount(这是迄今为止最好的返回量)。 如果 returnAmount 比 bestReturnAmount 好,则增加 b 并返回步骤 2)。 如果不是,算法已经找到了最终解决方案。 重要提示:请注意,如果 swapType 为 'swapExactIn' 具有更好的 returnAmount 意味着它高于 bestReturnAmount,即用户获得更多 tokenOut 。 相反,如果 swapType 为 'swapExactOut' 具有更好的 returnAmount 意味着它低于 bestReturnAmount,即用户为他们想要购买的 tokenOut 的所需数量(targetAmountSwap)支付更少的 tokenIn。

STEP2最关键,本质是DFS

  1. 先计算swapAmount。swapAmount的计算是根据b,进行等比例缩小。例如,b=2时,bestSwapAmounts是[150,30];b=3时,bestSwapAmounts是[100,20,60]
  2. 根据swapAmounts,调用getBestPathIds()【本质上是dfs穷举】,找到最佳路由
  3. 返回swapAmounts和bestPathIds

iterateSwapAmountsApproximation()

这个函数是用来找出swapAmounts的。这里注意保持的是,在拆分路由的时候,targetSP是不变的。如下图,在path1和path2直接做选择的时候,targetSp是不变的。直线targetSP和path1,path2的交点得到A1', A2'。我们就可以得到每一个Ai'。

关键公式如下:

总结

算法最核心的部分是DFS部分。但是很多小细节也很关键,例如如何计算swapAounts。

参考资料:

https://docs.balancer.fi/developers/smart-order-router