本文详细介绍了Fluid DEX协议的设计和功能,特别是其如何利用流动性层来支持去中心化交易所(DEX)与借贷的结合。文章深入探讨了智能抵押品、智能债务的概念以及流动性提供的动态机制,同时分析了其代码实现和复杂的数学模型。Fluid DEX的特点包括动态的价格变化、流动性合约的优化以及法国LEND-Dex的借贷机制,显示出在DeFi领域的创新潜力。
我们之前回顾了一个基于 Fluid 项目的流动性层构建的协议,称为 Fluid Vault 贷款协议。Fluid DEX 是另一个利用相同基础层的协议,展示了 Fluid 在开发 DeFi 项目时的多层次方法。Fluid DEX 的主要特点是能够使用贷款层的抵押/债务资产为 DEX 中的兑换提供流动性。这使得可以利用兑换费用来增强供应并减少债务。为了实现这些目标,Fluid DEX 采用了“智能债务”和“智能抵押”概念,这些概念是针对资产对而非单一资产工作的。高级概述可以在 这里 找到。
如前所述,Fluid 的基础流动性层提供了记账、重入保护、市场限速和其他基础机制,用于支持底层协议。Fluid DEX 作为第二个“协议层”,使用基础流动性层原语“结算”其资产。我们已经看到,跟踪用户债务/供应的机制可以在 DEX 中用来支持多次调用(例如:Uniswap V4 和 Balancer V3),允许用户通过不同的池执行多个操作,进行兑换,和在单个多次调用中管理流动性。在这些操作中,协议只是跟踪所有被使用代币的累计出入债务,仅允许在多次调用结束时提供所有所需代币,组合所有操作。这种方法显著降低了复杂交易操作的 gas 成本并增强了协议的灵活性。
Fluid DEX 采用类似的方法;然而,基础的抵押/债务层更加复杂,并充当“会计师”,而第二个 DEX 层则作为“操作员”。
让我们来考察一下这个协议的技术设计。
我们将跳过一些与 Fluid DEX 的基础流动性层相关的部分,因为在之前关于 Fluid Vault 的文章中已经讨论过。Fluid DEX 的核心机制是“DEX-on-lending”(其中“贷款”是在流动性层实现的,DEX 则在“协议”层上实现)。在这种设置中,单个 Fluid DEX 实例充当与贷款平台接口的唯一贷方/借方。在 Fluid DEX 中的兑换操作促进用户资产在流动性层中的结算,结合存款/取款/借贷/偿还功能来管理代币的“出入”操作。贷款协议的流动性提供者同时也是 DEX 的流动性提供者,而 DEX 的兑换则对抵押/债务资产分配进行再平衡。
作为贷款平台,Fluid DEX 利用“智能抵押”和“智能债务”,这意味着代币对可以作为抵押或债务,而不是单个代币,例如 wstETH-ETH 或 WBTC-cbBTC。因此,用户提供或借贷代币对。即便用户使用智能债务 USDT/USDC 借入 100 USDT,债务被视为持有 50 USDT/50 USDC 的头寸。这种分配可以通过涉及 USDT 或 USDC 的 DEX 交易进行更改。每次用户使用 Fluid DEX 兑换资产时,“智能”贷款供应/借贷头寸中的代币分配会相应调整。从兑换中获得的兑换费用会改变抵押或债务余额,或者增加供应 APR 或减少借款利率。这是 Fluid DEX 的主要概念(高层次的说明可以在 这里 找到)。
为了管理智能抵押和债务,Fluid DEX 中的兑换操作采用两个镜像池进行执行:一个是“供应代币1/借贷代币2”,另一个是“供应代币2/借贷代币1”。兑换过程包括“供应(抵押)& 还款(债务)”的“入”代币操作,和“提取(抵押)& 借贷(债务)”的“出”代币操作,这两个池在基础流动性层上有如下所示:
因此,Fluid 中每个独立的“dex”在流动性层端有两个底层的贷款池,而这个“dex”作为这两个贷款池的用户。在这个框架中,DEX 层根据类似 Uniswap V2 的不变量计算供应/借贷操作的金额,并在池之间对资产进行再平衡,以保持 token1->token2 和 token2->token1 的价格一致。
让我们更深入地探讨这段代码。
Fluid DEX 的代码库与 Fluid Vault 相同:https://github.com/Instadapp/fluid-contracts-public/tree/main/contracts,DEX 协议代码位于 protocols/dex 目录下。
主要合约 main.sol 的 构造函数 包含设置专用合约的地址:
正如前面提到的,Fluid DEX 是一个“DEX-on-lending”,包括同时作为流动性提供的“贷款”操作(存款、提取、借款、偿还)。这就是为什么在“DEX”协议中也包含传统贷款操作。代码分为三个部分:“抵押”、“债务”和“完美”,将相似操作分组。Fluid DEX 中的抵押和债务操作在两个贷款池中使用再平衡,而“完美”操作无需要再平衡,因此被单独分隔为独立模块。
让我们继续讨论兑换。
Fluid DEX 的核心功能是 main.sol 中的 _swapIn() 和 perfectOperationsAndSwapOut.sol 中的 _swapOut(),它们是该协议中最复杂的功能。我们从 _swapIn() 开始。
Fluid DEX 限制对兑换价格变化超过 5% 的操作(这是另一个“流动”部分),在兑换操作的最后一个部分(在 _updateOracle() 函数中,我们稍后将讨论)执行 _priceDiffCheck()。
Fluid DEX 的价格模型也是“流动”的,因为所有价格变动(甚至是区间和阈值的治理变更)都是根据先前价格的改变进行计算并逐渐执行的。当范围限制被达到时,价格值和范围开始连续地向新值移动。这要求跟踪以前的价格、时间的转移、价格转移的状态和其他变量,以控制池的“动态”行为。含有这些数据的 dex 状态被存储在两个主要变量中:
兑换过程参数 存储 在内存中的 SwapInMemory 结构中。
兑换过程中的第一站是 pex_ 结构,它保存协议的兑换价格。这些价格由 _getPricesAndExchangePrices() 函数计算,是 Fluid DEX 兑换的真正“核心”(稍后将讨论)。目前,需要注意的是,供应/借贷代币1/代币2 具有 分开 的价格。
正如先前所提到的,Fluid DEX 中的操作涉及 两个 兑换:在“抵押”和“债务”池中。因此,下一步是为兑换的两个部分准备储备。第 一部分 用于抵押,而第 二部分 用于债务(“虚拟”储备也将在下文中讨论)。
接下来的 部分 处理池中操作数量的限制。我们检查“入”转换的数量是否不会显著影响池的储备和价格。兑换结束时会执行 _priceDiffCheck(),但 Fluid 支持提前进行此检查。
然后进入计算“入”代币金额及其在池中的分配的部分(在一个池中,我们进行“存款”,在另一个池中进行“偿还”)。我们在 _swapRoutingIn() 函数中计算兑换数量,接受“入”数量 t 以及初始的、抵押和债务的“虚拟”储备。该函数的结果为系统方程提供解,同时确定兑换的哪一部分进入抵押、债务或两个池。这个结果形成这 三 个分支,指示多少数量链入“存款”,多少数量链入“偿还”。
接下来,我们需要计算“出”数量,以便在一个池中“提取”和在另一个池中“借款”。此外,我们需要检查这些所需的数量是否可用。这在“_amountOutCol”和“_amountOutDebt”部分中完成。
接下来,我们决定使用哪个池来确定兑换价格:抵押还是 债务。我们选择拥有较大兑换数量的作为价格来源,但仍需记住,在兑换结束时,给定资产在两个池中的最终价格将是相同的。
经过 转换 代币余额为正常数量后,并 设置 回调数据(如果代币通过回调进行传输),有两个与基础流动性层的操作。Fluid 的流动性层(所有 Fluid 协议共享)通过一个 operate() 函数处理所有操作:存款/提取/借款/偿还,由两个签名参数 supplyAmount_ 和 borrowAmount_ 决定(这些参数的负值会导致反向操作)。第一个操作是:
LIQUIDITY.operate(..., +supply_amount, -payback_amount, ...);
而第二个是:
LIQUIDITY.operate(..., -withdraw_amount, +borrowAmount, ...);
这些操作将所有“入”代币用于供应抵押和偿还债务,同时“出”代币则用于提取抵押和借款在协议的流动性(“贷款”)层之上。
接下来调用一个附加的钩子,如果抵押或债务池需要清算,则可以停止兑换。我们在贷款一侧有一个 Fluid DEX 的贷款头寸,这个头寸可能变得“不健康”,需要清算。在这种情况下,任何兑换在清算发生之前都应被中断。“健康”状态是通过该钩子进行检查的,其接口和说明可以在 这里 找到。然而,DEX 的组合、智能债务/抵押代币对的慎重选择,以及根据外部市场价格调整这些池中的资产的再平衡,使得这种情况不太可能发生。
兑换的下一部分包括 检查 流动性层中的利用率(total_debt/total_collateral 比)。函数 _utilizationVerify() 检查最终利用率是否 不超过 流动层中的限制(在流动性层的 operate() 函数中的利用率使用示例见 [这里](https://github.com/Instadapp/flu...
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!