Uniswap SDK主网交易Metamask Gas估算失败问题求助
Uniswap SDK主网兑换Gas估算失败问题排查
我用Uniswap SDK实现ETH与代币的兑换,流程如下:
- 通过Alpha Router SDK计算最优路由
- 基于Alpha Router返回的calldata构建交易
- 将交易提交至Metamask签名发送
当前问题:在Foundry本地测试网中交易可正常执行,但切换到以太坊主网后,Metamask提示**"无法估算Gas,合约可能存在错误,该交易或失败"**。尝试手动指定Gas参数、不指定Gas参数两种方式,均触发该错误。
相关代码配置
package.json 文件
{ "name": "routing", "version": "0.1.0", "private": true, "dependencies": { "@ethersproject/experimental": "^5.6.0", "@types/node": "^16.7.13", "@types/react": "^18.0.0", "@types/react-dom": "^18.0.0", "@uniswap/sdk-core": "^3.1.0", "@uniswap/smart-order-router": "^3.0.6", "@uniswap/v3-periphery": "^1.4.3", "@uniswap/v3-sdk": "^3.9.0", "@web3-react/coinbase-wallet": "^8.2.3", "@web3-react/core": "^8.2.3", "@web3-react/eip1193": "^8.2.2", "@web3-react/empty": "^8.2.2", "@web3-react/gnosis-safe": "^8.2.4", "@web3-react/injected-connector": "^6.0.7", "@web3-react/metamask": "^8.2.4", "@web3-react/network": "^8.2.3", "@web3-react/types": "^8.2.2", "@web3-react/url": "^8.2.2", "@web3-react/walletconnect": "^8.2.3", "@web3-react/walletconnect-v2": "^8.5.1", "bootstrap": "^5.3.3", "ethers": "^5.7.2", "lodash": "^4.17.21", "react": "^18.2.0", "react-bootstrap-icons": "^1.11.4", "react-dom": "^18.2.0", "react-scripts": "5.0.1", "react-spinners": "^0.14.1", "socket.io-client": "^4.7.5", "typescript": "^4.4.2", "yarn": "^1.22.22" }, "scripts": { "start": "react-scripts start", "build": "react-scripts build", "install:chain": "curl -L https://foundry.paradigm.xyz | bash && clear && echo $0 | exec && foundryup", "start:chain": "anvil --chain-id 1337 --fork-url" }, "eslintConfig": { "extends": [ "react-app", "react-app/jest" ] }, "browserslist": { "production": [ ">0.2%", "not dead", "not op_mini all" ], "development": [ "last 1 chrome version", "last 1 firefox version", "last 1 safari version" ] } }
Alpha Router获取路由代码
import { ethers, BigNumber } from "ethers"; import { TradeType, CurrencyAmount, Percent, Ether } from "@uniswap/sdk-core"; import { AlphaRouter, ChainId, SwapOptionsSwapRouter02, SwapRoute, SwapType, } from "@uniswap/smart-order-router"; import { getMainnetProvider } from "../providers"; import { PairTokenType } from "../../contexts/UniswapContexts/UniswapContexts"; export async function generateRouteEthToken( uniswapTokenOut, tokenInAmount, pairTokenType, account, slippageAmount, deadlineMinutes ): Promise<SwapRoute | null> { if (pairTokenType !== PairTokenType.EthToken) return; const router = new AlphaRouter({ chainId: ChainId.MAINNET, provider: getMainnetProvider(), }); const options: SwapOptionsSwapRouter02 = { recipient: account, slippageTolerance: slippageAmount ? new Percent(Number(slippageAmount), 10_000) : new Percent(100, 10_000), deadline: deadlineMinutes ? Math.floor(Date.now() / 1000) + 60 * Number(deadlineMinutes) : Math.floor(Date.now() / 1000) + 60 * 5, type: SwapType.SWAP_ROUTER_02, }; const amountIn = ethers.utils.parseEther(tokenInAmount); const currencyAmount = CurrencyAmount.fromRawAmount( Ether.onChain(ChainId.MAINNET), amountIn.toString() ); const route = await router.route( currencyAmount, uniswapTokenOut, TradeType.EXACT_INPUT, options ); if (!route || !route.methodParameters) { console.log('NOT FOUND ROUTE'); return null } return route; }
执行交易代码
import { SwapRoute } from "@uniswap/smart-order-router"; import { sendTransactionWalletExtention } from "../swapFunctions"; import { V3_SWAP_ROUTER_ADDRESS } from "../constants"; export async function executeTradeEthToken( route: SwapRoute, account, provider, ) { const transaction = { data: route.methodParameters?.calldata, to: V3_SWAP_ROUTER_ADDRESS, value: route?.methodParameters?.value, from: account }; const result = await sendTransactionWalletExtention( provider.provider, transaction, provider ); return result; }
交易发送方式
不带Gas参数
export async function sendTransactionWalletExtention( provider, transaction, innerProvider = null ) { try { const trx = await provider?.request({ method: "eth_sendTransaction", params: [ transaction], }); const receipt = await provider.waitForTransaction(trx); if (receipt.status === 1) { return { TransactionState: TransactionState.Sent, receipt: receipt, }; } else { return { TransactionState: TransactionState.Failed, receipt: receipt, }; } } catch (e) { console.log(e); return { TransactionState: TransactionState.Failed, receipt: null, }; } }
带Gas参数
export async function sendTransactionWalletExtention( provider, transaction, innerProvider = null ) { try { const trx = await provider?.request({ method: "eth_sendTransaction", params: [await estimateGasFees(innerProvider, transaction)], }); const receipt = await provider.waitForTransaction(trx); if (receipt.status === 1) { return { TransactionState: TransactionState.Sent, receipt: receipt, }; } else { return { TransactionState: TransactionState.Failed, receipt: receipt, }; } } catch (e) { console.log(e); return { TransactionState: TransactionState.Failed, receipt: null, }; } } export function estimateGasFees(provider, tx) { return provider.estimateGas(tx).then(async (estimatedGas) => { const pendingBlock = await provider.getBlock("pending"); const baseFee = pendingBlock.baseFeePerGas; const tip = ethers.utils.parseUnits("5", "gwei"); const maxFeePerGas = baseFee.add(tip); const txRequest = { ...tx, gasLimit: toHex(estimatedGas), maxPriorityFeePerGas: tip.toHexString(), maxFeePerGas: toHex(maxFeePerGas), }; return txRequest; }); }
报错截图描述
- 弹窗提示:无法估算Gas费用,无法确认交易有效性,可能原因包括合约错误、ETH余额不足或交易本身会失败。
- 交易预览页:显示"无法估算Gas",确认按钮不可点击,提示信息与弹窗一致。
排查建议
- 验证主网Provider:确认
getMainnetProvider()使用的是以太坊主网合法RPC节点,避免节点受限或延迟过高导致路由计算偏差。 - 检查代币合约:确认目标代币在主网正常部署,且支持Uniswap V3交易,避免输入错误地址。
- 调整路由参数:主网环境下适当延长deadline,避免签名时已过期;检查slippage设置是否合理。
- 修复Gas估算逻辑:带Gas参数的代码中
toHex函数未定义,替换为ethers.utils.hexlify确保参数格式正确。 - 同步Metamask状态:确认Metamask已切换到主网,账户余额足够支付Gas和交易金额。
- 升级SDK版本:检查@uniswap/smart-order-router等依赖是否为最新稳定版,避免版本兼容问题。
内容的提问来源于stack exchange,提问作者hamed
相关产品推荐
相关产品推荐

