We are trying to process a fee when tokens are "Sold" on PancakeSwap. For now "Sold" is when the user swaps their tokens for BNB. Initially our current logic would also charge a fee when adding to the LP. (Which is not considered a sell in our usecase)

We noticed Pancake uses AddLiquidityETH to transfer tokens to the LP, and SwapETHForExactTokens also performs the same action during execution.

How can we differentiate during execution time between AddLiquidtyETH or SwapETHForExactTokens?

Our current _transfer function looks as follows:

function _transfer(address from, address to, uint256 amount) private {

        require(from != address(0), "ERC20: transfer from the zero address");
        require(to != address(0), "ERC20: transfer to the zero address");
        require(amount > 0, "Transfer amount must be greater than zero");

        bool  chargeTax = true;
        if (from != owner() && to != owner() && !_isExcludedFromFee[from] && !_isExcludedFromFee[to]) {
            require(!_isBlacklisted[from] && !_isBlacklisted[to]);

            // buy
            if (from == pancakeswapPair && to != address(pancakeV2Router)) {
                if (limitTX) {
                    require(amount <= _maxTxAmount);
                //  only buy tax
                chargeTax = buyFeeEnabled;

                uint contractETHBalance = address(this).balance;
                if (contractETHBalance > 0) {

            //  sale 
            if(to == address(pancakeswapPair) || to == address(pancakeV2Router) ) {
                chargeTax = sellFeeEnabled;

                uint contractTokenBalance = balanceOf(address(this));
                if (!inSwap && from != pancakeswapPair && swapEnabled) {
                    if (limitTX) {
                    require(amount <= balanceOf(pancakeswapPair).mul(3).div(100) && amount <= _maxTxAmount);
                    uint initialETHBalance = address(this).balance;

                    uint newETHBalance = address(this).balance;
                    uint ethToDistribute = newETHBalance.sub(initialETHBalance);
                    if (ethToDistribute > 0) {
                chargeTax = sellFeeEnabled;

        bool takeFee = true;

        if (_isExcludedFromFee[from] || _isExcludedFromFee[to] || !feeEnabled || !chargeTax) {
            takeFee = false;
        _tokenTransfer(from, to, amount, takeFee);

Please help...

and there is anyway to override pancakeSwap function -> addLiquidityETH function in smart contract so we can add some code to disable and enable fee .

function addLiquidityETH(address token,uint amountTokenDesired,uint amountTokenMin,uint amountETHMin,address to,uint deadline) external payable returns (uint amountToken, uint amountETH, uint liquidity)
    bool _temp_feeEnabled = feeEnabled;
    feeEnabled = false;

    ( amountToken, amountETH, liquidity) = pancakeV2Router.addLiquidityETH(token,amountTokenDesired,amountTokenMin,amountETHMin,to,deadline);
    feeEnabled = _temp_feeEnabled;


1 Answer 1


Selling the token in the PancakeSwapRouter will call:

  • token.transferFrom(msg.sender, pancakeswapPair, amount)

And adding liquidity will also call:

  • token.transferFrom(msg.sender, pancakeswapPair, amount).

From the token contract's perspective they look the same. One would need a tx.callDataOrigin to distinguish the cases in the token contract which doesn't exist.

  • thanks for Answer ,what value tx.callDataOrigin return in above 2 scenario can you explain please Apr 4, 2022 at 17:31
  • 1
    Nothing, it doesn't exist. I was just saying you would need this feature (similar to the existing tx.origin), but since the EVM doesn't support it, it's not possible. Apr 7, 2022 at 9:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.