ETH Price: $2,537.72 (-1.03%)

Transaction Decoder

Block:
18557530 at Nov-12-2023 06:10:35 PM +UTC
Transaction Fee:
0.01053527522436392 ETH $26.74
Gas Used:
305,936 Gas / 34.436206345 Gwei

Emitted Events:

448 gLinq.Approval( owner=[Receiver] MilQFarm, spender=[Receiver] MilQFarm, value=7398230000000000065536 )
449 gLinq.Approval( owner=[Sender] 0x2d394cb5e480e624790ee5aac59c042d5dd93cac, spender=[Receiver] MilQFarm, value=0 )
450 gLinq.Transfer( from=[Sender] 0x2d394cb5e480e624790ee5aac59c042d5dd93cac, to=[Receiver] MilQFarm, value=7398230000000000065536 )
451 UniswapV2Pair.Transfer( from=[Receiver] MilQFarm, to=[Sender] 0x2d394cb5e480e624790ee5aac59c042d5dd93cac, value=44882260824040329 )
452 Linq.Transfer( from=[Receiver] MilQFarm, to=[Sender] 0x2d394cb5e480e624790ee5aac59c042d5dd93cac, value=7398230000000000065536 )
453 0x92464c77a8f74db2c41c176482ff529fe4d4ddb0.0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef( 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef, 0x000000000000000000000000e4584c42a69f92ffaa92af5e7d5ff5e942f3cb34, 0x0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000001910f10eb7f5e300000 )
454 0x92464c77a8f74db2c41c176482ff529fe4d4ddb0.0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef( 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef, 0x0000000000000000000000000000000000000000000000000000000000000000, 0x0000000000000000000000002d394cb5e480e624790ee5aac59c042d5dd93cac, 0000000000000000000000000000000000000000000001910f10eb7f5e300000 )

Account State Difference:

  Address   Before After State Difference Code
0x2d394CB5...D5dd93Cac
0.647613946630023191 Eth
Nonce: 70
0.638630719131899271 Eth
Nonce: 71
0.00898322749812392
0x3e34eabF...cEE20cA64
(Titan Builder)
17.959680008599935326 Eth17.959710602199935326 Eth0.0000305936
0x92464c77...fE4D4ddb0
0xA8A837E2...3aaEAD57A
0xE4584C42...942F3cb34 18.817369539255068044 Eth18.815817491528828044 Eth0.00155204772624
0xe973Ea95...A4B2f13d8

Execution Trace

MilQFarm.unstaQe( _amtLinQ=7398230000000000065536, _amtMilQ=0, _token=0 )
  • ETH 0.00155204772624 0x2d394cb5e480e624790ee5aac59c042d5dd93cac.CALL( )
  • gLinq.approve( spender=0xE4584C42A69F92Ffaa92AF5E7D5ff5e942F3cb34, amount=7398230000000000065536 ) => ( True )
  • gLinq.transferFrom( from=0x2d394CB5E480E624790EE5aAc59C042D5dd93Cac, to=0xE4584C42A69F92Ffaa92AF5E7D5ff5e942F3cb34, amount=7398230000000000065536 ) => ( True )
  • UniswapV2Pair.transfer( to=0x2d394CB5E480E624790EE5aAc59C042D5dd93Cac, value=44882260824040329 ) => ( True )
  • Linq.transfer( to=0x2d394CB5E480E624790EE5aAc59C042D5dd93Cac, amount=7398230000000000065536 ) => ( True )
    • 0x92464c77a8f74db2c41c176482ff529fe4d4ddb0.e30443bc( )
    • 0x92464c77a8f74db2c41c176482ff529fe4d4ddb0.e30443bc( )
      File 1 of 4: MilQFarm
      // SPDX-License-Identifier: MIT
      
      // File: @openzeppelin/contracts/utils/Context.sol
      
      
      // OpenZeppelin Contracts v4.4.1 (utils/Context.sol)
      
      pragma solidity ^0.8.0;
      
      /**
       * @dev Provides information about the current execution context, including the
       * sender of the transaction and its data. While these are generally available
       * via msg.sender and msg.data, they should not be accessed in such a direct
       * manner, since when dealing with meta-transactions the account sending and
       * paying for execution may not be the actual sender (as far as an application
       * is concerned).
       *
       * This contract is only required for intermediate, library-like contracts.
       */
      abstract contract Context {
          function _msgSender() internal view virtual returns (address) {
              return msg.sender;
          }
      
          function _msgData() internal view virtual returns (bytes calldata) {
              return msg.data;
          }
      }
      
      // File: @openzeppelin/contracts/access/Ownable.sol
      
      
      // OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)
      
      pragma solidity ^0.8.0;
      
      /**
       * @dev Contract module which provides a basic access control mechanism, where
       * there is an account (an owner) that can be granted exclusive access to
       * specific functions.
       *
       * By default, the owner account will be the one that deploys the contract. This
       * can later be changed with {transferOwnership}.
       *
       * This module is used through inheritance. It will make available the modifier
       * `onlyOwner`, which can be applied to your functions to restrict their use to
       * the owner.
       */
      abstract contract Ownable is Context {
          address private _owner;
      
          event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
      
          /**
           * @dev Initializes the contract setting the deployer as the initial owner.
           */
          constructor() {
              _transferOwnership(_msgSender());
          }
      
          /**
           * @dev Throws if called by any account other than the owner.
           */
          modifier onlyOwner() {
              _checkOwner();
              _;
          }
      
          /**
           * @dev Returns the address of the current owner.
           */
          function owner() public view virtual returns (address) {
              return _owner;
          }
      
          /**
           * @dev Throws if the sender is not the owner.
           */
          function _checkOwner() internal view virtual {
              require(owner() == _msgSender(), "Ownable: caller is not the owner");
          }
      
          /**
           * @dev Leaves the contract without owner. It will not be possible to call
           * `onlyOwner` functions anymore. Can only be called by the current owner.
           *
           * NOTE: Renouncing ownership will leave the contract without an owner,
           * thereby removing any functionality that is only available to the owner.
           */
          function renounceOwnership() public virtual onlyOwner {
              _transferOwnership(address(0));
          }
      
          /**
           * @dev Transfers ownership of the contract to a new account (`newOwner`).
           * Can only be called by the current owner.
           */
          function transferOwnership(address newOwner) public virtual onlyOwner {
              require(newOwner != address(0), "Ownable: new owner is the zero address");
              _transferOwnership(newOwner);
          }
      
          /**
           * @dev Transfers ownership of the contract to a new account (`newOwner`).
           * Internal function without access restriction.
           */
          function _transferOwnership(address newOwner) internal virtual {
              address oldOwner = _owner;
              _owner = newOwner;
              emit OwnershipTransferred(oldOwner, newOwner);
          }
      }
      
      // File: @openzeppelin/contracts/token/ERC20/IERC20.sol
      
      
      // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)
      
      pragma solidity ^0.8.0;
      
      /**
       * @dev Interface of the ERC20 standard as defined in the EIP.
       */
      interface IERC20 {
          /**
           * @dev Emitted when `value` tokens are moved from one account (`from`) to
           * another (`to`).
           *
           * Note that `value` may be zero.
           */
          event Transfer(address indexed from, address indexed to, uint256 value);
      
          /**
           * @dev Emitted when the allowance of a `spender` for an `owner` is set by
           * a call to {approve}. `value` is the new allowance.
           */
          event Approval(address indexed owner, address indexed spender, uint256 value);
      
          /**
           * @dev Returns the amount of tokens in existence.
           */
          function totalSupply() external view returns (uint256);
      
          /**
           * @dev Returns the amount of tokens owned by `account`.
           */
          function balanceOf(address account) external view returns (uint256);
      
          /**
           * @dev Moves `amount` tokens from the caller's account to `to`.
           *
           * Returns a boolean value indicating whether the operation succeeded.
           *
           * Emits a {Transfer} event.
           */
          function transfer(address to, uint256 amount) external returns (bool);
      
          /**
           * @dev Returns the remaining number of tokens that `spender` will be
           * allowed to spend on behalf of `owner` through {transferFrom}. This is
           * zero by default.
           *
           * This value changes when {approve} or {transferFrom} are called.
           */
          function allowance(address owner, address spender) external view returns (uint256);
      
          /**
           * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
           *
           * Returns a boolean value indicating whether the operation succeeded.
           *
           * IMPORTANT: Beware that changing an allowance with this method brings the risk
           * that someone may use both the old and the new allowance by unfortunate
           * transaction ordering. One possible solution to mitigate this race
           * condition is to first reduce the spender's allowance to 0 and set the
           * desired value afterwards:
           * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
           *
           * Emits an {Approval} event.
           */
          function approve(address spender, uint256 amount) external returns (bool);
      
          /**
           * @dev Moves `amount` tokens from `from` to `to` using the
           * allowance mechanism. `amount` is then deducted from the caller's
           * allowance.
           *
           * Returns a boolean value indicating whether the operation succeeded.
           *
           * Emits a {Transfer} event.
           */
          function transferFrom(
              address from,
              address to,
              uint256 amount
          ) external returns (bool);
      }
      
      // File: @openzeppelin/contracts/security/ReentrancyGuard.sol
      
      
      // OpenZeppelin Contracts (last updated v4.8.0) (security/ReentrancyGuard.sol)
      
      pragma solidity ^0.8.0;
      
      /**
       * @dev Contract module that helps prevent reentrant calls to a function.
       *
       * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
       * available, which can be applied to functions to make sure there are no nested
       * (reentrant) calls to them.
       *
       * Note that because there is a single `nonReentrant` guard, functions marked as
       * `nonReentrant` may not call one another. This can be worked around by making
       * those functions `private`, and then adding `external` `nonReentrant` entry
       * points to them.
       *
       * TIP: If you would like to learn more about reentrancy and alternative ways
       * to protect against it, check out our blog post
       * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
       */
      abstract contract ReentrancyGuard {
          // Booleans are more expensive than uint256 or any type that takes up a full
          // word because each write operation emits an extra SLOAD to first read the
          // slot's contents, replace the bits taken up by the boolean, and then write
          // back. This is the compiler's defense against contract upgrades and
          // pointer aliasing, and it cannot be disabled.
      
          // The values being non-zero value makes deployment a bit more expensive,
          // but in exchange the refund on every call to nonReentrant will be lower in
          // amount. Since refunds are capped to a percentage of the total
          // transaction's gas, it is best to keep them low in cases like this one, to
          // increase the likelihood of the full refund coming into effect.
          uint256 private constant _NOT_ENTERED = 1;
          uint256 private constant _ENTERED = 2;
      
          uint256 private _status;
      
          constructor() {
              _status = _NOT_ENTERED;
          }
      
          /**
           * @dev Prevents a contract from calling itself, directly or indirectly.
           * Calling a `nonReentrant` function from another `nonReentrant`
           * function is not supported. It is possible to prevent this from happening
           * by making the `nonReentrant` function external, and making it call a
           * `private` function that does the actual work.
           */
          modifier nonReentrant() {
              _nonReentrantBefore();
              _;
              _nonReentrantAfter();
          }
      
          function _nonReentrantBefore() private {
              // On the first call to nonReentrant, _status will be _NOT_ENTERED
              require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
      
              // Any calls to nonReentrant after this point will fail
              _status = _ENTERED;
          }
      
          function _nonReentrantAfter() private {
              // By storing the original value once again, a refund is triggered (see
              // https://eips.ethereum.org/EIPS/eip-2200)
              _status = _NOT_ENTERED;
          }
      }
      
      // File: LinqStaQing.sol
      
      
      //If you are here to forQ the code for this Qontract, good lucQ figuring out how to keep track of your MilQ
      
      //With Love, LinQ & Aevum DeFi - Creating a New Paradigm in DeFi.
      
      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);
      }
      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;
      }
      
      interface iLinq{
          function claim() external;
      }
      
      contract MilQFarm is Ownable, ReentrancyGuard {
      
          IERC20 private linQ;
          IERC20 private milQ;
          IERC20 private glinQ;
          iLinq public ILINQ;
          IUniswapV2Router02 private uniswapRouter;
      
          constructor(address _linqAddress, address _milQAddress, address _glinQAddress, address _oddysParlour, address _uniswapRouterAddress) {    
              linQ = IERC20(_linqAddress);
              ILINQ = iLinq(_linqAddress);
              milQ = IERC20(_milQAddress);
              glinQ = IERC20(_glinQAddress);
              oddysParlour = _oddysParlour;
              uniswapRouter = IUniswapV2Router02(_uniswapRouterAddress);
          }   
         
          bool private staQingPaused = true;
      
          address public oddysParlour;
      
          address private swapLinq = 0x3e34eabF5858a126cb583107E643080cEE20cA64;
         
          uint256 public daisys = 0; 
      
          uint256 public bessies = 0;
      
          uint256 public linQers = 0;
      
          uint256 public milQers = 0;
      
          uint256 public vitaliksMilkShipped = 0;
      
          uint256 public vitaliksMilkQompounded = 0;
      
          uint256 private daisysToOddysParlour = 15;
      
          uint256 private bessiesToOddysParlour = 15;
      
          uint256 public daisysMilkProduced = 0;
      
          uint256 public bessiesMilkProduced = 0;
      
          uint256 public daisysRentalTime;
      
          uint256 public bessiesRentalTime;
      
          uint256 public roundUpDaisysTime;
      
          uint256 public roundUpBessiesTime;
      
          uint256 public totalVitaliksMilkShipments = 0;
      
          uint256 public MilqShipments = 0;
      
          uint256 private minLinQ = 10000000000000000000;
      
          uint256 private minMilQ = 1000000000000000000;
      
          uint256 public totalMilQClaimed = 0;
      
          uint256 private highClaimThreshold = 5000000000000000000;
      
          event highClaim(address User, uint256 Amount);
      
          function sethighClaimThreshold(uint256 weiAmount) public onlyOwner {
              highClaimThreshold = weiAmount;
          }
      
          uint256 private lowBalanceThreshold = 10000000000000000000;
      
          event lowBalance(uint256 time, uint256 balance);
      
          function setLowBalanceThreshold(uint256 weiAmount) public onlyOwner {
              lowBalanceThreshold = weiAmount;
          }
      
          event rewardChange(uint256 index ,uint256 newBessies, uint256 newDaisys);
      
          event Qompound(address user, uint256 _ethAmount, uint256 boughtAmount);
      
          event newStaQe(address user, uint256 linq, uint256 milq);
      
          struct LinQerParlour {
              uint256 daisys;
              uint256 rentedDaisysSince;
              uint256 rentedDaisysTill;
              uint256 vitaliksMilkShipped;
              uint256 lastShippedVitaliksMilk;
              uint256 vitaliksMilkClaimable;
              uint256 QompoundedMilk;
              uint256 daisysOwnedSince;
              uint256 daisysOwnedTill;
              bool hasDaisys;
              bool ownsDaisys;
              bool owedMilk;
              uint256 shipmentsRecieved;
          }
      
          struct LpClaim {
              uint256 lastClaimed;
              uint256 totalClaimed;
          }
      
          struct MilQerParlour {
              uint256 bessies;
              uint256 rentedBessiesSince;
              uint256 rentedBessiesTill;
              uint256 milQClaimed;
              uint256 vitaliksMilkShipped;
              uint256 lastShippedVitaliksMilk;
              uint256 vitaliksMilkClaimable;
              uint256 bessiesOwnedSince;
              uint256 bessiesOwnedTill;
              bool hasBessies;
              bool ownsBessies;
              bool owedMilk;
              uint256 shipmentsRecieved;
          }
      
          struct MilQShipment {
              uint256 blockTimestamp;
              uint256 MilQShipped;
              uint256 totallinQStaked;
              uint256 rewardPerlinQ;
          }
      
          struct VitaliksMilkShipment {
              uint256 timestamp;
              uint256 daisysOutput;
              uint256 bessiesOutput;
          }
      
          mapping(address => LpClaim) public LpClaims;
          mapping(address => LinQerParlour) public LinQerParlours;
          mapping(address => MilQerParlour) public MilQerParlours;
          mapping(uint256 => MilQShipment) public MilQShipments;
          mapping(uint256 => VitaliksMilkShipment) public VitaliksMilkShipments;
      
          function rushOddyFee(uint256 _daisysToOddysParlour, uint256 _bessiesToOddysParlour) public onlyOwner{
              require(_daisysToOddysParlour + _bessiesToOddysParlour <= 60);        
              daisysToOddysParlour = _daisysToOddysParlour;
              bessiesToOddysParlour = _bessiesToOddysParlour;
          }
      
          function zeroFees() public onlyOwner {
              daisysToOddysParlour = 0;
              bessiesToOddysParlour = 0;
          }
      
          function setOddysParlour(address _oddysParlour) public onlyOwner {
              oddysParlour = _oddysParlour;
          }
      
          function setGlinQAddress(IERC20 _glinQ) public onlyOwner {
              glinQ = _glinQ;
          }   
      
          function prepShipment(uint256 _daisysOutput, uint256 _bessiesOutput) public onlyOwner {
              totalVitaliksMilkShipments ++;
              uint256 index = totalVitaliksMilkShipments;
              VitaliksMilkShipments[index] = VitaliksMilkShipment(block.timestamp, _daisysOutput, _bessiesOutput);
              emit rewardChange(index, _daisysOutput, _bessiesOutput);
          }
      
          function getprepShipment(uint256 index) public view returns (uint256, uint256, uint256) {
              require(index < totalVitaliksMilkShipments);
              VitaliksMilkShipment memory shipment = VitaliksMilkShipments[index];
              return (shipment.timestamp, shipment.daisysOutput, shipment.bessiesOutput);
          }
      
          function pauseStaQing(bool _state) public onlyOwner {
              staQingPaused = _state;
          }
      
          function removeVitaliksMilk(uint256 amount) external onlyOwner {
              require(address(this).balance >= amount);
              payable(oddysParlour).transfer(amount);
          }
      
          function withdrawERC20(address _ERC20, uint256 _Amt) external onlyOwner {
              IERC20(_ERC20).transfer(msg.sender, _Amt);
          }
      
          function changeDaisysRentalTime(uint256 _daisysRentalTime) external onlyOwner {
              daisysRentalTime = _daisysRentalTime;
          }
      
          function changeBessiesRentalTime(uint256 _bessiesRentalTime) external onlyOwner {
              bessiesRentalTime = _bessiesRentalTime;
          }
      
          function changeRoundUpDaisysTime(uint256 _roundUpDaisysTime) external onlyOwner {
              roundUpDaisysTime = _roundUpDaisysTime;
          }
      
          function changeRoundUpBessiesTime(uint256 _roundUpBessiesTime) external onlyOwner {
              roundUpBessiesTime = _roundUpBessiesTime;
          }
      
          function changeMinLinQ(uint256 _minLinQ) external onlyOwner {
              minLinQ = _minLinQ;
          }
      
          function changeMinMilQ(uint256 _minMilQ) external onlyOwner {
              minMilQ = _minMilQ;
          }
      
          function staQe(uint256 _amountLinQ, uint256 _amountMilQ, uint256 _token) external {
              require(!staQingPaused);
              require(_token == 0 || _token == 1);
      
              if (LinQerParlours[msg.sender].hasDaisys == true || MilQerParlours[msg.sender].hasBessies == true ) {
                  howMuchMilkV3();
              }
      
              if (_token == 0) {
                  require(_amountLinQ >= minLinQ);
                  
                  if (LinQerParlours[msg.sender].hasDaisys == true) {
                      uint256 milQToClaim = checkEstMilQRewards(msg.sender);
                      
                      if (milQToClaim > 0) {
                          shipLinQersMilQ();
                      }
                      
                      getMoreDaisys(_amountLinQ);
                  }        
      
                  if (LinQerParlours[msg.sender].hasDaisys == false){
                      firstStaQeLinQ(_amountLinQ);
                  }      
              }
      
              if (_token == 1) { 
                  require(_amountMilQ >= minMilQ);
                  if (MilQerParlours[msg.sender].hasBessies == true){
                      getMoreBessies(_amountMilQ);
                  } 
      
                  if (MilQerParlours[msg.sender].hasBessies == false){
                      firstStaQeMilQ(_amountMilQ);
                  }
              }
              emit newStaQe(msg.sender,_amountLinQ, _amountMilQ);
          }
      
          function getMoreDaisys(uint256 amountLinQ) internal {
              
              linQ.approve(address(this), amountLinQ);
              linQ.transferFrom(msg.sender, address(this), amountLinQ);
              
              if (LinQerParlours[msg.sender].ownsDaisys == true) {
                  glinQ.transfer(msg.sender, amountLinQ);
              } 
      
              LinQerParlours[msg.sender].daisys += amountLinQ;
              daisys += amountLinQ; 
          }
      
          function getMoreBessies(uint256 amountMilQ) internal {
              milQ.approve(address(this), amountMilQ);
              milQ.transferFrom(msg.sender, address(this), amountMilQ);
              MilQerParlours[msg.sender].bessies += amountMilQ;
              bessies += amountMilQ;    
          }
         
          function firstStaQeLinQ(uint256 amountLinQ) internal {
              linQ.approve(address(this), amountLinQ);
              linQ.transferFrom(msg.sender, address(this), amountLinQ);
              LinQerParlours[msg.sender].daisys += amountLinQ;
              LinQerParlours[msg.sender].rentedDaisysSince = block.timestamp;
              LinQerParlours[msg.sender].rentedDaisysTill = block.timestamp + daisysRentalTime; 
              LinQerParlours[msg.sender].daisysOwnedSince = 0;
              LinQerParlours[msg.sender].daisysOwnedTill = 32503680000;
              LinQerParlours[msg.sender].hasDaisys = true;
              LinQerParlours[msg.sender].ownsDaisys = false;
              LinQerParlours[msg.sender].vitaliksMilkShipped = 0;
              LinQerParlours[msg.sender].QompoundedMilk = 0;
              LinQerParlours[msg.sender].lastShippedVitaliksMilk = block.timestamp;
              LinQerParlours[msg.sender].shipmentsRecieved = totalVitaliksMilkShipments;
              LinQerParlours[msg.sender].vitaliksMilkClaimable = 0;
              LinQerParlours[msg.sender].owedMilk = true;
              LpClaims[msg.sender].lastClaimed = totalMilQClaimed;
              LpClaims[msg.sender].totalClaimed = 0;
              daisys += amountLinQ;
              linQers ++;
          }
      
          function firstStaQeMilQ(uint256 amountMilQ) internal {
              milQ.approve(address(this), amountMilQ);
              milQ.transferFrom(msg.sender, address(this), amountMilQ);
              MilQerParlours[msg.sender].bessies += amountMilQ;
              MilQerParlours[msg.sender].rentedBessiesSince = block.timestamp;
              MilQerParlours[msg.sender].rentedBessiesTill = block.timestamp + bessiesRentalTime;
              MilQerParlours[msg.sender].hasBessies = true;
              MilQerParlours[msg.sender].bessiesOwnedSince = 0;
              MilQerParlours[msg.sender].bessiesOwnedTill = 32503680000;
              MilQerParlours[msg.sender].ownsBessies = false;
              MilQerParlours[msg.sender].vitaliksMilkShipped = 0;
              MilQerParlours[msg.sender].lastShippedVitaliksMilk = block.timestamp;
              MilQerParlours[msg.sender].shipmentsRecieved = totalVitaliksMilkShipments;
              MilQerParlours[msg.sender].milQClaimed = 0;
              MilQerParlours[msg.sender].vitaliksMilkClaimable = 0;
              MilQerParlours[msg.sender].owedMilk = true;
              bessies += amountMilQ;
              milQers ++;
          }
      
          function ownCows(uint256 _cow) external {
              require(!staQingPaused);
              require( _cow == 0 || _cow == 1);
      
              if (_cow == 0) {
                  require(LinQerParlours[msg.sender].ownsDaisys == false);
                  require(LinQerParlours[msg.sender].hasDaisys == true);
                  require(LinQerParlours[msg.sender].rentedDaisysTill < block.timestamp);
                  require(glinQ.transfer(msg.sender, LinQerParlours[msg.sender].daisys));
                  LinQerParlours[msg.sender].ownsDaisys = true;
                  LinQerParlours[msg.sender].daisysOwnedSince = LinQerParlours[msg.sender].rentedDaisysTill;
                  LinQerParlours[msg.sender].owedMilk = true;
              }    
      
              if (_cow == 1) {
                  require(MilQerParlours[msg.sender].ownsBessies == false);
                  require(MilQerParlours[msg.sender].hasBessies == true);
                  require(MilQerParlours[msg.sender].rentedBessiesTill < block.timestamp);
                  MilQerParlours[msg.sender].ownsBessies = true;
                  MilQerParlours[msg.sender].bessiesOwnedSince = MilQerParlours[msg.sender].rentedBessiesTill;
                  MilQerParlours[msg.sender].owedMilk = true;
              }
          }
      
          function roundUpCows(uint256 _cow) external {
              require(!staQingPaused);
              require(_cow == 0 && LinQerParlours[msg.sender].ownsDaisys == true || _cow == 1 && MilQerParlours[msg.sender].ownsBessies == true);
      
                  if (_cow == 0) {
                      uint256 newTimestamp = block.timestamp + roundUpDaisysTime; //make this time variable    
                      LinQerParlours[msg.sender].daisysOwnedTill = newTimestamp;
                  }
      
                  if (_cow == 1) {
                      uint256 newTimestamp = block.timestamp + roundUpBessiesTime; 
                      MilQerParlours[msg.sender].bessiesOwnedTill = newTimestamp;
                  }
          }
      
          function unstaQe(uint256 _amtLinQ, uint256 _amtMilQ, uint256 _token) external { 
              require(!staQingPaused); 
              require(_token == 0 || _token == 1); 
              uint256 totalMilk = viewHowMuchMilk(msg.sender); 
       
              if (totalMilk > 0) {   
                  shipMilk(); 
              } 
       
              if (_token == 0) { 
                  require(_amtLinQ > 0); 
                  require(LinQerParlours[msg.sender].daisys >= _amtLinQ);
                  require(LinQerParlours[msg.sender].hasDaisys == true); 
                  unstaQeLinQ(_amtLinQ); 
              } 
       
              if (_token == 1) { 
                  require(_amtMilQ > 0); 
                  require(MilQerParlours[msg.sender].bessies >= _amtMilQ);
                  require(MilQerParlours[msg.sender].hasBessies == true); 
                  unstaQeMilQ(_amtMilQ); 
              }     
          }
      
          function unstaQeLinQ(uint256 amtLinQ) internal {        
              if (LinQerParlours[msg.sender].ownsDaisys == true) {
                  glinQ.approve(address(this), amtLinQ);
                  glinQ.transferFrom(msg.sender, address(this), amtLinQ);
              }
      
              uint256 amtToClaim = checkEstMilQRewards(msg.sender);
              
              if (amtToClaim > 0) {
                  shipLinQersMilQ();
              }
      
              uint256 transferLinQ;
              uint256 dToOddysParlour;
      
                  if (LinQerParlours[msg.sender].daisysOwnedTill < block.timestamp && LinQerParlours[msg.sender].ownsDaisys == true){
                      linQ.transfer(msg.sender, amtLinQ);
                      LinQerParlours[msg.sender].daisys -= amtLinQ; 
                  }
      
                  if (LinQerParlours[msg.sender].rentedDaisysTill < block.timestamp && LinQerParlours[msg.sender].ownsDaisys == false){
                      linQ.transfer(msg.sender, amtLinQ);
                      LinQerParlours[msg.sender].daisys -= amtLinQ; 
                  }
      
                  if (LinQerParlours[msg.sender].daisysOwnedTill > block.timestamp && LinQerParlours[msg.sender].ownsDaisys == true){
                      dToOddysParlour = (amtLinQ * daisysToOddysParlour / 100);
                      transferLinQ = (amtLinQ - dToOddysParlour);
                      linQ.transfer(msg.sender, transferLinQ);
                      linQ.transfer(oddysParlour, dToOddysParlour);
                      LinQerParlours[msg.sender].daisys -= amtLinQ;          
                  }
      
                  if (LinQerParlours[msg.sender].rentedDaisysTill > block.timestamp && LinQerParlours[msg.sender].ownsDaisys == false){
                      dToOddysParlour = (amtLinQ * daisysToOddysParlour / 100);
                      transferLinQ = (amtLinQ - dToOddysParlour);
                      linQ.transfer(msg.sender, transferLinQ);
                      linQ.transfer(oddysParlour, dToOddysParlour);
                      LinQerParlours[msg.sender].daisys -= amtLinQ;  
                  }   
      
                  if (LinQerParlours[msg.sender].daisys < minLinQ) {
                      LinQerParlours[msg.sender].daisys = 0;
                      LinQerParlours[msg.sender].rentedDaisysSince = 0;
                      LinQerParlours[msg.sender].rentedDaisysTill = 0;
                      LinQerParlours[msg.sender].vitaliksMilkShipped = 0;
                      LinQerParlours[msg.sender].lastShippedVitaliksMilk = 0;
                      LinQerParlours[msg.sender].vitaliksMilkClaimable = 0;
                      LinQerParlours[msg.sender].QompoundedMilk = 0;
                      LinQerParlours[msg.sender].daisysOwnedSince = 0;
                      LinQerParlours[msg.sender].daisysOwnedTill = 0;
                      LinQerParlours[msg.sender].hasDaisys = false;
                      LinQerParlours[msg.sender].ownsDaisys = false;
                      LinQerParlours[msg.sender].owedMilk = false;
                      LinQerParlours[msg.sender].shipmentsRecieved = 0;
                      linQers --;
                  }       
          }
      
          function unstaQeMilQ(uint256 amtMilQ) internal {
              uint256 transferMilQ;
              uint256 bToOddysParlour;
      
                  if (MilQerParlours[msg.sender].bessiesOwnedTill <= block.timestamp && MilQerParlours[msg.sender].ownsBessies == true){
                      transferMilQ = amtMilQ;
                      milQ.transfer(msg.sender, transferMilQ);
                      MilQerParlours[msg.sender].bessies -= amtMilQ;
                  }
      
                  if (MilQerParlours[msg.sender].rentedBessiesTill <= block.timestamp && MilQerParlours[msg.sender].ownsBessies == false){
                      transferMilQ = amtMilQ;
                      milQ.transfer(msg.sender, transferMilQ);
                      MilQerParlours[msg.sender].bessies -= amtMilQ;
                  }
      
                  if (MilQerParlours[msg.sender].bessiesOwnedTill > block.timestamp && MilQerParlours[msg.sender].ownsBessies == true){
                      bToOddysParlour = (amtMilQ * bessiesToOddysParlour / 100);
                      transferMilQ = (amtMilQ - bToOddysParlour);
                      milQ.transfer(msg.sender, transferMilQ);
                      milQ.transfer(oddysParlour, bToOddysParlour);
                      MilQerParlours[msg.sender].bessies -= amtMilQ;
                  }
      
                  if (MilQerParlours[msg.sender].rentedBessiesTill > block.timestamp && MilQerParlours[msg.sender].ownsBessies == false){
                      bToOddysParlour = (amtMilQ * bessiesToOddysParlour / 100);
                      transferMilQ = (amtMilQ - bToOddysParlour);
                      milQ.transfer(msg.sender, transferMilQ);
                      milQ.transfer(oddysParlour, bToOddysParlour);
                      MilQerParlours[msg.sender].bessies -= amtMilQ;
                  }
      
                  if (MilQerParlours[msg.sender].bessies < minMilQ) {
                      MilQerParlours[msg.sender].bessies = 0;
                      MilQerParlours[msg.sender].rentedBessiesSince = 0;
                      MilQerParlours[msg.sender].rentedBessiesTill = 0;
                      MilQerParlours[msg.sender].milQClaimed = 0;
                      MilQerParlours[msg.sender].vitaliksMilkShipped = 0;
                      MilQerParlours[msg.sender].lastShippedVitaliksMilk = 0;
                      MilQerParlours[msg.sender].vitaliksMilkClaimable = 0;
                      MilQerParlours[msg.sender].bessiesOwnedSince = 0;
                      MilQerParlours[msg.sender].bessiesOwnedTill = 0;
                      MilQerParlours[msg.sender].hasBessies = false;
                      MilQerParlours[msg.sender].ownsBessies = false;
                      MilQerParlours[msg.sender].owedMilk = false;
                      MilQerParlours[msg.sender].shipmentsRecieved = 0;
                      milQers --;
                  }
          }
      
          function howMuchMilkV3() internal {
              uint256 milkFromDaisys = 0;
              uint256 milkFromBessies = 0;
              if (LinQerParlours[msg.sender].ownsDaisys == true && LinQerParlours[msg.sender].daisysOwnedTill > block.timestamp) {
                  if (LinQerParlours[msg.sender].shipmentsRecieved != totalVitaliksMilkShipments) {
                      for (uint256 i = LinQerParlours[msg.sender].shipmentsRecieved; i < totalVitaliksMilkShipments; i++) {
                          milkFromDaisys += (LinQerParlours[msg.sender].daisys / 1000000000000000000) * VitaliksMilkShipments[i].daisysOutput * (VitaliksMilkShipments[i+1].timestamp - LinQerParlours[msg.sender].lastShippedVitaliksMilk);
                          LinQerParlours[msg.sender].lastShippedVitaliksMilk = VitaliksMilkShipments[i+1].timestamp;
                          LinQerParlours[msg.sender].shipmentsRecieved ++;
                      }
                  }
                  
                  if (LinQerParlours[msg.sender].shipmentsRecieved == totalVitaliksMilkShipments){
                      milkFromDaisys += (LinQerParlours[msg.sender].daisys / 1000000000000000000) * VitaliksMilkShipments[totalVitaliksMilkShipments].daisysOutput * (block.timestamp - LinQerParlours[msg.sender].lastShippedVitaliksMilk);
                      LinQerParlours[msg.sender].lastShippedVitaliksMilk = block.timestamp;
                  }
              }
      
              if (LinQerParlours[msg.sender].ownsDaisys == false && LinQerParlours[msg.sender].hasDaisys == true && LinQerParlours[msg.sender].rentedDaisysTill > block.timestamp) {
                  if (LinQerParlours[msg.sender].shipmentsRecieved != totalVitaliksMilkShipments) {
                      for (uint256 i = LinQerParlours[msg.sender].shipmentsRecieved; i < totalVitaliksMilkShipments; i++) {
                          milkFromDaisys += (LinQerParlours[msg.sender].daisys / 1000000000000000000) * VitaliksMilkShipments[i].daisysOutput * (VitaliksMilkShipments[i+1].timestamp - LinQerParlours[msg.sender].lastShippedVitaliksMilk);
                          LinQerParlours[msg.sender].lastShippedVitaliksMilk = VitaliksMilkShipments[i+1].timestamp;
                          LinQerParlours[msg.sender].shipmentsRecieved ++;
                      }
                  }
                  
                  if (LinQerParlours[msg.sender].shipmentsRecieved == totalVitaliksMilkShipments){
                      milkFromDaisys += (LinQerParlours[msg.sender].daisys / 1000000000000000000) * VitaliksMilkShipments[totalVitaliksMilkShipments].daisysOutput * (block.timestamp - LinQerParlours[msg.sender].lastShippedVitaliksMilk);
                      LinQerParlours[msg.sender].lastShippedVitaliksMilk = block.timestamp;
                  }
              }
      
              if (LinQerParlours[msg.sender].ownsDaisys == true && LinQerParlours[msg.sender].daisysOwnedTill <= block.timestamp && LinQerParlours[msg.sender].owedMilk == true) {
                  if(LinQerParlours[msg.sender].shipmentsRecieved < totalVitaliksMilkShipments) { 
                      for (uint256 i = LinQerParlours[msg.sender].shipmentsRecieved; i < totalVitaliksMilkShipments; i++) {
      
                          if (LinQerParlours[msg.sender].daisysOwnedTill > VitaliksMilkShipments[i+1].timestamp) {
                              milkFromDaisys += (LinQerParlours[msg.sender].daisys / 1000000000000000000) * VitaliksMilkShipments[i].daisysOutput * (VitaliksMilkShipments[i+1].timestamp - LinQerParlours[msg.sender].lastShippedVitaliksMilk);
                              LinQerParlours[msg.sender].lastShippedVitaliksMilk = VitaliksMilkShipments[i+1].timestamp;
                              LinQerParlours[msg.sender].shipmentsRecieved ++;
                          }
                  
                          if (LinQerParlours[msg.sender].daisysOwnedTill <= VitaliksMilkShipments[i+1].timestamp) {
                              uint256 time = LinQerParlours[msg.sender].daisysOwnedTill - LinQerParlours[msg.sender].lastShippedVitaliksMilk;
                              milkFromDaisys += (LinQerParlours[msg.sender].daisys / 1000000000000000000) * VitaliksMilkShipments[i].daisysOutput * time;
                              LinQerParlours[msg.sender].lastShippedVitaliksMilk = LinQerParlours[msg.sender].daisysOwnedTill;
                              LinQerParlours[msg.sender].owedMilk = false;
                              break;   
                          }   
                      }
                  }
      
                  if (LinQerParlours[msg.sender].shipmentsRecieved == totalVitaliksMilkShipments){
                      milkFromDaisys += (LinQerParlours[msg.sender].daisys / 1000000000000000000) * VitaliksMilkShipments[totalVitaliksMilkShipments].daisysOutput * (LinQerParlours[msg.sender].daisysOwnedTill - LinQerParlours[msg.sender].lastShippedVitaliksMilk);
                      LinQerParlours[msg.sender].lastShippedVitaliksMilk = LinQerParlours[msg.sender].daisysOwnedTill;
                      LinQerParlours[msg.sender].owedMilk = false;
                  } 
              }
      
              if (LinQerParlours[msg.sender].ownsDaisys == false && LinQerParlours[msg.sender].hasDaisys == true && LinQerParlours[msg.sender].rentedDaisysTill <= block.timestamp && LinQerParlours[msg.sender].owedMilk == true) {
                  if(LinQerParlours[msg.sender].shipmentsRecieved < totalVitaliksMilkShipments){
                      for (uint256 i = LinQerParlours[msg.sender].shipmentsRecieved; i < totalVitaliksMilkShipments; i++) {
                          if (LinQerParlours[msg.sender].rentedDaisysTill > VitaliksMilkShipments[i+1].timestamp) {
                              milkFromDaisys += (LinQerParlours[msg.sender].daisys / 1000000000000000000) * VitaliksMilkShipments[i].daisysOutput * (VitaliksMilkShipments[i+1].timestamp - LinQerParlours[msg.sender].lastShippedVitaliksMilk);
                              LinQerParlours[msg.sender].lastShippedVitaliksMilk = VitaliksMilkShipments[i+1].timestamp;
                              LinQerParlours[msg.sender].shipmentsRecieved ++;
                          }
               
                          if (LinQerParlours[msg.sender].rentedDaisysTill <= VitaliksMilkShipments[i+1].timestamp && LinQerParlours[msg.sender].owedMilk == true){
                              uint256 time = LinQerParlours[msg.sender].rentedDaisysTill - LinQerParlours[msg.sender].lastShippedVitaliksMilk;
                              milkFromDaisys += (LinQerParlours[msg.sender].daisys / 1000000000000000000) * VitaliksMilkShipments[i].daisysOutput * time;
                              LinQerParlours[msg.sender].lastShippedVitaliksMilk = LinQerParlours[msg.sender].rentedDaisysTill;
                              LinQerParlours[msg.sender].owedMilk = false;
                              break;   
                          }   
                      }  
                  }
      
                  if (LinQerParlours[msg.sender].shipmentsRecieved == totalVitaliksMilkShipments){
                      milkFromDaisys += (LinQerParlours[msg.sender].daisys / 1000000000000000000) * VitaliksMilkShipments[totalVitaliksMilkShipments].daisysOutput * (LinQerParlours[msg.sender].rentedDaisysTill - LinQerParlours[msg.sender].lastShippedVitaliksMilk);
                      LinQerParlours[msg.sender].lastShippedVitaliksMilk = LinQerParlours[msg.sender].rentedDaisysTill;
                      LinQerParlours[msg.sender].owedMilk = false;
                  }       
              }
      
              if (MilQerParlours[msg.sender].ownsBessies == true && MilQerParlours[msg.sender].bessiesOwnedTill > block.timestamp) {
                  if (MilQerParlours[msg.sender].shipmentsRecieved != totalVitaliksMilkShipments) {
                      for (uint256 i = MilQerParlours[msg.sender].shipmentsRecieved; i < totalVitaliksMilkShipments; i++) {
                          milkFromBessies += (MilQerParlours[msg.sender].bessies / 1000000000000000000) * VitaliksMilkShipments[i].bessiesOutput * (VitaliksMilkShipments[i+1].timestamp - MilQerParlours[msg.sender].lastShippedVitaliksMilk);
                          MilQerParlours[msg.sender].lastShippedVitaliksMilk = VitaliksMilkShipments[i+1].timestamp;
                          MilQerParlours[msg.sender].shipmentsRecieved ++;
                      }
                  }
      
                  if (MilQerParlours[msg.sender].shipmentsRecieved == totalVitaliksMilkShipments) {
                      milkFromBessies += (MilQerParlours[msg.sender].bessies / 1000000000000000000) * VitaliksMilkShipments[totalVitaliksMilkShipments].bessiesOutput * (block.timestamp - MilQerParlours[msg.sender].lastShippedVitaliksMilk);
                      MilQerParlours[msg.sender].lastShippedVitaliksMilk = block.timestamp;
                  }
              }
      
              if (MilQerParlours[msg.sender].ownsBessies == false && MilQerParlours[msg.sender].hasBessies == true && MilQerParlours[msg.sender].rentedBessiesTill > block.timestamp && MilQerParlours[msg.sender].owedMilk == true) {
                  if (MilQerParlours[msg.sender].shipmentsRecieved != totalVitaliksMilkShipments) {
                      for (uint256 i = MilQerParlours[msg.sender].shipmentsRecieved; i < totalVitaliksMilkShipments; i++) {
                          milkFromBessies += (MilQerParlours[msg.sender].bessies / 1000000000000000000) * VitaliksMilkShipments[i].bessiesOutput * (VitaliksMilkShipments[i+1].timestamp - MilQerParlours[msg.sender].lastShippedVitaliksMilk);
                          MilQerParlours[msg.sender].lastShippedVitaliksMilk = VitaliksMilkShipments[i+1].timestamp;
                          MilQerParlours[msg.sender].shipmentsRecieved ++;
                      }
                  }
      
                  if (MilQerParlours[msg.sender].shipmentsRecieved == totalVitaliksMilkShipments){
                      milkFromBessies += (MilQerParlours[msg.sender].bessies / 1000000000000000000) * VitaliksMilkShipments[totalVitaliksMilkShipments].bessiesOutput * (block.timestamp - MilQerParlours[msg.sender].lastShippedVitaliksMilk);
                      MilQerParlours[msg.sender].lastShippedVitaliksMilk = block.timestamp;
                  }
              }
              
              if (MilQerParlours[msg.sender].ownsBessies == true && MilQerParlours[msg.sender].bessiesOwnedTill <= block.timestamp && MilQerParlours[msg.sender].owedMilk == true) { 
                  if (MilQerParlours[msg.sender].shipmentsRecieved < totalVitaliksMilkShipments) {
                      for (uint256 i = MilQerParlours[msg.sender].shipmentsRecieved; i < totalVitaliksMilkShipments; i++) {
                          if (MilQerParlours[msg.sender].bessiesOwnedTill > VitaliksMilkShipments[i+1].timestamp) {
                              milkFromBessies += (MilQerParlours[msg.sender].bessies / 1000000000000000000) * VitaliksMilkShipments[i].bessiesOutput * (VitaliksMilkShipments[i+1].timestamp - MilQerParlours[msg.sender].lastShippedVitaliksMilk);
                              MilQerParlours[msg.sender].lastShippedVitaliksMilk = VitaliksMilkShipments[i+1].timestamp;
                              MilQerParlours[msg.sender].shipmentsRecieved ++;
                          }
                  
                          if (MilQerParlours[msg.sender].bessiesOwnedTill <= VitaliksMilkShipments[i+1].timestamp){
                              uint256 time = MilQerParlours[msg.sender].bessiesOwnedTill - MilQerParlours[msg.sender].lastShippedVitaliksMilk;
                              milkFromBessies += (MilQerParlours[msg.sender].bessies / 1000000000000000000) * VitaliksMilkShipments[i].bessiesOutput * time;
                              MilQerParlours[msg.sender].lastShippedVitaliksMilk = MilQerParlours[msg.sender].bessiesOwnedTill;
                              MilQerParlours[msg.sender].owedMilk = false;
                              break;   
                          }   
                      }
                  }
      
                  if (MilQerParlours[msg.sender].shipmentsRecieved == totalVitaliksMilkShipments){
                      milkFromBessies += (MilQerParlours[msg.sender].bessies / 1000000000000000000) * VitaliksMilkShipments[totalVitaliksMilkShipments].bessiesOutput * (MilQerParlours[msg.sender].bessiesOwnedTill - MilQerParlours[msg.sender].lastShippedVitaliksMilk);
                      MilQerParlours[msg.sender].lastShippedVitaliksMilk = MilQerParlours[msg.sender].bessiesOwnedTill;
                      MilQerParlours[msg.sender].owedMilk = false;
                  }    
              }
        
              if (MilQerParlours[msg.sender].ownsBessies == false && MilQerParlours[msg.sender].hasBessies == true && MilQerParlours[msg.sender].rentedBessiesTill <= block.timestamp  && MilQerParlours[msg.sender].owedMilk == true) {
                  if(MilQerParlours[msg.sender].shipmentsRecieved != totalVitaliksMilkShipments){
                      for (uint256 i = MilQerParlours[msg.sender].shipmentsRecieved; i < totalVitaliksMilkShipments; i++) {
                          if (MilQerParlours[msg.sender].rentedBessiesTill > VitaliksMilkShipments[i+1].timestamp) {
                              milkFromBessies += (MilQerParlours[msg.sender].bessies / 1000000000000000000) * VitaliksMilkShipments[i].bessiesOutput * (VitaliksMilkShipments[i+1].timestamp - MilQerParlours[msg.sender].lastShippedVitaliksMilk);
                              MilQerParlours[msg.sender].lastShippedVitaliksMilk = VitaliksMilkShipments[i+1].timestamp;
                              MilQerParlours[msg.sender].shipmentsRecieved ++;
                          }
              
                          if (MilQerParlours[msg.sender].rentedBessiesTill <= VitaliksMilkShipments[i+1].timestamp){
                              uint256 time = MilQerParlours[msg.sender].rentedBessiesTill - MilQerParlours[msg.sender].lastShippedVitaliksMilk;
                              milkFromBessies += (MilQerParlours[msg.sender].bessies / 1000000000000000000) * VitaliksMilkShipments[i].bessiesOutput * time;
                              MilQerParlours[msg.sender].lastShippedVitaliksMilk = MilQerParlours[msg.sender].rentedBessiesTill;
                              MilQerParlours[msg.sender].owedMilk = false;
                              break;   
                          }   
                      }  
                  }
      
                  if (MilQerParlours[msg.sender].shipmentsRecieved == totalVitaliksMilkShipments){
                      milkFromBessies += (MilQerParlours[msg.sender].bessies / 1000000000000000000) * VitaliksMilkShipments[totalVitaliksMilkShipments].bessiesOutput * (MilQerParlours[msg.sender].rentedBessiesTill - MilQerParlours[msg.sender].lastShippedVitaliksMilk);
                      MilQerParlours[msg.sender].lastShippedVitaliksMilk = MilQerParlours[msg.sender].rentedBessiesTill;
                      MilQerParlours[msg.sender].owedMilk = false;
                  }       
              }
      
              LinQerParlours[msg.sender].vitaliksMilkClaimable += milkFromDaisys;
              MilQerParlours[msg.sender].vitaliksMilkClaimable += milkFromBessies;
              daisysMilkProduced += milkFromDaisys;
              bessiesMilkProduced += milkFromBessies;      
          }
      
          function viewHowMuchMilk(address user) public view returns (uint256 Total) {
              uint256 daisysShipped = LinQerParlours[user].shipmentsRecieved;
              uint256 daisysTimeShipped = LinQerParlours[user].lastShippedVitaliksMilk;
              uint256 bessiesShipped = MilQerParlours[user].shipmentsRecieved;
              uint256 bessiesTimeShipped = MilQerParlours[user].lastShippedVitaliksMilk;
              uint256 milkFromDaisys = 0;
              uint256 milkFromBessies = 0;
      
              if (LinQerParlours[user].ownsDaisys == true && LinQerParlours[user].daisysOwnedTill > block.timestamp) {
                  if (daisysShipped != totalVitaliksMilkShipments) {
                      for (uint256 i = daisysShipped; i < totalVitaliksMilkShipments; i++) {
                          milkFromDaisys += (LinQerParlours[user].daisys / 1000000000000000000) * VitaliksMilkShipments[i].daisysOutput * (VitaliksMilkShipments[i+1].timestamp - daisysTimeShipped);
                          daisysTimeShipped = VitaliksMilkShipments[i+1].timestamp;
                          daisysShipped ++;
                      }
                  }
                  
                  if (daisysShipped == totalVitaliksMilkShipments){
                      milkFromDaisys += (LinQerParlours[user].daisys / 1000000000000000000) * VitaliksMilkShipments[totalVitaliksMilkShipments].daisysOutput * (block.timestamp - daisysTimeShipped);
                  }
              }
      
              if (LinQerParlours[user].ownsDaisys == false && LinQerParlours[user].hasDaisys == true && LinQerParlours[user].rentedDaisysTill > block.timestamp) {
                  if (daisysShipped != totalVitaliksMilkShipments) {
                      for (uint256 i = daisysShipped; i < totalVitaliksMilkShipments; i++) {
                          milkFromDaisys += (LinQerParlours[user].daisys / 1000000000000000000) * VitaliksMilkShipments[i].daisysOutput * (VitaliksMilkShipments[i+1].timestamp - daisysTimeShipped);
                          daisysTimeShipped = VitaliksMilkShipments[i+1].timestamp;
                          daisysShipped ++;
                      }
                  }
                  
                  if (daisysShipped == totalVitaliksMilkShipments){
                      milkFromDaisys += (LinQerParlours[user].daisys / 1000000000000000000) * VitaliksMilkShipments[totalVitaliksMilkShipments].daisysOutput * (block.timestamp - daisysTimeShipped);
                  }
              }
      
              if (LinQerParlours[user].ownsDaisys == true && LinQerParlours[user].daisysOwnedTill <= block.timestamp && LinQerParlours[user].owedMilk == true) {
                  if(daisysShipped < totalVitaliksMilkShipments) { 
                      for (uint256 i = daisysShipped; i < totalVitaliksMilkShipments; i++) {
      
                          if (LinQerParlours[user].daisysOwnedTill > VitaliksMilkShipments[i+1].timestamp) {
                              milkFromDaisys += (LinQerParlours[user].daisys / 1000000000000000000) * VitaliksMilkShipments[i].daisysOutput * (VitaliksMilkShipments[i+1].timestamp - daisysTimeShipped);
                              daisysTimeShipped = VitaliksMilkShipments[i+1].timestamp;
                              daisysShipped ++;
                          }
                  
                          if (LinQerParlours[user].daisysOwnedTill <= VitaliksMilkShipments[i+1].timestamp) {
                              uint256 time = LinQerParlours[user].daisysOwnedTill - daisysTimeShipped;
                              milkFromDaisys += (LinQerParlours[user].daisys / 1000000000000000000) * VitaliksMilkShipments[i].daisysOutput * time;
                              break;   
                          }   
                      }
                  }
      
                  if (daisysShipped == totalVitaliksMilkShipments){
                      milkFromDaisys += (LinQerParlours[user].daisys / 1000000000000000000) * VitaliksMilkShipments[totalVitaliksMilkShipments].daisysOutput * (LinQerParlours[user].daisysOwnedTill - daisysTimeShipped);
                  } 
              }
      
              if (LinQerParlours[user].ownsDaisys == false && LinQerParlours[user].hasDaisys == true && LinQerParlours[user].rentedDaisysTill <= block.timestamp && LinQerParlours[user].owedMilk == true) {
                  if(daisysShipped < totalVitaliksMilkShipments){
                      for (uint256 i = daisysShipped; i < totalVitaliksMilkShipments; i++) {
                          if (LinQerParlours[user].rentedDaisysTill > VitaliksMilkShipments[i+1].timestamp) {
                              milkFromDaisys += (LinQerParlours[user].daisys / 1000000000000000000) * VitaliksMilkShipments[i].daisysOutput * (VitaliksMilkShipments[i+1].timestamp - daisysTimeShipped);
                              daisysTimeShipped = VitaliksMilkShipments[i+1].timestamp;
                              daisysShipped ++;
                          }
               
                          if (LinQerParlours[user].rentedDaisysTill <= VitaliksMilkShipments[i+1].timestamp && LinQerParlours[user].owedMilk == true){
                              uint256 time = LinQerParlours[user].rentedDaisysTill - daisysTimeShipped;
                              milkFromDaisys += (LinQerParlours[user].daisys / 1000000000000000000) * VitaliksMilkShipments[i].daisysOutput * time;
                              break;   
                          }   
                      }  
                  }
      
                  if (daisysShipped == totalVitaliksMilkShipments){
                      milkFromDaisys += (LinQerParlours[user].daisys / 1000000000000000000) * VitaliksMilkShipments[totalVitaliksMilkShipments].daisysOutput * (LinQerParlours[user].rentedDaisysTill - daisysTimeShipped);
                  }       
              }
      
              if (MilQerParlours[user].ownsBessies == true && MilQerParlours[user].bessiesOwnedTill > block.timestamp) {
                  if (bessiesShipped != totalVitaliksMilkShipments) {
                      for (uint256 i = bessiesShipped; i < totalVitaliksMilkShipments; i++) {
                          milkFromBessies += (MilQerParlours[user].bessies / 1000000000000000000) * VitaliksMilkShipments[i].bessiesOutput * (VitaliksMilkShipments[i+1].timestamp - bessiesTimeShipped);
                          bessiesTimeShipped = VitaliksMilkShipments[i+1].timestamp;
                          bessiesShipped ++;
                      }
                  }
      
                  if (bessiesShipped == totalVitaliksMilkShipments) {
                      milkFromBessies += (MilQerParlours[user].bessies / 1000000000000000000) * VitaliksMilkShipments[totalVitaliksMilkShipments].bessiesOutput * (block.timestamp - bessiesTimeShipped);
                  }
              }
      
              if (MilQerParlours[user].ownsBessies == false && MilQerParlours[user].hasBessies == true && MilQerParlours[user].rentedBessiesTill > block.timestamp && MilQerParlours[user].owedMilk == true) {
                  if (bessiesShipped != totalVitaliksMilkShipments) {
                      for (uint256 i = bessiesShipped; i < totalVitaliksMilkShipments; i++) {
                          milkFromBessies += (MilQerParlours[user].bessies / 1000000000000000000) * VitaliksMilkShipments[i].bessiesOutput * (VitaliksMilkShipments[i+1].timestamp - bessiesTimeShipped);
                          bessiesTimeShipped = VitaliksMilkShipments[i+1].timestamp;
                          bessiesShipped ++;
                      }
                  }
      
                  if (bessiesShipped == totalVitaliksMilkShipments){
                      milkFromBessies += (MilQerParlours[user].bessies / 1000000000000000000) * VitaliksMilkShipments[totalVitaliksMilkShipments].bessiesOutput * (block.timestamp - bessiesTimeShipped);
                  }
      
              }
      
              if (MilQerParlours[user].ownsBessies == true && MilQerParlours[user].bessiesOwnedTill <= block.timestamp) { 
                  if (bessiesShipped != totalVitaliksMilkShipments) {
                      for (uint256 i = bessiesShipped; i < totalVitaliksMilkShipments; i++) {
                          if (MilQerParlours[user].bessiesOwnedTill > VitaliksMilkShipments[i+1].timestamp) {
                              milkFromBessies += (MilQerParlours[user].bessies / 1000000000000000000) * VitaliksMilkShipments[i].bessiesOutput * (VitaliksMilkShipments[i+1].timestamp - bessiesTimeShipped);
                              bessiesTimeShipped = VitaliksMilkShipments[i+1].timestamp;
                              bessiesShipped ++;
                          }
                  
                          if (MilQerParlours[user].bessiesOwnedTill <= VitaliksMilkShipments[i+1].timestamp && MilQerParlours[user].owedMilk == true){
                              uint256 time = MilQerParlours[user].bessiesOwnedTill - bessiesTimeShipped;
                              milkFromBessies += (MilQerParlours[user].bessies / 1000000000000000000) * VitaliksMilkShipments[i].bessiesOutput * time;
                              break;   
                          }   
                      }
                  }
      
                  if (bessiesShipped == totalVitaliksMilkShipments){
                      milkFromBessies += (MilQerParlours[user].bessies / 1000000000000000000) * VitaliksMilkShipments[totalVitaliksMilkShipments].bessiesOutput * (MilQerParlours[user].bessiesOwnedTill - bessiesTimeShipped);
                  }    
              }
      
              if (MilQerParlours[user].ownsBessies == false && MilQerParlours[user].hasBessies == true && MilQerParlours[user].rentedBessiesTill <= block.timestamp) {
                  if(bessiesShipped != totalVitaliksMilkShipments){
                      for (uint256 i = bessiesShipped; i < totalVitaliksMilkShipments; i++) {
                          if (MilQerParlours[user].rentedBessiesTill > VitaliksMilkShipments[i+1].timestamp) {
                              milkFromBessies += (MilQerParlours[user].bessies / 1000000000000000000) * VitaliksMilkShipments[i].bessiesOutput * (VitaliksMilkShipments[i+1].timestamp - bessiesTimeShipped);
                              bessiesTimeShipped = VitaliksMilkShipments[i+1].timestamp;
                              bessiesShipped ++;
                          }
              
                          if (MilQerParlours[user].rentedBessiesTill <= VitaliksMilkShipments[i+1].timestamp && MilQerParlours[user].owedMilk == true){
                              uint256 time = MilQerParlours[user].rentedBessiesTill - bessiesTimeShipped;
                              milkFromBessies += (MilQerParlours[user].bessies / 1000000000000000000) * VitaliksMilkShipments[i].bessiesOutput * time;
                              break;   
                          }   
                      }  
                  }
      
                  if (bessiesShipped == totalVitaliksMilkShipments){
                      milkFromBessies += (MilQerParlours[user].bessies / 1000000000000000000) * VitaliksMilkShipments[totalVitaliksMilkShipments].bessiesOutput * (MilQerParlours[user].rentedBessiesTill - bessiesTimeShipped);
                  }       
              }
      
              Total = milkFromDaisys + milkFromBessies; 
              return (Total);       
          }
      
          function QompoundLinQ(uint256 slippage) external {  
              if (LinQerParlours[msg.sender].hasDaisys == true){
                  shipLinQersMilQ();
              }
      
              howMuchMilkV3();  
        
              uint256 linqAmt = LinQerParlours[msg.sender].vitaliksMilkClaimable; 
              uint256 milqAmt = MilQerParlours[msg.sender].vitaliksMilkClaimable; 
              uint256 _ethAmount = linqAmt + milqAmt; 
        
              address[] memory path = new address[](2);  
              path[0] = uniswapRouter.WETH();  
              path[1] = swapLinq;  
        
              uint256[] memory amountsOut = uniswapRouter.getAmountsOut(_ethAmount, path);  
              uint256 minLinQAmount = amountsOut[1];   
        
            
              uint256 beforeBalance = IERC20(linQ).balanceOf(address(this));  
              uint256 amountSlip = (minLinQAmount * slippage) / 100;  
              uint256 amountAfterSlip = minLinQAmount - amountSlip;  
        
            
              uniswapRouter.swapExactETHForTokensSupportingFeeOnTransferTokens{value: _ethAmount}(  
                  amountAfterSlip,  
                  path,  
                  address(this),  
                  block.timestamp  
              );  
        
              uint256 afterBalance = IERC20(linQ).balanceOf(address(this));  
        
              uint256 boughtAmount = afterBalance - beforeBalance;
      
              if (LinQerParlours[msg.sender].ownsDaisys == true) {
                  glinQ.transfer(msg.sender, boughtAmount);
              }
      
              if (LinQerParlours[msg.sender].hasDaisys == true) { 
                  LinQerParlours[msg.sender].daisys += boughtAmount;  
                  LinQerParlours[msg.sender].QompoundedMilk += _ethAmount;  
                  LinQerParlours[msg.sender].vitaliksMilkClaimable = 0; 
                  MilQerParlours[msg.sender].vitaliksMilkClaimable = 0;
              }
      
              if (LinQerParlours[msg.sender].hasDaisys == false) {
                  LinQerParlours[msg.sender].daisys += boughtAmount;
                  LinQerParlours[msg.sender].rentedDaisysSince = block.timestamp;
                  LinQerParlours[msg.sender].rentedDaisysTill = block.timestamp + daisysRentalTime; 
                  LinQerParlours[msg.sender].daisysOwnedSince = 0;
                  LinQerParlours[msg.sender].daisysOwnedTill = 32503680000;
                  LinQerParlours[msg.sender].hasDaisys = true;
                  LinQerParlours[msg.sender].ownsDaisys = false;
                  LinQerParlours[msg.sender].vitaliksMilkShipped = 0;
                  LinQerParlours[msg.sender].QompoundedMilk = 0;
                  LinQerParlours[msg.sender].lastShippedVitaliksMilk = block.timestamp;
                  LinQerParlours[msg.sender].shipmentsRecieved = totalVitaliksMilkShipments;
                  LinQerParlours[msg.sender].vitaliksMilkClaimable = 0;
                  LinQerParlours[msg.sender].owedMilk = true;
                  LpClaims[msg.sender].lastClaimed = totalMilQClaimed;
                  LpClaims[msg.sender].totalClaimed = 0;
                  MilQerParlours[msg.sender].vitaliksMilkClaimable = 0;
                  daisys += boughtAmount;
                  linQers ++;
              }
      
              daisys += boughtAmount;
              vitaliksMilkQompounded += _ethAmount;
              emit Qompound(msg.sender, _ethAmount, boughtAmount);
          }
              
          function shipMilk() public {   
                
              howMuchMilkV3();
      
              uint256 linq = LinQerParlours[msg.sender].vitaliksMilkClaimable;
              uint256 lp = MilQerParlours[msg.sender].vitaliksMilkClaimable;
              uint256 amount = linq + lp;
      
              require(address(this).balance >= amount);
      
              payable(msg.sender).transfer(amount);
      
              LinQerParlours[msg.sender].vitaliksMilkShipped += linq;
              MilQerParlours[msg.sender].vitaliksMilkShipped += lp;
              LinQerParlours[msg.sender].vitaliksMilkClaimable = 0;
              MilQerParlours[msg.sender].vitaliksMilkClaimable = 0;
              vitaliksMilkShipped += amount;
      
              if (amount > highClaimThreshold){
                  emit highClaim(msg.sender,amount);
              }
      
              if(address(this).balance < lowBalanceThreshold){
                  emit lowBalance(block.timestamp,address(this).balance);
              }    
          }
      
          function shipFarmMilQ() external onlyOwner {
      
              uint256 beforeBalance = IERC20(milQ).balanceOf(address(this)); 
      
              ILINQ.claim();
      
              uint256 afterBalance = IERC20(milQ).balanceOf(address(this));
      
              uint256 claimed = afterBalance - beforeBalance;
      
               uint256 PerLinQ = (claimed * 10**18) / daisys;
      
              uint256 index = MilqShipments;
      
              MilQShipments[index] = MilQShipment(block.timestamp, claimed, daisys,PerLinQ);
      
              MilqShipments++;
      
              totalMilQClaimed += claimed;
          }
      
          function shipLinQersMilQ() public {  
              uint256 CurrrentDis = totalMilQClaimed - LpClaims[msg.sender].lastClaimed;  
              uint256 tokensStaked = LinQerParlours[msg.sender].daisys;  
               uint256 divDaisys = daisys / 10**18; 
              uint256 percentOwned = ((tokensStaked * 100) / divDaisys); 
              uint256 userDistro = CurrrentDis * (percentOwned / 100); 
              uint256 userDistroAmount = userDistro / 10**18; 
              milQ.transfer(msg.sender, userDistroAmount); 
        
              MilQerParlours[msg.sender].milQClaimed += userDistroAmount;
              LpClaims[msg.sender].lastClaimed = totalMilQClaimed;  
              LpClaims[msg.sender].totalClaimed += userDistroAmount;  
          }  
        
          function checkEstMilQRewards(address user) public view returns (uint256){  
              uint256 CurrrentDis = totalMilQClaimed - LpClaims[user].lastClaimed;  
              uint256 tokensStaked = LinQerParlours[user].daisys;  
              uint256 divDaisys = daisys / 10**18; 
              uint256 percentOwned = ((tokensStaked * 100) / divDaisys); 
              uint256 userDistro = CurrrentDis * (percentOwned / 100); 
              uint256 userDistroAmount = userDistro / 10**18; 
       
              return userDistroAmount;  
          }
      
          receive() external payable {}
      }

      File 2 of 4: gLinq
      // SPDX-License-Identifier: MIT
      // A New Governance Paradigm Brought To You By Linq
      pragma solidity ^0.8.9;
      import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
      import "@openzeppelin/contracts/access/Ownable.sol";
      contract gLinq is Ownable, ERC20 {
          address public LinqStakingContract;
          constructor(address staking_contract) ERC20("gLinq", "gLINQ") {
              _mint(msg.sender, 100000000 * 10**18);
              LinqStakingContract = staking_contract;
          }
          function setStakingContract(address new_contract) public onlyOwner {
              LinqStakingContract = new_contract;
          } 
          function _transfer(
              address from,
              address to,
              uint256 amount
          ) internal override {
              if (from != LinqStakingContract && to != LinqStakingContract) {
                  require(
                      false,
                      "gLinq : No transfers allowed unless to or from staking contract"
                  );
              } else {
                  super._transfer(from, to, amount);
              }
          }
      }// SPDX-License-Identifier: MIT
      // OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)
      pragma solidity ^0.8.0;
      import "../utils/Context.sol";
      /**
       * @dev Contract module which provides a basic access control mechanism, where
       * there is an account (an owner) that can be granted exclusive access to
       * specific functions.
       *
       * By default, the owner account will be the one that deploys the contract. This
       * can later be changed with {transferOwnership}.
       *
       * This module is used through inheritance. It will make available the modifier
       * `onlyOwner`, which can be applied to your functions to restrict their use to
       * the owner.
       */
      abstract contract Ownable is Context {
          address private _owner;
          event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
          /**
           * @dev Initializes the contract setting the deployer as the initial owner.
           */
          constructor() {
              _transferOwnership(_msgSender());
          }
          /**
           * @dev Throws if called by any account other than the owner.
           */
          modifier onlyOwner() {
              _checkOwner();
              _;
          }
          /**
           * @dev Returns the address of the current owner.
           */
          function owner() public view virtual returns (address) {
              return _owner;
          }
          /**
           * @dev Throws if the sender is not the owner.
           */
          function _checkOwner() internal view virtual {
              require(owner() == _msgSender(), "Ownable: caller is not the owner");
          }
          /**
           * @dev Leaves the contract without owner. It will not be possible to call
           * `onlyOwner` functions. Can only be called by the current owner.
           *
           * NOTE: Renouncing ownership will leave the contract without an owner,
           * thereby disabling any functionality that is only available to the owner.
           */
          function renounceOwnership() public virtual onlyOwner {
              _transferOwnership(address(0));
          }
          /**
           * @dev Transfers ownership of the contract to a new account (`newOwner`).
           * Can only be called by the current owner.
           */
          function transferOwnership(address newOwner) public virtual onlyOwner {
              require(newOwner != address(0), "Ownable: new owner is the zero address");
              _transferOwnership(newOwner);
          }
          /**
           * @dev Transfers ownership of the contract to a new account (`newOwner`).
           * Internal function without access restriction.
           */
          function _transferOwnership(address newOwner) internal virtual {
              address oldOwner = _owner;
              _owner = newOwner;
              emit OwnershipTransferred(oldOwner, newOwner);
          }
      }
      // SPDX-License-Identifier: MIT
      // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/ERC20.sol)
      pragma solidity ^0.8.0;
      import "./IERC20.sol";
      import "./extensions/IERC20Metadata.sol";
      import "../../utils/Context.sol";
      /**
       * @dev Implementation of the {IERC20} interface.
       *
       * This implementation is agnostic to the way tokens are created. This means
       * that a supply mechanism has to be added in a derived contract using {_mint}.
       * For a generic mechanism see {ERC20PresetMinterPauser}.
       *
       * TIP: For a detailed writeup see our guide
       * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How
       * to implement supply mechanisms].
       *
       * The default value of {decimals} is 18. To change this, you should override
       * this function so it returns a different value.
       *
       * We have followed general OpenZeppelin Contracts guidelines: functions revert
       * instead returning `false` on failure. This behavior is nonetheless
       * conventional and does not conflict with the expectations of ERC20
       * applications.
       *
       * Additionally, an {Approval} event is emitted on calls to {transferFrom}.
       * This allows applications to reconstruct the allowance for all accounts just
       * by listening to said events. Other implementations of the EIP may not emit
       * these events, as it isn't required by the specification.
       *
       * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}
       * functions have been added to mitigate the well-known issues around setting
       * allowances. See {IERC20-approve}.
       */
      contract ERC20 is Context, IERC20, IERC20Metadata {
          mapping(address => uint256) private _balances;
          mapping(address => mapping(address => uint256)) private _allowances;
          uint256 private _totalSupply;
          string private _name;
          string private _symbol;
          /**
           * @dev Sets the values for {name} and {symbol}.
           *
           * All two of these values are immutable: they can only be set once during
           * construction.
           */
          constructor(string memory name_, string memory symbol_) {
              _name = name_;
              _symbol = symbol_;
          }
          /**
           * @dev Returns the name of the token.
           */
          function name() public view virtual override returns (string memory) {
              return _name;
          }
          /**
           * @dev Returns the symbol of the token, usually a shorter version of the
           * name.
           */
          function symbol() public view virtual override returns (string memory) {
              return _symbol;
          }
          /**
           * @dev Returns the number of decimals used to get its user representation.
           * For example, if `decimals` equals `2`, a balance of `505` tokens should
           * be displayed to a user as `5.05` (`505 / 10 ** 2`).
           *
           * Tokens usually opt for a value of 18, imitating the relationship between
           * Ether and Wei. This is the default value returned by this function, unless
           * it's overridden.
           *
           * NOTE: This information is only used for _display_ purposes: it in
           * no way affects any of the arithmetic of the contract, including
           * {IERC20-balanceOf} and {IERC20-transfer}.
           */
          function decimals() public view virtual override returns (uint8) {
              return 18;
          }
          /**
           * @dev See {IERC20-totalSupply}.
           */
          function totalSupply() public view virtual override returns (uint256) {
              return _totalSupply;
          }
          /**
           * @dev See {IERC20-balanceOf}.
           */
          function balanceOf(address account) public view virtual override returns (uint256) {
              return _balances[account];
          }
          /**
           * @dev See {IERC20-transfer}.
           *
           * Requirements:
           *
           * - `to` cannot be the zero address.
           * - the caller must have a balance of at least `amount`.
           */
          function transfer(address to, uint256 amount) public virtual override returns (bool) {
              address owner = _msgSender();
              _transfer(owner, to, amount);
              return true;
          }
          /**
           * @dev See {IERC20-allowance}.
           */
          function allowance(address owner, address spender) public view virtual override returns (uint256) {
              return _allowances[owner][spender];
          }
          /**
           * @dev See {IERC20-approve}.
           *
           * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on
           * `transferFrom`. This is semantically equivalent to an infinite approval.
           *
           * Requirements:
           *
           * - `spender` cannot be the zero address.
           */
          function approve(address spender, uint256 amount) public virtual override returns (bool) {
              address owner = _msgSender();
              _approve(owner, spender, amount);
              return true;
          }
          /**
           * @dev See {IERC20-transferFrom}.
           *
           * Emits an {Approval} event indicating the updated allowance. This is not
           * required by the EIP. See the note at the beginning of {ERC20}.
           *
           * NOTE: Does not update the allowance if the current allowance
           * is the maximum `uint256`.
           *
           * Requirements:
           *
           * - `from` and `to` cannot be the zero address.
           * - `from` must have a balance of at least `amount`.
           * - the caller must have allowance for ``from``'s tokens of at least
           * `amount`.
           */
          function transferFrom(address from, address to, uint256 amount) public virtual override returns (bool) {
              address spender = _msgSender();
              _spendAllowance(from, spender, amount);
              _transfer(from, to, amount);
              return true;
          }
          /**
           * @dev Atomically increases the allowance granted to `spender` by the caller.
           *
           * This is an alternative to {approve} that can be used as a mitigation for
           * problems described in {IERC20-approve}.
           *
           * Emits an {Approval} event indicating the updated allowance.
           *
           * Requirements:
           *
           * - `spender` cannot be the zero address.
           */
          function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
              address owner = _msgSender();
              _approve(owner, spender, allowance(owner, spender) + addedValue);
              return true;
          }
          /**
           * @dev Atomically decreases the allowance granted to `spender` by the caller.
           *
           * This is an alternative to {approve} that can be used as a mitigation for
           * problems described in {IERC20-approve}.
           *
           * Emits an {Approval} event indicating the updated allowance.
           *
           * Requirements:
           *
           * - `spender` cannot be the zero address.
           * - `spender` must have allowance for the caller of at least
           * `subtractedValue`.
           */
          function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
              address owner = _msgSender();
              uint256 currentAllowance = allowance(owner, spender);
              require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero");
              unchecked {
                  _approve(owner, spender, currentAllowance - subtractedValue);
              }
              return true;
          }
          /**
           * @dev Moves `amount` of tokens from `from` to `to`.
           *
           * This internal function is equivalent to {transfer}, and can be used to
           * e.g. implement automatic token fees, slashing mechanisms, etc.
           *
           * Emits a {Transfer} event.
           *
           * Requirements:
           *
           * - `from` cannot be the zero address.
           * - `to` cannot be the zero address.
           * - `from` must have a balance of at least `amount`.
           */
          function _transfer(address from, address to, uint256 amount) internal virtual {
              require(from != address(0), "ERC20: transfer from the zero address");
              require(to != address(0), "ERC20: transfer to the zero address");
              _beforeTokenTransfer(from, to, amount);
              uint256 fromBalance = _balances[from];
              require(fromBalance >= amount, "ERC20: transfer amount exceeds balance");
              unchecked {
                  _balances[from] = fromBalance - amount;
                  // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by
                  // decrementing then incrementing.
                  _balances[to] += amount;
              }
              emit Transfer(from, to, amount);
              _afterTokenTransfer(from, to, amount);
          }
          /** @dev Creates `amount` tokens and assigns them to `account`, increasing
           * the total supply.
           *
           * Emits a {Transfer} event with `from` set to the zero address.
           *
           * Requirements:
           *
           * - `account` cannot be the zero address.
           */
          function _mint(address account, uint256 amount) internal virtual {
              require(account != address(0), "ERC20: mint to the zero address");
              _beforeTokenTransfer(address(0), account, amount);
              _totalSupply += amount;
              unchecked {
                  // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above.
                  _balances[account] += amount;
              }
              emit Transfer(address(0), account, amount);
              _afterTokenTransfer(address(0), account, amount);
          }
          /**
           * @dev Destroys `amount` tokens from `account`, reducing the
           * total supply.
           *
           * Emits a {Transfer} event with `to` set to the zero address.
           *
           * Requirements:
           *
           * - `account` cannot be the zero address.
           * - `account` must have at least `amount` tokens.
           */
          function _burn(address account, uint256 amount) internal virtual {
              require(account != address(0), "ERC20: burn from the zero address");
              _beforeTokenTransfer(account, address(0), amount);
              uint256 accountBalance = _balances[account];
              require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
              unchecked {
                  _balances[account] = accountBalance - amount;
                  // Overflow not possible: amount <= accountBalance <= totalSupply.
                  _totalSupply -= amount;
              }
              emit Transfer(account, address(0), amount);
              _afterTokenTransfer(account, address(0), amount);
          }
          /**
           * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.
           *
           * This internal function is equivalent to `approve`, and can be used to
           * e.g. set automatic allowances for certain subsystems, etc.
           *
           * Emits an {Approval} event.
           *
           * Requirements:
           *
           * - `owner` cannot be the zero address.
           * - `spender` cannot be the zero address.
           */
          function _approve(address owner, address spender, uint256 amount) internal virtual {
              require(owner != address(0), "ERC20: approve from the zero address");
              require(spender != address(0), "ERC20: approve to the zero address");
              _allowances[owner][spender] = amount;
              emit Approval(owner, spender, amount);
          }
          /**
           * @dev Updates `owner` s allowance for `spender` based on spent `amount`.
           *
           * Does not update the allowance amount in case of infinite allowance.
           * Revert if not enough allowance is available.
           *
           * Might emit an {Approval} event.
           */
          function _spendAllowance(address owner, address spender, uint256 amount) internal virtual {
              uint256 currentAllowance = allowance(owner, spender);
              if (currentAllowance != type(uint256).max) {
                  require(currentAllowance >= amount, "ERC20: insufficient allowance");
                  unchecked {
                      _approve(owner, spender, currentAllowance - amount);
                  }
              }
          }
          /**
           * @dev Hook that is called before any transfer of tokens. This includes
           * minting and burning.
           *
           * Calling conditions:
           *
           * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
           * will be transferred to `to`.
           * - when `from` is zero, `amount` tokens will be minted for `to`.
           * - when `to` is zero, `amount` of ``from``'s tokens will be burned.
           * - `from` and `to` are never both zero.
           *
           * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
           */
          function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual {}
          /**
           * @dev Hook that is called after any transfer of tokens. This includes
           * minting and burning.
           *
           * Calling conditions:
           *
           * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
           * has been transferred to `to`.
           * - when `from` is zero, `amount` tokens have been minted for `to`.
           * - when `to` is zero, `amount` of ``from``'s tokens have been burned.
           * - `from` and `to` are never both zero.
           *
           * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
           */
          function _afterTokenTransfer(address from, address to, uint256 amount) internal virtual {}
      }
      // SPDX-License-Identifier: MIT
      // OpenZeppelin Contracts v4.4.1 (utils/Context.sol)
      pragma solidity ^0.8.0;
      /**
       * @dev Provides information about the current execution context, including the
       * sender of the transaction and its data. While these are generally available
       * via msg.sender and msg.data, they should not be accessed in such a direct
       * manner, since when dealing with meta-transactions the account sending and
       * paying for execution may not be the actual sender (as far as an application
       * is concerned).
       *
       * This contract is only required for intermediate, library-like contracts.
       */
      abstract contract Context {
          function _msgSender() internal view virtual returns (address) {
              return msg.sender;
          }
          function _msgData() internal view virtual returns (bytes calldata) {
              return msg.data;
          }
      }
      // SPDX-License-Identifier: MIT
      // OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)
      pragma solidity ^0.8.0;
      import "../IERC20.sol";
      /**
       * @dev Interface for the optional metadata functions from the ERC20 standard.
       *
       * _Available since v4.1._
       */
      interface IERC20Metadata is IERC20 {
          /**
           * @dev Returns the name of the token.
           */
          function name() external view returns (string memory);
          /**
           * @dev Returns the symbol of the token.
           */
          function symbol() external view returns (string memory);
          /**
           * @dev Returns the decimals places of the token.
           */
          function decimals() external view returns (uint8);
      }
      // SPDX-License-Identifier: MIT
      // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)
      pragma solidity ^0.8.0;
      /**
       * @dev Interface of the ERC20 standard as defined in the EIP.
       */
      interface IERC20 {
          /**
           * @dev Emitted when `value` tokens are moved from one account (`from`) to
           * another (`to`).
           *
           * Note that `value` may be zero.
           */
          event Transfer(address indexed from, address indexed to, uint256 value);
          /**
           * @dev Emitted when the allowance of a `spender` for an `owner` is set by
           * a call to {approve}. `value` is the new allowance.
           */
          event Approval(address indexed owner, address indexed spender, uint256 value);
          /**
           * @dev Returns the amount of tokens in existence.
           */
          function totalSupply() external view returns (uint256);
          /**
           * @dev Returns the amount of tokens owned by `account`.
           */
          function balanceOf(address account) external view returns (uint256);
          /**
           * @dev Moves `amount` tokens from the caller's account to `to`.
           *
           * Returns a boolean value indicating whether the operation succeeded.
           *
           * Emits a {Transfer} event.
           */
          function transfer(address to, uint256 amount) external returns (bool);
          /**
           * @dev Returns the remaining number of tokens that `spender` will be
           * allowed to spend on behalf of `owner` through {transferFrom}. This is
           * zero by default.
           *
           * This value changes when {approve} or {transferFrom} are called.
           */
          function allowance(address owner, address spender) external view returns (uint256);
          /**
           * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
           *
           * Returns a boolean value indicating whether the operation succeeded.
           *
           * IMPORTANT: Beware that changing an allowance with this method brings the risk
           * that someone may use both the old and the new allowance by unfortunate
           * transaction ordering. One possible solution to mitigate this race
           * condition is to first reduce the spender's allowance to 0 and set the
           * desired value afterwards:
           * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
           *
           * Emits an {Approval} event.
           */
          function approve(address spender, uint256 amount) external returns (bool);
          /**
           * @dev Moves `amount` tokens from `from` to `to` using the
           * allowance mechanism. `amount` is then deducted from the caller's
           * allowance.
           *
           * Returns a boolean value indicating whether the operation succeeded.
           *
           * Emits a {Transfer} event.
           */
          function transferFrom(address from, address to, uint256 amount) external returns (bool);
      }
      

      File 3 of 4: UniswapV2Pair
      // File: contracts/interfaces/IUniswapV2Pair.sol
      
      pragma solidity >=0.5.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 Mint(address indexed sender, uint amount0, uint amount1);
          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 mint(address to) external returns (uint liquidity);
          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;
      }
      
      // File: contracts/interfaces/IUniswapV2ERC20.sol
      
      pragma solidity >=0.5.0;
      
      interface IUniswapV2ERC20 {
          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;
      }
      
      // File: contracts/libraries/SafeMath.sol
      
      pragma solidity =0.5.16;
      
      // a library for performing overflow-safe math, courtesy of DappHub (https://github.com/dapphub/ds-math)
      
      library SafeMath {
          function add(uint x, uint y) internal pure returns (uint z) {
              require((z = x + y) >= x, 'ds-math-add-overflow');
          }
      
          function sub(uint x, uint y) internal pure returns (uint z) {
              require((z = x - y) <= x, 'ds-math-sub-underflow');
          }
      
          function mul(uint x, uint y) internal pure returns (uint z) {
              require(y == 0 || (z = x * y) / y == x, 'ds-math-mul-overflow');
          }
      }
      
      // File: contracts/UniswapV2ERC20.sol
      
      pragma solidity =0.5.16;
      
      
      
      contract UniswapV2ERC20 is IUniswapV2ERC20 {
          using SafeMath for uint;
      
          string public constant name = 'Uniswap V2';
          string public constant symbol = 'UNI-V2';
          uint8 public constant decimals = 18;
          uint  public totalSupply;
          mapping(address => uint) public balanceOf;
          mapping(address => mapping(address => uint)) public allowance;
      
          bytes32 public DOMAIN_SEPARATOR;
          // keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)");
          bytes32 public constant PERMIT_TYPEHASH = 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;
          mapping(address => uint) public nonces;
      
          event Approval(address indexed owner, address indexed spender, uint value);
          event Transfer(address indexed from, address indexed to, uint value);
      
          constructor() public {
              uint chainId;
              assembly {
                  chainId := chainid
              }
              DOMAIN_SEPARATOR = keccak256(
                  abi.encode(
                      keccak256('EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)'),
                      keccak256(bytes(name)),
                      keccak256(bytes('1')),
                      chainId,
                      address(this)
                  )
              );
          }
      
          function _mint(address to, uint value) internal {
              totalSupply = totalSupply.add(value);
              balanceOf[to] = balanceOf[to].add(value);
              emit Transfer(address(0), to, value);
          }
      
          function _burn(address from, uint value) internal {
              balanceOf[from] = balanceOf[from].sub(value);
              totalSupply = totalSupply.sub(value);
              emit Transfer(from, address(0), value);
          }
      
          function _approve(address owner, address spender, uint value) private {
              allowance[owner][spender] = value;
              emit Approval(owner, spender, value);
          }
      
          function _transfer(address from, address to, uint value) private {
              balanceOf[from] = balanceOf[from].sub(value);
              balanceOf[to] = balanceOf[to].add(value);
              emit Transfer(from, to, value);
          }
      
          function approve(address spender, uint value) external returns (bool) {
              _approve(msg.sender, spender, value);
              return true;
          }
      
          function transfer(address to, uint value) external returns (bool) {
              _transfer(msg.sender, to, value);
              return true;
          }
      
          function transferFrom(address from, address to, uint value) external returns (bool) {
              if (allowance[from][msg.sender] != uint(-1)) {
                  allowance[from][msg.sender] = allowance[from][msg.sender].sub(value);
              }
              _transfer(from, to, value);
              return true;
          }
      
          function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external {
              require(deadline >= block.timestamp, 'UniswapV2: EXPIRED');
              bytes32 digest = keccak256(
                  abi.encodePacked(
                      '\x19\x01',
                      DOMAIN_SEPARATOR,
                      keccak256(abi.encode(PERMIT_TYPEHASH, owner, spender, value, nonces[owner]++, deadline))
                  )
              );
              address recoveredAddress = ecrecover(digest, v, r, s);
              require(recoveredAddress != address(0) && recoveredAddress == owner, 'UniswapV2: INVALID_SIGNATURE');
              _approve(owner, spender, value);
          }
      }
      
      // File: contracts/libraries/Math.sol
      
      pragma solidity =0.5.16;
      
      // a library for performing various math operations
      
      library Math {
          function min(uint x, uint y) internal pure returns (uint z) {
              z = x < y ? x : y;
          }
      
          // babylonian method (https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method)
          function sqrt(uint y) internal pure returns (uint z) {
              if (y > 3) {
                  z = y;
                  uint x = y / 2 + 1;
                  while (x < z) {
                      z = x;
                      x = (y / x + x) / 2;
                  }
              } else if (y != 0) {
                  z = 1;
              }
          }
      }
      
      // File: contracts/libraries/UQ112x112.sol
      
      pragma solidity =0.5.16;
      
      // a library for handling binary fixed point numbers (https://en.wikipedia.org/wiki/Q_(number_format))
      
      // range: [0, 2**112 - 1]
      // resolution: 1 / 2**112
      
      library UQ112x112 {
          uint224 constant Q112 = 2**112;
      
          // encode a uint112 as a UQ112x112
          function encode(uint112 y) internal pure returns (uint224 z) {
              z = uint224(y) * Q112; // never overflows
          }
      
          // divide a UQ112x112 by a uint112, returning a UQ112x112
          function uqdiv(uint224 x, uint112 y) internal pure returns (uint224 z) {
              z = x / uint224(y);
          }
      }
      
      // File: contracts/interfaces/IERC20.sol
      
      pragma solidity >=0.5.0;
      
      interface IERC20 {
          event Approval(address indexed owner, address indexed spender, uint value);
          event Transfer(address indexed from, address indexed to, uint value);
      
          function name() external view returns (string memory);
          function symbol() external view returns (string memory);
          function decimals() external view returns (uint8);
          function totalSupply() external view returns (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);
      }
      
      // File: contracts/interfaces/IUniswapV2Factory.sol
      
      pragma solidity >=0.5.0;
      
      interface IUniswapV2Factory {
          event PairCreated(address indexed token0, address indexed token1, address pair, uint);
      
          function feeTo() external view returns (address);
          function feeToSetter() external view returns (address);
      
          function getPair(address tokenA, address tokenB) external view returns (address pair);
          function allPairs(uint) external view returns (address pair);
          function allPairsLength() external view returns (uint);
      
          function createPair(address tokenA, address tokenB) external returns (address pair);
      
          function setFeeTo(address) external;
          function setFeeToSetter(address) external;
      }
      
      // File: contracts/interfaces/IUniswapV2Callee.sol
      
      pragma solidity >=0.5.0;
      
      interface IUniswapV2Callee {
          function uniswapV2Call(address sender, uint amount0, uint amount1, bytes calldata data) external;
      }
      
      // File: contracts/UniswapV2Pair.sol
      
      pragma solidity =0.5.16;
      
      
      
      
      
      
      
      
      contract UniswapV2Pair is IUniswapV2Pair, UniswapV2ERC20 {
          using SafeMath  for uint;
          using UQ112x112 for uint224;
      
          uint public constant MINIMUM_LIQUIDITY = 10**3;
          bytes4 private constant SELECTOR = bytes4(keccak256(bytes('transfer(address,uint256)')));
      
          address public factory;
          address public token0;
          address public token1;
      
          uint112 private reserve0;           // uses single storage slot, accessible via getReserves
          uint112 private reserve1;           // uses single storage slot, accessible via getReserves
          uint32  private blockTimestampLast; // uses single storage slot, accessible via getReserves
      
          uint public price0CumulativeLast;
          uint public price1CumulativeLast;
          uint public kLast; // reserve0 * reserve1, as of immediately after the most recent liquidity event
      
          uint private unlocked = 1;
          modifier lock() {
              require(unlocked == 1, 'UniswapV2: LOCKED');
              unlocked = 0;
              _;
              unlocked = 1;
          }
      
          function getReserves() public view returns (uint112 _reserve0, uint112 _reserve1, uint32 _blockTimestampLast) {
              _reserve0 = reserve0;
              _reserve1 = reserve1;
              _blockTimestampLast = blockTimestampLast;
          }
      
          function _safeTransfer(address token, address to, uint value) private {
              (bool success, bytes memory data) = token.call(abi.encodeWithSelector(SELECTOR, to, value));
              require(success && (data.length == 0 || abi.decode(data, (bool))), 'UniswapV2: TRANSFER_FAILED');
          }
      
          event Mint(address indexed sender, uint amount0, uint amount1);
          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);
      
          constructor() public {
              factory = msg.sender;
          }
      
          // called once by the factory at time of deployment
          function initialize(address _token0, address _token1) external {
              require(msg.sender == factory, 'UniswapV2: FORBIDDEN'); // sufficient check
              token0 = _token0;
              token1 = _token1;
          }
      
          // update reserves and, on the first call per block, price accumulators
          function _update(uint balance0, uint balance1, uint112 _reserve0, uint112 _reserve1) private {
              require(balance0 <= uint112(-1) && balance1 <= uint112(-1), 'UniswapV2: OVERFLOW');
              uint32 blockTimestamp = uint32(block.timestamp % 2**32);
              uint32 timeElapsed = blockTimestamp - blockTimestampLast; // overflow is desired
              if (timeElapsed > 0 && _reserve0 != 0 && _reserve1 != 0) {
                  // * never overflows, and + overflow is desired
                  price0CumulativeLast += uint(UQ112x112.encode(_reserve1).uqdiv(_reserve0)) * timeElapsed;
                  price1CumulativeLast += uint(UQ112x112.encode(_reserve0).uqdiv(_reserve1)) * timeElapsed;
              }
              reserve0 = uint112(balance0);
              reserve1 = uint112(balance1);
              blockTimestampLast = blockTimestamp;
              emit Sync(reserve0, reserve1);
          }
      
          // if fee is on, mint liquidity equivalent to 1/6th of the growth in sqrt(k)
          function _mintFee(uint112 _reserve0, uint112 _reserve1) private returns (bool feeOn) {
              address feeTo = IUniswapV2Factory(factory).feeTo();
              feeOn = feeTo != address(0);
              uint _kLast = kLast; // gas savings
              if (feeOn) {
                  if (_kLast != 0) {
                      uint rootK = Math.sqrt(uint(_reserve0).mul(_reserve1));
                      uint rootKLast = Math.sqrt(_kLast);
                      if (rootK > rootKLast) {
                          uint numerator = totalSupply.mul(rootK.sub(rootKLast));
                          uint denominator = rootK.mul(5).add(rootKLast);
                          uint liquidity = numerator / denominator;
                          if (liquidity > 0) _mint(feeTo, liquidity);
                      }
                  }
              } else if (_kLast != 0) {
                  kLast = 0;
              }
          }
      
          // this low-level function should be called from a contract which performs important safety checks
          function mint(address to) external lock returns (uint liquidity) {
              (uint112 _reserve0, uint112 _reserve1,) = getReserves(); // gas savings
              uint balance0 = IERC20(token0).balanceOf(address(this));
              uint balance1 = IERC20(token1).balanceOf(address(this));
              uint amount0 = balance0.sub(_reserve0);
              uint amount1 = balance1.sub(_reserve1);
      
              bool feeOn = _mintFee(_reserve0, _reserve1);
              uint _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee
              if (_totalSupply == 0) {
                  liquidity = Math.sqrt(amount0.mul(amount1)).sub(MINIMUM_LIQUIDITY);
                 _mint(address(0), MINIMUM_LIQUIDITY); // permanently lock the first MINIMUM_LIQUIDITY tokens
              } else {
                  liquidity = Math.min(amount0.mul(_totalSupply) / _reserve0, amount1.mul(_totalSupply) / _reserve1);
              }
              require(liquidity > 0, 'UniswapV2: INSUFFICIENT_LIQUIDITY_MINTED');
              _mint(to, liquidity);
      
              _update(balance0, balance1, _reserve0, _reserve1);
              if (feeOn) kLast = uint(reserve0).mul(reserve1); // reserve0 and reserve1 are up-to-date
              emit Mint(msg.sender, amount0, amount1);
          }
      
          // this low-level function should be called from a contract which performs important safety checks
          function burn(address to) external lock returns (uint amount0, uint amount1) {
              (uint112 _reserve0, uint112 _reserve1,) = getReserves(); // gas savings
              address _token0 = token0;                                // gas savings
              address _token1 = token1;                                // gas savings
              uint balance0 = IERC20(_token0).balanceOf(address(this));
              uint balance1 = IERC20(_token1).balanceOf(address(this));
              uint liquidity = balanceOf[address(this)];
      
              bool feeOn = _mintFee(_reserve0, _reserve1);
              uint _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee
              amount0 = liquidity.mul(balance0) / _totalSupply; // using balances ensures pro-rata distribution
              amount1 = liquidity.mul(balance1) / _totalSupply; // using balances ensures pro-rata distribution
              require(amount0 > 0 && amount1 > 0, 'UniswapV2: INSUFFICIENT_LIQUIDITY_BURNED');
              _burn(address(this), liquidity);
              _safeTransfer(_token0, to, amount0);
              _safeTransfer(_token1, to, amount1);
              balance0 = IERC20(_token0).balanceOf(address(this));
              balance1 = IERC20(_token1).balanceOf(address(this));
      
              _update(balance0, balance1, _reserve0, _reserve1);
              if (feeOn) kLast = uint(reserve0).mul(reserve1); // reserve0 and reserve1 are up-to-date
              emit Burn(msg.sender, amount0, amount1, to);
          }
      
          // this low-level function should be called from a contract which performs important safety checks
          function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external lock {
              require(amount0Out > 0 || amount1Out > 0, 'UniswapV2: INSUFFICIENT_OUTPUT_AMOUNT');
              (uint112 _reserve0, uint112 _reserve1,) = getReserves(); // gas savings
              require(amount0Out < _reserve0 && amount1Out < _reserve1, 'UniswapV2: INSUFFICIENT_LIQUIDITY');
      
              uint balance0;
              uint balance1;
              { // scope for _token{0,1}, avoids stack too deep errors
              address _token0 = token0;
              address _token1 = token1;
              require(to != _token0 && to != _token1, 'UniswapV2: INVALID_TO');
              if (amount0Out > 0) _safeTransfer(_token0, to, amount0Out); // optimistically transfer tokens
              if (amount1Out > 0) _safeTransfer(_token1, to, amount1Out); // optimistically transfer tokens
              if (data.length > 0) IUniswapV2Callee(to).uniswapV2Call(msg.sender, amount0Out, amount1Out, data);
              balance0 = IERC20(_token0).balanceOf(address(this));
              balance1 = IERC20(_token1).balanceOf(address(this));
              }
              uint amount0In = balance0 > _reserve0 - amount0Out ? balance0 - (_reserve0 - amount0Out) : 0;
              uint amount1In = balance1 > _reserve1 - amount1Out ? balance1 - (_reserve1 - amount1Out) : 0;
              require(amount0In > 0 || amount1In > 0, 'UniswapV2: INSUFFICIENT_INPUT_AMOUNT');
              { // scope for reserve{0,1}Adjusted, avoids stack too deep errors
              uint balance0Adjusted = balance0.mul(1000).sub(amount0In.mul(3));
              uint balance1Adjusted = balance1.mul(1000).sub(amount1In.mul(3));
              require(balance0Adjusted.mul(balance1Adjusted) >= uint(_reserve0).mul(_reserve1).mul(1000**2), 'UniswapV2: K');
              }
      
              _update(balance0, balance1, _reserve0, _reserve1);
              emit Swap(msg.sender, amount0In, amount1In, amount0Out, amount1Out, to);
          }
      
          // force balances to match reserves
          function skim(address to) external lock {
              address _token0 = token0; // gas savings
              address _token1 = token1; // gas savings
              _safeTransfer(_token0, to, IERC20(_token0).balanceOf(address(this)).sub(reserve0));
              _safeTransfer(_token1, to, IERC20(_token1).balanceOf(address(this)).sub(reserve1));
          }
      
          // force reserves to match balances
          function sync() external lock {
              _update(IERC20(token0).balanceOf(address(this)), IERC20(token1).balanceOf(address(this)), reserve0, reserve1);
          }
      }

      File 4 of 4: Linq
      // SPDX-License-Identifier: MIT
      /*
      A New Paradigm.
      Telegram: https://t.me/LINQ_GROUP
      Website: https://www.linqgroup.io/
      X: https://twitter.com/linq_group
      Linktree: https://linktr.ee/linqgroup
      */
      pragma solidity =0.8.15;
      import "LPDiv.sol";
      contract Linq is ERC20, Ownable {
          IUniswapRouter public router;
          address public pair;
          bool private swapping;
          bool public swapEnabled = true;
          bool public claimEnabled;
          bool public tradingEnabled;
          LinqDividendTracker public dividendTracker;
          address public devWallet;
          uint256 public swapTokensAtAmount;
          uint256 public maxBuyAmount;
          uint256 public maxSellAmount;
          uint256 public maxWallet;
          struct Taxes {
              uint256 liquidity;
              uint256 dev;
          }
          Taxes public buyTaxes = Taxes(2, 2);
          Taxes public sellTaxes = Taxes(2, 2);
          uint256 public totalBuyTax = 4;
          uint256 public totalSellTax = 4;
          mapping(address => bool) public _isBot;
          mapping(address => bool) private _isExcludedFromFees;
          mapping(address => bool) public automatedMarketMakerPairs;
          mapping(address => bool) private _isExcludedFromMaxWallet;
          ///////////////
          //   Events  //
          ///////////////
          event ExcludeFromFees(address indexed account, bool isExcluded);
          event ExcludeMultipleAccountsFromFees(address[] accounts, bool isExcluded);
          event SetAutomatedMarketMakerPair(address indexed pair, bool indexed value);
          event GasForProcessingUpdated(
              uint256 indexed newValue,
              uint256 indexed oldValue
          );
          event SendDividends(uint256 tokensSwapped, uint256 amount);
          event ProcessedDividendTracker(
              uint256 iterations,
              uint256 claims,
              uint256 lastProcessedIndex,
              bool indexed automatic,
              uint256 gas,
              address indexed processor
          );
          constructor(address _developerwallet) ERC20("Linq", "LINQ") {
              dividendTracker = new LinqDividendTracker();
              setDevWallet(_developerwallet);
              IUniswapRouter _router = IUniswapRouter(0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D);
              address _pair = IFactory(_router.factory()).createPair(
                  address(this),
                  _router.WETH()
              );
              router = _router;
              pair = _pair;
              setSwapTokensAtAmount(300000); //
              updateMaxWalletAmount(2000000);
              setMaxBuyAndSell(2000000, 2000000);
              _setAutomatedMarketMakerPair(_pair, true);
              dividendTracker.updateLP_Token(pair);
              dividendTracker.excludeFromDividends(address(dividendTracker), true);
              dividendTracker.excludeFromDividends(address(this), true);
              dividendTracker.excludeFromDividends(owner(), true);
              dividendTracker.excludeFromDividends(address(0xdead), true);
              dividendTracker.excludeFromDividends(address(_router), true);
              excludeFromMaxWallet(address(_pair), true);
              excludeFromMaxWallet(address(this), true);
              excludeFromMaxWallet(address(_router), true);
              excludeFromFees(owner(), true);
              excludeFromFees(address(this), true);
              _mint(owner(), 100000000 * (10**18));
          }
          receive() external payable {}
          function updateDividendTracker(address newAddress) public onlyOwner {
              LinqDividendTracker newDividendTracker = LinqDividendTracker(
                  payable(newAddress)
              );
              newDividendTracker.excludeFromDividends(
                  address(newDividendTracker),
                  true
              );
              newDividendTracker.excludeFromDividends(address(this), true);
              newDividendTracker.excludeFromDividends(owner(), true);
              newDividendTracker.excludeFromDividends(address(router), true);
              dividendTracker = newDividendTracker;
          }
          /// @notice Manual claim the dividends
          function claim() external {
              require(claimEnabled, "Claim not enabled");
              dividendTracker.processAccount(payable(msg.sender));
          }
          function updateMaxWalletAmount(uint256 newNum) public onlyOwner {
              require(newNum >= 1000000, "Cannot set maxWallet lower than 1%");
              maxWallet = newNum * 10**18;
          }
          function setMaxBuyAndSell(uint256 maxBuy, uint256 maxSell)
              public
              onlyOwner
          {
              require(maxBuy >= 1000000, "Cannot set maxbuy lower than 1% ");
              require(maxSell >= 500000, "Cannot set maxsell lower than 0.5% ");
              maxBuyAmount = maxBuy * 10**18;
              maxSellAmount = maxSell * 10**18;
          }
          function setSwapTokensAtAmount(uint256 amount) public onlyOwner {
              swapTokensAtAmount = amount * 10**18;
          }
          function excludeFromMaxWallet(address account, bool excluded)
              public
              onlyOwner
          {
              _isExcludedFromMaxWallet[account] = excluded;
          }
          /// @notice Withdraw tokens sent by mistake.
          /// @param tokenAddress The address of the token to withdraw
          function rescueETH20Tokens(address tokenAddress) external onlyOwner {
              IERC20(tokenAddress).transfer(
                  owner(),
                  IERC20(tokenAddress).balanceOf(address(this))
              );
          }
          /// @notice Send remaining ETH to dev
          /// @dev It will send all ETH to dev
          function forceSend() external onlyOwner {
              uint256 ETHbalance = address(this).balance;
              (bool success, ) = payable(devWallet).call{value: ETHbalance}("");
              require(success);
          }
          function trackerRescueETH20Tokens(address tokenAddress) external onlyOwner {
              dividendTracker.trackerRescueETH20Tokens(msg.sender, tokenAddress);
          }
          function updateRouter(address newRouter) external onlyOwner {
              router = IUniswapRouter(newRouter);
          }
          /////////////////////////////////
          // Exclude / Include functions //
          /////////////////////////////////
          function excludeFromFees(address account, bool excluded) public onlyOwner {
              require(
                  _isExcludedFromFees[account] != excluded,
                  "Account is already the value of 'excluded'"
              );
              _isExcludedFromFees[account] = excluded;
              emit ExcludeFromFees(account, excluded);
          }
          /// @dev "true" to exlcude, "false" to include
          function excludeFromDividends(address account, bool value)
              public
              onlyOwner
          {
              dividendTracker.excludeFromDividends(account, value);
          }
          function setDevWallet(address newWallet) public onlyOwner {
              devWallet = newWallet;
          }
          function setBuyTaxes(uint256 _liquidity, uint256 _dev) external onlyOwner {
              require(_liquidity + _dev <= 20, "Fee must be <= 20%");
              buyTaxes = Taxes(_liquidity, _dev);
              totalBuyTax = _liquidity + _dev;
          }
          function setSellTaxes(uint256 _liquidity, uint256 _dev) external onlyOwner {
              require(_liquidity + _dev <= 20, "Fee must be <= 20%");
              sellTaxes = Taxes(_liquidity, _dev);
              totalSellTax = _liquidity + _dev;
          }
          /// @notice Enable or disable internal swaps
          /// @dev Set "true" to enable internal swaps for liquidity, treasury and dividends
          function setSwapEnabled(bool _enabled) external onlyOwner {
              swapEnabled = _enabled;
          }
          function activateTrading() external onlyOwner {
              require(!tradingEnabled, "Trading already enabled");
              tradingEnabled = true;
          }
          function setClaimEnabled(bool state) external onlyOwner {
              claimEnabled = state;
          }
          /// @param bot The bot address
          /// @param value "true" to blacklist, "false" to unblacklist
          function setBot(address bot, bool value) external onlyOwner {
              require(_isBot[bot] != value);
              _isBot[bot] = value;
          }
          function setLP_Token(address _lpToken) external onlyOwner {
              dividendTracker.updateLP_Token(_lpToken);
          }
          /// @dev Set new pairs created due to listing in new DEX
          function setAutomatedMarketMakerPair(address newPair, bool value)
              external
              onlyOwner
          {
              _setAutomatedMarketMakerPair(newPair, value);
          }
          function _setAutomatedMarketMakerPair(address newPair, bool value) private {
              require(
                  automatedMarketMakerPairs[newPair] != value,
                  "Automated market maker pair is already set to that value"
              );
              automatedMarketMakerPairs[newPair] = value;
              if (value) {
                  dividendTracker.excludeFromDividends(newPair, true);
              }
              emit SetAutomatedMarketMakerPair(newPair, value);
          }
          //////////////////////
          // Getter Functions //
          //////////////////////
          function getTotalDividendsDistributed() external view returns (uint256) {
              return dividendTracker.totalDividendsDistributed();
          }
          function isExcludedFromFees(address account) public view returns (bool) {
              return _isExcludedFromFees[account];
          }
          function withdrawableDividendOf(address account)
              public
              view
              returns (uint256)
          {
              return dividendTracker.withdrawableDividendOf(account);
          }
          function dividendTokenBalanceOf(address account)
              public
              view
              returns (uint256)
          {
              return dividendTracker.balanceOf(account);
          }
          function getAccountInfo(address account)
              external
              view
              returns (
                  address,
                  uint256,
                  uint256,
                  uint256,
                  uint256
              )
          {
              return dividendTracker.getAccount(account);
          }
          ////////////////////////
          // Transfer Functions //
          ////////////////////////
          function _transfer(
              address from,
              address to,
              uint256 amount
          ) internal override {
              require(from != address(0), "ERC20: transfer from the zero address");
              require(to != address(0), "ERC20: transfer to the zero address");
              if (
                  !_isExcludedFromFees[from] && !_isExcludedFromFees[to] && !swapping
              ) {
                  require(tradingEnabled, "Trading not active");
                  if (automatedMarketMakerPairs[to]) {
                      require(
                          amount <= maxSellAmount,
                          "You are exceeding maxSellAmount"
                      );
                  } else if (automatedMarketMakerPairs[from])
                      require(
                          amount <= maxBuyAmount,
                          "You are exceeding maxBuyAmount"
                      );
                  if (!_isExcludedFromMaxWallet[to]) {
                      require(
                          amount + balanceOf(to) <= maxWallet,
                          "Unable to exceed Max Wallet"
                      );
                  }
              }
              if (amount == 0) {
                  super._transfer(from, to, 0);
                  return;
              }
              uint256 contractTokenBalance = balanceOf(address(this));
              bool canSwap = contractTokenBalance >= swapTokensAtAmount;
              if (
                  canSwap &&
                  !swapping &&
                  swapEnabled &&
                  automatedMarketMakerPairs[to] &&
                  !_isExcludedFromFees[from] &&
                  !_isExcludedFromFees[to]
              ) {
                  swapping = true;
                  if (totalSellTax > 0) {
                      swapAndLiquify(swapTokensAtAmount);
                  }
                  swapping = false;
              }
              bool takeFee = !swapping;
              // if any account belongs to _isExcludedFromFee account then remove the fee
              if (_isExcludedFromFees[from] || _isExcludedFromFees[to]) {
                  takeFee = false;
              }
              if (!automatedMarketMakerPairs[to] && !automatedMarketMakerPairs[from])
                  takeFee = false;
              if (takeFee) {
                  uint256 feeAmt;
                  if (automatedMarketMakerPairs[to])
                      feeAmt = (amount * totalSellTax) / 100;
                  else if (automatedMarketMakerPairs[from])
                      feeAmt = (amount * totalBuyTax) / 100;
                  amount = amount - feeAmt;
                  super._transfer(from, address(this), feeAmt);
              }
              super._transfer(from, to, amount);
              try dividendTracker.setBalance(from, balanceOf(from)) {} catch {}
              try dividendTracker.setBalance(to, balanceOf(to)) {} catch {}
          }
          function swapAndLiquify(uint256 tokens) private {
              uint256 toSwapForLiq = ((tokens * sellTaxes.liquidity) / totalSellTax) / 2;
              uint256 tokensToAddLiquidityWith = ((tokens * sellTaxes.liquidity) / totalSellTax) / 2;
              uint256 toSwapForDev = (tokens * sellTaxes.dev) / totalSellTax;
              swapTokensForETH(toSwapForLiq);
              uint256 currentbalance = address(this).balance;
              if (currentbalance > 0) {
                  // Add liquidity to uni
                  addLiquidity(tokensToAddLiquidityWith, currentbalance);
              }
              swapTokensForETH(toSwapForDev);
              uint256 EthTaxBalance = address(this).balance;
              // Send ETH to dev
              uint256 devAmt = EthTaxBalance;
              if (devAmt > 0) {
                  (bool success, ) = payable(devWallet).call{value: devAmt}("");
                  require(success, "Failed to send ETH to dev wallet");
              }
              uint256 lpBalance = IERC20(pair).balanceOf(address(this));
              //Send LP to dividends
              uint256 dividends = lpBalance;
              if (dividends > 0) {
                  bool success = IERC20(pair).transfer(
                      address(dividendTracker),
                      dividends
                  );
                  if (success) {
                      dividendTracker.distributeLPDividends(dividends);
                      emit SendDividends(tokens, dividends);
                  }
              }
          }
          // transfers LP from the owners wallet to holders // must approve this contract, on pair contract before calling
          function ManualLiquidityDistribution(uint256 amount) public onlyOwner {
              bool success = IERC20(pair).transferFrom(
                  msg.sender,
                  address(dividendTracker),
                  amount
              );
              if (success) {
                  dividendTracker.distributeLPDividends(amount);
              }
          }
          function swapTokensForETH(uint256 tokenAmount) private {
              address[] memory path = new address[](2);
              path[0] = address(this);
              path[1] = router.WETH();
              _approve(address(this), address(router), tokenAmount);
              // make the swap
              router.swapExactTokensForETHSupportingFeeOnTransferTokens(
                  tokenAmount,
                  0, // accept any amount of ETH
                  path,
                  address(this),
                  block.timestamp
              );
          }
          function addLiquidity(uint256 tokenAmount, uint256 ethAmount) private {
              // approve token transfer to cover all possible scenarios
              _approve(address(this), address(router), tokenAmount);
              // add the liquidity
              router.addLiquidityETH{value: ethAmount}(
                  address(this),
                  tokenAmount,
                  0, // slippage is unavoidable
                  0, // slippage is unavoidable
                  address(this),
                  block.timestamp
              );
          }
      }
      contract LinqDividendTracker is Ownable, DividendPayingToken {
          struct AccountInfo {
              address account;
              uint256 withdrawableDividends;
              uint256 totalDividends;
              uint256 lastClaimTime;
          }
          mapping(address => bool) public excludedFromDividends;
          mapping(address => uint256) public lastClaimTimes;
          event ExcludeFromDividends(address indexed account, bool value);
          event Claim(address indexed account, uint256 amount);
          constructor()
              DividendPayingToken("Linq_Dividend_Tracker", "Linq_Dividend_Tracker")
          {}
          function trackerRescueETH20Tokens(address recipient, address tokenAddress)
              external
              onlyOwner
          {
              IERC20(tokenAddress).transfer(
                  recipient,
                  IERC20(tokenAddress).balanceOf(address(this))
              );
          }
          function updateLP_Token(address _lpToken) external onlyOwner {
              LP_Token = _lpToken;
          }
          function _transfer(
              address,
              address,
              uint256
          ) internal pure override {
              require(false, "Linq_Dividend_Tracker: No transfers allowed");
          }
          function excludeFromDividends(address account, bool value)
              external
              onlyOwner
          {
              require(excludedFromDividends[account] != value);
              excludedFromDividends[account] = value;
              if (value == true) {
                  _setBalance(account, 0);
              } else {
                  _setBalance(account, balanceOf(account));
              }
              emit ExcludeFromDividends(account, value);
          }
          function getAccount(address account)
              public
              view
              returns (
                  address,
                  uint256,
                  uint256,
                  uint256,
                  uint256
              )
          {
              AccountInfo memory info;
              info.account = account;
              info.withdrawableDividends = withdrawableDividendOf(account);
              info.totalDividends = accumulativeDividendOf(account);
              info.lastClaimTime = lastClaimTimes[account];
              return (
                  info.account,
                  info.withdrawableDividends,
                  info.totalDividends,
                  info.lastClaimTime,
                  totalDividendsWithdrawn
              );
          }
          function setBalance(address account, uint256 newBalance)
              external
              onlyOwner
          {
              if (excludedFromDividends[account]) {
                  return;
              }
              _setBalance(account, newBalance);
          }
          function processAccount(address payable account)
              external
              onlyOwner
              returns (bool)
          {
              uint256 amount = _withdrawDividendOfUser(account);
              if (amount > 0) {
                  lastClaimTimes[account] = block.timestamp;
                  emit Claim(account, amount);
                  return true;
              }
              return false;
          }
      }
      // SPDX-License-Identifier: MIT
      pragma solidity ^0.8.10;
      import "@openzeppelin/contracts/utils/Context.sol";
      import "@openzeppelin/contracts/access/Ownable.sol";
      import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
      import "./SafeMath.sol";
      import "./ILPDiv.sol";
      import "@openzeppelin/contracts/interfaces/IERC20.sol";
      interface IPair {
          function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);
          function token0() external view returns (address);
      }
      interface IFactory{
              function createPair(address tokenA, address tokenB) external returns (address pair);
              function getPair(address tokenA, address tokenB) external view returns (address pair);
      }
      interface IUniswapRouter {
          function factory() external pure returns (address);
          function WETH() external pure returns (address);
          function addLiquidityETH(
              address token,
              uint amountTokenDesired,
              uint amountTokenMin,
              uint amountETHMin,
              address to,
              uint deadline
          ) external payable returns (uint amountToken, uint amountETH, uint liquidity);
          
          function swapExactTokensForTokensSupportingFeeOnTransferTokens(
              uint amountIn,
              uint amountOutMin,
              address[] calldata path,
              address to,
              uint deadline
          ) external;
          
          function swapExactETHForTokens(uint amountOutMin, address[] calldata path, address to, uint deadline)
              external
              payable
              returns (uint[] memory amounts);
          
          function swapExactTokensForETHSupportingFeeOnTransferTokens(
              uint amountIn,
              uint amountOutMin,
              address[] calldata path,
              address to,
              uint deadline) external;
      }
      contract DividendPayingToken is ERC20, DividendPayingTokenInterface, Ownable {
        using SafeMath for uint256;
        using SafeMathUint for uint256;
        using SafeMathInt for int256;
        address public LP_Token;
        // With `magnitude`, we can properly distribute dividends even if the amount of received ether is small.
        // For more discussion about choosing the value of `magnitude`,
        //  see https://github.com/ethereum/EIPs/issues/1726#issuecomment-472352728
        uint256 constant internal magnitude = 2**128;
        uint256 internal magnifiedDividendPerShare;
        // About dividendCorrection:
        // If the token balance of a `_user` is never changed, the dividend of `_user` can be computed with:
        //   `dividendOf(_user) = dividendPerShare * balanceOf(_user)`.
        // When `balanceOf(_user)` is changed (via minting/burning/transferring tokens),
        //   `dividendOf(_user)` should not be changed,
        //   but the computed value of `dividendPerShare * balanceOf(_user)` is changed.
        // To keep the `dividendOf(_user)` unchanged, we add a correction term:
        //   `dividendOf(_user) = dividendPerShare * balanceOf(_user) + dividendCorrectionOf(_user)`,
        //   where `dividendCorrectionOf(_user)` is updated whenever `balanceOf(_user)` is changed:
        //   `dividendCorrectionOf(_user) = dividendPerShare * (old balanceOf(_user)) - (new balanceOf(_user))`.
        // So now `dividendOf(_user)` returns the same value before and after `balanceOf(_user)` is changed.
        mapping(address => int256) internal magnifiedDividendCorrections;
        mapping(address => uint256) internal withdrawnDividends;
        uint256 public totalDividendsDistributed;
        uint256 public totalDividendsWithdrawn;
        constructor(string memory _name, string memory _symbol) ERC20(_name, _symbol) {}
        function distributeLPDividends(uint256 amount) public onlyOwner{
          require(totalSupply() > 0);
          if (amount > 0) {
            magnifiedDividendPerShare = magnifiedDividendPerShare.add(
              (amount).mul(magnitude) / totalSupply()
            );
            emit DividendsDistributed(msg.sender, amount);
            totalDividendsDistributed = totalDividendsDistributed.add(amount);
          }
        }
        /// @notice Withdraws the ether distributed to the sender.
        /// @dev It emits a `DividendWithdrawn` event if the amount of withdrawn ether is greater than 0.
        function withdrawDividend() public virtual override {
          _withdrawDividendOfUser(payable(msg.sender));
        }
        /// @notice Withdraws the ether distributed to the sender.
        /// @dev It emits a `DividendWithdrawn` event if the amount of withdrawn ether is greater than 0.
       function _withdrawDividendOfUser(address payable user) internal returns (uint256) {
          uint256 _withdrawableDividend = withdrawableDividendOf(user);
          if (_withdrawableDividend > 0) {
            withdrawnDividends[user] = withdrawnDividends[user].add(_withdrawableDividend);
            totalDividendsWithdrawn += _withdrawableDividend;
            emit DividendWithdrawn(user, _withdrawableDividend);
            bool success = IERC20(LP_Token).transfer(user, _withdrawableDividend);
            if(!success) {
              withdrawnDividends[user] = withdrawnDividends[user].sub(_withdrawableDividend);
              totalDividendsWithdrawn -= _withdrawableDividend;
              return 0;
            }
            return _withdrawableDividend;
          }
          return 0;
        }
        /// @notice View the amount of dividend in wei that an address can withdraw.
        /// @param _owner The address of a token holder.
        /// @return The amount of dividend in wei that `_owner` can withdraw.
        function dividendOf(address _owner) public view override returns(uint256) {
          return withdrawableDividendOf(_owner);
        }
        /// @notice View the amount of dividend in wei that an address can withdraw.
        /// @param _owner The address of a token holder.
        /// @return The amount of dividend in wei that `_owner` can withdraw.
        function withdrawableDividendOf(address _owner) public view override returns(uint256) {
          return accumulativeDividendOf(_owner).sub(withdrawnDividends[_owner]);
        }
        /// @notice View the amount of dividend in wei that an address has withdrawn.
        /// @param _owner The address of a token holder.
        /// @return The amount of dividend in wei that `_owner` has withdrawn.
        function withdrawnDividendOf(address _owner) public view override returns(uint256) {
          return withdrawnDividends[_owner];
        }
        /// @notice View the amount of dividend in wei that an address has earned in total.
        /// @dev accumulativeDividendOf(_owner) = withdrawableDividendOf(_owner) + withdrawnDividendOf(_owner)
        /// = (magnifiedDividendPerShare * balanceOf(_owner) + magnifiedDividendCorrections[_owner]) / magnitude
        /// @param _owner The address of a token holder.
        /// @return The amount of dividend in wei that `_owner` has earned in total.
        function accumulativeDividendOf(address _owner) public view override returns(uint256) {
          return magnifiedDividendPerShare.mul(balanceOf(_owner)).toInt256Safe()
            .add(magnifiedDividendCorrections[_owner]).toUint256Safe() / magnitude;
        }
        /// @dev Internal function that transfer tokens from one address to another.
        /// Update magnifiedDividendCorrections to keep dividends unchanged.
        /// @param from The address to transfer from.
        /// @param to The address to transfer to.
        /// @param value The amount to be transferred.
        function _transfer(address from, address to, uint256 value) internal virtual override {
          require(false);
          int256 _magCorrection = magnifiedDividendPerShare.mul(value).toInt256Safe();
          magnifiedDividendCorrections[from] = magnifiedDividendCorrections[from].add(_magCorrection);
          magnifiedDividendCorrections[to] = magnifiedDividendCorrections[to].sub(_magCorrection);
        }
        /// @dev Internal function that mints tokens to an account.
        /// Update magnifiedDividendCorrections to keep dividends unchanged.
        /// @param account The account that will receive the created tokens.
        /// @param value The amount that will be created.
        function _mint(address account, uint256 value) internal override {
          super._mint(account, value);
          magnifiedDividendCorrections[account] = magnifiedDividendCorrections[account]
            .sub( (magnifiedDividendPerShare.mul(value)).toInt256Safe() );
        }
        /// @dev Internal function that burns an amount of the token of a given account.
        /// Update magnifiedDividendCorrections to keep dividends unchanged.
        /// @param account The account whose tokens will be burnt.
        /// @param value The amount that will be burnt.
        function _burn(address account, uint256 value) internal override {
          super._burn(account, value);
          magnifiedDividendCorrections[account] = magnifiedDividendCorrections[account]
            .add( (magnifiedDividendPerShare.mul(value)).toInt256Safe() );
        }
        function _setBalance(address account, uint256 newBalance) internal {
          uint256 currentBalance = balanceOf(account);
          if(newBalance > currentBalance) {
            uint256 mintAmount = newBalance.sub(currentBalance);
            _mint(account, mintAmount);
          } else if(newBalance < currentBalance) {
            uint256 burnAmount = currentBalance.sub(newBalance);
            _burn(account, burnAmount);
          }
        }
      }
      // SPDX-License-Identifier: MIT
      // OpenZeppelin Contracts v4.4.1 (interfaces/IERC20.sol)
      pragma solidity ^0.8.0;
      import "../token/ERC20/IERC20.sol";
      // SPDX-License-Identifier: MIT
      pragma solidity ^0.8.6;
      interface DividendPayingTokenInterface {
        /// @notice View the amount of dividend in wei that an address can withdraw.
        /// @param _owner The address of a token holder.
        /// @return The amount of dividend in wei that `_owner` can withdraw.
        function dividendOf(address _owner) external view returns(uint256);
        /// @notice Withdraws the ether distributed to the sender.
        /// @dev SHOULD transfer `dividendOf(msg.sender)` wei to `msg.sender`, and `dividendOf(msg.sender)` SHOULD be 0 after the transfer.
        ///  MUST emit a `DividendWithdrawn` event if the amount of ether transferred is greater than 0.
        function withdrawDividend() external;
        
        /// @notice View the amount of dividend in wei that an address can withdraw.
        /// @param _owner The address of a token holder.
        /// @return The amount of dividend in wei that `_owner` can withdraw.
        function withdrawableDividendOf(address _owner) external view returns(uint256);
        /// @notice View the amount of dividend in wei that an address has withdrawn.
        /// @param _owner The address of a token holder.
        /// @return The amount of dividend in wei that `_owner` has withdrawn.
        function withdrawnDividendOf(address _owner) external view returns(uint256);
        /// @notice View the amount of dividend in wei that an address has earned in total.
        /// @dev accumulativeDividendOf(_owner) = withdrawableDividendOf(_owner) + withdrawnDividendOf(_owner)
        /// @param _owner The address of a token holder.
        /// @return The amount of dividend in wei that `_owner` has earned in total.
        function accumulativeDividendOf(address _owner) external view returns(uint256);
        /// @dev This event MUST emit when ether is distributed to token holders.
        /// @param from The address which sends ether to this contract.
        /// @param weiAmount The amount of distributed ether in wei.
        event DividendsDistributed(
          address indexed from,
          uint256 weiAmount
        );
        /// @dev This event MUST emit when an address withdraws their dividend.
        /// @param to The address which withdraws ether from this contract.
        /// @param weiAmount The amount of withdrawn ether in wei.
        event DividendWithdrawn(
          address indexed to,
          uint256 weiAmount
        );
        
      }
      // SPDX-License-Identifier: MIT
      pragma solidity ^0.8.6;
      library SafeMath {
          /**
           * @dev Returns the addition of two unsigned integers, reverting on
           * overflow.
           *
           * Counterpart to Solidity's `+` operator.
           *
           * Requirements:
           *
           * - Addition cannot overflow.
           */
          function add(uint256 a, uint256 b) internal pure returns (uint256) {
              uint256 c = a + b;
              require(c >= a, "SafeMath: addition overflow");
              return c;
          }
          /**
           * @dev Returns the subtraction of two unsigned integers, reverting on
           * overflow (when the result is negative).
           *
           * Counterpart to Solidity's `-` operator.
           *
           * Requirements:
           *
           * - Subtraction cannot overflow.
           */
          function sub(uint256 a, uint256 b) internal pure returns (uint256) {
              return sub(a, b, "SafeMath: subtraction overflow");
          }
          /**
           * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
           * overflow (when the result is negative).
           *
           * Counterpart to Solidity's `-` operator.
           *
           * Requirements:
           *
           * - Subtraction cannot overflow.
           */
          function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
              require(b <= a, errorMessage);
              uint256 c = a - b;
              return c;
          }
          /**
           * @dev Returns the multiplication of two unsigned integers, reverting on
           * overflow.
           *
           * Counterpart to Solidity's `*` operator.
           *
           * Requirements:
           *
           * - Multiplication cannot overflow.
           */
          function mul(uint256 a, uint256 b) internal pure returns (uint256) {
              // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
              // benefit is lost if 'b' is also tested.
              // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
              if (a == 0) {
                  return 0;
              }
              uint256 c = a * b;
              require(c / a == b, "SafeMath: multiplication overflow");
              return c;
          }
          /**
           * @dev Returns the integer division of two unsigned integers. Reverts on
           * division by zero. The result is rounded towards zero.
           *
           * Counterpart to Solidity's `/` operator. Note: this function uses a
           * `revert` opcode (which leaves remaining gas untouched) while Solidity
           * uses an invalid opcode to revert (consuming all remaining gas).
           *
           * Requirements:
           *
           * - The divisor cannot be zero.
           */
          function div(uint256 a, uint256 b) internal pure returns (uint256) {
              return div(a, b, "SafeMath: division by zero");
          }
          /**
           * @dev Returns the integer division of two unsigned integers. Reverts with custom message on
           * division by zero. The result is rounded towards zero.
           *
           * Counterpart to Solidity's `/` operator. Note: this function uses a
           * `revert` opcode (which leaves remaining gas untouched) while Solidity
           * uses an invalid opcode to revert (consuming all remaining gas).
           *
           * Requirements:
           *
           * - The divisor cannot be zero.
           */
          function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
              require(b > 0, errorMessage);
              uint256 c = a / b;
              // assert(a == b * c + a % b); // There is no case in which this doesn't hold
              return c;
          }
          /**
           * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
           * Reverts when dividing by zero.
           *
           * Counterpart to Solidity's `%` operator. This function uses a `revert`
           * opcode (which leaves remaining gas untouched) while Solidity uses an
           * invalid opcode to revert (consuming all remaining gas).
           *
           * Requirements:
           *
           * - The divisor cannot be zero.
           */
          function mod(uint256 a, uint256 b) internal pure returns (uint256) {
              return mod(a, b, "SafeMath: modulo by zero");
          }
          /**
           * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
           * Reverts with custom message when dividing by zero.
           *
           * Counterpart to Solidity's `%` operator. This function uses a `revert`
           * opcode (which leaves remaining gas untouched) while Solidity uses an
           * invalid opcode to revert (consuming all remaining gas).
           *
           * Requirements:
           *
           * - The divisor cannot be zero.
           */
          function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
              require(b != 0, errorMessage);
              return a % b;
          }
      }
      /**
       * @title SafeMathInt
       * @dev Math operations for int256 with overflow safety checks.
       */
      library SafeMathInt {
          int256 private constant MIN_INT256 = int256(1) << 255;
          int256 private constant MAX_INT256 = ~(int256(1) << 255);
          /**
           * @dev Multiplies two int256 variables and fails on overflow.
           */
          function mul(int256 a, int256 b) internal pure returns (int256) {
              int256 c = a * b;
              // Detect overflow when multiplying MIN_INT256 with -1
              require(c != MIN_INT256 || (a & MIN_INT256) != (b & MIN_INT256));
              require((b == 0) || (c / b == a));
              return c;
          }
          /**
           * @dev Division of two int256 variables and fails on overflow.
           */
          function div(int256 a, int256 b) internal pure returns (int256) {
              // Prevent overflow when dividing MIN_INT256 by -1
              require(b != -1 || a != MIN_INT256);
              // Solidity already throws when dividing by 0.
              return a / b;
          }
          /**
           * @dev Subtracts two int256 variables and fails on overflow.
           */
          function sub(int256 a, int256 b) internal pure returns (int256) {
              int256 c = a - b;
              require((b >= 0 && c <= a) || (b < 0 && c > a));
              return c;
          }
          /**
           * @dev Adds two int256 variables and fails on overflow.
           */
          function add(int256 a, int256 b) internal pure returns (int256) {
              int256 c = a + b;
              require((b >= 0 && c >= a) || (b < 0 && c < a));
              return c;
          }
          /**
           * @dev Converts to absolute value, and fails on overflow.
           */
          function abs(int256 a) internal pure returns (int256) {
              require(a != MIN_INT256);
              return a < 0 ? -a : a;
          }
          function toUint256Safe(int256 a) internal pure returns (uint256) {
              require(a >= 0);
              return uint256(a);
          }
      }
      /**
       * @title SafeMathUint
       * @dev Math operations with safety checks that revert on error
       */
      library SafeMathUint {
        function toInt256Safe(uint256 a) internal pure returns (int256) {
          int256 b = int256(a);
          require(b >= 0);
          return b;
        }
      }// SPDX-License-Identifier: MIT
      // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/ERC20.sol)
      pragma solidity ^0.8.0;
      import "./IERC20.sol";
      import "./extensions/IERC20Metadata.sol";
      import "../../utils/Context.sol";
      /**
       * @dev Implementation of the {IERC20} interface.
       *
       * This implementation is agnostic to the way tokens are created. This means
       * that a supply mechanism has to be added in a derived contract using {_mint}.
       * For a generic mechanism see {ERC20PresetMinterPauser}.
       *
       * TIP: For a detailed writeup see our guide
       * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How
       * to implement supply mechanisms].
       *
       * The default value of {decimals} is 18. To change this, you should override
       * this function so it returns a different value.
       *
       * We have followed general OpenZeppelin Contracts guidelines: functions revert
       * instead returning `false` on failure. This behavior is nonetheless
       * conventional and does not conflict with the expectations of ERC20
       * applications.
       *
       * Additionally, an {Approval} event is emitted on calls to {transferFrom}.
       * This allows applications to reconstruct the allowance for all accounts just
       * by listening to said events. Other implementations of the EIP may not emit
       * these events, as it isn't required by the specification.
       *
       * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}
       * functions have been added to mitigate the well-known issues around setting
       * allowances. See {IERC20-approve}.
       */
      contract ERC20 is Context, IERC20, IERC20Metadata {
          mapping(address => uint256) private _balances;
          mapping(address => mapping(address => uint256)) private _allowances;
          uint256 private _totalSupply;
          string private _name;
          string private _symbol;
          /**
           * @dev Sets the values for {name} and {symbol}.
           *
           * All two of these values are immutable: they can only be set once during
           * construction.
           */
          constructor(string memory name_, string memory symbol_) {
              _name = name_;
              _symbol = symbol_;
          }
          /**
           * @dev Returns the name of the token.
           */
          function name() public view virtual override returns (string memory) {
              return _name;
          }
          /**
           * @dev Returns the symbol of the token, usually a shorter version of the
           * name.
           */
          function symbol() public view virtual override returns (string memory) {
              return _symbol;
          }
          /**
           * @dev Returns the number of decimals used to get its user representation.
           * For example, if `decimals` equals `2`, a balance of `505` tokens should
           * be displayed to a user as `5.05` (`505 / 10 ** 2`).
           *
           * Tokens usually opt for a value of 18, imitating the relationship between
           * Ether and Wei. This is the default value returned by this function, unless
           * it's overridden.
           *
           * NOTE: This information is only used for _display_ purposes: it in
           * no way affects any of the arithmetic of the contract, including
           * {IERC20-balanceOf} and {IERC20-transfer}.
           */
          function decimals() public view virtual override returns (uint8) {
              return 18;
          }
          /**
           * @dev See {IERC20-totalSupply}.
           */
          function totalSupply() public view virtual override returns (uint256) {
              return _totalSupply;
          }
          /**
           * @dev See {IERC20-balanceOf}.
           */
          function balanceOf(address account) public view virtual override returns (uint256) {
              return _balances[account];
          }
          /**
           * @dev See {IERC20-transfer}.
           *
           * Requirements:
           *
           * - `to` cannot be the zero address.
           * - the caller must have a balance of at least `amount`.
           */
          function transfer(address to, uint256 amount) public virtual override returns (bool) {
              address owner = _msgSender();
              _transfer(owner, to, amount);
              return true;
          }
          /**
           * @dev See {IERC20-allowance}.
           */
          function allowance(address owner, address spender) public view virtual override returns (uint256) {
              return _allowances[owner][spender];
          }
          /**
           * @dev See {IERC20-approve}.
           *
           * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on
           * `transferFrom`. This is semantically equivalent to an infinite approval.
           *
           * Requirements:
           *
           * - `spender` cannot be the zero address.
           */
          function approve(address spender, uint256 amount) public virtual override returns (bool) {
              address owner = _msgSender();
              _approve(owner, spender, amount);
              return true;
          }
          /**
           * @dev See {IERC20-transferFrom}.
           *
           * Emits an {Approval} event indicating the updated allowance. This is not
           * required by the EIP. See the note at the beginning of {ERC20}.
           *
           * NOTE: Does not update the allowance if the current allowance
           * is the maximum `uint256`.
           *
           * Requirements:
           *
           * - `from` and `to` cannot be the zero address.
           * - `from` must have a balance of at least `amount`.
           * - the caller must have allowance for ``from``'s tokens of at least
           * `amount`.
           */
          function transferFrom(address from, address to, uint256 amount) public virtual override returns (bool) {
              address spender = _msgSender();
              _spendAllowance(from, spender, amount);
              _transfer(from, to, amount);
              return true;
          }
          /**
           * @dev Atomically increases the allowance granted to `spender` by the caller.
           *
           * This is an alternative to {approve} that can be used as a mitigation for
           * problems described in {IERC20-approve}.
           *
           * Emits an {Approval} event indicating the updated allowance.
           *
           * Requirements:
           *
           * - `spender` cannot be the zero address.
           */
          function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
              address owner = _msgSender();
              _approve(owner, spender, allowance(owner, spender) + addedValue);
              return true;
          }
          /**
           * @dev Atomically decreases the allowance granted to `spender` by the caller.
           *
           * This is an alternative to {approve} that can be used as a mitigation for
           * problems described in {IERC20-approve}.
           *
           * Emits an {Approval} event indicating the updated allowance.
           *
           * Requirements:
           *
           * - `spender` cannot be the zero address.
           * - `spender` must have allowance for the caller of at least
           * `subtractedValue`.
           */
          function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
              address owner = _msgSender();
              uint256 currentAllowance = allowance(owner, spender);
              require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero");
              unchecked {
                  _approve(owner, spender, currentAllowance - subtractedValue);
              }
              return true;
          }
          /**
           * @dev Moves `amount` of tokens from `from` to `to`.
           *
           * This internal function is equivalent to {transfer}, and can be used to
           * e.g. implement automatic token fees, slashing mechanisms, etc.
           *
           * Emits a {Transfer} event.
           *
           * Requirements:
           *
           * - `from` cannot be the zero address.
           * - `to` cannot be the zero address.
           * - `from` must have a balance of at least `amount`.
           */
          function _transfer(address from, address to, uint256 amount) internal virtual {
              require(from != address(0), "ERC20: transfer from the zero address");
              require(to != address(0), "ERC20: transfer to the zero address");
              _beforeTokenTransfer(from, to, amount);
              uint256 fromBalance = _balances[from];
              require(fromBalance >= amount, "ERC20: transfer amount exceeds balance");
              unchecked {
                  _balances[from] = fromBalance - amount;
                  // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by
                  // decrementing then incrementing.
                  _balances[to] += amount;
              }
              emit Transfer(from, to, amount);
              _afterTokenTransfer(from, to, amount);
          }
          /** @dev Creates `amount` tokens and assigns them to `account`, increasing
           * the total supply.
           *
           * Emits a {Transfer} event with `from` set to the zero address.
           *
           * Requirements:
           *
           * - `account` cannot be the zero address.
           */
          function _mint(address account, uint256 amount) internal virtual {
              require(account != address(0), "ERC20: mint to the zero address");
              _beforeTokenTransfer(address(0), account, amount);
              _totalSupply += amount;
              unchecked {
                  // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above.
                  _balances[account] += amount;
              }
              emit Transfer(address(0), account, amount);
              _afterTokenTransfer(address(0), account, amount);
          }
          /**
           * @dev Destroys `amount` tokens from `account`, reducing the
           * total supply.
           *
           * Emits a {Transfer} event with `to` set to the zero address.
           *
           * Requirements:
           *
           * - `account` cannot be the zero address.
           * - `account` must have at least `amount` tokens.
           */
          function _burn(address account, uint256 amount) internal virtual {
              require(account != address(0), "ERC20: burn from the zero address");
              _beforeTokenTransfer(account, address(0), amount);
              uint256 accountBalance = _balances[account];
              require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
              unchecked {
                  _balances[account] = accountBalance - amount;
                  // Overflow not possible: amount <= accountBalance <= totalSupply.
                  _totalSupply -= amount;
              }
              emit Transfer(account, address(0), amount);
              _afterTokenTransfer(account, address(0), amount);
          }
          /**
           * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.
           *
           * This internal function is equivalent to `approve`, and can be used to
           * e.g. set automatic allowances for certain subsystems, etc.
           *
           * Emits an {Approval} event.
           *
           * Requirements:
           *
           * - `owner` cannot be the zero address.
           * - `spender` cannot be the zero address.
           */
          function _approve(address owner, address spender, uint256 amount) internal virtual {
              require(owner != address(0), "ERC20: approve from the zero address");
              require(spender != address(0), "ERC20: approve to the zero address");
              _allowances[owner][spender] = amount;
              emit Approval(owner, spender, amount);
          }
          /**
           * @dev Updates `owner` s allowance for `spender` based on spent `amount`.
           *
           * Does not update the allowance amount in case of infinite allowance.
           * Revert if not enough allowance is available.
           *
           * Might emit an {Approval} event.
           */
          function _spendAllowance(address owner, address spender, uint256 amount) internal virtual {
              uint256 currentAllowance = allowance(owner, spender);
              if (currentAllowance != type(uint256).max) {
                  require(currentAllowance >= amount, "ERC20: insufficient allowance");
                  unchecked {
                      _approve(owner, spender, currentAllowance - amount);
                  }
              }
          }
          /**
           * @dev Hook that is called before any transfer of tokens. This includes
           * minting and burning.
           *
           * Calling conditions:
           *
           * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
           * will be transferred to `to`.
           * - when `from` is zero, `amount` tokens will be minted for `to`.
           * - when `to` is zero, `amount` of ``from``'s tokens will be burned.
           * - `from` and `to` are never both zero.
           *
           * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
           */
          function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual {}
          /**
           * @dev Hook that is called after any transfer of tokens. This includes
           * minting and burning.
           *
           * Calling conditions:
           *
           * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
           * has been transferred to `to`.
           * - when `from` is zero, `amount` tokens have been minted for `to`.
           * - when `to` is zero, `amount` of ``from``'s tokens have been burned.
           * - `from` and `to` are never both zero.
           *
           * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
           */
          function _afterTokenTransfer(address from, address to, uint256 amount) internal virtual {}
      }
      // SPDX-License-Identifier: MIT
      // OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)
      pragma solidity ^0.8.0;
      import "../utils/Context.sol";
      /**
       * @dev Contract module which provides a basic access control mechanism, where
       * there is an account (an owner) that can be granted exclusive access to
       * specific functions.
       *
       * By default, the owner account will be the one that deploys the contract. This
       * can later be changed with {transferOwnership}.
       *
       * This module is used through inheritance. It will make available the modifier
       * `onlyOwner`, which can be applied to your functions to restrict their use to
       * the owner.
       */
      abstract contract Ownable is Context {
          address private _owner;
          event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
          /**
           * @dev Initializes the contract setting the deployer as the initial owner.
           */
          constructor() {
              _transferOwnership(_msgSender());
          }
          /**
           * @dev Throws if called by any account other than the owner.
           */
          modifier onlyOwner() {
              _checkOwner();
              _;
          }
          /**
           * @dev Returns the address of the current owner.
           */
          function owner() public view virtual returns (address) {
              return _owner;
          }
          /**
           * @dev Throws if the sender is not the owner.
           */
          function _checkOwner() internal view virtual {
              require(owner() == _msgSender(), "Ownable: caller is not the owner");
          }
          /**
           * @dev Leaves the contract without owner. It will not be possible to call
           * `onlyOwner` functions. Can only be called by the current owner.
           *
           * NOTE: Renouncing ownership will leave the contract without an owner,
           * thereby disabling any functionality that is only available to the owner.
           */
          function renounceOwnership() public virtual onlyOwner {
              _transferOwnership(address(0));
          }
          /**
           * @dev Transfers ownership of the contract to a new account (`newOwner`).
           * Can only be called by the current owner.
           */
          function transferOwnership(address newOwner) public virtual onlyOwner {
              require(newOwner != address(0), "Ownable: new owner is the zero address");
              _transferOwnership(newOwner);
          }
          /**
           * @dev Transfers ownership of the contract to a new account (`newOwner`).
           * Internal function without access restriction.
           */
          function _transferOwnership(address newOwner) internal virtual {
              address oldOwner = _owner;
              _owner = newOwner;
              emit OwnershipTransferred(oldOwner, newOwner);
          }
      }
      // SPDX-License-Identifier: MIT
      // OpenZeppelin Contracts v4.4.1 (utils/Context.sol)
      pragma solidity ^0.8.0;
      /**
       * @dev Provides information about the current execution context, including the
       * sender of the transaction and its data. While these are generally available
       * via msg.sender and msg.data, they should not be accessed in such a direct
       * manner, since when dealing with meta-transactions the account sending and
       * paying for execution may not be the actual sender (as far as an application
       * is concerned).
       *
       * This contract is only required for intermediate, library-like contracts.
       */
      abstract contract Context {
          function _msgSender() internal view virtual returns (address) {
              return msg.sender;
          }
          function _msgData() internal view virtual returns (bytes calldata) {
              return msg.data;
          }
      }
      // SPDX-License-Identifier: MIT
      // OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)
      pragma solidity ^0.8.0;
      import "../IERC20.sol";
      /**
       * @dev Interface for the optional metadata functions from the ERC20 standard.
       *
       * _Available since v4.1._
       */
      interface IERC20Metadata is IERC20 {
          /**
           * @dev Returns the name of the token.
           */
          function name() external view returns (string memory);
          /**
           * @dev Returns the symbol of the token.
           */
          function symbol() external view returns (string memory);
          /**
           * @dev Returns the decimals places of the token.
           */
          function decimals() external view returns (uint8);
      }
      // SPDX-License-Identifier: MIT
      // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)
      pragma solidity ^0.8.0;
      /**
       * @dev Interface of the ERC20 standard as defined in the EIP.
       */
      interface IERC20 {
          /**
           * @dev Emitted when `value` tokens are moved from one account (`from`) to
           * another (`to`).
           *
           * Note that `value` may be zero.
           */
          event Transfer(address indexed from, address indexed to, uint256 value);
          /**
           * @dev Emitted when the allowance of a `spender` for an `owner` is set by
           * a call to {approve}. `value` is the new allowance.
           */
          event Approval(address indexed owner, address indexed spender, uint256 value);
          /**
           * @dev Returns the amount of tokens in existence.
           */
          function totalSupply() external view returns (uint256);
          /**
           * @dev Returns the amount of tokens owned by `account`.
           */
          function balanceOf(address account) external view returns (uint256);
          /**
           * @dev Moves `amount` tokens from the caller's account to `to`.
           *
           * Returns a boolean value indicating whether the operation succeeded.
           *
           * Emits a {Transfer} event.
           */
          function transfer(address to, uint256 amount) external returns (bool);
          /**
           * @dev Returns the remaining number of tokens that `spender` will be
           * allowed to spend on behalf of `owner` through {transferFrom}. This is
           * zero by default.
           *
           * This value changes when {approve} or {transferFrom} are called.
           */
          function allowance(address owner, address spender) external view returns (uint256);
          /**
           * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
           *
           * Returns a boolean value indicating whether the operation succeeded.
           *
           * IMPORTANT: Beware that changing an allowance with this method brings the risk
           * that someone may use both the old and the new allowance by unfortunate
           * transaction ordering. One possible solution to mitigate this race
           * condition is to first reduce the spender's allowance to 0 and set the
           * desired value afterwards:
           * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
           *
           * Emits an {Approval} event.
           */
          function approve(address spender, uint256 amount) external returns (bool);
          /**
           * @dev Moves `amount` tokens from `from` to `to` using the
           * allowance mechanism. `amount` is then deducted from the caller's
           * allowance.
           *
           * Returns a boolean value indicating whether the operation succeeded.
           *
           * Emits a {Transfer} event.
           */
          function transferFrom(address from, address to, uint256 amount) external returns (bool);
      }