去中心化交易所(DEX)原理:订单簿与AMM对比、流动性池概念、交易流程、无常损失初步认知
去中心化交易所(DEX)是DeFi生态中最核心的基础设施之一。与中心化交易所(CEX)依赖撮合引擎和托管钱包不同,DEX通过智能合约在链上完成资产兑换、流动性供给和价格发现。理解DEX的工作原理,尤其是自动化做市商(AMM)机制,是掌握链上交易合约实现的前提。本章将从订单簿与AMM的对比切入,深入拆解流动性池的运作逻辑、交易流程以及无常损失的本质,为后续编写AMM合约打下理论基础。
3.1 订单簿与AMM:两种截然不同的交易范式
3.1.1 核心原理对比
传统中心化交易所(如Binance、Coinbase)采用订单簿(Order Book)模式。买卖双方分别提交限价单,系统按照“价格优先、时间优先”的原则进行撮合。订单簿的深度取决于市场参与者的挂单数量,流动性不足时会出现较大的买卖价差(Spread),导致交易成本上升。
而AMM(Automated Market Maker,自动化做市商)彻底改变了这一范式。AMM不依赖对手方挂单,而是通过智能合约维护一个流动性池(Liquidity Pool)。池中同时存放两种代币(如ETH和USDC),交易者直接与池子进行兑换。价格由数学公式自动计算,最经典的是Uniswap的恒定乘积公式:
x · y = k
其中,x 和 y 分别代表池中两种代币的数量,k 为常数。当交易者买入一种代币时,池中该代币数量减少,另一种代币数量增加,乘积保持不变,价格随之动态调整。
| 对比维度 | 订单簿模式 | AMM模式 |
|---|---|---|
| 流动性来源 | 买卖双方挂单 | 流动性提供者存入资产 |
| 价格发现 | 市场竞价撮合 | 数学公式自动计算 |
| 交易对手 | 其他交易者 | 智能合约(流动性池) |
| 滑点特性 | 深度好时滑点小 | 交易额越大滑点越高 |
| 上币门槛 | 需申请、审核、做市 | 任何人可创建池子 |
| 资金效率 | 高(资金可复用) | 较低(资金锁定在池中) |
3.1.2 实战场景:为什么AMM更适合链上环境
在以太坊等公链上,每笔交易都需要支付Gas费,且区块确认有延迟。如果采用订单簿模式,挂单、撤单、撮合都需要多次链上交互,不仅成本高昂,而且难以保证撮合的原子性。AMM将交易简化为“一次兑换调用”,交易者在单笔交易内完成兑换,智能合约自动结算,避免了对手方风险和撮合延迟。
以Uniswap V2为例,用户调用swap()函数时,合约会检查池中储备量,计算应输出的代币数量,并在同一笔交易中完成转账。整个过程无需等待其他用户响应,实现了“即时流动性”。
3.2 流动性池:AMM的核心资产池
3.2.1 流动性池的构成与运作机制
流动性池本质上是一个由智能合约管理的代币储备库。以Uniswap V2的ETH/USDC池为例,池中同时持有ETH和USDC两种资产。流动性提供者(LP)按照当前池中两种代币的比例存入资产,获得代表其份额的LP 。当交易者进行兑换时,支付的手续费(如0.3%)会按比例分配给所有LP。
池子的价格锚定机制依赖于套利者。当池内价格与外部市场出现偏差时,套利者会在池中买入低价资产、卖出高价资产,直到价格回归均衡。这种机制使得AMM的价格始终贴近市场公允价。
3.2.2 流动性池的关键参数
- 储备量(Reserves):池中两种代币的数量,决定当前价格和滑点。
- 手续费率(Fee):每笔交易收取的比例,Uniswap V2为0.3%,V3支持多级费率。
- LP 总量:代表LP在池中的份额,用于计算收益和赎回资产。
- 价格影响(Price Impact):交易对池子价格造成的偏移程度,交易额越大影响越大。
3.2.3 案例拆解:向池中注入流动性
假设当前ETH/USDC池中储备为 100 ETH 和 200,000 USDC,价格为 1 ETH = 2,000 USDC。Alice决定注入 1 ETH 和 2,000 USDC,保持价格不变。她获得的LP 数量基于她注入的资产价值占池子总价值的比例。若池子总价值为 400,000 USDC,Alice注入 4,000 USDC 等值资产,则获得 1% 的池子份额。
当后续交易产生手续费时,Alice按 1% 的比例获得分红。但需要注意的是,如果ETH价格大幅上涨,池中ETH数量会减少、USDC数量会增加,Alice赎回时拿到的资产组合与存入时不同,这就是无常损失的来源。
3.3 交易流程:从用户输入到链上确认
3.3.1 标准AMM交易流程
- 用户发起交易:指定输入代币、输出代币、期望获得的最小输出数量(滑点容忍度)。
- 合约校验:检查输入代币余额、授权额度、池子是否存在。
- 价格计算:根据恒定乘积公式计算应输出的代币数量,并扣除手续费。
- 滑点检查:如果计算出的输出数量低于用户设定的最小值,交易回滚。
- 代币转账:将输入代币转入池子,将输出代币转给用户。
- 更新储备量:更新池中两种代币的储备量,为下一笔交易做准备。
3.3.2 交易流程中的关键校验
在合约实现中,滑点保护和闪电贷攻击防护是必须考虑的安全点。滑点保护通过minReceived参数实现,确保用户不会因价格波动而获得过少的输出。闪电贷攻击则要求合约在交易前后检查池子的储备量平衡,防止攻击者通过操纵价格获利。
// 伪代码示例:AMM交易核心逻辑
function swap(address tokenIn, uint amountIn, uint minOut) external {
uint reserveIn = getReserve(tokenIn);
uint reserveOut = getReserve(tokenOut);
uint amountOut = getAmountOut(amountIn, reserveIn, reserveOut);
require(amountOut >= minOut, "Slippage exceeded");
// 执行转账、更新储备量
}
3.3.3 实战场景:一笔真实交易的拆解
假设用户Bob在Uniswap上使用 1,000 USDC 兑换ETH。当前池中储备为 100 ETH 和 200,000 USDC,手续费率 0.3%。计算过程如下:
- 扣除手续费:
1,000 × 0.997 = 997 USDC实际进入池子。 - 根据恒定乘积公式:
(200,000 + 997) × (100 - ΔETH) = 200,000 × 100 - 解得
ΔETH ≈ 0.4963 ETH,即Bob获得约0.4963 ETH。 - 实际成交价格约为
2,014 USDC/ETH,高于交易前价格,体现了滑点。
这笔交易中,Bob承担了约 0.7% 的价格滑点,而LP则获得了 3 USDC 的手续费收入。
3.4 无常损失:LP必须理解的核心风险
3.4.1 无常损失的本质
无常损失(Impermanent Loss)是指LP在提供流动性后,由于池中资产价格相对变化,导致赎回时资产价值低于简单持有两种代币的价值。这种损失是“暂时”的,如果价格回归到存入时的水平,损失会消失;但如果价格持续偏离,损失就会变成永久性损失。
3.4.2 无常损失的计算方法
假设LP存入时 1 ETH = 2,000 USDC,存入 1 ETH 和 2,000 USDC。若ETH价格上涨至 4,000 USDC,套利者会在池中买入ETH,直到池中储备变为 70.71 ETH 和 282,840 USDC(根据恒定乘积公式)。此时LP赎回资产价值为:
70.71 × 4,000 + 282,840 = 565,680 USDC
而如果LP没有提供流动性,直接持有 1 ETH 和 2,000 USDC,价值为 6,000 USDC。无常损失约为 5.7%。
| 价格变化幅度 | 无常损失比例 | 说明 |
|---|---|---|
| ±10% | 约0.5% | 影响较小 |
| ±50% | 约5.7% | 需要手续费覆盖 |
| ±100% | 约20% | 损失显著 |
| ±200% | 约40% | 损失严重 |
3.4.3 案例复盘:ETH价格翻倍后的LP决策
某LP在ETH价格为 2,000 USDC 时向池中注入 10 ETH 和 20,000 USDC。三个月后ETH涨至 4,000 USDC,LP决定赎回。此时池中储备变为 7.07 ETH 和 28,284 USDC,赎回价值为 56,568 USDC。如果LP一直持有原始资产,价值为 60,000 USDC,无常损失约 5.7%。
但在此期间,LP累计获得了 1,200 USDC 的手续费收入。净收益为 56,568 + 1,200 - 60,000 = -2,232 USDC,仍然亏损。这说明在价格剧烈波动时,手续费收入可能无法完全覆盖无常损失。
3.4.4 常见误区
- 误区一:认为LP只赚不亏。实际上,无常损失可能超过手续费收益。
- 误区二:认为无常损失是“永久”的。如果价格回归,损失会消失,但机会成本依然存在。
- 误区三:忽略手续费收益的复利效应。长期持有LP 并自动复投,可以部分抵消无常损失。