/**
https://twitter.com/HungKongToken

https://t.me/Hung_Kong

...........................................::^~!!777!!~^^::.........................................
.........................................::~!7????JJ???7!^::........................................
........................................:^~7?JJJJJJJJJJ??!~::............................:::........
.......................................:^!7?JJJJJJJJJJJJJ?7~^:......................................
......................................:^!7?JJJJJJJJJJJJJJJ?7~:......................................
.....................................::~7?JJJJJJJJJJJJJJJJJ?!^:.....................................
.....................................:^!7?JJJJJJJJJJJJJJJJJ?!^:.....................................
....................................::^!?JJJJJYYYYYYJYYJJJJ?!~:.....................................
....................................:^~7?JJJJJYYYYYYYYYYJJJ?7~:.....................................
...................................:^~!?JJJJJYYYYYYYYYYJJJJJ7~^:....................................
...............................:::^~!7?JJJYYYYYYYYYYYYYYYYJJ?7!~^::..............................:::
............................::^^~!7?JJJJYYYYYYYYYYYYYYYYYYYJJJ??7!~^:::..................:::::::::::
:.........................::^!7??JJJJYYYYYYYYYYYYYYYYYYYYYYYYYYJJJ?7!~^^::::::::::::::::::::::::::::
:.....................::^^~!?JJJJYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYJJ??7!!~^::::::::^^^^~~~^^^^^^^~~
...................::^~!7?JJJJYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYJJJJ?7!~^^^^^^^^^~~~~~~^^~~~~~
................::^~7??JJJJJYYYYYYYYYYYYYYYYYYYY555YY55YYYYYYYYYYYYYYYYYYYYJJ?!~^^^^^^^~~~~~~~~~~~~~
...............::~7?JJJJJJJYYYYYYYYYYYYY5Y55YYYYY5555555555Y55555YYYYYYYYYYYYJ?7!~^^^^^~~~~~~~~~~~~~
..............::~7JJJJJJYYYYYYYYYYYYYYYY55555555555555555555555555555555YYYYYYY?7~~^^^^^^^^^^^^^^~~~
..............:^!?JJJJYYYYYYYYYYYYY555555555555555555555555555555555555555555YYJ?7~~~~~~~~~~~~~~~~~~
.............::~7JJJYYYYYYYYYYYY55555555555555555555555555555555555555555555555YJ?7!!!!!!~~~~~~~~~!!
.............:^!?JJYYYYYYYYYY555555555555555555555555555555555555555555555555555YJ?7!!!!!!~~~~~~!!!!
.............:~7JJJYYYYYYYYY55555555555555555555555555555555555555555555555555555YYJ?7!!!!!!!!!!!!!!
............:^!?JJYYYYYYYY555555555555555555555555555555555555555555555555555555555YJ?7!~~!!!!!!!!!!
....::::::::^!7JJYYYYYYYY55555555555555555555555555PPPPPPPPPPPP555555555555555555555YJ?7~~^^~~~~~~~~
...::::::::~!?JJYYYYYYYY555555555555555555555555555PPPPPPPP5PP55555555555555555555555YJ?!~^^^^^^^^^^
....::::::~7JJJYYYYYYYY555555555555555555555555PPPPPPPPPPPPPPP555555555555555555555555YJ7~^^^^^^^:::
.....::::^!?JYYYYYYYY555555555555555555555PPPPPPPPPPPPPPPPPPPPP5555555555555P5555555555Y?7~^^^^^^^::
::::::::^!7JJYYYYYYY5Y55555555555555555555PPPPPPPPPPPPPPPPPPPPPP55555555555PPP5555555555Y?!~^^^^^^^^
:::::::^!?JYYYYYYYYYYY55555555555555555PPPPPPPPPPPPPPPPPPPPPPPPPPP55555YYY555555555555555Y?!~^:::::^
:::.::~!?JYYYYYYYYYYYYYYYJJJY555555555PPPPPPPPPPPPPPPPPPPPPPPPPPPP555YJ777?Y555555P5555555YJ7~^:::::
....:~7JJYYYYYYYY555YYYY?!!!?Y55555555PPPPPPPPPPPPPPPPPPPPPPPPPPPP55YJ7~^~7JY55555555555555YJ?!^^::^
...:^7JJYYYYYYYYYYYYYYYJ?~^~7JY55555555P5PPPPPPPPPPPPPPPPPPPPPPPP555Y?~^:^!?Y555555555555555YJ?!~^^^
...:~?JJYYYYYYYYYYYYYYYJ7~^^!?Y555555555PPPPPPPPPPPPPPPPPPPPPPPPP55YJ7~^:^!?Y5555555555555555YJ7!~^^
..:^!?JJJYYYYYYYYYYYYYYJ7~^^!JY5555PPPPPPPPPPPPPPPPPPPPPPPPPPPPPP55J7~^::^~7J55555PPPPPP555555YJ7!~~
..:^!?JJJYYYYYY555YYYYY?!^:^!JY555PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP55J7~::::~7JY555PPPPPPPP55555YJ?7!!
...^!?JJJYYYYYYYY5YYYYJ7~^^~7J5555PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP55J7~::::^!?Y5555PPPPPPPP5555YJ?7!!
...:~7JJYYYYYYYYY5YYYYJ7~^^~?J5555PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP55Y?~^::::^!?Y5555PPPPPPPP55YJ?!~~~
...:~7JJYYYYYYYYY55YYJ7~^:^~7J55555PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP5YJ7^:::::^!7JY5555PPPP5555Y?!~^::
...:^!?JYYYYYYYYYYYJ?!^:::^!?Y5555PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP55Y?!~:::::^^!?J555PPP55555Y?!^:::
...:~7JYYYYYYYYYYYJ?!^:::^~7J555PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP55YJ7~^:::::^~7JY555555555YJ7~:::
:::^~7JYYYY55555YJ?!^^::^~7JY555PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP55J7~::::::^~7J555555555YJ7~^::
::^^!?JYYY555555YJ7~^^^^~7JY555PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP5Y?!^::..::^!JY555P5555Y?!~^^^
:::^~7JYYY555555YJ7~^^^~!?Y55PPPPPPPPPPPPPPPPPPPPPGGPPPPPPPPPPPPPPPPPP55Y?!^:...:^!?Y555PPP55Y?!^^^^
::::^!?YYY5555555J?!^^^~7J55PPPPPPPPPPPPPGGGGGGPGGGGGGGGGGGPPPPPPPPPPPP5Y?!^::::^~7JY55PPPP555J7~^::
^::^^!?YYYY555555Y?!~^~!JY55PPPPPPPPPPPPPGGGGGGGGGGGGGGGGGGGGGPPPPPPPPP5YJ7~^~~!?JY55PPPPPPP55Y?!^::
^^^^~!?YY55555555YY?7!!?Y55PPPPPPPPPPPPPGGGGGGGGGGGGGGGGGGGGGGGGPPPPPPPP5YJ7!!!7JY55PPPPPPPP55Y7!^^^
^^^^~!?YYY555YYJ?JJJ?77?Y5PPPPPPPPPPPPPPGGGGGGGGGGGGGGGGGGGGGGGGGGGPPPPPP5J7!~!7J55PPPPPPPPPP5Y7!~^^
::::^!?JY555YJ?!~~!7???JY5PPPPPPPPPPPPPGGGGGGGGGGGGGGGGGGGGGGGGGGGGGPPPPP5J777JY55PPPPPPPPPPP5J7!~^^
::::^~7JY555YJ7~^^^~~!7?Y5PPPPPPPPPPPGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGPPP5J??JY5PPPPPPPPPPPPP5J7!~~~
:::::^~7JYY5YJ7!~~~~~~!?Y5PPPPPPPPPPPGGGGGPPPPGGGGGGGGGGGGGGGGGGGGGGGGGGPPYJ?JY5PPPPPPPPPPPP55J?7!!!
::::::^~!?JYYYJ????7!~!?Y5PPPPPPPPPPGGGGGPP555PGGGGGGGGGGGGGGGGGGGGGGGGGPP5J??JY5PPPPPPPPPPPP5YJ?!!!
::::::::^~!7?JJJJJ?7~~!?Y5PPPPPPPGPGPGGGP5YJJYPGGGGGGPPPGGGGGGGGGGGGGGGPP5Y?77?J5555555PPPPPPP5YJ?77
:::::::::^^~~!!!!!~~^~!?Y5PPPPPPGGGGGGPP5Y?7?J5GGGGGPYYY5PGGGGGGGGGGGGGP5Y?!~~!7?JJ???JYYYYYYYYYYYJJ
::::::::^^^^^^^^^^^^^~7JYPPPPPPPPGGGGGPPY?!!7J5PGGGP5J?7?YPGGGGGGGGGGGGP5J7~^^^~~~~~~~~!77!!!77?JYYY
::::::::::^^^^^^:::^^~7J5PPPPPPPPGGGGPPY?!~!7J5PGGGP5J7!!7J5PGGGGGGGGGGP5Y7~^:::::::::::^^:^^^~!7?77
::::^^^^^^^^^::::::^^~7J5PPPPPGGGGGGGP5J7!~!7Y5PGGGP5J7~~!?YPGGGGGGGGGGPPY?~^:::::::::::::::::^^^^^^
^^^^^^^^^^^^^::::::^^~7J5PPPPPGGGGGGGP5J?!!!?YPPGGGP5J7~~!?YPGGGGGGGGGPP5Y?~^:::::::::::::::::::::::
^^^^^^^:::::::::::^^^!?Y5PPPGGGGGGGGGP5J7!~!7Y5PGGGP5J7~~7?5PGGGGGGGGGPP5Y7~^:::::::::...:::::::::::
^^^^^^^^:::::::::::^^!?Y5PPGGGGGGGGGGP5J7~~!7J5PGGGP5?!~~!?5PGGGGGGGGGPP5J7~::::::::::::::::::::::::
^^^^^^^^^::::^^^^^^^^!?Y5PPGGGGGGGGGPPY?!~~~7J5PGGGP5J!~~~7J5PGGGGGGGGGP5J7~^:::::::::::::::::::::::
^^^^^^^^^^^^^^^^^^^^^!7Y5PGGGGGGGGGGPYJ7~~^~!?YPGGGP5J7~^~!?YPGGGGGGGGGP5J7~^^^^^^::::::::::::^^::::
~~~~~~~~^^^^^^^~^^^^~~7J5PGGGGGGGGGP5J?!~^^~!?YPGGGP5J7~~~!?YPGGGGGGGGGP5J7!~^^^^^^^^^::::::^^^^^^::
~~~~~^^^^^^^^^^^^^^^^~!?YPGGGGGGGGGP5J7!~^^^~!?Y5PPP5?!~~~!?YPGGGGGGGGGGPY?!~^^^^^^^^^^^^^^^^^^^^^^:
!!!~~~~~~~~~~~~^^^^^^~!?YPGGGGGGGGGP5J7!~^^^^^~7?JYJ?!~~^~!?YPGGGGGGGGGGP5J7~^^^^^^^^^^^^^^^^^^^^^^^
YYJ?????????77!!!!~~!!7J5PGGGGGGGGGG5Y?!~~^^^^^~!!7!!!!!!!7JYPGBBBBBBBBGGG5Y?777777!!!~~!!!!!~~~~~~~
PPPP5555555555YYJJJJJY5PGGGGBBBBBBGGP5YJ???77777???JJYYY555PPGBBBBBBBBBBBBGGPP555555YYYJYYYYYJJJJJYY
GGGGGGGGGGGGGGGPPGPPGGGGGBBBBBBBBBGGGP55YYYYYY55PPGGGGGGGBBBBBBBBBBBBBBBBBBBBBGGGGGGGGGGGGGGGGGGGGGG
GGGGGGGGGGGGGGGGGGGGGGGBBBBBBBBBBBBGP5YJ?7??J5PGGBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBGBBBBBB
GGGGGGGGGGGGGGGGGGGGGGGBBBBBBBBBBBBGGP5J?777?JY5GGBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
BGGGGGGGGGGPPPPPPGGGGGBBBBBBBBBBBBBBBBGP55YYYYY5PBBBBBBBBBBBBB#B#################BBBBBBBBBBBBBBBBBBB
&#BP5YY5555YYJJY5PGBBBBBBBBBBBBBBBBBBBBBBBBGGPPGGBBBB#########################################B####B

  _    _ _    _ _   _  _____   _  ______  _   _  _____ 
 | |  | | |  | | \ | |/ ____| | |/ / __ \| \ | |/ ____|
 | |__| | |  | |  \| | |  __  | ' / |  | |  \| | |  __ 
 |  __  | |  | | . ` | | |_ | |  <| |  | | . ` | | |_ |
 | |  | | |__| | |\  | |__| | | . \ |__| | |\  | |__| |
 |_|  |_|\____/|_| \_|\_____| |_|\_\____/|_| \_|\_____|
                                                                                                          

*/

// SPDX-License-Identifier: MIT
pragma solidity 0.8.20;

abstract contract Context {
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes calldata) {
        this;
        return msg.data;
    }
}

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);
}

interface IERC20Metadata is IERC20 {
    function name() external view returns (string memory);
    function symbol() external view returns (string memory);
    function decimals() external view returns (uint8);
}

contract ERC20 is Context, IERC20, IERC20Metadata {
    mapping(address => uint256) private _balances;
    mapping(address => mapping(address => uint256)) private _allowances;
    uint256 private _totalSupply;
    string private _name;
    string private _symbol;

    constructor(string memory name_, string memory symbol_) {
        _name = name_;
        _symbol = symbol_;
    }

    function name() public view virtual override returns (string memory) {
        return _name;
    }

    function symbol() public view virtual override returns (string memory) {
        return _symbol;
    }

    function decimals() public view virtual override returns (uint8) {
        return 18;
    }

    function totalSupply() public view virtual override returns (uint256) {
        return _totalSupply;
    }

    function balanceOf(address account) public view virtual override returns (uint256) {
        return _balances[account];
    }

    function transfer(address recipient, uint256 amount) public virtual override returns (bool) {
        _transfer(_msgSender(), recipient, amount);
        return true;
    }

    function allowance(address owner, address spender) public view virtual override returns (uint256) {
        return _allowances[owner][spender];
    }

    function approve(address spender, uint256 amount) public virtual override returns (bool) {
        _approve(_msgSender(), spender, amount);
        return true;
    }

    function transferFrom(
        address sender,
        address recipient,
        uint256 amount
    ) public virtual override returns (bool) {
        _transfer(sender, recipient, amount);

        uint256 currentAllowance = _allowances[sender][_msgSender()];
        require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance");
    unchecked {
        _approve(sender, _msgSender(), currentAllowance - amount);
    }

        return true;
    }

    function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
        _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue);
        return true;
    }

    function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
        uint256 currentAllowance = _allowances[_msgSender()][spender];
        require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero");
    unchecked {
        _approve(_msgSender(), spender, currentAllowance - subtractedValue);
    }

        return true;
    }

    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");

        uint256 senderBalance = _balances[sender];
        require(senderBalance >= amount, "ERC20: transfer amount exceeds balance");
    unchecked {
        _balances[sender] = senderBalance - amount;
    }
        _balances[recipient] += amount;

        emit Transfer(sender, recipient, amount);
    }

    function _createInitialSupply(address account, uint256 amount) internal virtual {
        require(account != address(0), "ERC20: mint to the zero address");

        _totalSupply += amount;
        _balances[account] += amount;
        emit Transfer(address(0), account, amount);
    }

    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);
    }
}

contract Ownable is Context {
    address private _owner;

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    constructor () {
        address msgSender = _msgSender();
        _owner = msgSender;
        emit OwnershipTransferred(address(0), msgSender);
    }

    function owner() public view returns (address) {
        return _owner;
    }

    modifier onlyOwner() {
        require(_owner == _msgSender(), "Ownable: caller is not the owner");
        _;
    }

    function renounceOwnership() external 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 IDexRouter {
    function factory() external pure returns (address);
    function WETH() external pure returns (address);

    function swapExactTokensForETHSupportingFeeOnTransferTokens(
        uint amountIn,
        uint amountOutMin,
        address[] calldata path,
        address to,
        uint deadline
    ) external;

    function addLiquidityETH(
        address token,
        uint256 amountTokenDesired,
        uint256 amountTokenMin,
        uint256 amountETHMin,
        address to,
        uint256 deadline
    )
    external
    payable
    returns (
        uint256 amountToken,
        uint256 amountETH,
        uint256 liquidity
    );
}

interface IDexFactory {
    function createPair(address tokenA, address tokenB)
    external
    returns (address pair);
}

contract HungKong is ERC20, Ownable {

    uint256 public maxBuyAmount;
    uint256 public maxSellAmount;
    uint256 public maxWalletAmount;

    IDexRouter public immutable uniswapV2Router;
    address public immutable uniswapV2Pair;

    bool private swapping;
    uint256 public swapTokensAtAmount;

    address public HungAddress;

    bool public limitsInEffect = true;
    bool public tradingActive = false;
    bool public swapEnabled = false;

    uint256 public buyTotalFees;
    uint256 public buyHungFee;
    uint256 public buyLiquidityFee;

    uint256 public sellTotalFees;
    uint256 public sellHungFee;
    uint256 public sellLiquidityFee;

    uint256 public tokensForHung;
    uint256 public tokensForLiquidity;

    // exlcude from fees and max transaction amount
    mapping (address => bool) private _isExcludedFromFees;
    mapping (address => bool) public _isExcludedMaxTransactionAmount;

    // store addresses that a automatic market maker pairs. Any transfer *to* these addresses
    // could be subject to a maximum transfer amount
    mapping (address => bool) public automatedMarketMakerPairs;

    event SetAutomatedMarketMakerPair(address indexed pair, bool indexed value);
    event EnabledTrading(bool tradingActive);
    event RemovedLimits();
    event ExcludeFromFees(address indexed account, bool isExcluded);
    event UpdatedMaxBuyAmount(uint256 newAmount);
    event UpdatedMaxSellAmount(uint256 newAmount);
    event UpdatedMaxWalletAmount(uint256 newAmount);
    event UpdatedHungAddress(address indexed newWallet);
    event UpdatedRewardsAddress(address indexed newWallet);
    event MaxTransactionExclusion(address _address, bool excluded);
    event SwapAndLiquify(
        uint256 tokensSwapped,
        uint256 ethReceived,
        uint256 tokensIntoLiquidity
    );

    constructor() ERC20("Hung Kong", "HUNG") {

        address newOwner = msg.sender; 

        IDexRouter _uniswapV2Router = IDexRouter(0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D);

        _excludeFromMaxTransaction(address(_uniswapV2Router), true);
        uniswapV2Router = _uniswapV2Router;

        uniswapV2Pair = IDexFactory(_uniswapV2Router.factory()).createPair(address(this), _uniswapV2Router.WETH());
        _setAutomatedMarketMakerPair(address(uniswapV2Pair), true);

        uint256 totalSupply = 420690000 * 1e18;

        maxBuyAmount = totalSupply *  30 / 1000;
        maxSellAmount = totalSupply *  30 / 1000;
        maxWalletAmount = totalSupply * 30 / 1000;
        swapTokensAtAmount = totalSupply * 50 / 100000; 

        buyHungFee = 0;
        buyLiquidityFee = 0;
        buyTotalFees = buyHungFee + buyLiquidityFee;

        sellHungFee = 0;
        sellLiquidityFee = 0;
        sellTotalFees = sellHungFee + sellLiquidityFee;

        _excludeFromMaxTransaction(newOwner, true);
        _excludeFromMaxTransaction(address(this), true);
        _excludeFromMaxTransaction(address(0xdead), true);

        HungAddress = address(0x84874e64800a0fbAB5a303B022D9F1941041a78D);

        excludeFromFees(newOwner, true);
        excludeFromFees(address(this), true);
        excludeFromFees(address(0xdead), true);

        _createInitialSupply(newOwner, totalSupply);
        transferOwnership(newOwner);
    }

    receive() external payable {}

    // remove limits after token is stable
    function removeLimits() external onlyOwner {
        limitsInEffect = false;
        emit RemovedLimits();
    }

    function _excludeFromMaxTransaction(address updAds, bool isExcluded) private {
        _isExcludedMaxTransactionAmount[updAds] = isExcluded;
        emit MaxTransactionExclusion(updAds, isExcluded);
    }

    function excludeFromMaxTransaction(address updAds, bool isEx) external onlyOwner {
        if(!isEx){
            require(updAds != uniswapV2Pair, "Cannot remove uniswap pair from max txn");
        }
        _isExcludedMaxTransactionAmount[updAds] = isEx;

    }


    function excludeFromFees(address account, bool excluded) public onlyOwner {
        _isExcludedFromFees[account] = excluded;
        emit ExcludeFromFees(account, excluded);
    }

    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, "amount must be greater than 0");

        if(limitsInEffect){
            if (from != owner() && to != owner() && to != address(0) && to != address(0xdead)){
                if(!tradingActive){
                    require(_isExcludedMaxTransactionAmount[from] || _isExcludedMaxTransactionAmount[to], "Trading is not active.");
                    require(from == owner(), "Trading is enabled");
                }

                //when buy
                if (automatedMarketMakerPairs[from] && !_isExcludedMaxTransactionAmount[to]) {
                    require(amount <= maxBuyAmount, "Buy transfer amount exceeds the max buy.");
                    require(amount + balanceOf(to) <= maxWalletAmount, "Cannot Exceed max wallet");
                }
                //when sell
                else if (automatedMarketMakerPairs[to] && !_isExcludedMaxTransactionAmount[from]) {
                    require(amount <= maxSellAmount, "Sell transfer amount exceeds the max sell.");
                }
                else if (!_isExcludedMaxTransactionAmount[to] && !_isExcludedMaxTransactionAmount[from]){
                    require(amount + balanceOf(to) <= maxWalletAmount, "Cannot Exceed max wallet");
                }
            }
        }

        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 = true;
        // if any account belongs to _isExcludedFromFee account then remove the fee
        if(_isExcludedFromFees[from] || _isExcludedFromFees[to]) {
            takeFee = false;
        }

        uint256 fees = 0;
        // only take fees on Trades, not on wallet transfers

        if(takeFee){
            // on sell
            if (automatedMarketMakerPairs[to] && sellTotalFees > 0){
                fees = amount * sellTotalFees /100;
                tokensForLiquidity += fees * sellLiquidityFee / sellTotalFees;
                tokensForHung += fees * sellHungFee / sellTotalFees;
            }
            // on buy
            else if(automatedMarketMakerPairs[from] && buyTotalFees > 0) {
                fees = amount * buyTotalFees / 100;
                tokensForLiquidity += fees * buyLiquidityFee / buyTotalFees;
                tokensForHung += fees * buyHungFee / buyTotalFees;
            }

            if(fees > 0){
                super._transfer(from, address(this), 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 setAutomatedMarketMakerPair(address pair, bool value) external onlyOwner {
        require(pair != uniswapV2Pair, "The pair cannot be removed from automatedMarketMakerPairs");

        _setAutomatedMarketMakerPair(pair, value);
    }

    function _setAutomatedMarketMakerPair(address pair, bool value) private {
        automatedMarketMakerPairs[pair] = value;

        _excludeFromMaxTransaction(pair, value);

        emit SetAutomatedMarketMakerPair(pair, value);
    }

    // once enabled, can never be turned off
    function enableTrading(bool _status) external onlyOwner {
        require(!tradingActive, "Cannot re enable trading");
        tradingActive = _status;
        swapEnabled = true;
        emit EnabledTrading(tradingActive);
    }

    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
            address(owner()),
            block.timestamp
        );

    }

   
    function swapBack() private {
        uint256 contractBalance = balanceOf(address(this));
        uint256 totalTokensToSwap = tokensForLiquidity + tokensForHung;

        if(contractBalance == 0 || totalTokensToSwap == 0) {return;}

        if(contractBalance > swapTokensAtAmount * 10){
            contractBalance = swapTokensAtAmount * 10;
        }

        bool success;

        // Halve the amount of liquidity tokens
        uint256 liquidityTokens = contractBalance * tokensForLiquidity / totalTokensToSwap / 2;

        swapTokensForEth(contractBalance - liquidityTokens);

        uint256 ethBalance = address(this).balance;
        uint256 ethForLiquidity = ethBalance;

        uint256 ethForHung = ethBalance * tokensForHung / (totalTokensToSwap - (tokensForLiquidity/2));

        ethForLiquidity -= ethForHung;

        tokensForLiquidity = 0;
        tokensForHung = 0;

        if(liquidityTokens > 0 && ethForLiquidity > 0){
            addLiquidity(liquidityTokens, ethForLiquidity);
        }

        (success,) = address(HungAddress).call{value: address(this).balance}("");
    }

    function claimStuckTokens(address _token) external onlyOwner {
        if (_token == address(0x0)) {
            payable(owner()).transfer(address(this).balance);
            return;
        }
        IERC20 erc20token = IERC20(_token);
        uint256 balance = erc20token.balanceOf(address(this));
        erc20token.transfer(owner(), balance);
    }
    
}