使用Web3.py调用Uniswap swapExactTokensForTokens交易状态始终为0求助
1. 授权额度不匹配
你的代码中,approve的额度是am,但swap时传入的amountIn是web3.toWei('0.0001', 'ether'),这两个值必须完全一致(或am大于等于swap的amountIn)。如果am的计算没有对应0.0001 ether的代币数量,会导致授权额度不足,触发TransferHelper: TRANSFER_FROM_FAILED错误,直接导致交易失败。
修复建议:
把swap的amountIn替换为am,保持和approve的额度一致:
swap = routerContract.functions.swapExactTokensForTokens( am, # 用和approve一致的额度 0, [TOKEN_ADDRESS,TARGET_ADDRESS], SENDER_ADDRESS, (int(time.time()) + 1000000) ).buildTransaction({ # ... 其他参数不变 })
2. 代币小数位数不匹配
web3.toWei('0.0001', 'ether')仅适用于18位小数的代币。如果你的TOKEN_ADDRESS对应的代币小数位数不是18(比如USDT是6位),这个转换会导致传入的amountIn数值错误,要么金额过大超出余额,要么过小不符合池子要求,最终交易失败。
修复建议:
先获取代币的小数位数,再正确计算金额:
# 获取代币小数位数 decimals = tokenContract.functions.decimals().call() # 计算正确的amountIn amount_in = web3.toWei('0.0001', 'ether') if decimals == 18 else int(0.0001 * (10 ** decimals))
3. Gas设置不足
你手动设置了gas: 250000,但Uniswap的swap交易(尤其是涉及流动性较差的池子)可能需要更多Gas。固定Gas值可能导致交易因Out of Gas失败。
修复建议:
去掉手动设置的gas字段,让Web3自动估算Gas:
swap = routerContract.functions.swapExactTokensForTokens( # ... 参数不变 ).buildTransaction({ 'from': SENDER_ADDRESS, 'gasPrice': web3.toWei('60', 'gwei'), 'nonce': web3.eth.getTransactionCount(SENDER_ADDRESS), })
或者手动调高Gas值到300000-400000尝试。
4. 滑点参数设置问题
虽然你把amountOutMin设为0允许无限滑点,但部分链或Uniswap版本可能存在隐性限制,或者池子流动性不足导致实际输出为0,触发交易回滚。
修复建议:
用getAmountsOut获取预估的amountOut,然后设置一个合理的滑点(比如99%的预估量):
amounts = routerContract.functions.getAmountsOut(am, [TOKEN_ADDRESS, TARGET_ADDRESS]).call() amount_out_min = int(amounts[1] * 0.99) # 1%滑点 swap = routerContract.functions.swapExactTokensForTokens( am, amount_out_min, [TOKEN_ADDRESS,TARGET_ADDRESS], SENDER_ADDRESS, (int(time.time()) + 1000000) ).buildTransaction({ # ... 其他参数 })
5. 检查交易失败的具体原因
直接查看交易详情中的"Error"字段是最有效的方式,常见错误包括:
TransferHelper: TRANSFER_FROM_FAILED:授权不足UniswapV2Router: INSUFFICIENT_OUTPUT_AMOUNT:滑点设置过高或流动性不足Out of Gas:Gas设置不足
内容的提问来源于stack exchange,提问作者Jincowboy

