// SPDX-License-Identifier: Unlicensed

        pragma solidity ^0.8.4;

        interface IERC20 {
            
            function totalSupply() external view returns (uint256);
            function balanceOf(address account) external view returns (uint256);
            function transfer(address recipient, uint256 amount) external returns (bool);
            function allowance(address owner, address spender) external view returns (uint256);
            function approve(address spender, uint256 amount) external returns (bool);
            function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
            
            event Transfer(address indexed from, address indexed to, uint256 value);
            event Approval(address indexed owner, address indexed spender, uint256 value);
        }

        library SafeMath {
            
            function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
                unchecked {
                    uint256 c = a + b;
                    if (c < a) return (false, 0);
                    return (true, c);
                }
            }
            
            function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
                unchecked {
                    if (b > a) return (false, 0);
                    return (true, a - b);
                }
            }
            
            function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
                unchecked {
                    // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
                    // benefit is lost if 'b' is also tested.
                    // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
                    if (a == 0) return (true, 0);
                    uint256 c = a * b;
                    if (c / a != b) return (false, 0);
                    return (true, c);
                }
            }
            
            function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
                unchecked {
                    if (b == 0) return (false, 0);
                    return (true, a / b);
                }
            }
            
            function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
                unchecked {
                    if (b == 0) return (false, 0);
                    return (true, a % b);
                }
            }

            function add(uint256 a, uint256 b) internal pure returns (uint256) {
                return a + b;
            }


            function sub(uint256 a, uint256 b) internal pure returns (uint256) {
                return a - b;
            }


            function mul(uint256 a, uint256 b) internal pure returns (uint256) {
                return a * b;
            }
            
            function div(uint256 a, uint256 b) internal pure returns (uint256) {
                return a / b;
            }


            function mod(uint256 a, uint256 b) internal pure returns (uint256) {
                return a % b;
            }
            
            function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
                unchecked {
                    require(b <= a, errorMessage);
                    return a - b;
                }
            }
            
            function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
                unchecked {
                    require(b > 0, errorMessage);
                    return a / b;
                }
            }
            
            function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
                unchecked {
                    require(b > 0, errorMessage);
                    return a % b;
                }
            }
        }

        abstract contract Context {
            function _msgSender() internal view virtual returns (address) {
                return msg.sender;
            }

            function _msgData() internal view virtual returns (bytes calldata) {
                this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
                return msg.data;
            }
        }

        library Address {
            
            function isContract(address account) internal view returns (bool) {
                uint256 size;
                assembly { size := extcodesize(account) }
                return size > 0;
            }

            function sendValue(address payable recipient, uint256 amount) internal {
                require(address(this).balance >= amount, "Address: insufficient balance");
                (bool success, ) = recipient.call{ value: amount }("");
                require(success, "Address: unable to send value, recipient may have reverted");
            }
            
            function functionCall(address target, bytes memory data) internal returns (bytes memory) {
            return functionCall(target, data, "Address: low-level call failed");
            }
            
            function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
                return functionCallWithValue(target, data, 0, errorMessage);
            }
            
            function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
                return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
            }
            
            function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {
                require(address(this).balance >= value, "Address: insufficient balance for call");
                require(isContract(target), "Address: call to non-contract");
                (bool success, bytes memory returndata) = target.call{ value: value }(data);
                return _verifyCallResult(success, returndata, errorMessage);
            }
            
            function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
                return functionStaticCall(target, data, "Address: low-level static call failed");
            }
            
            function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {
                require(isContract(target), "Address: static call to non-contract");
                (bool success, bytes memory returndata) = target.staticcall(data);
                return _verifyCallResult(success, returndata, errorMessage);
            }


            function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
                return functionDelegateCall(target, data, "Address: low-level delegate call failed");
            }
            
            function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
                require(isContract(target), "Address: delegate call to non-contract");
                (bool success, bytes memory returndata) = target.delegatecall(data);
                return _verifyCallResult(success, returndata, errorMessage);
            }

            function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {
                if (success) {
                    return returndata;
                } else {
                    if (returndata.length > 0) {
                        assembly {
                            let returndata_size := mload(returndata)
                            revert(add(32, returndata), returndata_size)
                        }
                    } else {
                        revert(errorMessage);
                    }
                }
            }
        }

        abstract contract Ownable is Context {
            address internal _owner;
            address private _previousOwner;

            event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
            constructor () {
                _owner = _msgSender();
                emit OwnershipTransferred(address(0), _owner);
            }
            
            function owner() public view virtual returns (address) {
                return _owner;
            }
            
            modifier onlyOwner() {
                require(owner() == _msgSender(), "Ownable: caller is not the owner");
                _;
            }
            
            function renounceOwnership() public virtual onlyOwner {
                emit OwnershipTransferred(_owner, address(0));
                _owner = address(0);
            }


            function transferOwnership(address newOwner) public virtual onlyOwner {
                require(newOwner != address(0), "Ownable: new owner is the zero address");
                emit OwnershipTransferred(_owner, newOwner);
                _owner = newOwner;
            }
        }

         interface IERC20Metadata is IERC20 {
            /**
            * @dev Returns the name of the token.
            */
            function name() external view returns (string memory);

            /**
            * @dev Returns the symbol of the token.
            */
            function symbol() external view returns (string memory);

            /**
            * @dev Returns the decimals places of the token.
            */
            function decimals() external view returns (uint8);
        }
        contract ERC20 is Context,Ownable, IERC20, IERC20Metadata {
            using SafeMath for uint256;

            mapping(address => uint256) private _balances;

            mapping(address => mapping(address => uint256)) private _allowances;

            uint256 private _totalSupply;

            string private _name;
            string private _symbol;

            /**
            * @dev Sets the values for {name} and {symbol}.
            *
            * The default value of {decimals} is 18. To select a different value for
            * {decimals} you should overload it.
            *
            * All two of these values are immutable: they can only be set once during
            * construction.
            */
            constructor(string memory name_, string memory symbol_) {
                _name = name_;
                _symbol = symbol_;
            }

            /**
            * @dev Returns the name of the token.
            */
            function name() public view virtual override returns (string memory) {
                return _name;
            }

            /**
            * @dev Returns the symbol of the token, usually a shorter version of the
            * name.
            */
            function symbol() public view virtual override returns (string memory) {
                return _symbol;
            }

            /**
            * @dev Returns the number of decimals used to get its user representation.
            * For example, if `decimals` equals `2`, a balance of `505` tokens should
            * be displayed to a user as `5,05` (`505 / 10 ** 2`).
            *
            * Tokens usually opt for a value of 18, imitating the relationship between
            * Ether and Wei. This is the value {ERC20} uses, unless this function is
            * overridden;
            *
            * NOTE: This information is only used for _display_ purposes: it in
            * no way affects any of the arithmetic of the contract, including
            * {IERC20-balanceOf} and {IERC20-transfer}.
            */
            function decimals() public view virtual override returns (uint8) {
                return 18;
            }

            /**
            * @dev See {IERC20-totalSupply}.
            */
            function totalSupply() public view virtual override returns (uint256) {
                return _totalSupply;
            }

            /**
            * @dev See {IERC20-balanceOf}.
            */
            function balanceOf(address account) public view virtual override returns (uint256) {
                return _balances[account];
            }

            /**
            * @dev See {IERC20-transfer}.
            *
            * Requirements:
            *
            * - `recipient` cannot be the zero address.
            * - the caller must have a balance of at least `amount`.
            */
            function transfer(address recipient, uint256 amount) public virtual override returns (bool) {
                _transfer(_msgSender(), recipient, amount);
                return true;
            }

            /**
            * @dev See {IERC20-allowance}.
            */
            function allowance(address owner, address spender) public view virtual override returns (uint256) {
                return _allowances[owner][spender];
            }

            /**
            * @dev See {IERC20-approve}.
            *
            * Requirements:
            *
            * - `spender` cannot be the zero address.
            */
            function approve(address spender, uint256 amount) public virtual override returns (bool) {
                _approve(_msgSender(), spender, amount);
                return true;
            }

            /**
            * @dev See {IERC20-transferFrom}.
            *
            * Emits an {Approval} event indicating the updated allowance. This is not
            * required by the EIP. See the note at the beginning of {ERC20}.
            *
            * Requirements:
            *
            * - `sender` and `recipient` cannot be the zero address.
            * - `sender` must have a balance of at least `amount`.
            * - the caller must have allowance for ``sender``'s tokens of at least
            * `amount`.
            */
            function transferFrom(
                address sender,
                address recipient,
                uint256 amount
            ) public virtual override returns (bool) {
                _transfer(sender, recipient, amount);
                _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance"));
                return true;
            }

            /**
            * @dev Atomically increases the allowance granted to `spender` by the caller.
            *
            * This is an alternative to {approve} that can be used as a mitigation for
            * problems described in {IERC20-approve}.
            *
            * Emits an {Approval} event indicating the updated allowance.
            *
            * Requirements:
            *
            * - `spender` cannot be the zero address.
            */
            function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
                _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue));
                return true;
            }

            /**
            * @dev Atomically decreases the allowance granted to `spender` by the caller.
            *
            * This is an alternative to {approve} that can be used as a mitigation for
            * problems described in {IERC20-approve}.
            *
            * Emits an {Approval} event indicating the updated allowance.
            *
            * Requirements:
            *
            * - `spender` cannot be the zero address.
            * - `spender` must have allowance for the caller of at least
            * `subtractedValue`.
            */
            function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
                _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero"));
                return true;
            }

            /**
            * @dev Moves tokens `amount` from `sender` to `recipient`.
            *
            * This is internal function is equivalent to {transfer}, and can be used to
            * e.g. implement automatic token fees, slashing mechanisms, etc.
            *
            * Emits a {Transfer} event.
            *
            * Requirements:
            *
            * - `sender` cannot be the zero address.
            * - `recipient` cannot be the zero address.
            * - `sender` must have a balance of at least `amount`.
            */
            function _transfer(
                address sender,
                address recipient,
                uint256 amount
            ) internal virtual {
                require(sender != address(0), "ERC20: transfer from the zero address");
                require(recipient != address(0), "ERC20: transfer to the zero address");

                _beforeTokenTransfer(sender, recipient, amount);

                _balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance");
                _balances[recipient] = _balances[recipient].add(amount);
                emit Transfer(sender, recipient, amount);
            }

            /** @dev Creates `amount` tokens and assigns them to `account`, increasing
            * the total supply.
            *
            * Emits a {Transfer} event with `from` set to the zero address.
            *
            * Requirements:
            *
            * - `account` cannot be the zero address.
            */
            function _mint(address account, uint256 amount) internal virtual {
                require(account != address(0), "ERC20: mint to the zero address");

                _beforeTokenTransfer(address(0), account, amount);

                _totalSupply = _totalSupply.add(amount);
                _balances[account] = _balances[account].add(amount);
                emit Transfer(address(0), account, amount);
            }

            /**
            * @dev Destroys `amount` tokens from `account`, reducing the
            * total supply.
            *
            * Emits a {Transfer} event with `to` set to the zero address.
            *
            * Requirements:
            *
            * - `account` cannot be the zero address.
            * - `account` must have at least `amount` tokens.
            */
            function _burn(address account, uint256 amount) internal virtual {
                require(account != address(0), "ERC20: burn from the zero address");

                _beforeTokenTransfer(account, address(0), amount);

                _balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance");
                _totalSupply = _totalSupply.sub(amount);
                emit Transfer(account, address(0), amount);
            }

            /**
            * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.
            *
            * This internal function is equivalent to `approve`, and can be used to
            * e.g. set automatic allowances for certain subsystems, etc.
            *
            * Emits an {Approval} event.
            *
            * Requirements:
            *
            * - `owner` cannot be the zero address.
            * - `spender` cannot be the zero address.
            */
            function _approve(
                address owner,
                address spender,
                uint256 amount
            ) internal virtual {
                require(owner != address(0), "ERC20: approve from the zero address");
                require(spender != address(0), "ERC20: approve to the zero address");

                _allowances[owner][spender] = amount;
                emit Approval(owner, spender, amount);
            }

            /**
            * @dev Hook that is called before any transfer of tokens. This includes
            * minting and burning.
            *
            * Calling conditions:
            *
            * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
            * will be to transferred to `to`.
            * - when `from` is zero, `amount` tokens will be minted for `to`.
            * - when `to` is zero, `amount` of ``from``'s tokens will be burned.
            * - `from` and `to` are never both zero.
            *
            * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
            */
            function _beforeTokenTransfer(
                address from,
                address to,
                uint256 amount
            ) internal virtual {}
        }


        interface IUniswapV2Factory {
            event PairCreated(address indexed token0, address indexed token1, address pair, uint);
            function feeTo() external view returns (address);
            function feeToSetter() external view returns (address);
            function getPair(address tokenA, address tokenB) external view returns (address pair);
            function allPairs(uint) external view returns (address pair);
            function allPairsLength() external view returns (uint);
            function createPair(address tokenA, address tokenB) external returns (address pair);
            function setFeeTo(address) external;
            function setFeeToSetter(address) external;
        }

        interface IUniswapV2Pair {
            event Approval(address indexed owner, address indexed spender, uint value);
            event Transfer(address indexed from, address indexed to, uint value);
            function name() external pure returns (string memory);
            function symbol() external pure returns (string memory);
            function decimals() external pure returns (uint8);
            function totalSupply() external view returns (uint);
            function balanceOf(address owner) external view returns (uint);
            function allowance(address owner, address spender) external view returns (uint);
            function approve(address spender, uint value) external returns (bool);
            function transfer(address to, uint value) external returns (bool);
            function transferFrom(address from, address to, uint value) external returns (bool);
            function DOMAIN_SEPARATOR() external view returns (bytes32);
            function PERMIT_TYPEHASH() external pure returns (bytes32);
            function nonces(address owner) external view returns (uint);
            function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;
            event Mint(address indexed sender, uint amount0, uint amount1);
            event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);
            event Swap(
                address indexed sender,
                uint amount0In,
                uint amount1In,
                uint amount0Out,
                uint amount1Out,
                address indexed to
            );
            event Sync(uint112 reserve0, uint112 reserve1);
            function MINIMUM_LIQUIDITY() external pure returns (uint);
            function factory() external view returns (address);
            function token0() external view returns (address);
            function token1() external view returns (address);
            function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);
            function price0CumulativeLast() external view returns (uint);
            function price1CumulativeLast() external view returns (uint);
            function kLast() external view returns (uint);
            function mint(address to) external returns (uint liquidity);
            function burn(address to) external returns (uint amount0, uint amount1);
            function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;
            function skim(address to) external;
            function sync() external;
            function initialize(address, address) external;
        }

        interface IUniswapV2Router01 {
            function factory() external pure returns (address);
            function WETH() external pure returns (address);
            function addLiquidity(
                address tokenA,
                address tokenB,
                uint amountADesired,
                uint amountBDesired,
                uint amountAMin,
                uint amountBMin,
                address to,
                uint deadline
            ) external returns (uint amountA, uint amountB, uint liquidity);
            function addLiquidityETH(
                address token,
                uint amountTokenDesired,
                uint amountTokenMin,
                uint amountETHMin,
                address to,
                uint deadline
            ) external payable returns (uint amountToken, uint amountETH, uint liquidity);
            function removeLiquidity(
                address tokenA,
                address tokenB,
                uint liquidity,
                uint amountAMin,
                uint amountBMin,
                address to,
                uint deadline
            ) external returns (uint amountA, uint amountB);
            function removeLiquidityETH(
                address token,
                uint liquidity,
                uint amountTokenMin,
                uint amountETHMin,
                address to,
                uint deadline
            ) external returns (uint amountToken, uint amountETH);
            function removeLiquidityWithPermit(
                address tokenA,
                address tokenB,
                uint liquidity,
                uint amountAMin,
                uint amountBMin,
                address to,
                uint deadline,
                bool approveMax, uint8 v, bytes32 r, bytes32 s
            ) external returns (uint amountA, uint amountB);
            function removeLiquidityETHWithPermit(
                address token,
                uint liquidity,
                uint amountTokenMin,
                uint amountETHMin,
                address to,
                uint deadline,
                bool approveMax, uint8 v, bytes32 r, bytes32 s
            ) external returns (uint amountToken, uint amountETH);
            function swapExactTokensForTokens(
                uint amountIn,
                uint amountOutMin,
                address[] calldata path,
                address to,
                uint deadline
            ) external returns (uint[] memory amounts);
            function swapTokensForExactTokens(
                uint amountOut,
                uint amountInMax,
                address[] calldata path,
                address to,
                uint deadline
            ) external returns (uint[] memory amounts);
            function swapExactETHForTokens(uint amountOutMin, address[] calldata path, address to, uint deadline)
                external
                payable
                returns (uint[] memory amounts);
            function swapTokensForExactETH(uint amountOut, uint amountInMax, address[] calldata path, address to, uint deadline)
                external
                returns (uint[] memory amounts);
            function swapExactTokensForETH(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline)
                external
                returns (uint[] memory amounts);
            function swapETHForExactTokens(uint amountOut, address[] calldata path, address to, uint deadline)
                external
                payable
                returns (uint[] memory amounts);

            function quote(uint amountA, uint reserveA, uint reserveB) external pure returns (uint amountB);
            function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut) external pure returns (uint amountOut);
            function getAmountIn(uint amountOut, uint reserveIn, uint reserveOut) external pure returns (uint amountIn);
            function getAmountsOut(uint amountIn, address[] calldata path) external view returns (uint[] memory amounts);
            function getAmountsIn(uint amountOut, address[] calldata path) external view returns (uint[] memory amounts);
        }

        interface IUniswapV2Router02 is IUniswapV2Router01 {
            function removeLiquidityETHSupportingFeeOnTransferTokens(
                address token,
                uint liquidity,
                uint amountTokenMin,
                uint amountETHMin,
                address to,
                uint deadline
            ) external returns (uint amountETH);
            function removeLiquidityETHWithPermitSupportingFeeOnTransferTokens(
                address token,
                uint liquidity,
                uint amountTokenMin,
                uint amountETHMin,
                address to,
                uint deadline,
                bool approveMax, uint8 v, bytes32 r, bytes32 s
            ) external returns (uint amountETH);

            function swapExactTokensForTokensSupportingFeeOnTransferTokens(
                uint amountIn,
                uint amountOutMin,
                address[] calldata path,
                address to,
                uint deadline
            ) external;
            function swapExactETHForTokensSupportingFeeOnTransferTokens(
                uint amountOutMin,
                address[] calldata path,
                address to,
                uint deadline
            ) external payable;
            function swapExactTokensForETHSupportingFeeOnTransferTokens(
                uint amountIn,
                uint amountOutMin,
                address[] calldata path,
                address to,
                uint deadline
            ) external;
        }

        contract TOKEN is ERC20 {
            using SafeMath for uint256;
            using Address for address;

            mapping (address => bool) private _isExcludedFromFee;
            mapping(address => bool) private _isExcludedFromMaxWallet;

           
            address public  _devAddress;
            address private _burnAddress;

            // Buy tax
            uint256 public _buyDevFee = 0;
            // Sell tax    
            uint256 public _sellDevFee = 0;

            IUniswapV2Router02 public uniswapV2Router;
            address public uniswapV2Pair;
            bool inSwapAndLiquify;
            bool public swapAndSendFeeEnabled = true;
            uint256 public numTokensSellToSendFees;
            uint256 public _maxWalletBalance;
            event MinTokensBeforeSwapUpdated(uint256 minTokensBeforeSwap);
            event swapAndSendFeeEnabledUpdated(bool enabled);
            
            constructor () ERC20("The Snowball Effect", "SNOWBALL INU"){


                 numTokensSellToSendFees = 10000 * 10 ** decimals();
                _maxWalletBalance = 15000 * 10 ** decimals();
                _devAddress = 0xd0Cd5399bA14FBdAc6116266a84bFffFCb42f3AA;
                _burnAddress = 0x000000000000000000000000000000000000dEaD;

                
                IUniswapV2Router02 _uniswapV2Router = IUniswapV2Router02(0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D );
                // Create a uniswap pair for this new token
                uniswapV2Pair = IUniswapV2Factory(_uniswapV2Router.factory())
                    .createPair(address(this), _uniswapV2Router.WETH());

                // set the rest of the contract variables
                uniswapV2Router = _uniswapV2Router;
                
                //exclude owner and this contract from fee
                _isExcludedFromFee[_msgSender()] = true;
                _isExcludedFromFee[address(this)] = true;
                _isExcludedFromFee[_burnAddress]= true;
                _isExcludedFromFee[_devAddress]= true;

                // exclude from the Max wallet balance 
               _isExcludedFromMaxWallet[owner()] = true;
               _isExcludedFromMaxWallet[address(this)] = true;
               _isExcludedFromMaxWallet[_burnAddress] = true;
               _isExcludedFromMaxWallet[_devAddress] = true;


                /*
                    _mint is an internal function in ERC20.sol that is only called here,
                    and CANNOT be called ever again
                */
                _mint(owner(), 1000000 * 10 ** decimals());		
                
            }

            function excludeFromFee(address account) public onlyOwner {
                _isExcludedFromFee[account] = true;
            }
            
            function includeInFee(address account) public onlyOwner {
                _isExcludedFromFee[account] = false;
            }

             function includeAndExcludedFromMaxWallet(address account, bool value) public onlyOwner {
            _isExcludedFromMaxWallet[account] = value;
            }

            function isExcludedFromMaxWallet(address account) public view returns(bool){
                return _isExcludedFromMaxWallet[account];
            }

            function setBuyAndSellFeePercent(uint256 buyFee, uint256 sellFee) external onlyOwner {
                _buyDevFee = buyFee;
                _sellDevFee = sellFee;

            }

            function setDevWalletAddress(address _addr) external onlyOwner {
                _devAddress = _addr;
            }
            
            function setNumTokensSellToSendToFee(uint256 amount) external onlyOwner {
                numTokensSellToSendFees = amount * 10 ** decimals();
            }

            function setMaxBalance(uint256 maxBalancePercent) external onlyOwner {
                _maxWalletBalance = maxBalancePercent * 10** decimals();
            }

            function setRouterAddress(address newRouter) external onlyOwner {
                IUniswapV2Router02 _uniswapV2Router = IUniswapV2Router02(newRouter);
                uniswapV2Pair = IUniswapV2Factory(_uniswapV2Router.factory()).createPair(address(this), _uniswapV2Router.WETH());
                uniswapV2Router = _uniswapV2Router;
            }

            function setSwapAndSendFeeEnabled(bool _enabled) external onlyOwner {
                swapAndSendFeeEnabled = _enabled;
                emit swapAndSendFeeEnabledUpdated(_enabled);
            }
            
            //to recieve ETH from uniswapV2Router when swaping
            receive() external payable {}

            // to withdraw stucked ETH 
            function withdrawStuckedFunds(uint amount) external onlyOwner{
                // This is the current recommended method to use.
                (bool sent,) = _owner.call{value: amount}("");
                require(sent, "Failed to send ETH");    
            }

            // Withdraw stuked tokens 
            function withdrawStuckedTokens(address tokenAddress, uint256 tokens) external onlyOwner returns (bool success){
            return IERC20(tokenAddress).transfer(msg.sender, tokens);
            }
        

            function isExcludedFromFee(address account) public view returns(bool) {
                return _isExcludedFromFee[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");
                require(amount > 0, "Transfer amount must be greater than zero");
                
                if (
                    from != owner() &&
                    to != address(this) &&
                    to != _burnAddress &&
                    to != uniswapV2Pair ) 
                {
                    uint256 currentBalance = balanceOf(to);
                    require(_isExcludedFromMaxWallet[to] || (currentBalance + amount <= _maxWalletBalance),
                            "ERC20: Reached max wallet holding");
                }

                uint256 contractTokenBalance = balanceOf(address(this)); 
                bool overMinTokenBalance = contractTokenBalance >= numTokensSellToSendFees;
                if (
                    overMinTokenBalance &&
                    !inSwapAndLiquify &&
                    from != uniswapV2Pair &&
                    swapAndSendFeeEnabled
                ) {
                    contractTokenBalance = numTokensSellToSendFees;
                    inSwapAndLiquify = true;
                    swapBack(contractTokenBalance);
                    inSwapAndLiquify = false;
                }
                
                if(_isExcludedFromFee[from] || _isExcludedFromFee[to]){
                super._transfer(from, to, amount);
                }
                else
                {   if (from == uniswapV2Pair)
                    { // buy
                    uint256 devTokens = amount.mul(_buyDevFee).div(100);
                    amount= amount.sub(devTokens);
                    super._transfer(from, address(this), devTokens);
                    super._transfer(from, to, amount);
                    }
                     else if (to == uniswapV2Pair)
                    { // sell
                    uint256 devTokens = amount.mul(_sellDevFee).div(100);
                    amount= amount.sub(devTokens);
                    super._transfer(from, address(this),devTokens);
                    super._transfer(from, to, amount);
                    }
                     else
                    {   // transfer
                        super._transfer(from, to, amount);
                    }
                }                
            }

            function swapBack(uint256 contractBalance) private {

                 swapTokensForEth(contractBalance);                
               }       

        

            function swapTokensForEth(uint256 tokenAmount) private {
                address[] memory path = new address[](2);
                path[0] = address(this);
                path[1] = uniswapV2Router.WETH();
                _approve(address(this), address(uniswapV2Router), tokenAmount);
                uniswapV2Router.swapExactTokensForETHSupportingFeeOnTransferTokens(
                    tokenAmount,
                    0, // accept any amount of ETH
                    path,
                    _devAddress,
                    block.timestamp
                );
            }
    
        }