You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何使用Python、web3及eth-abi库离线计算Uniswap交易对地址?

离线计算Uniswap V2交易对地址:代码错误分析与正确实现

让我帮你梳理下当前代码里的问题,一步步修正后实现和Solidity逻辑完全对齐的离线计算逻辑:

你的代码存在的核心错误

  • 错误1:0xff的字节处理错误
    你用bytes(hexadem_1)(其中hexadem_1 = 0xff)会把整数255转换成一个长度为255的空字节数组,这完全不符合Solidity中hex'ff'的含义(单个字节0xff)。正确写法应该是直接使用b'\xff'

  • 错误2:盐值(salt)计算冗余且逻辑偏差
    Solidity里的saltkeccak256(abi.encodePacked(token0, token1)),你已经通过encode_abi_packed得到了打包后的字节,直接用web3.keccak(abiEncoded_1)就能得到正确的salt,不需要额外用solidityKeccak包裹bytes类型参数。

  • 错误3:最终哈希的打包逻辑错误
    Solidity中是把hex'ff'、factory地址、salt、init code hash这四个元素打包成一个连续字节数组后再做keccak256哈希,而你的代码把前三个元素打包成abiEncoded_2,再和hexadem_分开传入solidityKeccak,这相当于对两个独立的bytes做哈希,和原逻辑完全不符。

  • 错误4:未将哈希转换为以太坊地址
    最终交易对地址是哈希值的最后20字节,你当前代码只计算了哈希,没有截取并转换为标准地址格式。

  • 额外遗漏:token地址排序
    Uniswap V2工厂合约创建交易对时,会先对两个token地址按字典序排序(比较十六进制字符串大小,小的在前),如果不做排序,计算出的地址会和实际部署的交易对地址不符。


正确的Python实现代码

from web3 import Web3
from eth_abi.packed import encode_abi_packed

def calculate_uniswap_v2_pair_address(factory_address, token_a, token_b):
    # Uniswap V2 固定的init code hash(你提供的数值)
    INIT_CODE_HASH = "0x96e8ac4277198ff8b6f785478aa9a39f403cb768dd02cbee326c3e7da348845f"
    
    # 1. 对token地址按字典序排序,和Uniswap工厂逻辑对齐
    token0, token1 = sorted([token_a, token_b])
    
    # 2. 计算salt = keccak256(abi.encodePacked(token0, token1))
    packed_tokens = encode_abi_packed(['address', 'address'], (token0, token1))
    salt = Web3.keccak(packed_tokens)
    
    # 3. 打包所有元素:0xff + factory地址字节 + salt + init code hash字节
    factory_bytes = Web3.to_bytes(hexstr=factory_address)
    init_code_hash_bytes = Web3.to_bytes(hexstr=INIT_CODE_HASH)
    packed_data = b'\xff' + factory_bytes + salt + init_code_hash_bytes
    
    # 4. 计算keccak256哈希
    pair_hash = Web3.keccak(packed_data)
    
    # 5. 截取最后20字节并转换为校验和地址
    pair_address = Web3.to_checksum_address(pair_hash[-20:].hex())
    
    return pair_address

# 示例调用
if __name__ == "__main__":
    factory = "0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f"  # Uniswap V2 Factory地址
    token0 = "0xCAFE000000000000000000000000000000000000"
    token1 = "0xF00D000000000000000000000000000000000000"
    
    calculated_pair = calculate_uniswap_v2_pair_address(factory, token0, token1)
    print(f"计算得到的交易对地址:{calculated_pair}")

代码逻辑说明

这段代码完全复刻了你提供的Solidity逻辑:

  1. 排序token地址保证和Uniswap工厂的创建逻辑一致
  2. encode_abi_packed对应Solidity中的abi.encodePacked
  3. 按顺序打包0xff、factory地址、salt、init code hash后做哈希,对应Solidity的keccak256(abi.encodePacked(...))
  4. 截取哈希最后20字节并转换为校验和地址,对应Solidity的address(uint(...))

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

火山引擎 最新活动