首页 > 解决方案 > 我正在尝试使用 web3 在 Pancakeswap 上执行交换,但在计算交易成本时出现错误

问题描述

我是以太坊开发的新手,我正在编写一个简单的脚本来使用 Pancakeswap 执行交换。在我建立交易并计算 tx 成本之前,一切似乎都运行良好。我正在使用 UniswapRouterV02 abi 创建我的 Pancakeswap 合约。编码:

const init = async () => {

    const [WBNB, BUSD] = await Promise.all(
        [addresses.WBNB, addresses.BUSD].map(tokenAddress => (
            new Token(
                ChainId.MAINNET,
                tokenAddress,
                18
            )
        )));


    const pair = await Fetcher.fetchPairData(WBNB, BUSD, provider)
    const route = await new Route([pair], WBNB)
    const trade = await new Trade(route, new TokenAmount(WBNB, tradeAmount), TradeType.EXACT_INPUT)
    const executionPrice = trade.executionPrice.toSignificant(12)

    // Correct prices; everything seems correct up until here

    const slippageTolerance = new Percent('50', '10000')

    const amountOutMin = trade.minimumAmountOut(slippageTolerance).raw
    const path = [WBNB.address, BUSD.address]
    const to = MY_ADDRESS
    const deadline = Math.floor(Date.now() / 1000) + 60 * 20
    const value = trade.inputAmount.raw

    // Correct prices everything seems correct up until here

    const pancakeSwap = new web3.eth.Contract(
        abis.uniswapRouter.abi,
        addresses.PANCAKE_ROUTER //'0x05fF2B0DB69458A0750badebc4f9e13aDd608C7F'
    );

    let tx = pancakeSwap.methods.swapExactTokensForTokens(
        tradeAmount,
        web3.utils.toBN(amountOutMin.toString()),
        path,
        to,
        deadline
    )

    const [gasPrice, gasCost] = await Promise.all([
        web3.eth.getGasPrice(),
        tx.estimateGas({from: admin}),
    ]);


    console.log(`gasPrice: ${gasPrice}`)
    console.log(`gasCost: ${gasCost}`)
}

init()

掉期的价格计算返回正确的价格。但是,当我尝试计算交易成本时,会引发以下错误: 错误:返回错误:所需的气体超过限额 (44038122) 或交易总是失败

任何帮助将不胜感激,如果我的更多代码需要澄清,请告诉我!

标签: javascriptethereum

解决方案


事实证明,使用 web3 是不可能与 Pancakeswap 合约交互的。我找到了使用 ethers.js 的解决方案。以下代码为我在主网上的 Pancake 上执行交换工作。在执行第一个事务之前,需要允许 Pancakeswap,此代码被注释掉。我不得不稍微调整一下gasprice 和gasLimit 才能让它发挥作用。

require("dotenv").config()
const ethers = require('ethers')
const {ChainId, Token, TokenAmount, Fetcher, Pair, Route, Trade, TradeType, Percent} = 
require('@pancakeswap-libs/sdk');
const Web3 = require('web3');
const web3 = new Web3('wss://apis.ankr.com/wss/c40792ffe3514537be9fb4109b32d257/946dd909d324e5a6caa2b72ba75c5799/binance/full/main');
const {JsonRpcProvider} = require("@ethersproject/providers");
const provider = new JsonRpcProvider('https://bsc-dataseed1.binance.org/');
const { address: admin } = web3.eth.accounts.wallet.add(process.env.PRIVATE_KEY)

const addresses = {
    WBNB: '0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c',
    BUSD: '0xe9e7CEA3DedcA5984780Bafc599bD69ADd087D56',
    PANCAKE_ROUTER: '0x05fF2B0DB69458A0750badebc4f9e13aDd608C7F'
}

const ONE_ETH_IN_WEI = web3.utils.toBN(web3.utils.toWei('1'))
const tradeAmount = ONE_ETH_IN_WEI.div(web3.utils.toBN('1000'))

const init = async () => {

const [WBNB, BUSD] = await Promise.all(
    [addresses.WBNB, addresses.BUSD].map(tokenAddress => (
        new Token(
            ChainId.MAINNET,
            tokenAddress,
            18
        )
    )));

const pair = await Fetcher.fetchPairData(WBNB, BUSD, provider)
const route = await new Route([pair], WBNB)
const trade = await new Trade(route, new TokenAmount(WBNB, tradeAmount), TradeType.EXACT_INPUT)

const slippageTolerance = new Percent('50', '10000')

// create transaction parameters
const amountOutMin = trade.minimumAmountOut(slippageTolerance).raw
const path = [WBNB.address, BUSD.address]
const to = admin
const deadline = Math.floor(Date.now() / 1000) + 60 * 20

// Create signer
const wallet = new ethers.Wallet(
    Buffer.from(
    process.env.PRIVATE_KEY, // paste your private key from metamask here
    "hex"
    )
)
const signer = wallet.connect(provider)

// Create Pancakeswap ethers Contract
const pancakeswap = new ethers.Contract(
    addresses.PANCAKE_ROUTER,
    ['function swapExactTokensForTokens(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline) external returns (uint[] memory amounts)'],
    signer
)

// Allow Pancakeswap
// let abi = ["function approve(address _spender, uint256 _value) public returns (bool success)"]
// let contract = new ethers.Contract(WBNB.address, abi, signer)
// await contract.approve(addresses.PANCAKE_ROUTER, ethers.utils.parseUnits('1000.0', 18), {gasLimit: 100000, gasPrice: 5e9})

// Execute transaction
const tx = await pancakeswap.swapExactTokensForTokens(
    ethers.utils.parseUnits('0.001', 18),
    ethers.utils.parseUnits(web3.utils.fromWei(amountOutMin.toString()), 18),
    path,
    to,
    deadline,
    { gasLimit: ethers.utils.hexlify(200000), gasPrice: ethers.utils.parseUnits("10", "gwei") }
)

console.log(`Tx-hash: ${tx.hash}`)

const receipt = await tx.wait();

console.log(`Tx was mined in block: ${receipt.blockNumber}`)
}

init()

推荐阅读