Solidity
失敗並出現錯誤“TransferHelper:TRANSFER_FROM_FAILED”,所有氣體都用完了
我試圖在 Uniswap 主網上用 USDT 購買一些CHY ,但失敗了,
error 'TransferHelper: TRANSFER_FROM_FAILED'
這是我失敗的tx 連結。
這是來自其他人的成功tx 連結。
我注意到我的交易費異常高,比其他成功的交易高得多,而且無論我怎麼提高
gasLimit
,它總是用完,只需要更多的時間。tx 成功的頁面有Uniswap V2: CHY-USDT,我的程式碼中沒有用到,這就是我的 tx 從來沒有找到正確的方式,但總是不斷尋找並吃光所有 gas 的原因嗎?
如何更正程式碼?
更新 1:在交易前添加“approve()”。“approve()”第一次成功,之後就再也沒有成功,總是這樣失敗
const CHY = new Token(ChainId.MAINNET, '0x35A23BC27c345b36DeE700a256F69C6334030971', 9) const USDT = new Token(ChainId.MAINNET, '0xdAC17F958D2ee523a2206206994597C13D831ec7', 6) const pair = await Fetcher.fetchPairData(CHY, USDT) const route = new Route([pair], USDT) // direction, from USDT -> CHY var base = ethers.BigNumber.from(10).pow(route.path[0].decimals) var amountIn = ethers.BigNumber.from(50).mul(base) // 50 * 10^6 == 50 USDT console.log(amountIn.toString()) // 50 USDT const trade = new Trade( route, new TokenAmount(USDT, amountIn), TradeType.EXACT_INPUT) const slippageTolerance = new Percent('50', '10000') // 0.5% const amountOutMin = trade.minimumAmountOut(slippageTolerance).raw const path = [USDT.address, CHY.address] // <---------check direction const to = MY_WALLET; const deadline = Math.floor(Date.now() / 1000) + 20*60 // 20 minutes const provider = ethers.getDefaultProvider('mainnet', { infura: INFURA_ID }) const signer = new ethers.Wallet(MY_WALLET_PRIVATE_KEY) const account = signer.connect(provider) const uniswap = new ethers.Contract( '0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D', // fixed Route02.addr ['function swapExactTokensForTokens( uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline) external returns (uint[] memory amounts)'], account ) // approve const contract_usdt = new ethers.Contract( addr_usdt, //['function approve(address spender, uint value) public'], ['function approve(address spender, uint amount) public returns(bool)'], account ); const tx_approve = await contract_usdt.approve(uniswap.address, amountIn, { gasPrice: gasPrice, gasLimit: gasLimit }) console.log('tx_approve: ' + tx_approve.hash); const receipt_approve = await tx_approve.wait() console.log(receipt_approve) const tx = await uniswap.swapExactTokensForTokens( amountIn.toString(), amountOutMin.toString(), path, to, deadline, { gasLimit: 400000, gasPrice: ethers.utils.parseUnits("40", "gwei") } ) console.log(`Transaction hash: ${tx.hash}`) const receipt = await tx.wait()
我試過了
path=[USDT, UNIWAP_V2_CHY_USDT, CHY]
,也失敗了
在嘗試交換之前,您沒有批准 USDT 到路由器地址。
USDT 合約因未獲得批准而使用
assert
代替revert
或取消交易。throw
使用assert
將消耗所有剩餘的氣體。Tether 使用 是不好的做法assert
,但這可能是因為他們的契約真的很舊。編輯:此外,USDT 契約要求您在進行另一個批准呼叫之前將津貼設置為 0。下面是USDT合約的相關程式碼:
function approve(address _spender, uint _value) public onlyPayloadSize(2 * 32) { // To change the approve amount you first have to reduce the addresses` // allowance to zero by calling `approve(_spender, 0)` if it is not // already 0 to mitigate the race condition described here: // https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 require(!((_value != 0) && (allowed[msg.sender][_spender] != 0))); allowed[msg.sender][_spender] = _value; Approval(msg.sender, _spender, _value); }