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/,但没有解决方案。
提供一个可能性
在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'
);
}