5 改造safemoon的代码,将流动池由xxx-ETH-LP改为xxx-USDT-LP后,打开swap开关,转账时总会报错TransfeHelper:TRANSFER_FROM_FAILED

1 safemoon的逻辑是转账时token合约自己收取手续费,然后将手续费添加进流动性池。 2 改造后的swapAndLiquidity函数实现如下

function swapAndLiquify(uint256 contractTokenBalance) private lockTheSwap {
        // split the contract balance into halves
        uint256 half = contractTokenBalance.div(2);
        uint256 otherHalf = contractTokenBalance.sub(half);

        // capture the contract's current ETH balance.
        // this is so that we can capture exactly the amount of ETH that the
        // swap creates, and not make the liquidity event include any ETH that
        // has been manually sent to the contract
        // uint256 initialBalance = address(this).balance;
        uint256 initialBalance = usdtContract.balanceOf(address(this));

        // swap tokens for ETH // <- this breaks the ETH -> HATE swap when swap+liquify is triggered
        swapTokensForToken(half); 

        // how much ETH did we just swap into?
        // uint256 newBalance = address(this).balance.sub(initialBalance);

        uint256 newBalance = usdtContract.balanceOf(address(this)).sub(initialBalance);
        require(usdtContract.balanceOf(address(this)) > 0, "this Balance 0");
        require(newBalance > 0, "newBalance 0");
        require(otherHalf > 0, "otherHalf 0");
        // add liquidity to uniswap
        addLiquidity(otherHalf, newBalance);

        emit SwapAndLiquify(half, newBalance, otherHalf);
    }

3 一篇相关资料https://www.followchain.org/transfer-from-failed-pancakeswap/,但没有解决方案。

请先 登录 后评论

最佳答案 2021-08-18 18:07

提供一个可能性

在swap的pair实现里,有限制to的地址

function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external lock {
    require(to != _token0 && to != _token1, 'Uniswap: INVALID_TO');
}

safemoon中,调用swapTokensForToken时,是卖safemoon成ETH,卖到的safemoon到本合约里。to是address(this)

function swapTokensForEth(uint256 tokenAmount) private {
    // generate the uniswap pair path of token -> weth
    address[] memory path = new address[](2);
    path[0] = address(this);
    path[1] = uniswapV2Router.WETH();

    _approve(address(this), address(uniswapV2Router), tokenAmount);

    // make the swap
    uniswapV2Router.swapExactTokensForETHSupportingFeeOnTransferTokens(
        tokenAmount,
        0, // accept any amount of ETH
        path,
        address(this),
        block.timestamp
    );
}

如果是ETH/BNB的话,本币的话,在swap的router合约里会做转换,先pair.swap wrap token到router地址,再换成本币到safemoon合约。注意传递给swap的to是router地址。

function swapExactTokensForETHSupportingFeeOnTransferTokens(
    uint amountIn,
    uint amountOutMin,
    address[] calldata path,
    address to,
    uint deadline
)
external
virtual
override
ensure(deadline)
{
    require(path[path.length - 1] == WHT, 'MdexRouter: INVALID_PATH');
    TransferHelper.safeTransferFrom(
        path[0], msg.sender, pairFor(path[0], path[1]), amountIn
    );
    _swapSupportingFeeOnTransferTokens(path, address(this));
    uint amountOut = IERC20(WHT).balanceOf(address(this));
    require(amountOut >= amountOutMin, 'MdexRouter: INSUFFICIENT_OUTPUT_AMOUNT');
    IWHT(WHT).withdraw(amountOut);
    TransferHelper.safeTransferETH(to, amountOut);
}

但是如果你修改成对USDT对,卖币的时候,to就是safemoon地址,swap里的require就过不了

function swapExactTokensForTokensSupportingFeeOnTransferTokens(
        uint amountIn,
        uint amountOutMin,
        address[] calldata path,
        address to,
        uint deadline
    ) external virtual override ensure(deadline) {
        TransferHelper.safeTransferFrom(
            path[0], msg.sender, pairFor(path[0], path[1]), amountIn
        );
        uint balanceBefore = IERC20(path[path.length - 1]).balanceOf(to);
        _swapSupportingFeeOnTransferTokens(path, to);
        require(
            IERC20(path[path.length - 1]).balanceOf(to).sub(balanceBefore) >= amountOutMin,
            'MdexRouter: INSUFFICIENT_OUTPUT_AMOUNT'
        );
    }
请先 登录 后评论

其它 2 个回答

Tiny熊
  擅长:智能合约,以太坊
请先 登录 后评论
嘟噜嘟噜
请先 登录 后评论
  • 4 关注
  • 1 收藏,4208 浏览
  • Ethereal 提出于 2021-07-22 11:20