Failing to sell token on PCS buys

I’m creating a token where Txes are taxed, but rather than having a bunch of token sitting around in a wallet that I’d have to sell before I could use for e.g. marketing I’d like to automatically convert to BNB as I go.

I only want to do this conversion on buys, as on sells it’s useful to reduce the amount of token sold (so it’s a little like fees to an LP provider). Because I’m unimaginative it’s based on Safemoon.

I’m having an issue whereby if I try to implement this it fails with every buy, however, if I change it so it only swaps into BNB on sells (changing nothing else) it works without problem.

For those familiar with Safemoon, this process is done in the _getValues function, where fees are calculated, calling this function:

    function _takeFee (uint256 tFee, address recipient, bool transferAsBNB) private {
        uint256 currentRate =  _getRate();
        uint256 rFee = tFee.mul(currentRate);
            
        // if it's a sell then take token as normal
        if (!transferAsBNB) {
            _rOwned[recipient] = _rOwned[recipient].add(rFee);
            
            if(_isExcluded[recipient])
                _tOwned[recipient] = _tOwned[recipient].add(tFee);
                
            emit FeeTransfer (tFee, recipient);
        } else {
            // if it's a buy swap to BNB first
            // transfer tokens to the contract then we can swap them to BNB
            // the contract address can't be excluded from the award so we only need to update the reflected balance
            _rOwned[address(this)] = _rOwned[address(this)].add(rFee);
            uint256 bnbReceived = swapTokensForBNB (tFee);
            
            if (bnbReceived > 0)
                payable(recipient).transfer(bnbReceived);
        }
    }

swapTokensToBNB is the same function that is used when adding to liquidity (check contract balance, swap, check contract balance again - that’s how much BNB you have). This function works when called as part of the swap & liquify process (but that is also only done on sells).

Basically is there something that stops me from transferring tokens to BNB (i.e. selling tokens to take a fee in BNB) when I’m buying the token? Is there another way to get round this if so?

Thanks

I’m removing the safemoon tag from this (FYI @spalladino) as it’s not a specifically safemoon issue.

I’ve tested this by stripping out automated liquidity and reflection from the token, and I still get the same issue. To recap - I tax buys and sells. When someone buys I would like to swap the taxed tokens into BNB. When I try to do this the Tx reverts.

If I disable fees it works fine, if I’m selling it works fine, so it’s definitely something to do with swapping tokens to BNB whilst buying but I’m a bit stumped as to what.

The simplified _takeFees function (called as part of transfer, passing in the amount of tokens to transfer to the fee wallet) and swapTokensForBNB function are below:

   function _takeFee (uint256 tFee, address recipient, bool transferAsBNB) private {
        if (!transferAsBNB) {
             _balances[recipient] = _balances[recipient].add(tFee);
            emit FeeTransfer (tFee, recipient);
        } else {
            // need to make sure the tokens are transferred to the contract then we can swap them to BNB
            _balances[address(this)] = _balances[address(this)].add(tFee);
            uint256 bnbReceived = swapTokensForBNB (tFee);
            
            if (bnbReceived > 0)
                payable(recipient).sendValue(bnbReceived);
        }
    }

    function swapTokensForBNB (uint256 tokenAmount) private returns (uint256) {
       // get the contract's current BNB balance so we know how much BNB the swap creates, and don't include any BNB that has been manually sent to the contract
        uint256 initialBalance = address(this).balance;
        
        // generate the pancakeswap pair path of Token -> WBNB
        address[] memory path = new address[](2);
        path[0] = address(this);
        path[1] = _pancakeswapV2Router.WETH();

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

        // make the swap
        _pancakeswapV2Router.swapExactTokensForETHSupportingFeeOnTransferTokens(
            tokenAmount,
            0, // accept any amount of BNB
            path,
            address(this),
            block.timestamp
        );
        
        // return how much BNB did we just swapped into
        return address(this).balance.sub(initialBalance);
    }