You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Python解码Uniswap V3 Router 2的交易数据?

Uniswap V3 Router2交易数据解码方案

1. 核心问题定位

Web3的decode_function_input失效,本质是使用的ABI不完整或未包含目标函数定义。你的交易数据前4字节0x5ae401dc对应Uniswap V3 Router2的exactInput函数,该函数的参数是一个包含path字节数组的结构体,必须在ABI中明确结构体定义才能完成解码。

2. 解决方案步骤

第一步:使用正确的ABI

确保ABI包含exactInput函数及对应结构体的定义,以下是关键ABI片段:

[
  {
    "inputs": [
      {
        "components": [
          {
            "internalType": "bytes",
            "name": "path",
            "type": "bytes"
          },
          {
            "internalType": "address",
            "name": "recipient",
            "type": "address"
          },
          {
            "internalType": "uint256",
            "name": "deadline",
            "type": "uint256"
          },
          {
            "internalType": "uint256",
            "name": "amountIn",
            "type": "uint256"
          },
          {
            "internalType": "uint256",
            "name": "amountOutMinimum",
            "type": "uint256"
          },
          {
            "internalType": "uint160",
            "name": "sqrtPriceLimitX96",
            "type": "uint160"
          }
        ],
        "internalType": "struct ISwapRouter.ExactInputParams",
        "name": "params",
        "type": "tuple"
      }
    ],
    "name": "exactInput",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "amountOut",
        "type": "uint256"
      }
    ],
    "stateMutability": "payable",
    "type": "function"
  }
]

第二步:完整解码与路径解析

使用正确ABI解码后,需进一步解析path字节数组提取交易路径中的代币地址和手续费层级,完整代码示例如下:

from web3 import Web3

# 初始化Web3实例
w3 = Web3(Web3.HTTPProvider('你的RPC节点地址'))

# Router2地址与交易数据
router_address = "0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45"
tx_data = "0x5ae401dc0000000000000000000000000000000000000000000000000000000063bd8fab00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000e404e45aaf000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec700000000000000000000000000000000000000000000000000000000000001f4000000000000000000000000dc06b8c890e100ba78888fede3d0c4bc769f41b400000000000000000000000000000000000000000000000000b08416c4bb7d2e0000000000000000000000000000000000000000000000000000000003eb71f4000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"

# 导入正确的ABI片段
abi = [
  {
    "inputs": [
      {
        "components": [
          {
            "internalType": "bytes",
            "name": "path",
            "type": "bytes"
          },
          {
            "internalType": "address",
            "name": "recipient",
            "type": "address"
          },
          {
            "internalType": "uint256",
            "name": "deadline",
            "type": "uint256"
          },
          {
            "internalType": "uint256",
            "name": "amountIn",
            "type": "uint256"
          },
          {
            "internalType": "uint256",
            "name": "amountOutMinimum",
            "type": "uint256"
          },
          {
            "internalType": "uint160",
            "name": "sqrtPriceLimitX96",
            "type": "uint160"
          }
        ],
        "internalType": "struct ISwapRouter.ExactInputParams",
        "name": "params",
        "type": "tuple"
      }
    ],
    "name": "exactInput",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "amountOut",
        "type": "uint256"
      }
    ],
    "stateMutability": "payable",
    "type": "function"
  }
]

# 解码交易输入数据
contract_instance = w3.eth.contract(address=router_address, abi=abi)
func_obj, func_params = contract_instance.decode_function_input(tx_data)

# 解析Uniswap V3路径字节数组
def parse_uniswap_v3_path(path_bytes):
    path = []
    current_index = 0
    # 路径格式:代币地址(20字节) + 手续费(3字节) + 代币地址(20字节) + [手续费+代币地址]...
    while current_index < len(path_bytes):
        # 提取代币地址
        token_addr = w3.to_checksum_address(path_bytes[current_index:current_index+20].hex())
        path.append(token_addr)
        current_index += 20
        # 提取手续费(若剩余字节足够)
        if current_index + 3 <= len(path_bytes):
            fee = int.from_bytes(path_bytes[current_index:current_index+3], byteorder='big')
            path.append(f"手续费: {fee}")
            current_index += 3
    return path

# 输出解码结果
path = parse_uniswap_v3_path(func_params['params']['path'])
print("解码后的交易参数:")
print(f"调用函数: {func_obj.fn_name}")
print(f"接收地址: {func_params['params']['recipient']}")
print(f"交易截止时间: {func_params['params']['deadline']}")
print(f"输入金额: {func_params['params']['amountIn']}")
print(f"最小输出金额: {func_params['params']['amountOutMinimum']}")
print(f"价格限制: {func_params['params']['sqrtPriceLimitX96']}")
print(f"完整交易路径: {' -> '.join(path)}")

3. 关键说明

  • 函数签名匹配:必须确保ABI中包含交易数据对应函数的完整定义(包括结构体参数),否则解码会失败。
  • 路径解析逻辑:Uniswap V3的path字节数组遵循固定格式,通过逐段截取20字节的地址和3字节的手续费,即可还原完整交易路径。
  • 兼容性扩展:该方法可适配Uniswap V3的其他swap函数(如exactInputSingle、exactOutput),只需调整ABI和路径解析逻辑即可。

内容的提问来源于stack exchange,提问作者evan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 12:15:43