Solidity

如何在 UniSwap 分叉上的合約函式執行中區分 AddLiquidity 和 SwapExactTokensForETH

  • August 9, 2021

我們正在嘗試在 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 個輸入之一觸發fromtovalue

但是,fromandtovalue兩個函式是相同的,因此無法檢測使用了哪個函式,從而實際上阻止了您創建一個鉤子來區分函式。

引用自:https://ethereum.stackexchange.com/questions/106673