web3py调用Uniswap V3 quoteExactInputSingle报ValidationError问题
问题原因
报错来自web3py的合约函数参数校验,触发原因有两点:
- 参数顺序完全错误:Uniswap V3 Quoter合约
quoteExactInputSingle的链上参数顺序为quoteExactInputSingle(address tokenIn, address tokenOut, uint24 fee, uint256 amountIn, uint160 sqrtPriceLimitX96),你的代码将amountIn(交易数额)放在第三个参数位,将fee(手续费层级,3000对应0.3%费率池)放在第四个参数位,和ABI定义的顺序完全颠倒。 - 参数值与类型不兼容:你传给第三个参数位的
web3.toWei(0.01, 'ether')生成的是1e16量级的整数,远大于uint24类型支持的最大值16777215,根本无法被uint24类型容纳,直接导致类型匹配失败;最后一个参数sqrtPriceLimitX96为uint160类型,直接传Python原生int 0在部分web3py版本中也会触发类型校验错误。
额外注意:如果你的入金token是WBTC,其精度为8位,直接用web3.toWei(0.01, 'ether')会按18位精度计算数额,最终得到的报价完全错误。
修复方案
- 调整参数顺序,严格按照
tokenIn -> tokenOut -> fee -> amountIn -> sqrtPriceLimitX96的顺序传参 - 对Solidity定长整数类型的参数,用web3py内置方法做显式类型转换,避免校验失败
- 传入的token地址统一转换为checksum格式,避免地址校验报错
- 按交易token的实际精度计算交易数额,不要硬用以太坊18位精度的换算结果
可运行代码示例
from web3 import Web3 # 转换地址为checksum格式 wbtc_addr = Web3.toChecksumAddress(wbtc_token) weth_addr = Web3.toChecksumAddress(weth_token) # 按token实际精度计算数额,示例为WETH/WBTC 0.3%费率池,输入0.01 WBTC的情况 # WBTC精度为8,所以数额为0.01 * 10**8 amount_in = int(0.01 * 10**8) # 如果是输入0.01 WETH,用下面这行 # amount_in = Web3.toWei(0.01, 'ether') fee_tier = 3000 # 传0代表不设置价格滑点限制,使用池内当前价格报价 sqrt_price_limit = 0 # 显式转换定长整数类型,匹配ABI参数要求 quote_amount = uniswap_v3_quoter_contract.functions.quoteExactInputSingle( wbtc_addr, weth_addr, Web3.to_uint24(fee_tier), amount_in, Web3.to_uint160(sqrt_price_limit) ).call()
如果你的web3py版本较低找不到to_uint24/to_uint160方法,可以直接升级web3py到6.0以上版本,绝大多数场景下只要参数顺序正确、数值在对应类型的取值范围内,web3py 5.x以上版本会自动完成隐式类型转换。
内容的提问来源于stack exchange,提问作者Donghui HU
相关产品推荐
相关产品推荐

