swapExactETHForTokens 一直失败

swapExactETHForTokens keeps failing

我遇到了一个我无法解决的问题,上周我一直被困在这个问题上... 我正在尝试在 ropsten 网络上使用 UNISWAP 路由器执行 swapExactETHForTokens。 我想用 0.01 ETH 购买 USDC 代币。 首先,我批准 uniswap 使用 ETH 的数量。 其次,我执行交换功能,但它不断恢复我的交易 https://ropsten.etherscan.io/tx/0x176bae743bcc193b776a45b0389bc4934c5d1db5df85d991a37f2faca72db0c2 失败并出现错误 'UniswapV2Router: EXPIRED' 这是我的代码:(它在某些地方说 pancakeswap 但它的 uniswap 路由器)

const ethers = require('ethers')
const to = '0xD5768aa815D590494277f558Ee5cbeC5FAF1501C'; // my account
const value = ethers.utils.parseUnits('0.01', 'ether')
let provider = new ethers.providers.InfuraProvider('ropsten', 'key');
const signer = new ethers.Wallet('privte_key');
const account = signer.connect(provider);
const config = {
    wbnb: '0xc778417E063141139Fce010982780140Aa0cD5Ab', //weth
    safemoon: '0x07865c6E87B9F70255377e024ace6630C1Eaa37F', //usdc
    pancakeSwapRouter: '0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D',
    slippage: 12,
}

const pancakeswap = new ethers.Contract(
    config.pancakeSwapRouter,
    [
        '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 wbnb = new ethers.Contract(
    config.wbnb,
    ['function approve(address spender, uint amount) public returns(bool)'],
    account
)

const buyToken = async () => {
    try {
        const deadline = Math.floor(Date.now() / 1000) + 60 * 10
        const tokenIn = config.wbnb
        const tokenOut = config.safemoon
        const amountIn = value;
        const ETHAmount = ethers.utils.parseEther('0.1').toHexString();
        const gasPrice = ethers.utils.parseUnits('1.5', 'gwei');
        const gas = {
            gasPrice: gasPrice,
            gasLimit: 6000000
        }
        const tx = await pancakeswap.swapExactETHForTokens(
            0, // Degen ape don't give a fuxk about slippage
            [tokenIn, tokenOut],
            to,
            Math.floor(Date.now() / 1000) + 60 * 20, // 10 minutes from now
            {
                ...gas,
                value: ETHAmount
            }
        );
        console.log(`Swapping WETH for tokens...`);
        const receipt = await tx.wait();
        console.log(`Transaction hash: ${receipt.transactionHash}`);
    } catch (error) {
        console.log(error)
    }
}

const approve = async () => {
    const ETHAmount = ethers.utils.parseEther('0.1').toHexString();
    const gasPrice = ethers.utils.parseUnits('1.5', 'gwei');
    const gas = {
        gasPrice: gasPrice,
        gasLimit: 6000000
    }
    const tx = await wbnb.approve(pancakeswap.address, ETHAmount, gas)
    console.log('Approving...')
    const receipt = await tx.wait()
    console.log('Approve receipt')
    console.log(receipt)
}

const main = async () => {
    await approve()
    await buyToken()
}

main()

swapExactETHForTokens()定义

function swapExactETHForTokens(uint amountOutMin, address[] calldata path, address to, uint deadline)
    external
    virtual
    override
    payable
    ensure(deadline)
    returns (uint[] memory amounts)
{

接受第 4 个参数 deadline 并将其传递给 ensure 修饰符

modifier ensure(uint deadline) {
    require(deadline >= block.timestamp, 'UniswapV2Router: EXPIRED');
    _;
}

如果 deadline(传递给函数的第 4 个参数)比出块时间 更短 ,它会有效地恢复带有 EXPIRED 消息的交易。

linked transaction中,你传递了1637842091作为deadline的值,即2021-11-25 12:08:11 UTC。然而,包含交易的区块大约被开采了。 1.5 小时后 - 2021-11-25 13:48:34 UTCdeadline 比阻塞时间,这导致交易恢复。


解决方案:要么提供更高的gasPrice,让交易在10分钟内被挖掘的概率更高window(在JS片段中指定) ),或增加 deadline 值,使其在区块被开采时仍然有效。