Tokens

ethers.js swapExactTokensForTokens 沒有發生(沒有錯誤)

  • September 23, 2022

一直堅持使用 ethers js 交換令牌,這是我正在使用的程式碼:

const https_provider = new ethers.providers.JsonRpcProvider(https_provider_addres)
const wallet = new ethers.Wallet.fromMnemonic(mnemonic)
const account = wallet.connect(provider)
const https_account = wallet.connect(https_provider)

const erc20_ABI =
   [
       {
           "constant": true,
           "inputs": [],
           "name": "name",
           "outputs": [
               {
                   "name": "",
                   "type": "string"
               }
           ],
           "payable": false,
           "stateMutability": "view",
           "type": "function"
       },
       {
           "constant": false,
           "inputs": [
               {
                   "name": "_spender",
                   "type": "address"
               },
               {
                   "name": "_value",
                   "type": "uint256"
               }
           ],
           "name": "approve",
           "outputs": [
               {
                   "name": "",
                   "type": "bool"
               }
           ],
           "payable": false,
           "stateMutability": "nonpayable",
           "type": "function"
       },
       {
           "constant": true,
           "inputs": [],
           "name": "totalSupply",
           "outputs": [
               {
                   "name": "",
                   "type": "uint256"
               }
           ],
           "payable": false,
           "stateMutability": "view",
           "type": "function"
       },
       {
           "constant": false,
           "inputs": [
               {
                   "name": "_from",
                   "type": "address"
               },
               {
                   "name": "_to",
                   "type": "address"
               },
               {
                   "name": "_value",
                   "type": "uint256"
               }
           ],
           "name": "transferFrom",
           "outputs": [
               {
                   "name": "",
                   "type": "bool"
               }
           ],
           "payable": false,
           "stateMutability": "nonpayable",
           "type": "function"
       },
       {
           "constant": true,
           "inputs": [],
           "name": "decimals",
           "outputs": [
               {
                   "name": "",
                   "type": "uint8"
               }
           ],
           "payable": false,
           "stateMutability": "view",
           "type": "function"
       },
       {
           "constant": true,
           "inputs": [
               {
                   "name": "_owner",
                   "type": "address"
               }
           ],
           "name": "balanceOf",
           "outputs": [
               {
                   "name": "balance",
                   "type": "uint256"
               }
           ],
           "payable": false,
           "stateMutability": "view",
           "type": "function"
       },
       {
           "constant": true,
           "inputs": [],
           "name": "symbol",
           "outputs": [
               {
                   "name": "",
                   "type": "string"
               }
           ],
           "payable": false,
           "stateMutability": "view",
           "type": "function"
       },
       {
           "constant": false,
           "inputs": [
               {
                   "name": "_to",
                   "type": "address"
               },
               {
                   "name": "_value",
                   "type": "uint256"
               }
           ],
           "name": "transfer",
           "outputs": [
               {
                   "name": "",
                   "type": "bool"
               }
           ],
           "payable": false,
           "stateMutability": "nonpayable",
           "type": "function"
       },
       {
           "constant": true,
           "inputs": [
               {
                   "name": "_owner",
                   "type": "address"
               },
               {
                   "name": "_spender",
                   "type": "address"
               }
           ],
           "name": "allowance",
           "outputs": [
               {
                   "name": "",
                   "type": "uint256"
               }
           ],
           "payable": false,
           "stateMutability": "view",
           "type": "function"
       },
       {
           "payable": true,
           "stateMutability": "payable",
           "type": "fallback"
       },
       {
           "anonymous": false,
           "inputs": [
               {
                   "indexed": true,
                   "name": "owner",
                   "type": "address"
               },
               {
                   "indexed": true,
                   "name": "spender",
                   "type": "address"
               },
               {
                   "indexed": false,
                   "name": "value",
                   "type": "uint256"
               }
           ],
           "name": "Approval",
           "type": "event"
       },
       {
           "anonymous": false,
           "inputs": [
               {
                   "indexed": true,
                   "name": "from",
                   "type": "address"
               },
               {
                   "indexed": true,
                   "name": "to",
                   "type": "address"
               },
               {
                   "indexed": false,
                   "name": "value",
                   "type": "uint256"
               }
           ],
           "name": "Transfer",
           "type": "event"
       }
   ]

const addresses = {
   WAVAX: "0xB31f66AA3C1e785363F0875A1B74E27b85FD66c7",
   router: "0x60aE616a2155Ee3d9A68541Ba4544862310933d4",
   factory: "0x9Ad6C38BE94206cA50bb0d90783181662f0Cfa10",
}

const router = new ethers.Contract(
   addresses.router,
   [
       'function getAmountsOut(uint amountIn, address[] memory path) public view returns (uint[] memory amounts)',
       'function swapExactTokensForTokens(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline) external returns (uint[] memory amounts)',
       'function swapExactETHForTokens(uint amountOutMin, address[] calldata path, address to, uint deadline) external payable returns (uint[] memory amounts)',
   ],
   account
)

const USDC_address = '0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E'

const STG_address = "0x2F6F07CDcf3588944Bf4C42aC74ff24bF56e7590"
const STG_contract = new ethers.Contract(
   STG_address,
   erc20_ABI,
   https_account
)

const swap = async () => {

   console.log('swap starting')

   const amountIn = "22146823544065952776"

   const amounts = await router.getAmountsOut(amountIn, [
       STG_address,
       USDC_address
   ])

   const amountOutMin = amounts[1].sub(amounts[1].div(12))
   console.log('amountOutMin: ' + amountOutMin)

   const tx = await router.swapExactTokensForTokens(
       amountIn,
       amountOutMin,
       [STG_address, USDC_address],
       https_account.address,
       Math.floor(Date.now() / 1000) + 60 * 6, // 6 mins from current
       {
           gasLimit: 5000009999
       }
   )

   console.log('Swap done!')
   const receipt = await tx.wait()
   console.log('Transaction receipt' + receipt)
}

const init = async () => {
   console.log('before contract approve')

   //
   let receipt = STG_contract.connect(https_account).approve("0x60aE616a2155Ee3d9A68541Ba4544862310933d4", ethers.utils.parseUnits('1000.0', 18)).then((results) => {
       console.log(results)
       swap()
   })

   console.log(receipt)
   console.log('await contract approve happened')
}

init()

批准工作正常,我得到了預期的控制台輸出,tx 雜湊(可以在 snowtrace 等上驗證)

問題在於實際的交換,我得到了金額,但是在嘗試 swapExactTokensForTokens 之後基本上什麼都沒有發生 - 它只是永遠掛起,沒有錯誤,什麼都沒有

有任何想法嗎?

我不會gasLimit在雪崩上投入大量資金,因為根據我的經驗,它會導致額外的汽油費。首先,嘗試將其更改為至少1_000_000. 理想情況下,通過 估計它await router.estimateGas['swapExactTokensForTokens'](...params)

我也同意0xSanson 的回复——你必須等待 tx 得到確認。在您的情況下,您正在使用回調來等待 tx 被簽名,而不是被確認。

首先,我會嘗試使用單個提供程序。現在你有providerand https_provider,我猜這不一樣?這可能provider不起作用,因此我將更改以下內容:

//const account = wallet.connect(provider)
const account = wallet.connect(https_provider)

另外我會嘗試以下方法,在交換之前等待批准收據:

const init = async () => {
   console.log('before contract approve')

   // let's complete the approve first
   let tx_receipt = await STG_contract.connect(https_account).approve("0x60aE616a2155Ee3d9A68541Ba4544862310933d4", ethers.utils.parseUnits('1000.0', 18));
   let receipt = await tx_receipt.wait();
   console.log(receipt)

   // onto the swap
   await swap()
}

如果上述兩種解決方案都不起作用,我想這是一個 nonce 問題。有可能通過在短時間內發送兩個 tx,提供者在兩者中使用了相同的 nonce,所以第二個被丟棄了。要解決此問題,您需要獲取帳戶的隨機數,並專門用於nonce批准和nonce+1交換。

const nonce = await account.getTransactionCount();

let tx_receipt = await STG_contract.connect(account).approve(
   "0x60aE616a2155Ee3d9A68541Ba4544862310933d4",
   ethers.utils.parseUnits('1000.0', 18),
   {
       nonce: nonce,
   }
);

// ...

const tx = await router.swapExactTokensForTokens(
   amountIn,
   amountOutMin,
   [STG_address, USDC_address],
   https_account.address,
   Math.floor(Date.now() / 1000) + 60 * 6, // 6 mins from current
   {
       nonce: nonce+1,
       gasLimit: 5000009999
   }
)

引用自:https://ethereum.stackexchange.com/questions/136173