creation_sourcecode: // SPDX-License-Identifier: MIT
  pragma solidity 0.8.19;
  
  abstract contract Context {
      function _msgSender() internal view virtual returns (address) {
          return msg.sender;
      }
  
      function _msgData() internal view virtual returns (bytes calldata) {
          this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
          return msg.data;
      }
  }
  
  interface IERC165 {
  
      function supportsInterface(bytes4 interfaceId) external view returns (bool);
  }
  
  abstract contract ERC165 is IERC165 {
  
      function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
          return interfaceId == type(IERC165).interfaceId;
      }
  }
  
  interface IAccessControl {
  
      event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);
  
      event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);
  
      event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);
  
      function hasRole(bytes32 role, address account) external view returns (bool);
  
      function getRoleAdmin(bytes32 role) external view returns (bytes32);
  
      function grantRole(bytes32 role, address account) external;
  
      function revokeRole(bytes32 role, address account) external;
  
      function renounceRole(bytes32 role, address account) external;
  }
  
  library Math {
      enum Rounding {
          Down, 
          Up, 
          Zero 
      }
  
      function max(uint256 a, uint256 b) internal pure returns (uint256) {
          return a > b ? a : b;
      }
  
      function min(uint256 a, uint256 b) internal pure returns (uint256) {
          return a < b ? a : b;
      }
  
      function average(uint256 a, uint256 b) internal pure returns (uint256) {
  
          return (a & b) + (a ^ b) / 2;
      }
  
      function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
  
          return a == 0 ? 0 : (a - 1) / b + 1;
      }
  
      function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {
          unchecked {
  
              uint256 prod0; 
              uint256 prod1; 
              assembly {
                  let mm := mulmod(x, y, not(0))
                  prod0 := mul(x, y)
                  prod1 := sub(sub(mm, prod0), lt(mm, prod0))
              }
  
              if (prod1 == 0) {
  
                  return prod0 / denominator;
              }
  
              require(denominator > prod1, "Math: mulDiv overflow");
  
              uint256 remainder;
              assembly {
  
                  remainder := mulmod(x, y, denominator)
  
                  prod1 := sub(prod1, gt(remainder, prod0))
                  prod0 := sub(prod0, remainder)
              }
  
              uint256 twos = denominator & (~denominator + 1);
              assembly {
  
                  denominator := div(denominator, twos)
  
                  prod0 := div(prod0, twos)
  
                  twos := add(div(sub(0, twos), twos), 1)
              }
  
              prod0 |= prod1 * twos;
  
              uint256 inverse = (3 * denominator) ^ 2;
  
              inverse *= 2 - denominator * inverse; 
              inverse *= 2 - denominator * inverse; 
              inverse *= 2 - denominator * inverse; 
              inverse *= 2 - denominator * inverse; 
              inverse *= 2 - denominator * inverse; 
              inverse *= 2 - denominator * inverse; 
  
              result = prod0 * inverse;
              return result;
          }
      }
  
      function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {
          uint256 result = mulDiv(x, y, denominator);
          if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {
              result += 1;
          }
          return result;
      }
  
      function sqrt(uint256 a) internal pure returns (uint256) {
          if (a == 0) {
              return 0;
          }
  
          uint256 result = 1 << (log2(a) >> 1);
  
          unchecked {
              result = (result + a / result) >> 1;
              result = (result + a / result) >> 1;
              result = (result + a / result) >> 1;
              result = (result + a / result) >> 1;
              result = (result + a / result) >> 1;
              result = (result + a / result) >> 1;
              result = (result + a / result) >> 1;
              return min(result, a / result);
          }
      }
  
      function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
          unchecked {
              uint256 result = sqrt(a);
              return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);
          }
      }
  
      function log2(uint256 value) internal pure returns (uint256) {
          uint256 result = 0;
          unchecked {
              if (value >> 128 > 0) {
                  value >>= 128;
                  result += 128;
              }
              if (value >> 64 > 0) {
                  value >>= 64;
                  result += 64;
              }
              if (value >> 32 > 0) {
                  value >>= 32;
                  result += 32;
              }
              if (value >> 16 > 0) {
                  value >>= 16;
                  result += 16;
              }
              if (value >> 8 > 0) {
                  value >>= 8;
                  result += 8;
              }
              if (value >> 4 > 0) {
                  value >>= 4;
                  result += 4;
              }
              if (value >> 2 > 0) {
                  value >>= 2;
                  result += 2;
              }
              if (value >> 1 > 0) {
                  result += 1;
              }
          }
          return result;
      }
  
      function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
          unchecked {
              uint256 result = log2(value);
              return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);
          }
      }
  
      function log10(uint256 value) internal pure returns (uint256) {
          uint256 result = 0;
          unchecked {
              if (value >= 10 ** 64) {
                  value /= 10 ** 64;
                  result += 64;
              }
              if (value >= 10 ** 32) {
                  value /= 10 ** 32;
                  result += 32;
              }
              if (value >= 10 ** 16) {
                  value /= 10 ** 16;
                  result += 16;
              }
              if (value >= 10 ** 8) {
                  value /= 10 ** 8;
                  result += 8;
              }
              if (value >= 10 ** 4) {
                  value /= 10 ** 4;
                  result += 4;
              }
              if (value >= 10 ** 2) {
                  value /= 10 ** 2;
                  result += 2;
              }
              if (value >= 10 ** 1) {
                  result += 1;
              }
          }
          return result;
      }
  
      function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
          unchecked {
              uint256 result = log10(value);
              return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);
          }
      }
  
      function log256(uint256 value) internal pure returns (uint256) {
          uint256 result = 0;
          unchecked {
              if (value >> 128 > 0) {
                  value >>= 128;
                  result += 16;
              }
              if (value >> 64 > 0) {
                  value >>= 64;
                  result += 8;
              }
              if (value >> 32 > 0) {
                  value >>= 32;
                  result += 4;
              }
              if (value >> 16 > 0) {
                  value >>= 16;
                  result += 2;
              }
              if (value >> 8 > 0) {
                  result += 1;
              }
          }
          return result;
      }
  
      function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
          unchecked {
              uint256 result = log256(value);
              return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);
          }
      }
  }
  
  library SignedMath {
  
      function max(int256 a, int256 b) internal pure returns (int256) {
          return a > b ? a : b;
      }
  
      function min(int256 a, int256 b) internal pure returns (int256) {
          return a < b ? a : b;
      }
  
      function average(int256 a, int256 b) internal pure returns (int256) {
  
          int256 x = (a & b) + ((a ^ b) >> 1);
          return x + (int256(uint256(x) >> 255) & (a ^ b));
      }
  
      function abs(int256 n) internal pure returns (uint256) {
          unchecked {
  
              return uint256(n >= 0 ? n : -n);
          }
      }
  }
  
  library Strings {
      bytes16 private constant _SYMBOLS = "0123456789abcdef";
      uint8 private constant _ADDRESS_LENGTH = 20;
  
      function toString(uint256 value) internal pure returns (string memory) {
          unchecked {
              uint256 length = Math.log10(value) + 1;
              string memory buffer = new string(length);
              uint256 ptr;
  
              assembly {
                  ptr := add(buffer, add(32, length))
              }
              while (true) {
                  ptr--;
  
                  assembly {
                      mstore8(ptr, byte(mod(value, 10), _SYMBOLS))
                  }
                  value /= 10;
                  if (value == 0) break;
              }
              return buffer;
          }
      }
  
      function toString(int256 value) internal pure returns (string memory) {
          return string(abi.encodePacked(value < 0 ? "-" : "", toString(SignedMath.abs(value))));
      }
  
      function toHexString(uint256 value) internal pure returns (string memory) {
          unchecked {
              return toHexString(value, Math.log256(value) + 1);
          }
      }
  
      function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
          bytes memory buffer = new bytes(2 * length + 2);
          buffer[0] = "0";
          buffer[1] = "x";
          for (uint256 i = 2 * length + 1; i > 1; --i) {
              buffer[i] = _SYMBOLS[value & 0xf];
              value >>= 4;
          }
          require(value == 0, "Strings: hex length insufficient");
          return string(buffer);
      }
  
      function toHexString(address addr) internal pure returns (string memory) {
          return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);
      }
  
      function equal(string memory a, string memory b) internal pure returns (bool) {
          return keccak256(bytes(a)) == keccak256(bytes(b));
      }
  }
  
  abstract contract AccessControl is Context, IAccessControl, ERC165 {
      struct RoleData {
          mapping(address => bool) members;
          bytes32 adminRole;
      }
  
      mapping(bytes32 => RoleData) private _roles;
  
      bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;
  
      modifier onlyRole(bytes32 role) {
          _checkRole(role);
          _;
      }
  
      function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
          return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);
      }
  
      function hasRole(bytes32 role, address account) public view virtual override returns (bool) {
          return _roles[role].members[account];
      }
  
      function _checkRole(bytes32 role) internal view virtual {
          _checkRole(role, _msgSender());
      }
  
      function _checkRole(bytes32 role, address account) internal view virtual {
          if (!hasRole(role, account)) {
              revert(
                  string(
                      abi.encodePacked(
                          "AccessControl: account ",
                          Strings.toHexString(account),
                          " is missing role ",
                          Strings.toHexString(uint256(role), 32)
                      )
                  )
              );
          }
      }
  
      function getRoleAdmin(bytes32 role) public view virtual override returns (bytes32) {
          return _roles[role].adminRole;
      }
  
      function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {
          _grantRole(role, account);
      }
  
      function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {
          _revokeRole(role, account);
      }
  
      function renounceRole(bytes32 role, address account) public virtual override {
          require(account == _msgSender(), "AccessControl: can only renounce roles for self");
  
          _revokeRole(role, account);
      }
  
      function _setupRole(bytes32 role, address account) internal virtual {
          _grantRole(role, account);
      }
  
      function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {
          bytes32 previousAdminRole = getRoleAdmin(role);
          _roles[role].adminRole = adminRole;
          emit RoleAdminChanged(role, previousAdminRole, adminRole);
      }
  
      function _grantRole(bytes32 role, address account) internal virtual {
          if (!hasRole(role, account)) {
              _roles[role].members[account] = true;
              emit RoleGranted(role, account, _msgSender());
          }
      }
  
      function _revokeRole(bytes32 role, address account) internal virtual {
          if (hasRole(role, account)) {
              _roles[role].members[account] = false;
              emit RoleRevoked(role, account, _msgSender());
          }
      }
  }
  
  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);
      }
  }
  
  interface ILpPair {
      function sync() external;
  }
  
  interface IDexRouter {
      function factory() external pure returns (address);
  
      function WETH() external pure returns (address);
  
      function swapExactTokensForETHSupportingFeeOnTransferTokens(
          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 addLiquidityETH(
          address token,
          uint256 amountTokenDesired,
          uint256 amountTokenMin,
          uint256 amountETHMin,
          address to,
          uint256 deadline
      )
          external
          payable
          returns (uint256 amountToken, uint256 amountETH, uint256 liquidity);
  
      function getAmountsOut(
          uint256 amountIn,
          address[] calldata path
      ) external view returns (uint256[] memory amounts);
  
      function removeLiquidityETH(
          address token,
          uint256 liquidity,
          uint256 amountTokenMin,
          uint256 amountETHMin,
          address to,
          uint256 deadline
      ) external returns (uint256 amountToken, uint256 amountETH);
  }
  
  interface IDexFactory {
      function createPair(
          address tokenA,
          address tokenB
      ) external returns (address pair);
  }
  
  contract ATESTTOKEN is ERC20, AccessControl {
      uint256 public maxBuyAmount;
      uint256 public maxSellAmount;
      uint256 public maxWallet;
  
      IDexRouter public dexRouter;
      address public lpPair;
  
      bool private swapping;
      uint256 public swapTokensAtAmount;
      address public operationsAddress;
  
      uint256 public tradingActiveBlock = 0;
      mapping(address => bool) public markedAsSniper;
  
      bytes32 public constant MANAGER_ROLE = keccak256("MANAGER_ROLE");
      bytes32 public constant AUTHENTICATOR_ROLE =
          keccak256("AUTHENTICATOR_ROLE");    
  
      bool public limitsInEffect = true;
      bool public tradingActive = false;
      bool public swapEnabled = false;
      bool public flagSnipersEnabled = true;
  
      mapping(address => uint256) private _holderLastTransferTimestamp;
      bool public transferDelayEnabled = true;
  
      uint256 public buyTotalFees;
      uint256 public buyOperationsFee;
      uint256 public buyLiquidityFee;
  
      uint256 public sellTotalFees;
      uint256 public sellOperationsFee;
      uint256 public sellLiquidityFee;
  
      uint256 public tokensForOperations;
      uint256 public tokensForLiquidity;
  
      mapping(address => bool) private _isExcludedFromFees;
      mapping(address => bool) public _isExcludedMaxTransactionAmount;
      mapping(address => bool) public automatedMarketMakerPairs;
  
      event SetAutomatedMarketMakerPair(address indexed pair, bool indexed value);
  
      event EnabledTrading();
  
      event ExcludeFromFees(address indexed account, bool isExcluded);
  
      event UpdatedOperationsAddress(address indexed newWallet);
  
      event MaxTransactionExclusion(address _address, bool excluded);
  
      event OwnerForcedSwapBack(uint256 timestamp);
  
      event CaughtEarlyBuyer(address sniper);
  
      event SwapAndLiquify(
          uint256 tokensSwapped,
          uint256 ethReceived,
          uint256 tokensIntoLiquidity
      );
  
      event TransferForeignToken(address token, uint256 amount);
  
      // Modifiers
      modifier onlyManager() {
          require(hasRole(MANAGER_ROLE, msg.sender), "Not a manager");
          _;
      }
  
      modifier onlyAuthenticators() {
          require(
              hasRole(AUTHENTICATOR_ROLE, msg.sender),
              "Not an authenticator"
          );
          _;
      }
  
      constructor() payable ERC20("ATEST2", "ATEST2") {
          address newOwner = msg.sender;  
  
          _setupRole(MANAGER_ROLE, newOwner); // Assign the manager role to the contract deployer
          _setRoleAdmin(AUTHENTICATOR_ROLE, MANAGER_ROLE); // Assign manager as the administrator of the authenticator role
          grantRole(AUTHENTICATOR_ROLE, newOwner); // Grant the authenticator role to the contract deployer
  
          uint256 totalSupply = 100 * 1e6 * 1e18; 
  
          buyOperationsFee = 10;
          buyLiquidityFee = 0;
          buyTotalFees = buyOperationsFee + buyLiquidityFee;
  
          sellOperationsFee = 20;
          sellLiquidityFee = 0;
          sellTotalFees = sellOperationsFee + sellLiquidityFee;        
  
          maxBuyAmount = (totalSupply * 1) / 100; // 1%
          maxSellAmount = (totalSupply * 1) / 100; // 1%
          maxWallet = (totalSupply * 1) / 100; // 1%
          swapTokensAtAmount = (totalSupply * 5) / 10000; // 0.05 %
  
          operationsAddress = address(msg.sender);
  
          _excludeFromMaxTransaction(newOwner, true);
          _excludeFromMaxTransaction(address(this), true);
          _excludeFromMaxTransaction(address(0xdead), true);
          _excludeFromMaxTransaction(address(operationsAddress), true);
  
          excludeFromFees(newOwner, true);
          excludeFromFees(address(this), true);
          excludeFromFees(address(0xdead), true);
          excludeFromFees(address(operationsAddress), true);
  
          _createInitialSupply(address(this), totalSupply);     
      }
  
      receive() external payable {}
  
      function addAuthenticator(address _authenticator) external onlyManager {
          require(_authenticator != address(0), "Invalid address");
          grantRole(AUTHENTICATOR_ROLE, _authenticator);
      }
  
      function removeAuthenticator(address _authenticator) external onlyManager {
          require(_authenticator != address(0), "Invalid address");
          revokeRole(AUTHENTICATOR_ROLE, _authenticator);
      }    
  
      // disable Transfer delay - cannot be reenabled
      function disableTransferDelay() external onlyManager {
          transferDelayEnabled = false;
      }
  
      function _excludeFromMaxTransaction(
          address updAds,
          bool isExcluded
      ) private {
          _isExcludedMaxTransactionAmount[updAds] = isExcluded;
          emit MaxTransactionExclusion(updAds, isExcluded);
      }
  
      function excludeFromMaxTransaction(
          address updAds,
          bool isEx
      ) external onlyManager {
          if (!isEx) {
              require(
                  updAds != lpPair,
                  "Cannot remove uniswap pair from max txn"
              );
          }
          _isExcludedMaxTransactionAmount[updAds] = isEx;
      }
  
      function _setAutomatedMarketMakerPair(address pair, bool value) private {
          automatedMarketMakerPairs[pair] = value;
          _excludeFromMaxTransaction(pair, value);
          emit SetAutomatedMarketMakerPair(pair, value);
      }
  
      function setAutomatedMarketMakerPair(
          address pair,
          bool value
      ) external onlyManager {
          require(
              pair != lpPair,
              "The pair cannot be removed from automatedMarketMakerPairs"
          );
          _setAutomatedMarketMakerPair(pair, value);
          emit SetAutomatedMarketMakerPair(pair, value);
      }        
  
      function updateBuyTax(
          uint256 _operationsFee,
          uint256 _liquidityFee
      ) external onlyManager {
          buyOperationsFee = _operationsFee;
          buyLiquidityFee = _liquidityFee;
          buyTotalFees = buyOperationsFee + buyLiquidityFee;
          require(buyTotalFees <= 10, "Must keep fees at 10% or less");
      }
  
      function updateSellTax(
          uint256 _operationsFee,
          uint256 _liquidityFee
      ) external onlyManager {
          sellOperationsFee = _operationsFee;
          sellLiquidityFee = _liquidityFee;
          sellTotalFees = sellOperationsFee + sellLiquidityFee;
          require(sellTotalFees <= 10, "Must keep fees at 10% or less");
      }    
  
      function excludeFromFees(address account, bool excluded) public onlyManager {
          _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 (!tradingActive) {
              require(
                  _isExcludedFromFees[from] || _isExcludedFromFees[to],
                  "Trading is not active."
              );
          } else {
              require(
                  !markedAsSniper[from],
                  "Snipers cannot transfer tokens"
              );
          }
  
          if (limitsInEffect) {
              if (to != address(0xdead) &&
                  !_isExcludedFromFees[from] &&
                  !_isExcludedFromFees[to]
              ) {
                  if (transferDelayEnabled) {
                      if (to != address(dexRouter) && to != address(lpPair)) {
                          require(
                              _holderLastTransferTimestamp[tx.origin] <
                                  block.number - 2 &&
                                  _holderLastTransferTimestamp[to] <
                                  block.number - 2,
                              "_transfer:: Transfer Delay enabled.  Try again later."
                          );
                          _holderLastTransferTimestamp[tx.origin] = block.number;
                          _holderLastTransferTimestamp[to] = block.number;
                      }
                  }
  
                  //when buy
                  if (
                      automatedMarketMakerPairs[from] &&
                      !_isExcludedMaxTransactionAmount[to]
                  ) {
                      require(
                          amount <= maxBuyAmount,
                          "Buy transfer amount exceeds the max buy."
                      );
                      require(
                          amount + balanceOf(to) <= maxWallet,
                          "Max Wallet Exceeded"
                      );
                  }
                  //when sell
                  else if (
                      automatedMarketMakerPairs[to] &&
                      !_isExcludedMaxTransactionAmount[from]
                  ) {
                      require(
                          amount <= maxSellAmount,
                          "Sell transfer amount exceeds the max sell."
                      );
                  } 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[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 buys/sells, do not take on wallet transfers
          if (takeFee) {    
              // on sell
              if (automatedMarketMakerPairs[to] && sellTotalFees > 0) {
                  fees = (amount * sellTotalFees) / 100;
                  tokensForLiquidity += (fees * sellLiquidityFee) / sellTotalFees;
                  tokensForOperations +=
                      (fees * sellOperationsFee) /
                      sellTotalFees;
              }
              // on buy
              else if (automatedMarketMakerPairs[from] && buyTotalFees > 0) {
                  fees = (amount * buyTotalFees) / 100;
                  tokensForLiquidity += (fees * buyLiquidityFee) / buyTotalFees;
                  tokensForOperations += (fees * buyOperationsFee) / 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] = dexRouter.WETH();
  
          _approve(address(this), address(dexRouter), tokenAmount);
  
          // make the swap
          dexRouter.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(dexRouter), tokenAmount);
  
          // add the liquidity
          dexRouter.addLiquidityETH{value: ethAmount}(
              address(this),
              tokenAmount,
              0, // slippage is unavoidable
              0, // slippage is unavoidable
              address(0xdead),
              block.timestamp
          );
      }
  
      function swapBack() private {
          uint256 contractBalance = balanceOf(address(this));
          uint256 totalTokensToSwap = tokensForLiquidity + tokensForOperations;
  
          if (contractBalance == 0 || totalTokensToSwap == 0) {
              return;
          }
  
          if (contractBalance > swapTokensAtAmount * 15) {
              contractBalance = swapTokensAtAmount * 15;
          }
  
          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 ethForOperations = (ethBalance * tokensForOperations) /
              (totalTokensToSwap - (tokensForLiquidity / 2));
  
          ethForLiquidity -= ethForOperations;
  
          tokensForLiquidity = 0;
          tokensForOperations = 0;
  
          if (liquidityTokens > 0 && ethForLiquidity > 0) {
              addLiquidity(liquidityTokens, ethForLiquidity);
          }
  
          (success, ) = address(operationsAddress).call{
              value: address(this).balance
          }("");
      }
  
      function transferForeignToken(
          address _token,
          address _to
      ) external onlyManager returns (bool _sent) {
          require(_token != address(0), "_token address cannot be 0");
          require(
              _token != address(this) || !tradingActive,
              "Can't withdraw native tokens while trading is active"
          );
          uint256 _contractBalance = IERC20(_token).balanceOf(address(this));
          _sent = IERC20(_token).transfer(_to, _contractBalance);
          emit TransferForeignToken(_token, _contractBalance);
      }
  
      function setOperationsAddress(
          address _operationsAddress
      ) external onlyManager {
          require(
              _operationsAddress != address(0),
              "_operationsAddress address cannot be 0"
          );
          operationsAddress = payable(_operationsAddress);
          emit UpdatedOperationsAddress(_operationsAddress);
      }
  
      function removeLimits() external onlyManager {
          limitsInEffect = false;
      }
  
      function restoreLimits() external onlyManager { 
          limitsInEffect = true;
      }
  
      function flagSniper(address wallet) external onlyAuthenticators {
          require(
              flagSnipersEnabled,
              "Flag sniper functionality disabled forever!"
          );
  
          require(!markedAsSniper[wallet], "Wallet is already flagged.");
          markedAsSniper[wallet] = true;
      }
  
      function massFlagSnipers(address[] calldata wallets)
          external onlyAuthenticators
      {
          require(
              flagSnipersEnabled,
              "Flag sniper functionality disabled forever!"
          );        
  
          for (uint256 i = 0; i < wallets.length; i++) {
              markedAsSniper[wallets[i]] = true;
          }
      }
  
      function unflagSniper(address wallet) external onlyAuthenticators {
          require(markedAsSniper[wallet], "Wallet is already not marked.");
          markedAsSniper[wallet] = false;
      }        
  
      function massUnflagSnipers(address[] calldata wallets)
          external onlyAuthenticators
      {
          for (uint256 i = 0; i < wallets.length; i++) {
              markedAsSniper[wallets[i]] = false;
          }
      }    
  
      function disableFlagSnipersForever() external onlyManager {
          require(
              flagSnipersEnabled,
              "Flag sniper functionality already disabled forever!!"
          );
  
          flagSnipersEnabled = false;
      }    
  
      function emergencyETHRecovery() external onlyManager {
          bool success;
          (success, ) = address(msg.sender).call{value: address(this).balance}(
              ""
          );
      }      
  
      function prepareLaunch() external onlyManager {
          require(!tradingActive, "Trading is already active, cannot relaunch.");     
  
          address _dexRouter;
  
          if (block.chainid == 1) {
              _dexRouter = 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D; // ETH: Uniswap V2
          } else if (block.chainid == 11155111) {
              _dexRouter = 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D; // ETH: Sepolia
          } else if (block.chainid == 56) {
              _dexRouter = 0x10ED43C718714eb63d5aA57B78B54704E256024E; // BNB Chain: PCS V2
          } else if (block.chainid == 97) {
              _dexRouter = 0xD99D1c33F9fC3444f8101754aBC46c52416550D1; // BNB Chain: PCS V2
          } else if (block.chainid == 42161) {
              _dexRouter = 0x1b02dA8Cb0d097eB8D57A175b88c7D8b47997506; // Arbitrum: SushiSwap
          } else {
              revert("Chain not configured");
          }
  
          // initialize router
          dexRouter = IDexRouter(_dexRouter);
          
          // create pair
          lpPair = IDexFactory(dexRouter.factory()).createPair(
              address(this),
              dexRouter.WETH()
          );
  
          _excludeFromMaxTransaction(address(lpPair), true);
          _setAutomatedMarketMakerPair(address(lpPair), true);        
  
          _excludeFromMaxTransaction(address(dexRouter), true);
          excludeFromFees(address(dexRouter), true);  
  
          require(
              address(this).balance > 0,
              "Must have ETH on contract to launch"
          );
          require(
              balanceOf(address(this)) > 0,
              "Must have Tokens on contract to launch"
          );           
  
          _approve(address(this), address(dexRouter), balanceOf(address(this)));
  
          dexRouter.addLiquidityETH{value: address(this).balance}(
              address(this),
              balanceOf(address(this)),
              0, // slippage is unavoidable
              0, // slippage is unavoidable
              msg.sender,
              block.timestamp
          ); 
      }
  
      function enableTrading() external onlyAuthenticators {
          require(!tradingActive, "Cannot reenable trading");
          tradingActive = true;
          swapEnabled = true;
          tradingActiveBlock = block.number;
          emit EnabledTrading();
      }      
  }