第三章:原始交易日志解析——Swap、Mint/Burn 事件深度拆解

好,咱们直接进入正题。上一章我们聊了怎么从链上捞数据,这一章就手把手教你——拿到这些原始日志后,怎么把「天书」变成「账本」。

说白了,DEX 的核心就三件事:Swap(交换)、Mint(添加流动性)、Burn(移除流动性)。这三个事件,几乎覆盖了所有 AMM 协议的数据源头。你只要会解析它们,Uniswap、Pancake、Sushi……一通百通。

核心认知: 链上日志不是给你看的,是给合约读的。我们做数据分析,就是要把这些「机器语言」翻译成「人类语言」。

3.1 Swap 事件:交易对、数量、价格的提取逻辑

先看 Swap。这是最频繁、也是最有价值的事件。我刚开始做链上分析时,以为 Swap 就是「谁给了谁多少钱」,后来发现——远没那么简单。

一个标准的 Swap 事件,通常长这样(以 Uniswap V2 为例):

event Swap(
    address indexed sender,
    uint256 amount0In,
    uint256 amount1In,
    uint256 amount0Out,
    uint256 amount1Out,
    address indexed to
);

嗯,这里要注意:amount0In 和 amount1In 不是同时有值的。你想想看,一次 Swap 要么是 token0 换 token1,要么是 token1 换 token0。所以一定是「一进一出」。

我个人习惯这样判断方向:

  • 如果 amount0In > 0amount1Out > 0:用户用 token0 买了 token1
  • 如果 amount1In > 0amount0Out > 0:用户用 token1 买了 token0

那价格怎么算?别急,这里有个坑。我在项目中遇到过,有人直接用 amountOut / amountIn 算价格,结果小数点差了 18 位——因为没考虑 token 的 decimals。

我的经验: 先统一精度。比如 USDC 是 6 位,WETH 是 18 位。你必须在计算前,把两个数量都转换成「人类可读」的数值。

正确的价格公式:

// 假设 token0 是 WETH(18位),token1 是 USDC(6位)
// 用户用 1 WETH 换出 2000 USDC
// 实际价格 = (2000 * 10^6) / (1 * 10^18) = 2000 USDC/WETH

price = (amountOut / 10^decimals_out) / (amountIn / 10^decimals_in)

说白了,你拿到的原始数值是「wei」级别的,不除精度就是天文数字。

3.2 Mint/Burn 事件:流动性变化的真相

Mint 和 Burn 是流动性提供者的操作日志。很多人以为 Mint 就是「存钱」,Burn 就是「取钱」——其实不完全对。

看事件定义:

event Mint(
    address indexed sender,
    uint256 amount0,
    uint256 amount1
);

event Burn(
    address indexed sender,
    uint256 amount0,
    uint256 amount1,
    address indexed to
);

这里有个关键点:Mint 事件里的 amount0 和 amount1,是用户实际存入的 token 数量。但 Burn 事件里的 amount0 和 amount1,是用户赎回的数量。

我曾经踩过一个坑:以为 Burn 的数值就是用户当初存进去的数值。其实不是!因为池子里的比例会变,你 Burn 的时候拿到的 token 数量,取决于当时的池子比例。

避坑指南: 如果你要计算 LP 的盈亏,不能只看 Burn 事件。必须把 Mint 时的价格和 Burn 时的价格做对比。我曾经有个项目,用户 Burn 时拿到的 token 数量比 Mint 时还多,但实际因为价格波动,他亏了 20%。

3.3 实战:从原始日志到结构化数据

好,理论说完了,咱们来点实际的。假设你从链上拿到了这样一条 Swap 日志:

交易哈希: 0xabc...123
事件类型: Swap
参数:
  sender: 0xuser1
  amount0In: 1000000000000000000  (1 WETH, 18位)
  amount1In: 0
  amount0Out: 0
  amount1Out: 2000000000  (2000 USDC, 6位)
  to: 0xuser1

解析步骤:

  1. 判断方向: amount0In > 0,amount1Out > 0 → 用 WETH 买 USDC
  2. 提取数量: 入账 1 WETH,出账 2000 USDC
  3. 计算价格: 2000 / 1 = 2000 USDC/WETH
  4. 记录交易对: WETH/USDC

你看,就这么简单。但实际项目中,你可能会遇到:

  • 同一个交易对,不同池子的地址不同(比如 V2 和 V3)
  • 同一个池子,token0 和 token1 的顺序可能不同
  • 有些协议会 emit 额外的自定义字段

我的建议: 写一个通用的解析器,把 token 地址、精度、池子地址都做成配置表。别硬编码。我见过有人把 WETH 地址写死在代码里,结果换了个链就崩了。

3.4 知识体系:事件解析的核心逻辑

下面这张图,是我自己总结的「事件解析四步法」。你照着这个流程走,基本不会漏东西。

事件解析四步法 Step 1: 识别事件 Swap / Mint / Burn Step 2: 提取参数 amount0/1, sender, to Step 3: 精度转换 除以 10^decimals Step 4 计算价格 关键数据提取对照表 事件类型 | 提取字段 | 计算逻辑 Swap | amount0In/Out, amount1In/Out | 价格 = 出账 / 入账(精度归一后) Mint | amount0, amount1 | 记录存入的 token 数量 Burn | amount0, amount1 | 记录赎回的 token 数量(需对比 Mint)

嗯,这张图基本概括了本章的核心。你只要按这个流程走,90% 的 DEX 事件都能解析。

3.5 常见问题与避坑

最后,分享几个我实际踩过的坑:

  • 事件顺序问题: 同一个交易里,可能先 Burn 再 Mint(比如移除流动性后重新添加)。别假设顺序。
  • 零值问题: 有些事件会 emit 0 值。比如 Swap 时,如果 amount0In 是 0,不代表没有,只是方向问题。
  • 多池子问题: 同一个交易对,可能有多个池子(V2、V3、不同费率)。解析时一定要带上池子地址。

我曾经犯过的错: 有一次解析 PancakeSwap 的日志,发现 Swap 事件里多了个 amount0Fee 字段。我没注意,直接用标准 Uniswap V2 的解析器去读,结果数据全乱了。后来才发现 Pancake 在 V2 基础上加了手续费字段。

所以,永远不要假设所有 DEX 的事件结构完全一样。先看合约源码,再写解析器。

好了,这一章就到这里。你只要把 Swap、Mint、Burn 这三个事件吃透,链上交易数据的半壁江山就到手了。下一章我们聊聊更进阶的——如何从这些数据里挖掘交易策略和套利机会。


专注资料整理