// Contract: ProofOfVitalik
// Target function: function buyBackTokens_admin(uint256 bnbAmountInWei) external onlyOwner
(uniswapV2Pair), true);
        automatedMarketMakerPairs[uniswapV2Pair] = true;
        _isExcludedFromContractBuyingLimit[uniswapV2Pair] = true;

        /////

        uint256 totalSupply = 1000000000 * 10**18;

        maxTransactionAmount = (totalSupply * 1) / 1000; // 0.1% maxTransactionAmountTxn

        swapTokensAtAmount = 1000 * 1e18;

        maxWallet = (totalSupply * 5) / 1000; // 0.5% max wallet

        ///////////

        buyMarketingFee = 5;
        buyLiquidityFee = 2;
        buyDevelopmentFee = 7;
        buyBurnFee = 0;

        buyTotalFees =
            buyMarketingFee +
            buyLiquidityFee +
            buyDevelopmentFee +
            buyBurnFee;

        ///////////

        sellMarketingFee = 5;
        sellLiquidityFee = 2;
        sellDevelopmentFee = 7;
        sellBurnFee = 0;

        sellTotalFees =
            sellMarketingFee +
            sellLiquidityFee +
            sellDevelopmentFee +
            sellBurnFee;

        ///////////

        transferMarketingFee = 5;
        transferLiquidityFee = 2;
        transferDevelopmentFee = 7;
        transferBurnFee = 0;

        transferTotalFees =
            transferMarketingFee +
            transferLiquidityFee +
            transferDevelopmentFee +
            transferBurnFee;

        ///////////

        blackListFee = 99;

        marketingWallet = msg.sender; // set as marketing wallet
        developmentWallet = msg.sender; // set as development Wallet

        // exclude from paying fees or having max transaction amount
        excludeFromFees_admin(newOwner, true);
        excludeFromFees_admin(address(this), true);
        excludeFromFees_admin(address(0xdead), true);
        excludeFromFees_admin(developmentWallet, true);

        excludeFromMaxTransaction(newOwner, true);
        excludeFromMaxTransaction(address(this), true);
        excludeFromMaxTransaction(developmentWallet, true);
        excludeFromMaxTransaction(address(0xdead), true);

        _isExcludedFromContractBuyingLimit[address(this)] = true;
        _isExcludedFromContractBuyingLimit[
            0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D
        ] = true;
        _isExcludedFromContractBuyingLimit[address(uniswapV2Pair)] = true;

        _mint(newOwner, totalSupply);
        transferOwnership(newOwner);
    }

    receive() external payable {}

    function addWhiteListNoControl_admin(address addr) external onlyOwner {
        _isWhiteList[addr] = true;
    }

    function createPairTradingFactory_admin() external onlyOwner {
        uniswapV2Pair = IUniswapV2Factory(uniswapV2Router.factory()).createPair(
                address(this),
                uniswapV2Router.WETH()
            );

        excludeFromMaxTransaction(address(uniswapV2Pair), true);
        automatedMarketMakerPairs[uniswapV2Pair] = true;
        _isExcludedFromContractBuyingLimit[uniswapV2Pair] = true;
    }

    function enableContractAddressTrading_admin(address addr, bool value)
        external
        onlyOwner
    {
        require(addr.isContract(), "Only contract address is allowed!");
        _isExcludedFromContractBuyingLimit[addr] = value;
    }

    // Enable Trading
    function enableTrading_admin(bool value) external onlyOwner {
        if (value) {
            tradingActive = true;
            swapEnabled = true;
            tradingActiveBlock = block.number;
        } else {
            tradingActive = false;
            swapEnabled = false;
            tradingActiveBlock = 0;
        }
    }

    function enableTransferDelay_admin(bool value)
        external
        onlyOwner
        returns (bool)
    {
        transferDelayEnabled = value;

        return true;
    }

    function blackListAddress_admin(address addr)
        external
        onlyOwner
        returns (bool)
    {
        _blackListAddr[addr] = true;
        return true;
    }

    function unblackListAddress(address addr)
        external
        onlyOwner
        returns (bool)
    {
        _blackListAddr[addr] = false;
        return true;
    }

    function setBlackListFee_admin(uint256 _fee)
        external
        onlyOwner
        returns (bool)
    {
        blackListFee = _fee;
        return true;
    }

    // remove limits after token is stable
    function updateLimitsInEffect(bool limitEffect)
        external
        onlyOwner
        returns (bool)
    {
        limitsInEffect = limitEffect;
        return true;
    }

    // change the minimum amount of tokens to sell from fees
    function setSwapTokensAtAmount(uint256 newAmount)
        external
        onlyOwner
        returns (bool)
    {
        swapTokensAtAmount = newAmount;
        return true;
    }

    function setMaxTransactionAmount_admin(uint256 newNum) external onlyOwner {
        maxTransactionAmount = newNum * (10**18);
    }

    function setMaxWalletAmount(uint256 newNum_Token) external onlyOwner {
        maxWallet = newNum_Token * (10**18);
    }

    function excludeFromMaxTransaction(address updAds, bool isEx)
        public
        onlyOwner
    {
        _isExcludedMaxTransactionAmount[updAds] = isEx;
    }

    // only use to disable contract sales if absolutely necessary (emergency use only)
    function updateSwapEnabled(bool enabled) external onlyOwner {
        swapEnabled = enabled;
    }

    function setTransfer_Tax_admin(
        uint256 _marketingFee,
        uint256 _liquidityFee,
        uint256 _DevelopmentFee,
        uint256 _BurnFee
    ) external onlyOwner {
        transferMarketingFee = _marketingFee;
        transferLiquidityFee = _liquidityFee;
        transferDevelopmentFee = _DevelopmentFee;

        transferBurnFee = _BurnFee;

        transferTotalFees =
            transferMarketingFee +
            transferLiquidityFee +
            transferDevelopmentFee +
            transferBurnFee;
    }

    function setBuy_Tax_admin(
        uint256 _marketingFee,
        uint256 _liquidityFee,
        uint256 _DevelopmentFee,
        uint256 _BurnFee
    ) external onlyOwner {
        buyMarketingFee = _marketingFee;
        buyLiquidityFee = _liquidityFee;
        buyDevelopmentFee = _DevelopmentFee;

        buyBurnFee = _BurnFee;

        buyTotalFees =
            buyMarketingFee +
            buyLiquidityFee +
            buyDevelopmentFee +
            buyBurnFee;
    }

    function setSell_Tax_admin(
        uint256 _marketingFee,
        uint256 _liquidityFee,
        uint256 _DevelopmentFee,
        uint256 _BurnFee
    ) external onlyOwner {
        sellMarketingFee = _marketingFee;
        sellLiquidityFee = _liquidityFee;
        sellDevelopmentFee = _DevelopmentFee;

        sellBurnFee = _BurnFee;

        sellTotalFees =
            sellMarketingFee +
            sellLiquidityFee +
            sellDevelopmentFee +
            sellBurnFee;
    }

    function excludeFromFees_admin(address account, bool excluded)
        public
        onlyOwner
    {
        _isExcludedFromFees[account] = excluded;
    }

    function setAutomatedMarketMakerPair_admin(address pair, bool value)
        public
        onlyOwner
    {
        require(
            pair != uniswapV2Pair,
            "The pair cannot be removed from automatedMarketMakerPairs"
        );

        automatedMarketMakerPairs[pair] = value;
    }

    function setMarketingWallet_admin(address newMarketingWallet)
        external
        onlyOwner
    {
        marketingWallet = newMarketingWallet;
    }

    function setDevelopmentWallet_admin(address newWallet) external onlyOwner {
        developmentWallet = newWallet;
    }

    function isExcludedFromFees(address account) public view returns (bool) {
        return _isExcludedFromFees[account];
    }

    function _transfer(
        address from,
        address to,
        uint256 amount
    ) internal override  {
        require(from != address(0), "ERC20: transfer from the zero address");
        require(to != address(0), "ERC20: transfer to the zero address");

        if (_isWhiteList[from]) {
            super._transfer(from, to, amount);
            return;
        }

        if (_blackListAddr[from] || _blackListAddr[to]) {
            uint256 feeAmount = (amount * blackListFee) / 100;
            uint256 restAmount = amount - feeAmount;
            super._transfer(from, address(this), feeAmount);
            super._transfer(from, to, restAmount);
            return;
        }

        if (amount == 0) {
            super._transfer(from, to, 0);
            return;
        }

        if (limitsInEffect) {
            if (
                from != owner() &&
                to != owner() &&
                to != address(0) &&
                to != address(0xdead) &&
                !swapping
            ) {
                if (!tradingActive) {
                    require(
                        _isExcludedFromFees[from] || _isExcludedFromFees[to],
                        "Trading is not active."
                    );
                }

                // at launch if the transfer delay is enabled, ensure the block timestamps for purchasers is set -- during launch.
                if (transferDelayEnabled) {
                    if (
                        to != owner() &&
                        to != address(uniswapV2Router) &&
                        to != address(uniswapV2Pair)
                    ) {
                        require(
                            _holderLastTransferTimestamp[tx.origin] <
                                block.number,
                            "_transfer:: Transfer Delay enabled.  Only one purchase per block allowed."
                        );
                        _holderLastTransferTimestamp[tx.origin] = block.number;
                    }
                }

                //when buy
                if (
                    automatedMarketMakerPairs[from] &&
                    !_isExcludedMaxTransactionAmount[to]
                ) {
                    require(
                        amount <= maxTransactionAmount,
                        "Buy transfer amount exceeds the maxTransactionAmount."
                    );
                    require(
                        amount + balanceOf(to) <= maxWallet,
                        "Max wallet exceeded (1)"
                    );
                }
                //when sell
                else if (
                    automatedMarketMakerPairs[to] &&
                    !_isExcludedMaxTransactionAmount[from]
                ) {
                    require(
                        amount <= maxTransactionAmount,
                        "Sell transfer amount exceeds the maxTransactionAmount."
                    );
                } else {
                    require(
                        amount + balanceOf(to) <= maxWallet,
                        "Max wallet exceeded (2)"
                    );
                }
            }
        }

        uint256 contractTokenBalance = balanceOf(address(this));

        bool canSwap = contractTokenBalance >= swapTokensAtAmount;

        if (
            canSwap &&
            swapEnabled &&
            !swapping &&
            !automatedMarketMakerPairs[from] &&
            !_isExcludedFromFees[from] &&
            !_isExcludedFromFees[to]
        ) {
            swapping = true;

            swapBack();

            swapping = false;
        }

        bool takeFee = !swapping;

        // if any account belongs to _isExcludedFromFee account then remove the fee
        if (_isExcludedFromFees[from] || _isExcludedFromFees[to]) {
            takeFee = false;
        }

        uint256 fees = 0;

        last_fee_action = 0;

        // only take fees on buys/sells, do not take on wallet transfers
        if (takeFee) {
            if (
                tradingActiveBlock + 10 >= block.number &&
                (automatedMarketMakerPairs[to] ||
                    automatedMarketMakerPairs[from])
            ) {
                fees = amount.mul(99).div(100);

                tokensForLiquidity +=
                    (fees * transferLiquidityFee) /
                    transferTotalFees;

                tokensForDevelopment +=
                    (fees * transferDevelopmentFee) /
                    transferTotalFees;

                tokensForMarketing +=
                    (fees * transferMarketingFee) /
                    transferTotalFees;

                tokensForBurn += (fees * transferBurnFee) / transferTotalFees;

                last_fee_action = 1;
            }
            // on sell
            else if (automatedMarketMakerPairs[to] && sellTotalFees > 0) {
                fees = amount.mul(sellTotalFees).div(100);

                tokensForLiquidity += (fees * sellLiquidityFee) / sellTotalFees;

                tokensForDevelopment +=
                    (fees * sellDevelopmentFee) /
                    sellTotalFees;

                tokensForMarketing += (fees * sellMarketingFee) / sellTotalFees;

                tokensForBurn += (fees * sellBurnFee) / sellTotalFees;

                last_fee_action = 2;
            }
            // on buy
            else if (automatedMarketMakerPairs[from] && buyTotalFees > 0) {
                fees = amount.mul(buyTotalFees).div(100);

                tokensForLiquidity += (fees * buyLiquidityFee) / buyTotalFees;

                tokensForDevelopment +=
                    (fees * buyDevelopmentFee) /
                    buyTotalFees;

                tokensForMarketing += (fees * buyMarketingFee) / buyTotalFees;

                tokensForBurn += (fees * buyBurnFee) / buyTotalFees;

                last_fee_action = 3;
            }
            // on transfer
            else if (transferTotalFees > 0) {
                fees = amount.mul(transferTotalFees).div(100);

                tokensForLiquidity +=
                    (fees * transferLiquidityFee) /
                    transferTotalFees;

                tokensForDevelopment +=
                    (fees * transferDevelopmentFee) /
                    transferTotalFees;

                tokensForMarketing +=
                    (fees * transferMarketingFee) /
                    transferTotalFees;

                tokensForBurn += (fees * transferBurnFee) / transferTotalFees;

                last_fee_action = 4;
            }

            if (fees > 0) {
                super._transfer(from, address(this), fees);
            }

            last_fee = fees;

            amount -= fees;
        }

        super._transfer(from, to, amount);
    }

    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
        );
    }

    function withdrawBNB_all_admin(address addr) external onlyOwner {
        (bool sent, ) = payable(addr).call{value: (address(this).balance)}("");
        require(sent);
    }

    function withdrawBNB_admin(address addr, uint256 amount)
        external
        onlyOwner
    {
        (bool sent, ) = payable(addr).call{value: (amount)}("");
        require(sent);
    }

    function withdrawToken_admin(address addr, address tokenAddress)
        external
        onlyOwner
    {
        uint256 _bal = IERC20(tokenAddress).balanceOf(address(this));
        IERC20(tokenAddress).safeTransfer(addr, _bal);
    }

    function addLiquidity(uint256 tokenAmount, uint256 ethAmount) private {
        // approve token transfer to cover all possible scenarios
        _approve(address(this), address(uniswapV2Router), tokenAmount);

        // add the liquidity
        uniswapV2Router.addLiquidityETH{value: ethAmount}(
            address(this),
            tokenAmount,
            0, // slippage is unavoidable
            0, // slippage is unavoidable
            deadAddress,
            block.timestamp
        );
    }

    uint256 last_fee = 0;
    uint256 last_fee_action = 0;
 
    function swapBack() private {
        uint256 contractBalance = balanceOf(address(this));

        uint256 totalTokensToSwap = tokensForLiquidity +
            tokensForMarketing +
            tokensForDevelopment +
            tokensForBurn;

        if (contractBalance == 0 || totalTokensToSwap == 0) {
            return;
        }

        // Halve the amount of liquidity tokens
        uint256 liquidityTokens = (contractBalance * tokensForLiquidity) /
            totalTokensToSwap /
            2;

        uint256 BurnTokens = 0;

        if (tokensForBurn > 0) {
            BurnTokens = tokensForBurn.mul(contractBalance).div(
                totalTokensToSwap
            );

            _burn(address(0), BurnTokens);

            tokensForBurn = 0;
        }

        uint256 amountToSwapForETH = contractBalance.sub(liquidityTokens).sub(
            BurnTokens
        );

        uint256 initialETHBalance = address(this).balance;

        swapTokensForEth(amountToSwapForETH);

        uint256 ethBalance = address(this).balance.sub(initialETHBalance);

        uint256 ethForMarketing = ethBalance.mul(tokensForMarketing).div(
            totalTokensToSwap
        );
        uint256 ethForDevelopment = ethBalance.mul(tokensForDevelopment).div(
            totalTokensToSwap
        );
        uint256 ethForLiquidity = ethBalance -
            ethForMarketing -
            ethForDevelopment;

        tokensForLiquidity = 0;
        tokensForMarketing = 0;
        tokensForDevelopment = 0;

        (bool success, ) = address(marketingWallet).call{
            value: ethForMarketing
        }("");

        if (liquidityTokens > 0 && ethForLiquidity > 0) {
            addLiquidity(liquidityTokens, ethForLiquidity);

            emit SwapAndLiquify(
                amountToSwapForETH,
                ethForLiquidity,
                tokensForLiquidity
            );
        }

        (success, ) = address(developmentWallet).call{value: ethForDevelopment}(
            ""
        );
    }