Solidity
如何在 UniSwap 分叉上的合約函式執行中區分 AddLiquidity 和 SwapExactTokensForETH
我們正在嘗試在 PancakeSwap 上“出售”代幣時收取費用。目前,“已售出”是使用者將其代幣換成 BNB 的時候。最初,我們目前的邏輯在添加到 LP 時也會收取費用。(在我們的案例中不被視為銷售)
我們注意到 Pancake 使用 AddLiquidityETH 將代幣轉移到 LP,並且 SwapExactTokensForETH 在執行期間也執行相同的操作。
我們如何在執行期間區分 AddLiquidtyETH 或 SwapExactTokensForETH?
我們目前的
_transfer
函式如下所示:/// @dev overrides transfer function to meet tokenomics of UFF function _transfer(address sender, address recipient, uint256 amount) internal virtual override antiWhale(sender, recipient, amount) { // If not modified, full ammount is transfer uint256 sendAmount = amount; // Buy action? if(lpToken != address(0) && msg.sender == lpToken && recipient != PCSRouter){ // default buy fee is 5% / Token OPs Team (dev and marketing) uint256 buyFeeAmount = amount.mul(maxBuyFee).div(10000); sendAmount = amount.sub(buyFeeAmount); require(amount == sendAmount.add(buyFeeAmount), "UFF::transfer: Buy value invalid"); super._transfer(sender, team, buyFeeAmount); } // Sell Action? if(lpToken != address(0) && recipient == lpToken && msg.sender != PCSRouter){ uint256 sellFeeAmount = amount.mul(maxSellFee).div(10000); sendAmount = amount.sub(sellFeeAmount); require(amount == sendAmount.add(sellFeeAmount), "UFF::transfer: Sell value invalid"); super._transfer(sender, team, sellFeeAmount); } // default 100% of transfer sent to recipient super._transfer(sender, recipient, sendAmount); }
先感謝您。
不幸的是,如果您不知道您的代幣何時添加到流動性中,這是不可能的。為什麼?
下面是 pancakeSwap 路由器的“sell”功能:
function swapExactTokensForETHSupportingFeeOnTransferTokens( uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline ) external virtual override ensure(deadline) { require(path[path.length - 1] == WETH, 'PancakeRouter: INVALID_PATH'); TransferHelper.safeTransferFrom( path[0], msg.sender, PancakeLibrary.pairFor(factory, path[0], path[1]), amountIn ); // <- transfer happens here _swapSupportingFeeOnTransferTokens(path, address(this)); uint amountOut = IERC20(WETH).balanceOf(address(this)); require(amountOut >= amountOutMin, 'PancakeRouter: INSUFFICIENT_OUTPUT_AMOUNT'); IWETH(WETH).withdraw(amountOut); TransferHelper.safeTransferETH(to, amountOut); }
如您所見,代幣是使用
TransferHelper.safeTransferFrom(path[0], msg.sender, PancakeLibrary.pairFor(factory, path[0], path[1]), amountIn);
這是
transfer()
函式的包裝器:function safeTransfer( address token, address to, uint256 value ) internal { // bytes4(keccak256(bytes('transfer(address,uint256)'))); (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0xa9059cbb, to, value)); require( success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper::safeTransfer: transfer failed' ); }
同樣適用
addLiquidityEth()
:function addLiquidityETH( address token, uint amountTokenDesired, uint amountTokenMin, uint amountETHMin, address to, uint deadline ) external virtual override payable ensure(deadline) returns (uint amountToken, uint amountETH, uint liquidity) { (amountToken, amountETH) = _addLiquidity( token, WETH, amountTokenDesired, msg.value, amountTokenMin, amountETHMin ); address pair = PancakeLibrary.pairFor(factory, token, WETH); TransferHelper.safeTransferFrom(token, msg.sender, pair, amountToken); // <- transfer happens here IWETH(WETH).deposit{value: amountETH}(); assert(IWETH(WETH).transfer(pair, amountETH)); liquidity = IPancakePair(pair).mint(to); // refund dust eth, if any if (msg.value > amountETH) TransferHelper.safeTransferETH(msg.sender, msg.value - amountETH); }
您只能通過添加一個掛鉤來修改傳遞函式的行為,該掛鉤將根據 3 個輸入之一觸發
from
:to
和value
。但是,
from
andto
和value
兩個函式是相同的,因此無法檢測使用了哪個函式,從而實際上阻止了您創建一個鉤子來區分函式。