探索 MetaMask 聚合交易

4月份那会业余有参与几个Swap的项目,

有部署 PancakeSwap V2 版本的,其实也就是 Uniswap V2,我主要是作为前端贡献者参与,React 的前端工程,修改了Swap相关的界面,增加挖矿功能,管理代币白名单。

还有的其实就是聚合交易,通过对比三个去中心化交易所的汇率,找到价路由返回给前端,然后前端去展示出来,通过自己的合约进行交易抽成。

公司准备做这一块业务,今天让我调研了一下。实际上这个模式就是我参与过的那另一个项目,但是我们对标的是 MetaMask,今天奶爸就说一说 MetaMask 是怎么做的聚合交易和这背后的原理。

MetaMask 的聚合交易

我在MetaMask插件版中体验了一下 swap,1 BNB -> BUSD -> 0.979 BNB,两次兑换损失了 0.021 个 BNB,大概损失了有 10 USD。其实是失误操作了合作伙伴的钱包,原本想点击一下确认看一下 MetaMask 部署的抽成合约地址呢,结果直接就兑换了。然后奶爸只能将错就错,将兑换的 BUSD 又兑换回了 BNB。

tx1 BNB->BUSD: 0x72b5c9d5656......7e514eb098cb

tx2 BUSD->BNB: 0x44895dd7608......22dcb9eba10b

MetaMask 插件版本是开源的,然后奶爸根据 MetaMask 插件版界面上的 「Review Swap」关键字找到了这个按钮,从按钮又找到了具体实现:ui/pages/swaps/swaps.util.js#L264

前端这里做的工作比较少,只是把参数拼接出来传递给后端API,真正去做策略、真正牛逼的地方还是在后端。虽然后端的代码没有开源,我们没法了解其具体实现,但是还是可以通过后端API开放出来的几个API接口去猜整个流程。

  • /networks/[chainID]/trades 聚合交易接口,这个接口是重中之重,是整个业务的核心,传入消耗代币 A 的地址及数额,和期望获得的代币 B 的地址,最大滑点及你的钱包地址。返回的参数是一个策略数组,每个策略定义如下:
    • aggType 交易类型

      • DEXexchanges,去中心化交易所
      • RFQ0滑点,汇率更好 request for quotation,professional market makers,专业做市商直接询价?
      • AGG aggregators,像 1inch 类的聚合商,我们相当于他的 layer2
    • aggregator 交易swap

    • approvalNeeded 如果需要 approve 的话(推测如果使用原生币交易也是这样走),直接使用这里的数据 sendRawTransaction

      • data
      • from
      • to
      • value
    • destinationAmount 预计获得的代币数额

    • trade 如果交易的话直接使用返回的数据 sendRawTransaction 即可,使用这种方式而不是前端去构造参数的原因奶爸推测是:1、MetaMask 抽成用的中介合约做的比较简单灵活,直接传入一个 swap 地址和交易路径和一些他们自定义参数即可随意交易,他们在收到的代币中抽成。2、为了代码保密。

      • data
      • from
      • to
      • value
    • 其他还有一些参数不详细说了,最重要的参数已经介绍完了。

  • /networks/[chainID]/tokens 这个接口返回了 chainID 的链下的代币列表,特别的是下面这个字段
    • aggregators 有哪些swap支持这个代币
  • /networks/[chanID]/token 有代币列表就有单个代币信息接口
  • /networks/[chainID]/topAssets 顶尖份额的代币列表,维护这个信息是非常重要的,接下来奶爸在原理部分告诉你为什么重要。
  • /networks/[chainID]/aggregatorMetadata 接入的其他聚合交易列表
  • /networks/[chainID]/gasPrices GasPrice API

好 MetaMask 大致就是这样吧,分享一下之前参与过项目的一点心得。

聚合交易原理

先说下 DEX 前端的魔法,

其实每个 DEX 的前端都是一个简易聚合交易器,他要根据流动性关系去撮合这次交易。就 DEX 的前端来说,会有预置的一个中间代币列表,比如说 USDT 这种稳定币和WETH,比如 A 买 B,AB并没有流动性,但是 有 A-C 和 B-C,那么 DEX 的前端就会撮合 A-C-B 这个路径进行交易。其实这个过程是比较复杂的,不仅考虑有没有,还要考虑流动性够不够。流程就是这样的:

  1. 使用 multicall 遍历 A、B 对 中间代币列表,每一个的流动性信息
  2. 筛选满足金额和滑点的 pair,匹配出 A->B 的路径,返回给前端
  3. 交易

接下来就说下聚合交易基本原理了,

聚合交易实际上就是把各个 DEX 前端做的那套事情,都做一遍并且在几个DEX的结果中比较,择优。

实际上想要获取到新的、及时的数据并不简单,这可能价值 150,000 USD。

市面上大多 swap 的 info 站点使用的都是 https://thegraph.com 的服务

然后 PancakeSwap 直接花了 15w 从社区中悬赏找团队做了一个后端 https://streamingfast.io (他们目前并没有搞 SaaS)

抽成

关于这种方式 ParaSwap 有个较为详细的说明 https://doc.paraswap.network/understanding-paraswap/fees#revenue-sharing-integrators

sequenceDiagram autonumber 用户 ->> MetaMask API: 我要用 200A 买 B MetaMask API ->> 用户: 最佳交易是使用 Uniswap 用户 ->> MetaMask 中介合约: API让我告诉你 [200A->B@Uniswap] MetaMask 中介合约 ->> Uniswap: 200A 买 B Uniswap ->> MetaMask 中介合约: 100B MetaMask 中介合约 ->> 受益人: 1B 抽成 MetaMask 中介合约 ->> 用户: 最终获得 99B

其他

MetaMask 的中介合约里面集成了 chiToken。

Comments