ETH Price: $2,479.65 (+1.76%)

Transaction Decoder

Block:
20404414 at Jul-28-2024 10:21:23 AM +UTC
Transaction Fee:
0.00022313972947581 ETH $0.55
Gas Used:
101,331 Gas / 2.20208751 Gwei

Emitted Events:

362 OE.Transfer( from=[Receiver] Vesting, to=[Sender] 0xb42ccf5488e28b08a64c9316a1d8282843a07223, value=783333333333333333334 )
363 Vesting.Claim( account=[Sender] 0xb42ccf5488e28b08a64c9316a1d8282843a07223, amount=783333333333333333334 )

Account State Difference:

  Address   Before After State Difference Code
0x22b5b518...359E754cb
(Titan Builder)
9.921667152502014992 Eth9.921730295450330711 Eth0.000063142948315719
0x615c4e92...26AF9768f
0xb42cCF54...843A07223
0.008803034662198624 Eth
Nonce: 95
0.008579894932722814 Eth
Nonce: 96
0.00022313972947581

Execution Trace

Vesting.claim( )
  • OE.transfer( recipient=0xb42cCF5488E28b08A64c9316A1d8282843A07223, amount=783333333333333333334 ) => ( True )
    • PRIZEPOOL.deleteBuyer( buyerAddress=0x22b5b51834Bf3417ADE217cD798E40E359E754cb )
      File 1 of 3: Vesting
      // SPDX-License-Identifier: UNLICENSED
      pragma solidity 0.8.17;
      
      // OpenZeppelin Contracts (last updated v4.9.2) (utils/cryptography/MerkleProof.sol)
      
      /**
       * @dev These functions deal with verification of Merkle Tree proofs.
       *
       * The tree and the proofs can be generated using our
       * https://github.com/OpenZeppelin/merkle-tree[JavaScript library].
       * You will find a quickstart guide in the readme.
       *
       * WARNING: You should avoid using leaf values that are 64 bytes long prior to
       * hashing, or use a hash function other than keccak256 for hashing leaves.
       * This is because the concatenation of a sorted pair of internal nodes in
       * the merkle tree could be reinterpreted as a leaf value.
       * OpenZeppelin's JavaScript library generates merkle trees that are safe
       * against this attack out of the box.
       */
      library MerkleProof {
          /**
           * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree
           * defined by `root`. For this, a `proof` must be provided, containing
           * sibling hashes on the branch from the leaf to the root of the tree. Each
           * pair of leaves and each pair of pre-images are assumed to be sorted.
           */
          function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {
              return processProof(proof, leaf) == root;
          }
      
          /**
           * @dev Calldata version of {verify}
           *
           * _Available since v4.7._
           */
          function verifyCalldata(bytes32[] calldata proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {
              return processProofCalldata(proof, leaf) == root;
          }
      
          /**
           * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up
           * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt
           * hash matches the root of the tree. When processing the proof, the pairs
           * of leafs & pre-images are assumed to be sorted.
           *
           * _Available since v4.4._
           */
          function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {
              bytes32 computedHash = leaf;
              for (uint256 i = 0; i < proof.length; i++) {
                  computedHash = _hashPair(computedHash, proof[i]);
              }
              return computedHash;
          }
      
          /**
           * @dev Calldata version of {processProof}
           *
           * _Available since v4.7._
           */
          function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) {
              bytes32 computedHash = leaf;
              for (uint256 i = 0; i < proof.length; i++) {
                  computedHash = _hashPair(computedHash, proof[i]);
              }
              return computedHash;
          }
      
          /**
           * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a merkle tree defined by
           * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}.
           *
           * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.
           *
           * _Available since v4.7._
           */
          function multiProofVerify(
              bytes32[] memory proof,
              bool[] memory proofFlags,
              bytes32 root,
              bytes32[] memory leaves
          ) internal pure returns (bool) {
              return processMultiProof(proof, proofFlags, leaves) == root;
          }
      
          /**
           * @dev Calldata version of {multiProofVerify}
           *
           * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.
           *
           * _Available since v4.7._
           */
          function multiProofVerifyCalldata(
              bytes32[] calldata proof,
              bool[] calldata proofFlags,
              bytes32 root,
              bytes32[] memory leaves
          ) internal pure returns (bool) {
              return processMultiProofCalldata(proof, proofFlags, leaves) == root;
          }
      
          /**
           * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction
           * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another
           * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false
           * respectively.
           *
           * CAUTION: Not all merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree
           * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the
           * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer).
           *
           * _Available since v4.7._
           */
          function processMultiProof(
              bytes32[] memory proof,
              bool[] memory proofFlags,
              bytes32[] memory leaves
          ) internal pure returns (bytes32 merkleRoot) {
              // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by
              // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the
              // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of
              // the merkle tree.
              uint256 leavesLen = leaves.length;
              uint256 proofLen = proof.length;
              uint256 totalHashes = proofFlags.length;
      
              // Check proof validity.
              require(leavesLen + proofLen - 1 == totalHashes, "MerkleProof: invalid multiproof");
      
              // The xxxPos values are "pointers" to the next value to consume in each array. All accesses are done using
              // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's "pop".
              bytes32[] memory hashes = new bytes32[](totalHashes);
              uint256 leafPos = 0;
              uint256 hashPos = 0;
              uint256 proofPos = 0;
              // At each step, we compute the next hash using two values:
              // - a value from the "main queue". If not all leaves have been consumed, we get the next leaf, otherwise we
              //   get the next hash.
              // - depending on the flag, either another value from the "main queue" (merging branches) or an element from the
              //   `proof` array.
              for (uint256 i = 0; i < totalHashes; i++) {
                  bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];
                  bytes32 b = proofFlags[i]
                      ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])
                      : proof[proofPos++];
                  hashes[i] = _hashPair(a, b);
              }
      
              if (totalHashes > 0) {
                  require(proofPos == proofLen, "MerkleProof: invalid multiproof");
                  unchecked {
                      return hashes[totalHashes - 1];
                  }
              } else if (leavesLen > 0) {
                  return leaves[0];
              } else {
                  return proof[0];
              }
          }
      
          /**
           * @dev Calldata version of {processMultiProof}.
           *
           * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.
           *
           * _Available since v4.7._
           */
          function processMultiProofCalldata(
              bytes32[] calldata proof,
              bool[] calldata proofFlags,
              bytes32[] memory leaves
          ) internal pure returns (bytes32 merkleRoot) {
              // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by
              // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the
              // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of
              // the merkle tree.
              uint256 leavesLen = leaves.length;
              uint256 proofLen = proof.length;
              uint256 totalHashes = proofFlags.length;
      
              // Check proof validity.
              require(leavesLen + proofLen - 1 == totalHashes, "MerkleProof: invalid multiproof");
      
              // The xxxPos values are "pointers" to the next value to consume in each array. All accesses are done using
              // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's "pop".
              bytes32[] memory hashes = new bytes32[](totalHashes);
              uint256 leafPos = 0;
              uint256 hashPos = 0;
              uint256 proofPos = 0;
              // At each step, we compute the next hash using two values:
              // - a value from the "main queue". If not all leaves have been consumed, we get the next leaf, otherwise we
              //   get the next hash.
              // - depending on the flag, either another value from the "main queue" (merging branches) or an element from the
              //   `proof` array.
              for (uint256 i = 0; i < totalHashes; i++) {
                  bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];
                  bytes32 b = proofFlags[i]
                      ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])
                      : proof[proofPos++];
                  hashes[i] = _hashPair(a, b);
              }
      
              if (totalHashes > 0) {
                  require(proofPos == proofLen, "MerkleProof: invalid multiproof");
                  unchecked {
                      return hashes[totalHashes - 1];
                  }
              } else if (leavesLen > 0) {
                  return leaves[0];
              } else {
                  return proof[0];
              }
          }
      
          function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) {
              return a < b ? _efficientHash(a, b) : _efficientHash(b, a);
          }
      
          function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {
              /// @solidity memory-safe-assembly
              assembly {
                  mstore(0x00, a)
                  mstore(0x20, b)
                  value := keccak256(0x00, 0x40)
              }
          }
      }
      
      // OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol)
      
      // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)
      
      /**
       * @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);
      }
      
      // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)
      
      /**
       * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
       * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
       *
       * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
       * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
       * need to send a transaction, and thus is not required to hold Ether at all.
       */
      interface IERC20Permit {
          /**
           * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
           * given ``owner``'s signed approval.
           *
           * IMPORTANT: The same issues {IERC20-approve} has related to transaction
           * ordering also apply here.
           *
           * Emits an {Approval} event.
           *
           * Requirements:
           *
           * - `spender` cannot be the zero address.
           * - `deadline` must be a timestamp in the future.
           * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
           * over the EIP712-formatted function arguments.
           * - the signature must use ``owner``'s current nonce (see {nonces}).
           *
           * For more information on the signature format, see the
           * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
           * section].
           */
          function permit(
              address owner,
              address spender,
              uint256 value,
              uint256 deadline,
              uint8 v,
              bytes32 r,
              bytes32 s
          ) external;
      
          /**
           * @dev Returns the current nonce for `owner`. This value must be
           * included whenever a signature is generated for {permit}.
           *
           * Every successful call to {permit} increases ``owner``'s nonce by one. This
           * prevents a signature from being used multiple times.
           */
          function nonces(address owner) external view returns (uint256);
      
          /**
           * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.
           */
          // solhint-disable-next-line func-name-mixedcase
          function DOMAIN_SEPARATOR() external view returns (bytes32);
      }
      
      // OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)
      
      /**
       * @dev Collection of functions related to the address type
       */
      library Address {
          /**
           * @dev Returns true if `account` is a contract.
           *
           * [IMPORTANT]
           * ====
           * It is unsafe to assume that an address for which this function returns
           * false is an externally-owned account (EOA) and not a contract.
           *
           * Among others, `isContract` will return false for the following
           * types of addresses:
           *
           *  - an externally-owned account
           *  - a contract in construction
           *  - an address where a contract will be created
           *  - an address where a contract lived, but was destroyed
           *
           * Furthermore, `isContract` will also return true if the target contract within
           * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,
           * which only has an effect at the end of a transaction.
           * ====
           *
           * [IMPORTANT]
           * ====
           * You shouldn't rely on `isContract` to protect against flash loan attacks!
           *
           * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
           * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
           * constructor.
           * ====
           */
          function isContract(address account) internal view returns (bool) {
              // This method relies on extcodesize/address.code.length, which returns 0
              // for contracts in construction, since the code is only stored at the end
              // of the constructor execution.
      
              return account.code.length > 0;
          }
      
          /**
           * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
           * `recipient`, forwarding all available gas and reverting on errors.
           *
           * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
           * of certain opcodes, possibly making contracts go over the 2300 gas limit
           * imposed by `transfer`, making them unable to receive funds via
           * `transfer`. {sendValue} removes this limitation.
           *
           * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].
           *
           * IMPORTANT: because control is transferred to `recipient`, care must be
           * taken to not create reentrancy vulnerabilities. Consider using
           * {ReentrancyGuard} or the
           * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
           */
          function sendValue(address payable recipient, uint256 amount) internal {
              require(address(this).balance >= amount, "Address: insufficient balance");
      
              (bool success, ) = recipient.call{value: amount}("");
              require(success, "Address: unable to send value, recipient may have reverted");
          }
      
          /**
           * @dev Performs a Solidity function call using a low level `call`. A
           * plain `call` is an unsafe replacement for a function call: use this
           * function instead.
           *
           * If `target` reverts with a revert reason, it is bubbled up by this
           * function (like regular Solidity function calls).
           *
           * Returns the raw returned data. To convert to the expected return value,
           * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
           *
           * Requirements:
           *
           * - `target` must be a contract.
           * - calling `target` with `data` must not revert.
           *
           * _Available since v3.1._
           */
          function functionCall(address target, bytes memory data) internal returns (bytes memory) {
              return functionCallWithValue(target, data, 0, "Address: low-level call failed");
          }
      
          /**
           * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
           * `errorMessage` as a fallback revert reason when `target` reverts.
           *
           * _Available since v3.1._
           */
          function functionCall(
              address target,
              bytes memory data,
              string memory errorMessage
          ) internal returns (bytes memory) {
              return functionCallWithValue(target, data, 0, errorMessage);
          }
      
          /**
           * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
           * but also transferring `value` wei to `target`.
           *
           * Requirements:
           *
           * - the calling contract must have an ETH balance of at least `value`.
           * - the called Solidity function must be `payable`.
           *
           * _Available since v3.1._
           */
          function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
              return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
          }
      
          /**
           * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
           * with `errorMessage` as a fallback revert reason when `target` reverts.
           *
           * _Available since v3.1._
           */
          function functionCallWithValue(
              address target,
              bytes memory data,
              uint256 value,
              string memory errorMessage
          ) internal returns (bytes memory) {
              require(address(this).balance >= value, "Address: insufficient balance for call");
              (bool success, bytes memory returndata) = target.call{value: value}(data);
              return verifyCallResultFromTarget(target, success, returndata, errorMessage);
          }
      
          /**
           * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
           * but performing a static call.
           *
           * _Available since v3.3._
           */
          function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
              return functionStaticCall(target, data, "Address: low-level static call failed");
          }
      
          /**
           * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
           * but performing a static call.
           *
           * _Available since v3.3._
           */
          function functionStaticCall(
              address target,
              bytes memory data,
              string memory errorMessage
          ) internal view returns (bytes memory) {
              (bool success, bytes memory returndata) = target.staticcall(data);
              return verifyCallResultFromTarget(target, success, returndata, errorMessage);
          }
      
          /**
           * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
           * but performing a delegate call.
           *
           * _Available since v3.4._
           */
          function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
              return functionDelegateCall(target, data, "Address: low-level delegate call failed");
          }
      
          /**
           * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
           * but performing a delegate call.
           *
           * _Available since v3.4._
           */
          function functionDelegateCall(
              address target,
              bytes memory data,
              string memory errorMessage
          ) internal returns (bytes memory) {
              (bool success, bytes memory returndata) = target.delegatecall(data);
              return verifyCallResultFromTarget(target, success, returndata, errorMessage);
          }
      
          /**
           * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
           * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
           *
           * _Available since v4.8._
           */
          function verifyCallResultFromTarget(
              address target,
              bool success,
              bytes memory returndata,
              string memory errorMessage
          ) internal view returns (bytes memory) {
              if (success) {
                  if (returndata.length == 0) {
                      // only check isContract if the call was successful and the return data is empty
                      // otherwise we already know that it was a contract
                      require(isContract(target), "Address: call to non-contract");
                  }
                  return returndata;
              } else {
                  _revert(returndata, errorMessage);
              }
          }
      
          /**
           * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
           * revert reason or using the provided one.
           *
           * _Available since v4.3._
           */
          function verifyCallResult(
              bool success,
              bytes memory returndata,
              string memory errorMessage
          ) internal pure returns (bytes memory) {
              if (success) {
                  return returndata;
              } else {
                  _revert(returndata, errorMessage);
              }
          }
      
          function _revert(bytes memory returndata, string memory errorMessage) private pure {
              // Look for revert reason and bubble it up if present
              if (returndata.length > 0) {
                  // The easiest way to bubble the revert reason is using memory via assembly
                  /// @solidity memory-safe-assembly
                  assembly {
                      let returndata_size := mload(returndata)
                      revert(add(32, returndata), returndata_size)
                  }
              } else {
                  revert(errorMessage);
              }
          }
      }
      
      /**
       * @title SafeERC20
       * @dev Wrappers around ERC20 operations that throw on failure (when the token
       * contract returns false). Tokens that return no value (and instead revert or
       * throw on failure) are also supported, non-reverting calls are assumed to be
       * successful.
       * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
       * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
       */
      library SafeERC20 {
          using Address for address;
      
          /**
           * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,
           * non-reverting calls are assumed to be successful.
           */
          function safeTransfer(IERC20 token, address to, uint256 value) internal {
              _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
          }
      
          /**
           * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the
           * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.
           */
          function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
              _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
          }
      
          /**
           * @dev Deprecated. This function has issues similar to the ones found in
           * {IERC20-approve}, and its usage is discouraged.
           *
           * Whenever possible, use {safeIncreaseAllowance} and
           * {safeDecreaseAllowance} instead.
           */
          function safeApprove(IERC20 token, address spender, uint256 value) internal {
              // safeApprove should only be called when setting an initial allowance,
              // or when resetting it to zero. To increase and decrease it, use
              // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
              require(
                  (value == 0) || (token.allowance(address(this), spender) == 0),
                  "SafeERC20: approve from non-zero to non-zero allowance"
              );
              _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
          }
      
          /**
           * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
           * non-reverting calls are assumed to be successful.
           */
          function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
              uint256 oldAllowance = token.allowance(address(this), spender);
              _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));
          }
      
          /**
           * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
           * non-reverting calls are assumed to be successful.
           */
          function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
              unchecked {
                  uint256 oldAllowance = token.allowance(address(this), spender);
                  require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
                  _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));
              }
          }
      
          /**
           * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,
           * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval
           * to be set to zero before setting it to a non-zero value, such as USDT.
           */
          function forceApprove(IERC20 token, address spender, uint256 value) internal {
              bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);
      
              if (!_callOptionalReturnBool(token, approvalCall)) {
                  _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));
                  _callOptionalReturn(token, approvalCall);
              }
          }
      
          /**
           * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.
           * Revert on invalid signature.
           */
          function safePermit(
              IERC20Permit token,
              address owner,
              address spender,
              uint256 value,
              uint256 deadline,
              uint8 v,
              bytes32 r,
              bytes32 s
          ) internal {
              uint256 nonceBefore = token.nonces(owner);
              token.permit(owner, spender, value, deadline, v, r, s);
              uint256 nonceAfter = token.nonces(owner);
              require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed");
          }
      
          /**
           * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
           * on the return value: the return value is optional (but if data is returned, it must not be false).
           * @param token The token targeted by the call.
           * @param data The call data (encoded using abi.encode or one of its variants).
           */
          function _callOptionalReturn(IERC20 token, bytes memory data) private {
              // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
              // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that
              // the target address contains contract code and also asserts for success in the low-level call.
      
              bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
              require(returndata.length == 0 || abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
          }
      
          /**
           * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
           * on the return value: the return value is optional (but if data is returned, it must not be false).
           * @param token The token targeted by the call.
           * @param data The call data (encoded using abi.encode or one of its variants).
           *
           * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.
           */
          function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
              // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
              // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false
              // and not revert is the subcall reverts.
      
              (bool success, bytes memory returndata) = address(token).call(data);
              return
                  success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token));
          }
      }
      
      // OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)
      
      /**
       * @dev Standard math utilities missing in the Solidity language.
       */
      library Math {
          enum Rounding {
              Down, // Toward negative infinity
              Up, // Toward infinity
              Zero // Toward zero
          }
      
          /**
           * @dev Returns the largest of two numbers.
           */
          function max(uint256 a, uint256 b) internal pure returns (uint256) {
              return a > b ? a : b;
          }
      
          /**
           * @dev Returns the smallest of two numbers.
           */
          function min(uint256 a, uint256 b) internal pure returns (uint256) {
              return a < b ? a : b;
          }
      
          /**
           * @dev Returns the average of two numbers. The result is rounded towards
           * zero.
           */
          function average(uint256 a, uint256 b) internal pure returns (uint256) {
              // (a + b) / 2 can overflow.
              return (a & b) + (a ^ b) / 2;
          }
      
          /**
           * @dev Returns the ceiling of the division of two numbers.
           *
           * This differs from standard division with `/` in that it rounds up instead
           * of rounding down.
           */
          function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
              // (a + b - 1) / b can overflow on addition, so we distribute.
              return a == 0 ? 0 : (a - 1) / b + 1;
          }
      
          /**
           * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
           * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)
           * with further edits by Uniswap Labs also under MIT license.
           */
          function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {
              unchecked {
                  // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use
                  // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
                  // variables such that product = prod1 * 2^256 + prod0.
                  uint256 prod0; // Least significant 256 bits of the product
                  uint256 prod1; // Most significant 256 bits of the product
                  assembly {
                      let mm := mulmod(x, y, not(0))
                      prod0 := mul(x, y)
                      prod1 := sub(sub(mm, prod0), lt(mm, prod0))
                  }
      
                  // Handle non-overflow cases, 256 by 256 division.
                  if (prod1 == 0) {
                      // Solidity will revert if denominator == 0, unlike the div opcode on its own.
                      // The surrounding unchecked block does not change this fact.
                      // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.
                      return prod0 / denominator;
                  }
      
                  // Make sure the result is less than 2^256. Also prevents denominator == 0.
                  require(denominator > prod1, "Math: mulDiv overflow");
      
                  ///////////////////////////////////////////////
                  // 512 by 256 division.
                  ///////////////////////////////////////////////
      
                  // Make division exact by subtracting the remainder from [prod1 prod0].
                  uint256 remainder;
                  assembly {
                      // Compute remainder using mulmod.
                      remainder := mulmod(x, y, denominator)
      
                      // Subtract 256 bit number from 512 bit number.
                      prod1 := sub(prod1, gt(remainder, prod0))
                      prod0 := sub(prod0, remainder)
                  }
      
                  // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.
                  // See https://cs.stackexchange.com/q/138556/92363.
      
                  // Does not overflow because the denominator cannot be zero at this stage in the function.
                  uint256 twos = denominator & (~denominator + 1);
                  assembly {
                      // Divide denominator by twos.
                      denominator := div(denominator, twos)
      
                      // Divide [prod1 prod0] by twos.
                      prod0 := div(prod0, twos)
      
                      // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.
                      twos := add(div(sub(0, twos), twos), 1)
                  }
      
                  // Shift in bits from prod1 into prod0.
                  prod0 |= prod1 * twos;
      
                  // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such
                  // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for
                  // four bits. That is, denominator * inv = 1 mod 2^4.
                  uint256 inverse = (3 * denominator) ^ 2;
      
                  // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works
                  // in modular arithmetic, doubling the correct bits in each step.
                  inverse *= 2 - denominator * inverse; // inverse mod 2^8
                  inverse *= 2 - denominator * inverse; // inverse mod 2^16
                  inverse *= 2 - denominator * inverse; // inverse mod 2^32
                  inverse *= 2 - denominator * inverse; // inverse mod 2^64
                  inverse *= 2 - denominator * inverse; // inverse mod 2^128
                  inverse *= 2 - denominator * inverse; // inverse mod 2^256
      
                  // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
                  // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is
                  // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1
                  // is no longer required.
                  result = prod0 * inverse;
                  return result;
              }
          }
      
          /**
           * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.
           */
          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;
          }
      
          /**
           * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.
           *
           * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11).
           */
          function sqrt(uint256 a) internal pure returns (uint256) {
              if (a == 0) {
                  return 0;
              }
      
              // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.
              //
              // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have
              // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.
              //
              // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`
              // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`
              // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`
              //
              // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.
              uint256 result = 1 << (log2(a) >> 1);
      
              // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,
              // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at
              // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision
              // into the expected uint128 result.
              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);
              }
          }
      
          /**
           * @notice Calculates sqrt(a), following the selected rounding direction.
           */
          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);
              }
          }
      
          /**
           * @dev Return the log in base 2, rounded down, of a positive value.
           * Returns 0 if given 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;
          }
      
          /**
           * @dev Return the log in base 2, following the selected rounding direction, of a positive value.
           * Returns 0 if given 0.
           */
          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);
              }
          }
      
          /**
           * @dev Return the log in base 10, rounded down, of a positive value.
           * Returns 0 if given 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;
          }
      
          /**
           * @dev Return the log in base 10, following the selected rounding direction, of a positive value.
           * Returns 0 if given 0.
           */
          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);
              }
          }
      
          /**
           * @dev Return the log in base 256, rounded down, of a positive value.
           * Returns 0 if given 0.
           *
           * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
           */
          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;
          }
      
          /**
           * @dev Return the log in base 256, following the selected rounding direction, of a positive value.
           * Returns 0 if given 0.
           */
          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);
              }
          }
      }
      
      // OpenZeppelin Contracts (last updated v4.9.0) (utils/structs/BitMaps.sol)
      
      /**
       * @dev Library for managing uint256 to bool mapping in a compact and efficient way, providing the keys are sequential.
       * Largely inspired by Uniswap's https://github.com/Uniswap/merkle-distributor/blob/master/contracts/MerkleDistributor.sol[merkle-distributor].
       */
      library BitMaps {
          struct BitMap {
              mapping(uint256 => uint256) _data;
          }
      
          /**
           * @dev Returns whether the bit at `index` is set.
           */
          function get(BitMap storage bitmap, uint256 index) internal view returns (bool) {
              uint256 bucket = index >> 8;
              uint256 mask = 1 << (index & 0xff);
              return bitmap._data[bucket] & mask != 0;
          }
      
          /**
           * @dev Sets the bit at `index` to the boolean `value`.
           */
          function setTo(BitMap storage bitmap, uint256 index, bool value) internal {
              if (value) {
                  set(bitmap, index);
              } else {
                  unset(bitmap, index);
              }
          }
      
          /**
           * @dev Sets the bit at `index`.
           */
          function set(BitMap storage bitmap, uint256 index) internal {
              uint256 bucket = index >> 8;
              uint256 mask = 1 << (index & 0xff);
              bitmap._data[bucket] |= mask;
          }
      
          /**
           * @dev Unsets the bit at `index`.
           */
          function unset(BitMap storage bitmap, uint256 index) internal {
              uint256 bucket = index >> 8;
              uint256 mask = 1 << (index & 0xff);
              bitmap._data[bucket] &= ~mask;
          }
      }
      
      contract Vesting {
          using BitMaps for BitMaps.BitMap;
          using SafeERC20 for IERC20;
      
          address public immutable token;
          bytes32 public immutable merkleRoot;
          uint256 public constant MAX_PERCENTAGE = 1e4;
      
          address public owner;
      
          mapping(uint256 => uint256) public claimed;
          BitMaps.BitMap private _revokedBitmap;
      
          error InvalidProof();
          error NothingToClaim();
          error InvalidDates();
          error EmptyMerkleRoot();
          error OnlyOwner();
          error AlreadyRevoked();
          error ZeroAddress();
          error CantRevokeEndedVesting();
          error UnrevocableVesting();
          error ClaimAmountGtClaimable();
          error Revoked();
      
          event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
          event Claim(address indexed account, uint256 amount);
          event VestingRevoked(address indexed account, uint256 amountUnvested);
      
          constructor(
              address _token,
              bytes32 _merkleRoot,
              address _owner
          ) {
              if (_merkleRoot == "") revert EmptyMerkleRoot();
      
              token = _token;
              merkleRoot = _merkleRoot;
      
              owner = _owner;
          }
      
          modifier onlyOwner() {
              if (msg.sender != owner) revert OnlyOwner();
              _;
          }
      
          function claim(
              uint256 index,
              address account,
              uint256 amount,
              bool revocable,
              uint256 start,
              uint256 end,
              uint256 cadence,
              uint256 percentageOnStart,
              bytes32[] calldata merkleProof,
              uint256 claimAmount
          ) public {
              bytes32 node = keccak256(
                  abi.encodePacked(index, account, amount, revocable, start, end, cadence, percentageOnStart)
              );
              if (!MerkleProof.verify(merkleProof, merkleRoot, node)) revert InvalidProof();
      
              if (getRevoked(index)) revert Revoked();
      
              uint256 claimable = getClaimable(index, amount, start, end, cadence, percentageOnStart);
      
              if (claimable == 0) revert NothingToClaim();
              if (claimAmount > claimable) revert ClaimAmountGtClaimable();
      
              claimed[index] += claimAmount;
      
              IERC20(token).safeTransfer(account, claimAmount);
      
              emit Claim(account, claimAmount);
          }
      
          function stopVesting(
              uint256 index,
              address account,
              uint256 amount,
              bool revocable,
              uint256 start,
              uint256 end,
              uint256 cadence,
              uint256 percentageOnStart,
              bytes32[] calldata merkleProof
          ) external onlyOwner {
              bytes32 node = keccak256(
                  abi.encodePacked(index, account, amount, revocable, start, end, cadence, percentageOnStart)
              );
              if (!MerkleProof.verify(merkleProof, merkleRoot, node)) revert InvalidProof();
      
              if (!revocable) revert UnrevocableVesting();
      
              if (getRevoked(index)) revert AlreadyRevoked();
      
              if (block.timestamp >= end) revert CantRevokeEndedVesting();
      
              uint256 claimable = getClaimable(index, amount, start, end, cadence, percentageOnStart);
      
              setRevoked(index);
      
              if (claimable != 0) {
                  IERC20(token).safeTransfer(account, claimable);
                  emit Claim(account, claimable);
              }
      
              uint256 rest = amount - (claimable + claimed[index]);
      
              IERC20(token).safeTransfer(owner, rest);
      
              emit VestingRevoked(account, rest);
          }
      
          function getClaimable(
              uint256 index,
              uint256 amount,
              uint256 start,
              uint256 end,
              uint256 cadence,
              uint256 percentageOnStart
          ) public view returns (uint256) {
              if (block.timestamp < start) return 0;
              if (block.timestamp > end) return amount - claimed[index];
      
              uint256 elapsed = ((block.timestamp - start) / cadence) * cadence;
      
              if (percentageOnStart != 0) {
                  uint256 claimableOnStart = (percentageOnStart * amount) / MAX_PERCENTAGE;
                  uint256 claimableRest = (elapsed * (amount - claimableOnStart)) / (end - start);
      
                  return claimableRest + claimableOnStart - claimed[index];
              }
      
              return (elapsed * amount) / (end - start) - claimed[index];
          }
      
          function transferOwnership(address newOwner) public virtual onlyOwner {
              if (newOwner == address(0)) revert ZeroAddress();
              owner = newOwner;
          }
      
          function getRevoked(uint256 index) public view returns (bool) {
              return _revokedBitmap.get(index);
          }
      
          function setRevoked(uint256 index) internal {
              _revokedBitmap.set(index);
          }
      }

      File 2 of 3: OE
      // SPDX-License-Identifier: Unlicensed
      pragma solidity ^0.8.0;
      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);
      }// SPDX-License-Identifier: Unlicensed
      pragma solidity ^0.8.0;
      interface Iinfl {
          function addPayment() external payable;
          function emergencyWithdraw() external;
          function inflWithdraw() external;
          function setTokenAddress(address _token) external;
          function addInfl(address _infl, uint256 _percent) external;
          function deleteInfl(address infl) external;
      }
      // SPDX-License-Identifier: Unlicensed
      pragma solidity ^0.8.0;
      interface IPool {
          function addBuyer(address buyerAddress, uint256 amount, bool isOdd) external;
          function updateBuyer(address buyerAddress, uint256 amount, bool isOdd) external;
          function deleteBuyer(address buyerAddress) external;
      }
      // SPDX-License-Identifier: Unlicensed
      pragma solidity ^0.8.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;
      }// SPDX-License-Identifier: Unlicensed
      pragma solidity ^0.8.0;
      interface IUniswapV2Pair {
          event Approval(address indexed owner, address indexed spender, uint value);
          event Transfer(address indexed from, address indexed to, uint value);
          function name() external pure returns (string memory);
          function symbol() external pure returns (string memory);
          function decimals() external pure returns (uint8);
          function totalSupply() external view returns (uint);
          function balanceOf(address owner) external view returns (uint);
          function allowance(address owner, address spender) external view returns (uint);
          function approve(address spender, uint value) external returns (bool);
          function transfer(address to, uint value) external returns (bool);
          function transferFrom(address from, address to, uint value) external returns (bool);
          function DOMAIN_SEPARATOR() external view returns (bytes32);
          function PERMIT_TYPEHASH() external pure returns (bytes32);
          function nonces(address owner) external view returns (uint);
          function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;
          event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);
          event Swap(
              address indexed sender,
              uint amount0In,
              uint amount1In,
              uint amount0Out,
              uint amount1Out,
              address indexed to
          );
          event Sync(uint112 reserve0, uint112 reserve1);
          function MINIMUM_LIQUIDITY() external pure returns (uint);
          function factory() external view returns (address);
          function token0() external view returns (address);
          function token1() external view returns (address);
          function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);
          function price0CumulativeLast() external view returns (uint);
          function price1CumulativeLast() external view returns (uint);
          function kLast() external view returns (uint);
          function burn(address to) external returns (uint amount0, uint amount1);
          function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;
          function skim(address to) external;
          function sync() external;
          function initialize(address, address) external;
      }// SPDX-License-Identifier: Unlicensed
      pragma solidity ^0.8.0;
      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);
      }// SPDX-License-Identifier: Unlicensed
      pragma solidity ^0.8.0;
      import "./IUniswapV2Router01.sol";
      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;
      }// SPDX-License-Identifier: Unlicensed
      pragma solidity ^0.8.0;
      abstract contract Context {
          function _msgSender() internal view virtual returns (address payable) {
              return payable(msg.sender);
          }
          function _msgData() internal view virtual returns (bytes memory) {
              this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
              return msg.data;
          }
      }
      contract Ownable is Context {
          address private _owner;
          event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
          constructor () {
              address msgSender = _msgSender();
              _owner = msgSender;
              emit OwnershipTransferred(address(0), msgSender);
          }
          function owner() public view returns (address) {
              return _owner;
          }
          modifier onlyOwner() {
              require(_owner == _msgSender(), "Ownable: caller is not the owner");
              _;
          }
          function waiveOwnership() public virtual onlyOwner {
              emit OwnershipTransferred(_owner, address(0));
              _owner = address(0);
          }
          function transferOwnership(address newOwner) public virtual onlyOwner {
              require(newOwner != address(0), "Ownable: new owner is the zero address");
              emit OwnershipTransferred(_owner, newOwner);
              _owner = newOwner;
          }
      }// SPDX-License-Identifier: Unlicensed
      pragma solidity ^0.8.4;
      import "./libraries/Ownable.sol";
      import "./interfaces/IERC20.sol";
      import "./interfaces/IPool.sol";
      import "./interfaces/IUniswapV2Router02.sol";
      import "./interfaces/IUniswapV2Factory.sol";
      import "./interfaces/IUniswapV2Pair.sol";
      import "./interfaces/Iinfl.sol";
      library SafeMath {
          function add(uint256 a, uint256 b) internal pure returns (uint256) {
              uint256 c = a + b;
              require(c >= a, "SafeMath: addition overflow");
              return c;
          }
          function sub(uint256 a, uint256 b) internal pure returns (uint256) {
              return sub(a, b, "SafeMath: subtraction overflow");
          }
          function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
              require(b <= a, errorMessage);
              uint256 c = a - b;
              return c;
          }
          function mul(uint256 a, uint256 b) internal pure returns (uint256) {
              if (a == 0) {
                  return 0;
              }
              uint256 c = a * b;
              require(c / a == b, "SafeMath: multiplication overflow");
              return c;
          }
          function div(uint256 a, uint256 b) internal pure returns (uint256) {
              return div(a, b, "SafeMath: division by zero");
          }
          function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
              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;
          }
          function mod(uint256 a, uint256 b) internal pure returns (uint256) {
              return mod(a, b, "SafeMath: modulo by zero");
          }
          function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
              require(b != 0, errorMessage);
              return a % b;
          }
      }
      library Address {
          function isContract(address account) internal view returns (bool) {
              // According to EIP-1052, 0x0 is the value returned for not-yet created accounts
              // and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned
              // for accounts without code, i.e. `keccak256('')`
              bytes32 codehash;
              bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;
              // solhint-disable-next-line no-inline-assembly
              assembly { codehash := extcodehash(account) }
              return (codehash != accountHash && codehash != 0x0);
          }
          function sendValue(address payable recipient, uint256 amount) internal {
              require(address(this).balance >= amount, "Address: insufficient balance");
              // solhint-disable-next-line avoid-low-level-calls, avoid-call-value
              (bool success, ) = recipient.call{ value: amount }("");
              require(success, "Address: unable to send value, recipient may have reverted");
          }
          function functionCall(address target, bytes memory data) internal returns (bytes memory) {
              return functionCall(target, data, "Address: low-level call failed");
          }
          function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
              return _functionCallWithValue(target, data, 0, errorMessage);
          }
          function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
              return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
          }
          function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {
              require(address(this).balance >= value, "Address: insufficient balance for call");
              return _functionCallWithValue(target, data, value, errorMessage);
          }
          function _functionCallWithValue(address target, bytes memory data, uint256 weiValue, string memory errorMessage) private returns (bytes memory) {
              require(isContract(target), "Address: call to non-contract");
              (bool success, bytes memory returndata) = target.call{ value: weiValue }(data);
              if (success) {
                  return returndata;
              } else {
                  if (returndata.length > 0) {
                      assembly {
                          let returndata_size := mload(returndata)
                          revert(add(32, returndata), returndata_size)
                      }
                  } else {
                      revert(errorMessage);
                  }
              }
          }
      }
      contract OE is Context, IERC20, Ownable {
          using SafeMath for uint256;
          using Address for address;
          string private _name = "ODD/EVEN TOKEN";
          string private _symbol = "OE";
          uint8 private _decimals = 18;
          address payable public buybackAddress;
          address payable public soFiPoolAddress;
          address payable public housePoolAddress;
          Iinfl public marketingWalletAddress;
          IPool public prizePoolAddress;
          IUniswapV2Router02 public _uniswapV2Router;
          address public immutable deadAddress = 0x000000000000000000000000000000000000dEaD;
          address public usdtAddress;
          mapping (address => uint256) _balances;
          mapping (address => mapping (address => uint256)) private _allowances;
          mapping (address => bool) public isExcludedFromFee;
          mapping (address => bool) public isWalletLimitExempt;
          mapping (address => bool) public isTxLimitExempt;
          mapping (address => bool) public isMarketPair;
          //Contract fees
          uint256 public _buyPrizeFee = 15;
          uint256 public _sellPrizeFee = 15;
          uint256 public _buyLpFee = 2;
          uint256 public _sellLpFee = 2;
          uint256 public _buyBuyBackFee = 2;
          uint256 public _sellBuyBackFee = 2;
          uint256 public _buyMarketingFee = 2;
          uint256 public _sellMarketingFee = 2;
          uint256 public _buySofiFee = 2;
          uint256 public _sellSofiFee = 2;
          uint256 public _buyHouseFee = 2;
          uint256 public _sellHouseFee = 2;
          //Contract share parameters
          uint256 public _prizeShare = 15;
          uint256 public _lpShare = 2;
          uint256 public _buyBackShare = 2;
          uint256 public _marketingShare = 2;
          uint256 public _sofiShare = 2;
          uint256 public _houseShare = 2;
          uint256 public _totalTaxIfBuying = 25;
          uint256 public _totalTaxIfSelling = 25;
          uint256 public _totalDistributionShares = 25;
          uint256 private _totalSupply = 111_111 * 10**_decimals;
          uint256 public _maxTxAmount = 111_111 * 10**_decimals;
          uint256 public _walletMax = 111_111 * 10**_decimals;
          uint256 private minimumTokensBeforeSwap = 1_111 * 10**_decimals;
          address public uniswapPair;
          bool inSwapAndLiquify;
          bool public swapAndLiquifyEnabled = true;
          bool public swapAndLiquifyByLimitOnly = false;
          bool public checkWalletLimit = true;
          event SwapAndLiquifyEnabledUpdated(bool enabled);
          event SwapAndLiquify(
              uint256 tokensSwapped,
              uint256 ethReceived,
              uint256 tokensIntoLiqudity
          );
          event SwapETHForTokens(
              uint256 amountIn,
              address[] path
          );
          event SwapTokensForETH(
              uint256 amountIn,
              address[] path
          );
          modifier lockTheSwap {
              inSwapAndLiquify = true;
              _;
              inSwapAndLiquify = false;
          }
          constructor (
              address _router,
              address _prizePool,
              address _buyBack,
              address _marketing,
              address _sofi,
              address _house,
              address _usdt
          ) {
              _uniswapV2Router = IUniswapV2Router02(_router);
              prizePoolAddress = IPool(_prizePool);
              buybackAddress = payable(_buyBack);
              marketingWalletAddress = Iinfl(_marketing);
              soFiPoolAddress = payable(_sofi);
              housePoolAddress = payable(_house);
              usdtAddress = _usdt;
              uniswapPair = IUniswapV2Factory(_uniswapV2Router.factory())
              .createPair(address(this), _uniswapV2Router.WETH());
              _allowances[address(this)][address(_uniswapV2Router)] = _totalSupply;
              isExcludedFromFee[owner()] = true;
              isExcludedFromFee[address(this)] = true;
              isExcludedFromFee[_buyBack] = true;
              isExcludedFromFee[_marketing] = true;
              _totalTaxIfBuying = _buyPrizeFee + _buyBuyBackFee + _buyLpFee + _buyMarketingFee + _buySofiFee + _buyHouseFee;
              _totalTaxIfSelling = _sellPrizeFee + _sellLpFee + _sellBuyBackFee + _sellMarketingFee + _sellSofiFee + _sellHouseFee;
              _totalDistributionShares = _marketingShare + _prizeShare + _lpShare + _buyBackShare + _sofiShare + _houseShare;
              isWalletLimitExempt[owner()] = true;
              isWalletLimitExempt[address(uniswapPair)] = true;
              isWalletLimitExempt[address(this)] = true;
              isTxLimitExempt[owner()] = true;
              isTxLimitExempt[address(this)] = true;
              isMarketPair[address(uniswapPair)] = true;
              _balances[_msgSender()] = _totalSupply;
              emit Transfer(address(0), _msgSender(), _totalSupply);
          }
          function name() public view returns (string memory) {
              return _name;
          }
          function symbol() public view returns (string memory) {
              return _symbol;
          }
          function decimals() public view 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 allowance(address owner, address spender) public view override returns (uint256) {
              return _allowances[owner][spender];
          }
          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 minimumTokensBeforeSwapAmount() public view returns (uint256) {
              return minimumTokensBeforeSwap;
          }
          function approve(address spender, uint256 amount) public override returns (bool) {
              _approve(_msgSender(), spender, amount);
              return true;
          }
          function _approve(address owner, address spender, uint256 amount) private {
              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 setMarketPairStatus(address account, bool newValue) public onlyOwner {
              isMarketPair[account] = newValue;
          }
          function setIsTxLimitExempt(address holder, bool exempt) external onlyOwner {
              isTxLimitExempt[holder] = exempt;
          }
          function setIsExcludedFromFee(address account, bool newValue) public onlyOwner {
              isExcludedFromFee[account] = newValue;
          }
          function setDistributionShares(
              uint256 prizeShare,
              uint256 lpShare,
              uint256 buyBackShare,
              uint256 marketingShare,
              uint256 sofiShare,
              uint256 houseShare
          ) external onlyOwner {
              _marketingShare = marketingShare;
              _prizeShare = prizeShare;
              _lpShare = lpShare;
              _buyBackShare = buyBackShare;
              _sofiShare = sofiShare;
              _houseShare = houseShare;
              _totalDistributionShares = _marketingShare + _prizeShare + _lpShare + _buyBackShare + _sofiShare + _houseShare;
          }
          function setBuyTaxes(
              uint256 newMarketingTax,
              uint256 newLpPercent,
              uint256 newBuyBackPercent,
              uint256 newPrizePercent,
              uint256 newSofiPercent,
              uint256 newHousePercent
          ) external onlyOwner {
              _buyMarketingFee = newMarketingTax;
              _buyLpFee = newLpPercent;
              _buyBuyBackFee = newBuyBackPercent;
              _buyPrizeFee = newPrizePercent;
              _buySofiFee = newSofiPercent;
              _buyHouseFee = newHousePercent;
              _totalTaxIfBuying = _buyPrizeFee + _buyBuyBackFee + _buyLpFee + _buyMarketingFee + _buySofiFee + _buyHouseFee;
              require(_totalTaxIfBuying <= 25, 'Error fee too high');
          }
          function setSellTaxes(
              uint256 newMarketingTax,
              uint256 newLpPercent,
              uint256 newBuyBackPercent,
              uint256 newPrizePercent,
              uint256 newSofiPercent,
              uint256 newHousePercent
          ) external onlyOwner {
              _sellMarketingFee = newMarketingTax;
              _sellBuyBackFee = newBuyBackPercent;
              _sellLpFee = newLpPercent;
              _sellPrizeFee = newPrizePercent;
              _sellSofiFee = newSofiPercent;
              _sellHouseFee = newHousePercent;
              _totalTaxIfSelling = _sellPrizeFee + _sellLpFee + _sellBuyBackFee + _sellMarketingFee + _sellSofiFee + _sellHouseFee;
              require(_totalTaxIfSelling <= 25, 'Error fee to high');
          }
          function setMaxTxAmount(uint256 maxTxAmount) external onlyOwner {
              require(maxTxAmount >= 2_500_000, 'Min maxTxAmount error');
              _maxTxAmount = maxTxAmount;
          }
          function enableDisableWalletLimit(bool newValue) external onlyOwner {
              checkWalletLimit = newValue;
          }
          function setIsWalletLimitExempt(address holder, bool exempt) external onlyOwner {
              isWalletLimitExempt[holder] = exempt;
          }
          function setWalletLimit(uint256 newLimit) external onlyOwner {
              _walletMax  = newLimit;
          }
          function setNumTokensBeforeSwap(uint256 newLimit) external onlyOwner() {
              minimumTokensBeforeSwap = newLimit;
          }
          function setMarketingWalletAddress(address newAddress) external onlyOwner {
              require(newAddress != address(0), 'newAddress must not be equal to 0x');
              marketingWalletAddress = Iinfl(newAddress);
          }
          function setSofiPoolWalletAddress(address newAddress) external onlyOwner {
              require(newAddress != address(0), 'newAddress must not be equal to 0x');
              soFiPoolAddress = payable(newAddress);
          }
          function setBuybackAddress(address newAddress) external onlyOwner {
              require(newAddress != address(0), 'newAddress must not be equal to 0x');
              buybackAddress = payable(newAddress);
          }
          function setHouseWalletAddress(address newAddress) external onlyOwner {
              require(newAddress != address(0), 'newAddress must not be equal to 0x');
              housePoolAddress = payable(newAddress);
          }
          function setPrizePoolAddress(address newAddress) external onlyOwner {
              require(newAddress != address(0), 'newAddress must not be equal to 0x');
              prizePoolAddress = IPool(newAddress);
          }
          function setSwapAndLiquifyEnabled(bool _enabled) public onlyOwner {
              swapAndLiquifyEnabled = _enabled;
              emit SwapAndLiquifyEnabledUpdated(_enabled);
          }
          function setSwapAndLiquifyByLimitOnly(bool newValue) public onlyOwner {
              swapAndLiquifyByLimitOnly = newValue;
          }
          function getCirculatingSupply() public view returns (uint256) {
              return _totalSupply.sub(balanceOf(deadAddress));
          }
          function transferToAddressETH(address payable recipient, uint256 amount) private {
              recipient.transfer(amount);
          }
          function changeRouterVersion(address newRouterAddress) public onlyOwner returns(address newPairAddress) {
              _uniswapV2Router = IUniswapV2Router02(newRouterAddress);
              newPairAddress = IUniswapV2Factory(_uniswapV2Router.factory()).getPair(address(this), _uniswapV2Router.WETH());
              if(newPairAddress == address(0)) //Create If Doesnt exist
              {
                  newPairAddress = IUniswapV2Factory(_uniswapV2Router.factory())
                  .createPair(address(this), _uniswapV2Router.WETH());
              }
              uniswapPair = newPairAddress; //Set new pair address
              isWalletLimitExempt[address(uniswapPair)] = true;
              isMarketPair[address(uniswapPair)] = true;
          }
          //to recieve ETH from uniswapV2Router when swaping
          receive() external payable {}
          function transfer(address recipient, uint256 amount) public override returns (bool) {
              _transfer(_msgSender(), recipient, amount);
              return true;
          }
          function transferFrom(address sender, address recipient, uint256 amount) public override returns (bool) {
              _transfer(sender, recipient, amount);
              _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance"));
              return true;
          }
          function _transfer(address sender, address recipient, uint256 amount) private returns (bool) {
              require(sender != address(0), "ERC20: transfer from the zero address");
              require(recipient != address(0), "ERC20: transfer to the zero address");
              if(inSwapAndLiquify)
              {
                  return _basicTransfer(sender, recipient, amount);
              }
              else
              {
                  uint256 finalAmount = (isExcludedFromFee[sender] || isExcludedFromFee[recipient]) ?
                  amount : takeFee(sender, recipient, amount);
                  if (sender != buybackAddress && recipient != buybackAddress) {
                      if (isMarketPair[sender] && recipient != address(this)) {
                          prizePoolAddress.addBuyer(recipient, finalAmount, _getIsOdd());
                      }
                      if (isMarketPair[recipient] && sender != address(this) && sender != owner()) {
                          prizePoolAddress.updateBuyer(sender, amount, _getIsOdd());
                      }
                      if (!isMarketPair[sender] && !isMarketPair[recipient]) {
                          prizePoolAddress.deleteBuyer(sender);
                      }
                  }
                  if(!isTxLimitExempt[sender] && !isTxLimitExempt[recipient]) {
                      require(amount <= _maxTxAmount, "Transfer amount exceeds the maxTxAmount.");
                  }
                  uint256 contractTokenBalance = balanceOf(address(this));
                  bool overMinimumTokenBalance = contractTokenBalance >= minimumTokensBeforeSwap;
                  if (overMinimumTokenBalance && !inSwapAndLiquify && !isMarketPair[sender] && swapAndLiquifyEnabled)
                  {
                      if(swapAndLiquifyByLimitOnly)
                          contractTokenBalance = minimumTokensBeforeSwap;
                      swapAndLiquify(contractTokenBalance);
                  }
                  _balances[sender] = _balances[sender].sub(amount, "Insufficient Balance");
                  if(checkWalletLimit && !isWalletLimitExempt[recipient])
                      require(balanceOf(recipient).add(finalAmount) <= _walletMax);
                  _balances[recipient] = _balances[recipient].add(finalAmount);
                  emit Transfer(sender, recipient, finalAmount);
                  return true;
              }
          }
          function _basicTransfer(address sender, address recipient, uint256 amount) internal returns (bool) {
              _balances[sender] = _balances[sender].sub(amount, "Insufficient Balance");
              _balances[recipient] = _balances[recipient].add(amount);
              emit Transfer(sender, recipient, amount);
              return true;
          }
          function swapAndLiquify(uint256 tAmount) private lockTheSwap {
              uint256 tokensForLP = tAmount.mul(_lpShare).div(_totalDistributionShares).div(2);
              uint256 tokensForSwap = tAmount.sub(tokensForLP);
              swapTokensForEth(tokensForSwap);
              uint256 amountReceived = address(this).balance;
              uint256 totalETHFee = _totalDistributionShares.sub(_lpShare.div(2));
              uint256 amountETHLiquidity = amountReceived.mul(_lpShare).div(totalETHFee).div(2);
              uint256 amountETHPool = amountReceived.mul(_prizeShare).div(totalETHFee);
              uint256 amountETHBuyback = amountReceived.mul(_buyBackShare).div(totalETHFee);
              uint256 amountETHSofi = amountReceived.mul(_sofiShare).div(totalETHFee);
              uint256 amountETHHouse = amountReceived.mul(_houseShare).div(totalETHFee);
              uint256 amountETHMarketing = amountReceived - amountETHLiquidity - amountETHPool - amountETHBuyback - amountETHSofi - amountETHHouse;
              if(amountETHMarketing > 0)
                  marketingWalletAddress.addPayment{value: amountETHMarketing}();
              if(amountETHBuyback > 0)
                  transferToAddressETH(payable(address(buybackAddress)), amountETHBuyback);
              if(amountETHSofi > 0) {
                  transferToAddressETH(soFiPoolAddress, amountETHSofi);
              }
              if(amountETHHouse > 0) {
                  transferToAddressETH(housePoolAddress, amountETHHouse);
              }
              if(amountETHPool > 0)
                  transferToAddressETH(payable(address(prizePoolAddress)), amountETHPool);
              if(amountETHLiquidity > 0 && tokensForLP > 0)
                  addLiquidity(tokensForLP, amountETHLiquidity);
          }
          function addLiquidity(uint256 tokenAmount, uint256 ethAmount) private {
              // approve token transfer to cover all possible scenarios
              _approve(address(this), address(_uniswapV2Router), tokenAmount);
              // add the liquidity
              _uniswapV2Router.addLiquidityETH{value: ethAmount}(
                  address(this),
                  tokenAmount,
                  0, // slippage is unavoidable
                  0, // slippage is unavoidable
                  owner(),
                  block.timestamp
              );
          }
          function swapTokensForEth(uint256 tokenAmount) private {
              // generate the uniswap pair path of token -> weth
              address[] memory path = new address[](2);
              path[0] = address(this);
              path[1] = _uniswapV2Router.WETH();
              _approve(address(this), address(_uniswapV2Router), tokenAmount);
              // make the swap
              _uniswapV2Router.swapExactTokensForETHSupportingFeeOnTransferTokens(
                  tokenAmount,
                  0, // accept any amount of ETH
                  path,
                  address(this), // The contract
                  block.timestamp
              );
              emit SwapTokensForETH(tokenAmount, path);
          }
          function takeFee(address sender, address recipient, uint256 amount) internal returns (uint256) {
              uint256 feeAmount = 0;
              if(isMarketPair[sender]) {
                  feeAmount = amount.mul(_totalTaxIfBuying).div(100);
              }
              else if(isMarketPair[recipient]) {
                  feeAmount = amount.mul(_totalTaxIfSelling).div(100);
              }
              if(feeAmount > 0) {
                  _balances[address(this)] = _balances[address(this)].add(feeAmount);
                  emit Transfer(sender, address(this), feeAmount);
              }
              return amount.sub(feeAmount);
          }
          function getUsdtEthPrice() external view returns(uint256) {
              return _getUsdtEthPrice();
          }
          function getPrice() external view returns(uint256) {
              return _getPrice();
          }
          function _getUsdtEthPrice() internal view returns(uint256) {
              IUniswapV2Pair pair = IUniswapV2Pair(_getUsdtPair());
              address token0 = pair.token0();
              (uint256 reserve0, uint256 reserve1,) = pair.getReserves();
              if (token0 == usdtAddress) {
                  return uint256(reserve0 * (10**30) / reserve1);
              } else {
                  return uint256(reserve1 * (10**30) / reserve0);
              }
          }
          function getIsOdd() external view returns(bool) {
              return _getIsOdd();
          }
          function _getIsOdd() internal view returns(bool) {
              uint reminder = _getTokenPriceInUsd() % 2;
              if(reminder == 0)
                  return false;
              else
                  return true;
          }
          function getTokenPriceInUsd() external view returns(uint256) {
              return _getTokenPriceInUsd();
          }
          function _getTokenPriceInUsd() internal view returns(uint256) {
              return (_getPrice() * _getUsdtEthPrice()) / 10**30;
          }
          function _getUsdtPair() internal view returns(address) {
              return IUniswapV2Factory(_uniswapV2Router.factory()).getPair(usdtAddress, _uniswapV2Router.WETH());
          }
          function _getPrice() internal view returns(uint256) {
              IUniswapV2Pair pair = IUniswapV2Pair(uniswapPair);
              address token0 = pair.token0();
              (uint256 reserve0, uint256 reserve1,) = pair.getReserves();
              if (token0 == address(this)) {
                  return uint256(reserve1 * 1 ether / reserve0);
              } else {
                  return uint256(reserve0 * 1 ether / reserve1);
              }
          }
      }

      File 3 of 3: PRIZEPOOL
      // SPDX-License-Identifier: Unlicensed
      pragma solidity ^0.8.0;
      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);
      }// SPDX-License-Identifier: Unlicensed
      pragma solidity ^0.8.0;
      import "./IERC20.sol";
      interface IOE is IERC20 {
          function getIsOdd() external view returns(bool);
      }
      // SPDX-License-Identifier: Unlicensed
      pragma solidity ^0.8.0;
      interface IPool {
          function addBuyer(address buyerAddress, uint256 amount, bool isOdd) external;
          function updateBuyer(address buyerAddress, uint256 amount, bool isOdd) external;
          function deleteBuyer(address buyerAddress) external;
      }
      // SPDX-License-Identifier: Unlicensed
      pragma solidity ^0.8.0;
      abstract contract Context {
          function _msgSender() internal view virtual returns (address payable) {
              return payable(msg.sender);
          }
          function _msgData() internal view virtual returns (bytes memory) {
              this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
              return msg.data;
          }
      }
      contract Ownable is Context {
          address private _owner;
          event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
          constructor () {
              address msgSender = _msgSender();
              _owner = msgSender;
              emit OwnershipTransferred(address(0), msgSender);
          }
          function owner() public view returns (address) {
              return _owner;
          }
          modifier onlyOwner() {
              require(_owner == _msgSender(), "Ownable: caller is not the owner");
              _;
          }
          function waiveOwnership() public virtual onlyOwner {
              emit OwnershipTransferred(_owner, address(0));
              _owner = address(0);
          }
          function transferOwnership(address newOwner) public virtual onlyOwner {
              require(newOwner != address(0), "Ownable: new owner is the zero address");
              emit OwnershipTransferred(_owner, newOwner);
              _owner = newOwner;
          }
      }// SPDX-License-Identifier: Unlicensed
      pragma solidity ^0.8.0;
      import "./Ownable.sol";
      import "../interfaces/IPool.sol";
      import "../interfaces/IOE.sol";
      contract PRIZEPOOL is Ownable, IPool {
          uint256 public evenAmount;
          uint256 public oddAmount;
          uint256 public lastBalance;
          struct withdrawItem {
              uint256 amount;
              uint256 time;
          }
          struct oeStorage {
              uint256 odd;
              uint256 even;
              uint256 oddIndex;
              uint256 evenIndex;
              uint256 balance;
          }
          event AddOdd(address user, uint256 amount);
          event AddEven(address user, uint256 amount);
          event RemoveOdd(address user);
          event RemoveEven(address user);
          event Update(address user, uint256 newOdd, uint256 newEven);
          event Withdraw(address user, uint256 amount);
          mapping(address => withdrawItem[]) public withdraws;
          mapping(address => oeStorage) public users;
          address[] public evenUsers;
          address[] public oddUsers;
          address public token;
          modifier onlyToken() {
              require(token == _msgSender() || owner() == _msgSender(), "Ownable: caller is not the owner");
              _;
          }
          receive() external payable {}
          fallback() external payable {}
          function setTokenAddress(address _token) external onlyOwner {
              require(_token != address(0), 'Error: zero address');
              token = _token;
          }
          function getListOfUsers(bool isOdd) external view returns(address[] memory){
              if (isOdd) {
                  return oddUsers;
              }
              return evenUsers;
          }
          function getUserWithdraws(address user) external view returns(withdrawItem[] memory) {
              return withdraws[user];
          }
          function addBuyer(address buyerAddress, uint256 amount, bool isOdd) external onlyToken {
              if (buyerAddress == address(0) || buyerAddress == token) {
                  return;
              }
              if (isOdd) {
                  oddAmount += amount;
                  if (users[buyerAddress].odd == 0) {
                      oddUsers.push(buyerAddress);
                      users[buyerAddress].oddIndex = oddUsers.length;
                  }
                  users[buyerAddress].odd += amount;
                  emit AddOdd(buyerAddress, amount);
              } else {
                  evenAmount += amount;
                  if (users[buyerAddress].even == 0) {
                      evenUsers.push(buyerAddress);
                      users[buyerAddress].evenIndex = evenUsers.length;
                  }
                  users[buyerAddress].even += amount;
                  emit AddEven(buyerAddress, amount);
              }
          }
          function updateBuyer(address buyerAddress, uint256 amount, bool isOdd) external onlyToken {
              if (buyerAddress == address(0) || buyerAddress == token) {
                  return;
              }
              uint256 balance = IOE(token).balanceOf(buyerAddress) - amount;
              if (isOdd) {
                  if (users[buyerAddress].evenIndex > 0) {
                      _updateEvenArrays(buyerAddress);
                      evenAmount -= users[buyerAddress].even;
                      users[buyerAddress].even = 0;
                  }
                  if (balance > 0) {
                      oddAmount -= users[buyerAddress].odd;
                      oddAmount += balance;
                      if (users[buyerAddress].oddIndex == 0) {
                          oddUsers.push(buyerAddress);
                          users[buyerAddress].oddIndex = oddUsers.length;
                      }
                      users[buyerAddress].odd = balance;
                  }
              } else {
                  if (users[buyerAddress].oddIndex > 0) {
                      _updateOddArrays(buyerAddress);
                      oddAmount -= users[buyerAddress].odd;
                      users[buyerAddress].odd = 0;
                  }
                  if (balance > 0) {
                      evenAmount -= users[buyerAddress].even;
                      evenAmount += balance;
                      if (users[buyerAddress].evenIndex == 0) {
                          evenUsers.push(buyerAddress);
                          users[buyerAddress].evenIndex = evenUsers.length;
                      }
                      users[buyerAddress].even = balance;
                  }
              }
              emit Update(buyerAddress, users[buyerAddress].odd, users[buyerAddress].even);
          }
          function _updateEvenArrays(address buyerAddress) internal {
              address lastEvenUser = evenUsers[evenUsers.length - 1];
              evenUsers[users[buyerAddress].evenIndex - 1] = lastEvenUser;
              evenUsers.pop();
              users[lastEvenUser].evenIndex = users[buyerAddress].evenIndex;
              users[buyerAddress].evenIndex = 0;
          }
          function _updateOddArrays(address buyerAddress) internal {
              address lastOddUser = oddUsers[oddUsers.length - 1];
              oddUsers[users[buyerAddress].oddIndex - 1] = lastOddUser;
              oddUsers.pop();
              users[lastOddUser].oddIndex = users[buyerAddress].oddIndex;
              users[buyerAddress].oddIndex = 0;
          }
          function deleteBuyer(address buyerAddress) external onlyToken {
              if (buyerAddress == address(0) || buyerAddress == token) {
                  return;
              }
              if (users[buyerAddress].oddIndex > 0) {
                  _updateOddArrays(buyerAddress);
                  oddAmount -= users[buyerAddress].odd;
                  users[buyerAddress].odd = 0;
                  emit RemoveOdd(buyerAddress);
              }
              if (users[buyerAddress].evenIndex > 0) {
                  _updateEvenArrays(buyerAddress);
                  evenAmount -= users[buyerAddress].even;
                  users[buyerAddress].even = 0;
                  emit RemoveEven(buyerAddress);
              }
          }
          function withdrawByUser() external {
              require(users[msg.sender].balance > 0, 'Error balance amount');
              lastBalance -= users[msg.sender].balance;
              uint256 transferBalance = users[msg.sender].balance;
              users[msg.sender].balance = 0;
              payable(msg.sender).transfer(transferBalance);
              withdrawItem memory item = withdrawItem(transferBalance, block.timestamp);
              withdraws[msg.sender].push(item);
              emit Withdraw(msg.sender, transferBalance);
          }
          function activatePool() external onlyOwner {
              bool isOdd = IOE(token).getIsOdd();
              uint256 balance = address(this).balance - lastBalance;
              uint256 amount = 0;
              if (isOdd) {
                  uint256 unit = balance * 1 ether / oddAmount;
                  for (uint256 i = 0; i < oddUsers.length; i++) {
                      amount = unit * users[oddUsers[i]].odd;
                      users[oddUsers[i]].balance += amount / 1 ether;
                  }
              } else {
                  uint256 unit = balance * 1 ether / evenAmount;
                  for (uint256 i = 0; i < evenUsers.length; i++) {
                      amount = unit * users[evenUsers[i]].even;
                      users[evenUsers[i]].balance += amount / 1 ether;
                  }
              }
              lastBalance = address(this).balance;
          }
      }