ETH Price: $2,487.68 (+1.24%)
Gas: 1.24 Gwei

Transaction Decoder

Block:
21092414 at Nov-01-2024 11:11:35 AM +UTC
Transaction Fee:
0.002902279876548975 ETH $7.22
Gas Used:
496,275 Gas / 5.848128309 Gwei

Emitted Events:

231 ZAIBOT.Transfer( from=[Receiver] TransparentUpgradeableProxy, to=0xecbF1b7241020227b1f6E23787B753eea5ba3e8a, value=45237681700000000000000 )

Account State Difference:

  Address   Before After State Difference Code
(Titan Builder)
9.809923844176920944 Eth9.809975157014414069 Eth0.000051312837493125
0x5880a0E3...8Ffc9c532
0x68449870...21Fd8F101
0xA4868098...96BEa690c
0.370884215309546321 Eth
Nonce: 14
0.367981935432997346 Eth
Nonce: 15
0.002902279876548975

Execution Trace

TransparentUpgradeableProxy.e3ec5351( )
  • 0xe1823c5a85e8d5ed385fb25cc70781ee4195bcf7.e3ec5351( )
    • ZAIBOT.transfer( recipient=0xecbF1b7241020227b1f6E23787B753eea5ba3e8a, amount=45237681700000000000000 ) => ( True )
      File 1 of 2: TransparentUpgradeableProxy
      pragma solidity ^0.6.12;
      
      /**
       * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM
       * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to
       * be specified by overriding the virtual {_implementation} function.
       * 
       * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a
       * different contract through the {_delegate} function.
       * 
       * The success and return data of the delegated call will be returned back to the caller of the proxy.
       */
      abstract contract Proxy {
          /**
           * @dev Delegates the current call to `implementation`.
           * 
           * This function does not return to its internall call site, it will return directly to the external caller.
           */
          function _delegate(address implementation) internal {
              // solhint-disable-next-line no-inline-assembly
              assembly {
                  // Copy msg.data. We take full control of memory in this inline assembly
                  // block because it will not return to Solidity code. We overwrite the
                  // Solidity scratch pad at memory position 0.
                  calldatacopy(0, 0, calldatasize())
      
                  // Call the implementation.
                  // out and outsize are 0 because we don't know the size yet.
                  let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)
      
                  // Copy the returned data.
                  returndatacopy(0, 0, returndatasize())
      
                  switch result
                  // delegatecall returns 0 on error.
                  case 0 { revert(0, returndatasize()) }
                  default { return(0, returndatasize()) }
              }
          }
      
          /**
           * @dev This is a virtual function that should be overriden so it returns the address to which the fallback function
           * and {_fallback} should delegate.
           */
          function _implementation() internal virtual view returns (address);
      
          /**
           * @dev Delegates the current call to the address returned by `_implementation()`.
           * 
           * This function does not return to its internall call site, it will return directly to the external caller.
           */
          function _fallback() internal {
              _delegate(_implementation());
          }
      
          /**
           * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other
           * function in the contract matches the call data.
           */
          fallback () payable external {
              _delegate(_implementation());
          }
      
          /**
           * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if call data
           * is empty.
           */
          receive () payable external {
              _delegate(_implementation());
          }
      }
      
      /**
       * @dev This contract implements an upgradeable proxy. It is upgradeable because calls are delegated to an
       * implementation address that can be changed. This address is stored in storage in the location specified by
       * https://eips.ethereum.org/EIPS/eip-1967[EIP1967], so that it doesn't conflict with the storage layout of the
       * implementation behind the proxy.
       * 
       * Upgradeability is only provided internally through {_upgradeTo}. For an externally upgradeable proxy see
       * {TransparentUpgradeableProxy}.
       */
      contract UpgradeableProxy is Proxy {
          /**
           * @dev Initializes the upgradeable proxy with an initial implementation specified by `_logic`.
           * 
           * If `_data` is nonempty, it's used as data in a delegate call to `_logic`. This will typically be an encoded
           * function call, and allows initializating the storage of the proxy like a Solidity constructor.
           */
          constructor() public payable {
              assert(_IMPLEMENTATION_SLOT == bytes32(uint256(keccak256("eip1967.proxy.implementation")) - 1));
          }
      
          /**
           * @dev Emitted when the implementation is upgraded.
           */
          event Upgraded(address indexed implementation);
      
          /**
           * @dev Storage slot with the address of the current implementation.
           * This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1, and is
           * validated in the constructor.
           */
          bytes32 private constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
      
          /**
           * @dev Returns the current implementation address.
           */
          function _implementation() internal override view returns (address impl) {
              bytes32 slot = _IMPLEMENTATION_SLOT;
              // solhint-disable-next-line no-inline-assembly
              assembly {
                  impl := sload(slot)
              }
          }
      
          /**
           * @dev Upgrades the proxy to a new implementation.
           * 
           * Emits an {Upgraded} event.
           */
          function _upgradeTo(address newImplementation) virtual internal {
              _setImplementation(newImplementation);
              emit Upgraded(newImplementation);
          }
      
          /**
           * @dev Stores a new address in the EIP1967 implementation slot.
           */
          function _setImplementation(address newImplementation) private {
              address implementation = _implementation();
              require(implementation != newImplementation, "Proxy: Attemps update proxy with the same implementation");
      
              bytes32 slot = _IMPLEMENTATION_SLOT;
      
              // solhint-disable-next-line no-inline-assembly
              assembly {
                  sstore(slot, newImplementation)
              }
          }
      }
      
      /**
       * @dev This contract implements a proxy that is upgradeable by an admin.
       * 
       * To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector
       * clashing], which can potentially be used in an attack, this contract uses the
       * https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two
       * things that go hand in hand:
       * 
       * 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if
       * that call matches one of the admin functions exposed by the proxy itself.
       * 2. If the admin calls the proxy, it can access the admin functions, but its calls will never be forwarded to the
       * implementation. If the admin tries to call a function on the implementation it will fail with an error that says
       * "admin cannot fallback to proxy target".
       * 
       * These properties mean that the admin account can only be used for admin actions like upgrading the proxy or changing
       * the admin, so it's best if it's a dedicated account that is not used for anything else. This will avoid headaches due
       * to sudden errors when trying to call a function from the proxy implementation.
       * 
       * Our recommendation is for the dedicated account to be an instance of the {ProxyAdmin} contract. If set up this way,
       * you should think of the `ProxyAdmin` instance as the real administrative inerface of your proxy.
       */
      contract TransparentUpgradeableProxy is UpgradeableProxy {
          /**
           * @dev Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and
           * optionally initialized with `_data` as explained in {UpgradeableProxy-constructor}.
           */
          constructor(address admin, address implementation) public payable UpgradeableProxy() {
              require(_ADMIN_SLOT == bytes32(uint256(keccak256("eip1967.proxy.admin")) - 1), "Wrong admin slot");
              _setAdmin(admin);
              _upgradeTo(implementation);
          }
      
          /**
           * @dev Emitted when the admin account has changed.
           */
          event AdminChanged(address previousAdmin, address newAdmin);
      
          /**
           * @dev Storage slot with the admin of the contract.
           * This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1, and is
           * validated in the constructor.
           */
          bytes32 private constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;
      
          /**
           * @dev Modifier used internally that will delegate the call to the implementation unless the sender is the admin.
           */
          modifier ifAdmin() {
              if (msg.sender == _admin()) {
                  _;
              } else {
                  _fallback();
              }
          }
      
          /**
           * @dev Returns the current admin.
           * 
           * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyAdmin}.
           * 
           * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the
           * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.
           * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`
           */
          function admin() external ifAdmin returns (address) {
              return _admin();
          }
      
          /**
           * @dev Returns the current implementation.
           * 
           * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyImplementation}.
           * 
           * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the
           * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.
           * `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`
           */
          function implementation() external ifAdmin returns (address) {
              return _implementation();
          }
      
          /**
           * @dev Changes the admin of the proxy.
           * 
           * Emits an {AdminChanged} event.
           * 
           * NOTE: Only the admin can call this function. See {ProxyAdmin-changeProxyAdmin}.
           */
          function changeAdmin(address newAdmin) external ifAdmin {
              require(newAdmin != _admin(), "Proxy: new admin is the same admin.");
              emit AdminChanged(_admin(), newAdmin);
              _setAdmin(newAdmin);
          }
      
          /**
           * @dev Upgrade the implementation of the proxy.
           * 
           * NOTE: Only the admin can call this function. See {ProxyAdmin-upgrade}.
           */
          function upgradeTo(address newImplementation) external ifAdmin {
              _upgradeTo(newImplementation);
          }
      
          /**
           * @dev Upgrade the implementation of the proxy, and then call a function from the new implementation as specified
           * by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the
           * proxied contract.
           * 
           * NOTE: Only the admin can call this function. See {ProxyAdmin-upgradeAndCall}.
           */
          function upgradeToAndCall(address newImplementation, bytes calldata data) external payable ifAdmin {
              _upgradeTo(newImplementation);
              // solhint-disable-next-line avoid-low-level-calls
              (bool success,) = newImplementation.delegatecall(data);
              require(success);
          }
      
          /**
           * @dev Returns the current admin.
           */
          function _admin() internal view returns (address adm) {
              bytes32 slot = _ADMIN_SLOT;
              // solhint-disable-next-line no-inline-assembly
              assembly {
                  adm := sload(slot)
              }
          }
      
          /**
           * @dev Stores a new address in the EIP1967 admin slot.
           */
          function _setAdmin(address newAdmin) private {
              bytes32 slot = _ADMIN_SLOT;
              require(newAdmin != address(0), "Proxy: Can't set admin to zero address.");
      
              // solhint-disable-next-line no-inline-assembly
              assembly {
                  sstore(slot, newAdmin)
              }
          }
      }

      File 2 of 2: ZAIBOT
      // SPDX-License-Identifier: MIT
      
      pragma solidity 0.8.19;
      
      /**
      
      THE VANGUARD OF AI BOTS.
      
      Website: https://zaibot.io/
      Twitter: https://x.com/zaibotio/      
      Public Chat: https://t.me/zaibotpublic
      Announcement channel: https://t.me/zaibotann
      
      **/
      
      /**
       * @dev Wrappers over Solidity's arithmetic operations with added overflow
       * checks.
       *
       * Arithmetic operations in Solidity wrap on overflow. This can easily result
       * in bugs, because programmers usually assume that an overflow raises an
       * error, which is the standard behavior in high level programming languages.
       * `SafeMath` restores this intuition by reverting the transaction when an
       * operation overflows.
       *
       * Using this library instead of the unchecked operations eliminates an entire
       * class of bugs, so it's recommended to use it always.
       */
      library SafeMath {
        /**
         * @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) {
          uint256 c = a + b;
          require(c >= a, "SafeMath: addition overflow");
      
          return c;
        }
      
        /**
         * @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 sub(a, b, "SafeMath: subtraction overflow");
        }
      
        /**
         * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
         * overflow (when the result is negative).
         *
         * Counterpart to Solidity's `-` operator.
         *
         * Requirements:
         * - Subtraction cannot overflow.
         */
        function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
          require(b <= a, errorMessage);
          uint256 c = a - b;
      
          return c;
        }
      
        /**
         * @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) {
          // 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 0;
          }
      
          uint256 c = a * b;
          require(c / a == b, "SafeMath: multiplication overflow");
      
          return c;
        }
      
        /**
         * @dev Returns the integer division of two unsigned integers. Reverts 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) internal pure returns (uint256) {
          return div(a, b, "SafeMath: division by zero");
        }
      
        /**
         * @dev Returns the integer division of two unsigned integers. Reverts 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) {
          // Solidity only automatically asserts when dividing by 0
          require(b > 0, errorMessage);
          uint256 c = a / b;
          // assert(a == b * c + a % b); // There is no case in which this doesn't hold
      
          return c;
        }
      
        /**
         * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
         * Reverts 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 mod(a, b, "SafeMath: modulo by zero");
        }
      
        /**
         * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
         * Reverts with custom message 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, string memory errorMessage) internal pure returns (uint256) {
          require(b != 0, errorMessage);
          return a % b;
        }
      }
      
      interface IERC20 {
          function totalSupply() external view returns (uint256);
          function decimals() external view returns (uint8);
          function symbol() external view returns (string memory);
          function name() external view returns (string memory);
          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 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);
      }
      
      
      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;
      }
      
      /*
       * @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) {
              this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
              return msg.data;
          }
      }
      
      // File: @openzeppelin/contracts/access/Ownable.sol
      
      /**
       * @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 () {
              address msgSender = _msgSender();
              _owner = msgSender;
              emit OwnershipTransferred(address(0), 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");
              _;
          }
      
          /**
           * @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 {
              emit OwnershipTransferred(_owner, address(0));
              _owner = 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");
              emit OwnershipTransferred(_owner, newOwner);
              _owner = newOwner;
          }
      }
      
      
      contract LGEWhitelisted is Context {
          struct WhitelistRound {
              uint256 duration;
              uint256 amountMax;
              mapping(address => bool) addresses;
              mapping(address => uint256) purchased;
          }
      
          WhitelistRound[] public _lgeWhitelistRounds;
      
          uint256 public _lgeTimestamp;
          address public _lgePairAddress;
      
          address public _whitelister;
      
          event WhitelisterTransferred(address indexed previousWhitelister, address indexed newWhitelister);
      
          constructor() {
              _whitelister = _msgSender();
          }
      
          modifier onlyWhitelister() {
              require(_whitelister == _msgSender(), "Caller is not the whitelister");
              _;
          }
      
          function renounceWhitelister() external onlyWhitelister {
              emit WhitelisterTransferred(_whitelister, address(0));
              _whitelister = address(0);
          }
      
          function transferWhitelister(address newWhitelister) external onlyWhitelister {
              _transferWhitelister(newWhitelister);
          }
      
          function _transferWhitelister(address newWhitelister) internal {
              require(newWhitelister != address(0), "New whitelister is the zero address");
              emit WhitelisterTransferred(_whitelister, newWhitelister);
              _whitelister = newWhitelister;
          }
      
          /*
           * createLGEWhitelist - Call this after initial Token Generation Event (TGE)
           *
           * pairAddress - address generated from createPair() event on DEX
           * durations - array of durations (seconds) for each whitelist rounds
           * amountsMax - array of max amounts (TOKEN decimals) for each whitelist round
           *
           */
      
          function createLGEWhitelist(
              address pairAddress,
              uint256[] calldata durations,
              uint256[] calldata amountsMax
          ) external onlyWhitelister() {
              require(durations.length == amountsMax.length, "Invalid whitelist(s)");
      
              _lgePairAddress = pairAddress;
      
              if (durations.length > 0) {
                  delete _lgeWhitelistRounds;
      
                  for (uint256 i = 0; i < durations.length; i++) {
                      WhitelistRound storage whitelistRound = _lgeWhitelistRounds.push();
                      whitelistRound.duration = durations[i];
                      whitelistRound.amountMax = amountsMax[i];
                  }
              }
          }
      
          /*
           * modifyLGEWhitelistAddresses - Define what addresses are included/excluded from a whitelist round
           *
           * index - 0-based index of round to modify whitelist
           * duration - period in seconds from LGE event or previous whitelist round
           * amountMax - max amount (TOKEN decimals) for each whitelist round
           *
           */
      
          function modifyLGEWhitelist(
              uint256 index,
              uint256 duration,
              uint256 amountMax,
              address[] calldata addresses,
              bool enabled
          ) external onlyWhitelister() {
              require(index < _lgeWhitelistRounds.length, "Invalid index");
              require(amountMax > 0, "Invalid amountMax");
      
              if (duration != _lgeWhitelistRounds[index].duration) _lgeWhitelistRounds[index].duration = duration;
      
              if (amountMax != _lgeWhitelistRounds[index].amountMax) _lgeWhitelistRounds[index].amountMax = amountMax;
      
              for (uint256 i = 0; i < addresses.length; i++) {
                  _lgeWhitelistRounds[index].addresses[addresses[i]] = enabled;
              }
          }
      
          /*
           *  getLGEWhitelistRound
           *
           *  returns:
           *
           *  1. whitelist round number ( 0 = no active round now )
           *  2. duration, in seconds, current whitelist round is active for
           *  3. timestamp current whitelist round closes at
           *  4. maximum amount a whitelister can purchase in this round
           *  5. is caller whitelisted
           *  6. how much caller has purchased in current whitelist round
           *
           */
      
          function getLGEWhitelistRound()
              public
              view
              returns (
                  uint256,
                  uint256,
                  uint256,
                  uint256,
                  bool,
                  uint256
              )
          {
              if (_lgeTimestamp > 0) {
                  uint256 wlCloseTimestampLast = _lgeTimestamp;
      
                  for (uint256 i = 0; i < _lgeWhitelistRounds.length; i++) {
                      WhitelistRound storage wlRound = _lgeWhitelistRounds[i];
      
                      wlCloseTimestampLast = wlCloseTimestampLast + wlRound.duration;
                      if (block.timestamp <= wlCloseTimestampLast)
                          return (
                              i + 1,
                              wlRound.duration,
                              wlCloseTimestampLast,
                              wlRound.amountMax,
                              wlRound.addresses[_msgSender()],
                              wlRound.purchased[_msgSender()]
                          );
                  }
              }
      
              return (0, 0, 0, 0, false, 0);
          }
      
          /*
           * _applyLGEWhitelist - internal function to be called initially before any transfers
           *
           */
      
          function _applyLGEWhitelist(
              address sender,
              address recipient,
              uint256 amount
          ) internal {
              if (_lgePairAddress == address(0) || _lgeWhitelistRounds.length == 0) return;
      
              if (_lgeTimestamp == 0 && sender != _lgePairAddress && recipient == _lgePairAddress && amount > 0)
                  _lgeTimestamp = block.timestamp;
      
              if (sender == _lgePairAddress && recipient != _lgePairAddress) {
                  //buying
      
                  (uint256 wlRoundNumber, , , , , ) = getLGEWhitelistRound();
      
                  if (wlRoundNumber > 0) {
                      WhitelistRound storage wlRound = _lgeWhitelistRounds[wlRoundNumber - 1];
      
                      require(wlRound.addresses[recipient], "LGE - Buyer is not whitelisted");
      
                      uint256 amountRemaining = 0;
      
                      if (wlRound.purchased[recipient] < wlRound.amountMax)
                          amountRemaining = wlRound.amountMax - wlRound.purchased[recipient];
      
                      require(amount <= amountRemaining, "LGE - Amount exceeds whitelist maximum");
                      wlRound.purchased[recipient] = wlRound.purchased[recipient] + amount;
                  }
              }
          }
      }
      
      contract ZAIBOT is Context, IERC20, Ownable, LGEWhitelisted {
          
          using SafeMath for uint256;
          
          mapping (address => uint256) private _balances;
          
          mapping (address => mapping (address => uint256)) private _allowances;
          
          uint256 private _totalSupply;
          uint8 private _decimals;
          string private _symbol;
          string private _name;
      	
      	mapping(address => bool) public _feeExcluded;
      
      	uint256 public _feeBurnPct;
      	uint256 public _feeRewardPct;
      	
      	address public _feeRewardAddress;
      
      	mapping(address => bool) public _pair;
      	
      	address public _router;
      	
      	address[] public _feeRewardSwapPath;
          
          constructor(uint256 feeBurnPct, uint256 feeRewardPct, address feeRewardAddress, address router) {
      	
              _name = "ZAIBOT.io";
              _symbol = "ZAI";
              _decimals = 18;
              _totalSupply = 100000000e18;
      		
      		IUniswapV2Router02 r = IUniswapV2Router02(router);
              
              address[] memory feeRewardSwapPath = new address[](2);
                  
              feeRewardSwapPath[0] = address(this);
              feeRewardSwapPath[1] = r.WETH();
      		
      		setFees(feeBurnPct, feeRewardPct, feeRewardSwapPath, feeRewardAddress);
      		
      		_router = router;
      		
      		setFeeExcluded(_msgSender(), true);
      		setFeeExcluded(address(this), true);
      		
      		
              _balances[_msgSender()] = _totalSupply;
              emit Transfer(address(0), _msgSender(), _totalSupply);
          }
      	
      	function setRouter(address r) public onlyOwner {
              _router = r;
          }
      	
      	function setPair(address a, bool pair) public onlyOwner {
              _pair[a] = pair;
          }
      
      	function setFeeExcluded(address a, bool excluded) public onlyOwner {
              _feeExcluded[a] = excluded;
          }
          
          function setFees(uint256 feeBurnPct, uint256 feeRewardPct, address[] memory feeRewardSwapPath, address feeRewardAddress) public onlyOwner {
              require(feeBurnPct.add(feeRewardPct) <= 2500, "Fees must not total more than 100%");
              require(feeRewardSwapPath.length > 1, "Invalid path");
      		require(feeRewardAddress != address(0), "Fee reward address must not be zero address");
      		
      		_feeBurnPct = feeBurnPct;
      		_feeRewardPct = feeRewardPct;
      		_feeRewardSwapPath = feeRewardSwapPath;
      		_feeRewardAddress = feeRewardAddress;
      		
          }
      	
      	function burn(uint256 amount) external {
              _burn(_msgSender(), 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;
                  // Overflow not possible: amount <= accountBalance <= totalSupply.
                  _totalSupply -= amount;
              }
      
              emit Transfer(account, address(0), amount);
      
              _afterTokenTransfer(account, address(0), amount);
          }
          
          /**
          * @dev Returns the token decimals.
          */
          function decimals() external view override returns (uint8) {
              return _decimals;
          }
          
          /**
          * @dev Returns the token symbol.
          */
          function symbol() external view override returns (string memory) {
              return _symbol;
          }
          
          /**
          * @dev Returns the token name.
          */
          function name() external view override returns (string memory) {
              return _name;
          }
          
          /**
          * @dev See {ERC20-totalSupply}.
          */
          function totalSupply() external view override returns (uint256) {
              return _totalSupply;
          }
          
          /**
          * @dev See {ERC20-balanceOf}.
          */
          function balanceOf(address account) external view override returns (uint256) {
              return _balances[account];
          }
          
          /**
          * @dev See {ERC20-transfer}.
          *
          * Requirements:
          *
          * - `recipient` cannot be the zero address.
          * - the caller must have a balance of at least `amount`.
          */
          function transfer(address recipient, uint256 amount) external override returns (bool) {
              _transfer(_msgSender(), recipient, amount);
              return true;
          }
          
          /**
          * @dev See {ERC20-allowance}.
          */
          function allowance(address owner, address spender) external view override returns (uint256) {
              return _allowances[owner][spender];
          }
          
          /**
          * @dev See {ERC20-approve}.
          *
          * Requirements:
          *
          * - `spender` cannot be the zero address.
          */
          function approve(address spender, uint256 amount) external override returns (bool) {
              _approve(_msgSender(), spender, amount);
              return true;
          }
          
          /**
          * @dev See {ERC20-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) external override returns (bool) {
              _transfer(sender, recipient, amount);
              _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance"));
              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 {ERC20-approve}.
          *
          * Emits an {Approval} event indicating the updated allowance.
          *
          * Requirements:
          *
          * - `spender` cannot be the zero address.
          */
          function increaseAllowance(address spender, uint256 addedValue) external returns (bool) {
              _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(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 {ERC20-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) external returns (bool) {
              _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero"));
              return true;
          }
      	
          function _beforeTokenTransfer(address sender, address recipient, uint256 amount) internal {
      	
      		LGEWhitelisted._applyLGEWhitelist(sender, recipient, amount);
      		
          }
      
          function _afterTokenTransfer(address sender, address recipient, uint256 amount) internal {}
          
          /**
          * @dev Moves tokens `amount` from `sender` to `recipient`.
          *
          * This is 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 {
              require(sender != address(0), "ERC20: transfer from the zero address");
              require(recipient != address(0), "ERC20: transfer to the zero address");
              
              _beforeTokenTransfer(sender, recipient, amount);
      		
      		if(recipient == address(0x000000000000000000000000000000000000dEaD)) {
                  _burn(sender, amount);
                  return;
              }
              
              _balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance");
      		
      		if(_pair[recipient] && !_feeExcluded[sender]) {
      			
      			uint256 feeBurnAmount = 0;
      			
      			if(_feeBurnPct > 0) {
      			
      				feeBurnAmount = amount.mul(_feeBurnPct).div(10000);
      
      				_totalSupply = _totalSupply.sub(feeBurnAmount);
      				emit Transfer(sender, address(0), feeBurnAmount);
      				
      			}
      			
      			uint256 feeRewardAmount = 0;
      			
      			if(_feeRewardPct > 0 && _feeRewardAddress != address(0))  {
      			    
      				feeRewardAmount = amount.mul(_feeRewardPct).div(10000);
      				
      				if(_router != address(0)) {
      				    
          				_balances[address(this)] = _balances[address(this)].add(feeRewardAmount);
          				
          				emit Transfer(sender, address(this), feeRewardAmount);
          				
          				IUniswapV2Router02 r = IUniswapV2Router02(_router);
                          
                          _approve(address(this), _router, feeRewardAmount);
          
                          r.swapExactTokensForTokensSupportingFeeOnTransferTokens(
                              feeRewardAmount,
                              0,
                              _feeRewardSwapPath,
                              _feeRewardAddress,
                              block.timestamp
                          );
                      
      				} else {
      				    _balances[_feeRewardAddress] = _balances[_feeRewardAddress].add(feeRewardAmount);
      				    emit Transfer(sender, _feeRewardAddress, feeRewardAmount);
      				}
      				
      			}
      			
      			amount = amount.sub(feeBurnAmount).sub(feeRewardAmount);
      			
      		}
      		
              _balances[recipient] = _balances[recipient].add(amount);
              emit Transfer(sender, recipient, amount);
      		
      		_afterTokenTransfer(sender, recipient, amount);
          }
          
          /**
          * @dev Sets `amount` as the allowance of `spender` over the `owner`s tokens.
          *
          * This is 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 {
              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);
          }
          
      }