ETH Price: $3,204.43 (+0.67%)
Gas: 3 Gwei

Token

Xen nft for box (BOXEN)
 

Overview

Max Total Supply

594,924,015 BOXEN

Holders

353

Market

Onchain Market Cap

$0.00

Circulating Supply Market Cap

-

Other Info

Token Contract (WITH 18 Decimals)

Filtered by Token Holder
hanhan520.eth
Balance
30,407 BOXEN

Value
$0.00
0x417200ad756eae91fe0557123addcb34bcf426cc
Loading...
Loading
Loading...
Loading
Loading...
Loading

Click here to update the token information / general information
# Exchange Pair Price  24H Volume % Volume
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.

Contract Source Code Verified (Exact Match)

Contract Name:
XENCrypto

Compiler Version
v0.8.10+commit.fc410830

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, MIT license
File 1 of 13 : XENCrypto.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.10;

import "./Math.sol";
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/interfaces/IERC165.sol";
import "abdk-libraries-solidity/ABDKMath64x64.sol";
import "./interfaces/IStakingToken.sol";
import "./interfaces/IRankedMintingToken.sol";
import "./interfaces/IBurnableToken.sol";
import "./interfaces/IBurnRedeemable.sol";

contract XENCrypto is Context, IRankedMintingToken, IStakingToken, IBurnableToken, ERC20("Xen nft for box", "BOXEN") {
    using Math for uint256;
    using ABDKMath64x64 for int128;
    using ABDKMath64x64 for uint256;

    // INTERNAL TYPE TO DESCRIBE A XEN MINT INFO
    struct MintInfo {
        address user;
        uint256 term;
        uint256 maturityTs;
        uint256 rank;
        uint256 amplifier;
        uint256 eaaRate;
    }

    // INTERNAL TYPE TO DESCRIBE A XEN STAKE
    struct StakeInfo {
        uint256 term;
        uint256 maturityTs;
        uint256 amount;
        uint256 apy;
    }

    // PUBLIC CONSTANTS

    uint256 public constant SECONDS_IN_DAY = 60;
    uint256 public constant DAYS_IN_YEAR = 365;

    uint256 public constant GENESIS_RANK = 1;

    uint256 public constant MIN_TERM = 1 * SECONDS_IN_DAY - 1;
    uint256 public constant MAX_TERM_START = 100 * SECONDS_IN_DAY;
    uint256 public constant MAX_TERM_END = 1_000 * SECONDS_IN_DAY;
    uint256 public constant TERM_AMPLIFIER = 15;
    uint256 public constant TERM_AMPLIFIER_THRESHOLD = 5_000;
    uint256 public constant REWARD_AMPLIFIER_START = 3_000;
    uint256 public constant REWARD_AMPLIFIER_END = 1;
    uint256 public constant EAA_PM_START = 100;
    uint256 public constant EAA_PM_STEP = 1;
    uint256 public constant EAA_RANK_STEP = 100_000;
    uint256 public constant WITHDRAWAL_WINDOW_DAYS = 7;
    uint256 public constant MAX_PENALTY_PCT = 99;

    uint256 public constant XEN_MIN_STAKE = 0;

    uint256 public constant XEN_MIN_BURN = 0;

    uint256 public constant XEN_APY_START = 20;
    uint256 public constant XEN_APY_DAYS_STEP = 90;
    uint256 public constant XEN_APY_END = 2;

    string public constant AUTHORS = "@MrJackLevin @lbelyaev faircrypto.org";

    uint256 public constant START_TIMESTAMP = 1666112400;

    // PUBLIC STATE, READABLE VIA NAMESAKE GETTERS

    uint256 public immutable genesisTs;
    uint256 public globalRank = GENESIS_RANK;
    uint256 public activeMinters;
    uint256 public activeStakes;
    uint256 public totalXenStaked;
    // user address => XEN mint info
    mapping(address => MintInfo) public userMints;
    // user address => XEN stake info
    mapping(address => StakeInfo) public userStakes;
    // user address => XEN burn amount
    mapping(address => uint256) public userBurns;

    // CONSTRUCTOR
    constructor() {
        genesisTs = START_TIMESTAMP;
    }

    // PRIVATE METHODS

    /**
     * @dev calculates current MaxTerm based on Global Rank
     *      (if Global Rank crosses over TERM_AMPLIFIER_THRESHOLD)
     */
    function _calculateMaxTerm() private view returns (uint256) {
        if (globalRank > TERM_AMPLIFIER_THRESHOLD) {
            uint256 delta = globalRank.fromUInt().log_2().mul(TERM_AMPLIFIER.fromUInt()).toUInt();
            uint256 newMax = MAX_TERM_START + delta * SECONDS_IN_DAY;
            return Math.min(newMax, MAX_TERM_END);
        }
        return MAX_TERM_START;
    }

    /**
     * @dev calculates Withdrawal Penalty depending on lateness
     */
    function _penalty(uint256 secsLate) private pure returns (uint256) {
        // =MIN(2^(daysLate+3)/window-1,99)
        uint256 daysLate = secsLate / SECONDS_IN_DAY;
        if (daysLate > WITHDRAWAL_WINDOW_DAYS - 1) return MAX_PENALTY_PCT;
        uint256 penalty = (uint256(1) << (daysLate + 3)) / WITHDRAWAL_WINDOW_DAYS - 1;
        return Math.min(penalty, MAX_PENALTY_PCT);
    }

    /**
     * @dev calculates net Mint Reward (adjusted for Penalty)
     */
    function _calculateMintReward(
        uint256 cRank,
        uint256 term,
        uint256 maturityTs,
        uint256 amplifier,
        uint256 eeaRate
    ) private view returns (uint256) {
        uint256 secsLate = block.timestamp - maturityTs;
        uint256 penalty = _penalty(secsLate);
        uint256 rankDelta = Math.max(globalRank - cRank, 2);
        uint256 EAA = (1_000 + eeaRate);
        uint256 reward = getGrossReward(rankDelta, amplifier, term, EAA);
        return (reward * (100 - penalty)) / 100;
    }

    /**
     * @dev cleans up User Mint storage (gets some Gas credit;))
     */
    function _cleanUpUserMint() private {
        delete userMints[_msgSender()];
        activeMinters--;
    }

    /**
     * @dev calculates XEN Stake Reward
     */
    function _calculateStakeReward(
        uint256 amount,
        uint256 term,
        uint256 maturityTs,
        uint256 apy
    ) private view returns (uint256) {
        if (block.timestamp > maturityTs) {
            uint256 rate = (apy * term * 1_000_000) / DAYS_IN_YEAR;
            return (amount * rate) / 100_000_000;
        }
        return 0;
    }

    /**
     * @dev calculates Reward Amplifier
     */
    function _calculateRewardAmplifier() private view returns (uint256) {
        uint256 amplifierDecrease = (block.timestamp - genesisTs) / SECONDS_IN_DAY;
        if (amplifierDecrease < REWARD_AMPLIFIER_START) {
            return Math.max(REWARD_AMPLIFIER_START - amplifierDecrease, REWARD_AMPLIFIER_END);
        } else {
            return REWARD_AMPLIFIER_END;
        }
    }

    /**
     * @dev calculates Early Adopter Amplifier Rate (in 1/000ths)
     *      actual EAA is (1_000 + EAAR) / 1_000
     */
    function _calculateEAARate() private view returns (uint256) {
        uint256 decrease = (EAA_PM_STEP * globalRank) / EAA_RANK_STEP;
        if (decrease > EAA_PM_START) return 0;
        return EAA_PM_START - decrease;
    }

    /**
     * @dev calculates APY (in %)
     */
    function _calculateAPY() private view returns (uint256) {
        uint256 decrease = (block.timestamp - genesisTs) / (SECONDS_IN_DAY * XEN_APY_DAYS_STEP);
        if (XEN_APY_START - XEN_APY_END < decrease) return XEN_APY_END;
        return XEN_APY_START - decrease;
    }

    /**
     * @dev creates User Stake
     */
    function _createStake(uint256 amount, uint256 term) private {
        userStakes[_msgSender()] = StakeInfo({
            term: term,
            maturityTs: block.timestamp + term * SECONDS_IN_DAY,
            amount: amount,
            apy: _calculateAPY()
        });
        activeStakes++;
        totalXenStaked += amount;
    }

    // PUBLIC CONVENIENCE GETTERS

    /**
     * @dev calculates gross Mint Reward
     */
    function getGrossReward(
        uint256 rankDelta,
        uint256 amplifier,
        uint256 term,
        uint256 eaa
    ) public pure returns (uint256) {
        int128 log128 = rankDelta.fromUInt().log_2();
        int128 reward128 = log128.mul(amplifier.fromUInt()).mul(term.fromUInt()).mul(eaa.fromUInt());
        return reward128.div(uint256(1_000).fromUInt()).toUInt();
    }

    /**
     * @dev returns User Mint object associated with User account address
     */
    function getUserMint() external view returns (MintInfo memory) {
        return userMints[_msgSender()];
    }

    /**
     * @dev returns XEN Stake object associated with User account address
     */
    function getUserStake() external view returns (StakeInfo memory) {
        return userStakes[_msgSender()];
    }

    /**
     * @dev returns current AMP
     */
    function getCurrentAMP() external view returns (uint256) {
        return _calculateRewardAmplifier();
    }

    /**
     * @dev returns current EAA Rate
     */
    function getCurrentEAAR() external view returns (uint256) {
        return _calculateEAARate();
    }

    /**
     * @dev returns current APY
     */
    function getCurrentAPY() external view returns (uint256) {
        return _calculateAPY();
    }

    /**
     * @dev returns current MaxTerm
     */
    function getCurrentMaxTerm() external view returns (uint256) {
        return _calculateMaxTerm();
    }

    // PUBLIC STATE-CHANGING METHODS

    /**
     * @dev accepts User cRank claim provided all checks pass (incl. no current claim exists)
     */
    function claimRank(uint256 term) external {
        require(block.timestamp >= START_TIMESTAMP, "CRank: Not started");
        uint256 termSec = term * SECONDS_IN_DAY;
        require(termSec > MIN_TERM, "CRank: Term less than min");
        require(termSec < _calculateMaxTerm() + 1, "CRank: Term more than current max term");
        require(userMints[_msgSender()].rank == 0, "CRank: Mint already in progress");

        // create and store new MintInfo
        MintInfo memory mintInfo = MintInfo({
            user: _msgSender(),
            term: term,
            maturityTs: block.timestamp + termSec,
            rank: globalRank,
            amplifier: _calculateRewardAmplifier(),
            eaaRate: _calculateEAARate()
        });
        userMints[_msgSender()] = mintInfo;
        activeMinters++;

        emit RankClaimed(_msgSender(), term, globalRank++);
    }

    /**
     * @dev ends minting upon maturity (and within permitted Withdrawal Time Window), gets minted XEN
     */
    function claimMintReward() external {
        MintInfo memory mintInfo = userMints[_msgSender()];
        require(mintInfo.rank > 0, "CRank: No mint exists");
        require(block.timestamp > mintInfo.maturityTs, "CRank: Mint maturity not reached");

        // calculate reward and mint tokens
        uint256 rewardAmount = _calculateMintReward(
            mintInfo.rank,
            mintInfo.term,
            mintInfo.maturityTs,
            mintInfo.amplifier,
            mintInfo.eaaRate
        ) * 1 ether;
        _mint(_msgSender(), rewardAmount);

        _cleanUpUserMint();
        emit MintClaimed(_msgSender(), rewardAmount);
    }

    /**
     * @dev  ends minting upon maturity (and within permitted Withdrawal time Window)
     *       mints XEN coins and splits them between User and designated other address
     */
    function claimMintRewardAndShare(address other, uint256 pct) external {
        MintInfo memory mintInfo = userMints[_msgSender()];
        require(other != address(0), "CRank: Cannot share with zero address");
        require(pct > 0, "CRank: Cannot share zero percent");
        require(pct < 101, "CRank: Cannot share 100+ percent");
        require(mintInfo.rank > 0, "CRank: No mint exists");
        require(block.timestamp > mintInfo.maturityTs, "CRank: Mint maturity not reached");

        // calculate reward
        uint256 rewardAmount = _calculateMintReward(
            mintInfo.rank,
            mintInfo.term,
            mintInfo.maturityTs,
            mintInfo.amplifier,
            mintInfo.eaaRate
        ) * 1 ether;
        uint256 sharedReward = (rewardAmount * pct) / 100;
        uint256 ownReward = rewardAmount - sharedReward;

        // mint reward tokens
        _mint(_msgSender(), ownReward);
        _mint(other, sharedReward);

        _cleanUpUserMint();
        emit MintClaimed(_msgSender(), rewardAmount);
    }

    /**
     * @dev  ends minting upon maturity (and within permitted Withdrawal time Window)
     *       mints XEN coins and stakes 'pct' of it for 'term'
     */
    function claimMintRewardAndStake(uint256 pct, uint256 term) external {
        MintInfo memory mintInfo = userMints[_msgSender()];
        // require(pct > 0, "CRank: Cannot share zero percent");
        require(pct < 101, "CRank: Cannot share >100 percent");
        require(mintInfo.rank > 0, "CRank: No mint exists");
        require(block.timestamp > mintInfo.maturityTs, "CRank: Mint maturity not reached");

        // calculate reward
        uint256 rewardAmount = _calculateMintReward(
            mintInfo.rank,
            mintInfo.term,
            mintInfo.maturityTs,
            mintInfo.amplifier,
            mintInfo.eaaRate
        ) * 1 ether;
        uint256 stakedReward = (rewardAmount * pct) / 100;
        uint256 ownReward = rewardAmount - stakedReward;

        // mint reward tokens part
        _mint(_msgSender(), ownReward);
        _cleanUpUserMint();
        emit MintClaimed(_msgSender(), rewardAmount);

        // nothing to burn since we haven't minted this part yet
        // stake extra tokens part
        require(stakedReward > XEN_MIN_STAKE, "XEN: Below min stake");
        require(term * SECONDS_IN_DAY > MIN_TERM, "XEN: Below min stake term");
        require(term * SECONDS_IN_DAY < MAX_TERM_END + 1, "XEN: Above max stake term");
        require(userStakes[_msgSender()].amount == 0, "XEN: stake exists");

        _createStake(stakedReward, term);
        emit Staked(_msgSender(), stakedReward, term);
    }

    /**
     * @dev initiates XEN Stake in amount for a term (days)
     */
    function stake(uint256 amount, uint256 term) external {
        require(balanceOf(_msgSender()) >= amount, "XEN: not enough balance");
        require(amount > XEN_MIN_STAKE, "XEN: Below min stake");
        require(term * SECONDS_IN_DAY > MIN_TERM, "XEN: Below min stake term");
        require(term * SECONDS_IN_DAY < MAX_TERM_END + 1, "XEN: Above max stake term");
        require(userStakes[_msgSender()].amount == 0, "XEN: stake exists");

        // burn staked XEN
        _burn(_msgSender(), amount);
        // create XEN Stake
        _createStake(amount, term);
        emit Staked(_msgSender(), amount, term);
    }

    /**
     * @dev ends XEN Stake and gets reward if the Stake is mature
     */
    function withdraw() external {
        StakeInfo memory userStake = userStakes[_msgSender()];
        require(userStake.amount > 0, "XEN: no stake exists");

        uint256 xenReward = _calculateStakeReward(
            userStake.amount,
            userStake.term,
            userStake.maturityTs,
            userStake.apy
        );
        activeStakes--;
        totalXenStaked -= userStake.amount;

        // mint staked XEN (+ reward)
        _mint(_msgSender(), userStake.amount + xenReward);
        emit Withdrawn(_msgSender(), userStake.amount, xenReward);
        delete userStakes[_msgSender()];
    }

    /**
     * @dev burns XEN tokens and creates Proof-Of-Burn record to be used by connected DeFi services
     */
    function burn(address user, uint256 amount) public {
        require(amount > XEN_MIN_BURN, "Burn: Below min limit");
        require(
            IERC165(_msgSender()).supportsInterface(type(IBurnRedeemable).interfaceId),
            "Burn: not a supported contract"
        );

        _spendAllowance(user, _msgSender(), amount);
        _burn(user, amount);
        userBurns[user] += amount;
        IBurnRedeemable(_msgSender()).onTokenBurned(user, amount);
    }
}

File 2 of 13 : IBurnRedeemable.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.10;

interface IBurnRedeemable {
    event Redeemed(
        address indexed user,
        address indexed xenContract,
        address indexed tokenContract,
        uint256 xenAmount,
        uint256 tokenAmount
    );

    function onTokenBurned(address user, uint256 amount) external;
}

File 3 of 13 : IBurnableToken.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.10;

interface IBurnableToken {
    function burn(address user, uint256 amount) external;
}

File 4 of 13 : IRankedMintingToken.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.10;

interface IRankedMintingToken {
    event RankClaimed(address indexed user, uint256 term, uint256 rank);

    event MintClaimed(address indexed user, uint256 rewardAmount);

    function claimRank(uint256 term) external;

    function claimMintReward() external;
}

File 5 of 13 : IStakingToken.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.10;

interface IStakingToken {
    event Staked(address indexed user, uint256 amount, uint256 term);

    event Withdrawn(address indexed user, uint256 amount, uint256 reward);

    function stake(uint256 amount, uint256 term) external;

    function withdraw() external;
}

File 6 of 13 : ABDKMath64x64.sol
// SPDX-License-Identifier: BSD-4-Clause
/*
 * ABDK Math 64.64 Smart Contract Library.  Copyright © 2019 by ABDK Consulting.
 * Author: Mikhail Vladimirov <[email protected]>
 */
pragma solidity ^0.8.0;

/**
 * Smart contract library of mathematical functions operating with signed
 * 64.64-bit fixed point numbers.  Signed 64.64-bit fixed point number is
 * basically a simple fraction whose numerator is signed 128-bit integer and
 * denominator is 2^64.  As long as denominator is always the same, there is no
 * need to store it, thus in Solidity signed 64.64-bit fixed point numbers are
 * represented by int128 type holding only the numerator.
 */
library ABDKMath64x64 {
  /*
   * Minimum value signed 64.64-bit fixed point number may have. 
   */
  int128 private constant MIN_64x64 = -0x80000000000000000000000000000000;

  /*
   * Maximum value signed 64.64-bit fixed point number may have. 
   */
  int128 private constant MAX_64x64 = 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;

  /**
   * Convert signed 256-bit integer number into signed 64.64-bit fixed point
   * number.  Revert on overflow.
   *
   * @param x signed 256-bit integer number
   * @return signed 64.64-bit fixed point number
   */
  function fromInt (int256 x) internal pure returns (int128) {
    unchecked {
      require (x >= -0x8000000000000000 && x <= 0x7FFFFFFFFFFFFFFF);
      return int128 (x << 64);
    }
  }

  /**
   * Convert signed 64.64 fixed point number into signed 64-bit integer number
   * rounding down.
   *
   * @param x signed 64.64-bit fixed point number
   * @return signed 64-bit integer number
   */
  function toInt (int128 x) internal pure returns (int64) {
    unchecked {
      return int64 (x >> 64);
    }
  }

  /**
   * Convert unsigned 256-bit integer number into signed 64.64-bit fixed point
   * number.  Revert on overflow.
   *
   * @param x unsigned 256-bit integer number
   * @return signed 64.64-bit fixed point number
   */
  function fromUInt (uint256 x) internal pure returns (int128) {
    unchecked {
      require (x <= 0x7FFFFFFFFFFFFFFF);
      return int128 (int256 (x << 64));
    }
  }

  /**
   * Convert signed 64.64 fixed point number into unsigned 64-bit integer
   * number rounding down.  Revert on underflow.
   *
   * @param x signed 64.64-bit fixed point number
   * @return unsigned 64-bit integer number
   */
  function toUInt (int128 x) internal pure returns (uint64) {
    unchecked {
      require (x >= 0);
      return uint64 (uint128 (x >> 64));
    }
  }

  /**
   * Convert signed 128.128 fixed point number into signed 64.64-bit fixed point
   * number rounding down.  Revert on overflow.
   *
   * @param x signed 128.128-bin fixed point number
   * @return signed 64.64-bit fixed point number
   */
  function from128x128 (int256 x) internal pure returns (int128) {
    unchecked {
      int256 result = x >> 64;
      require (result >= MIN_64x64 && result <= MAX_64x64);
      return int128 (result);
    }
  }

  /**
   * Convert signed 64.64 fixed point number into signed 128.128 fixed point
   * number.
   *
   * @param x signed 64.64-bit fixed point number
   * @return signed 128.128 fixed point number
   */
  function to128x128 (int128 x) internal pure returns (int256) {
    unchecked {
      return int256 (x) << 64;
    }
  }

  /**
   * Calculate x + y.  Revert on overflow.
   *
   * @param x signed 64.64-bit fixed point number
   * @param y signed 64.64-bit fixed point number
   * @return signed 64.64-bit fixed point number
   */
  function add (int128 x, int128 y) internal pure returns (int128) {
    unchecked {
      int256 result = int256(x) + y;
      require (result >= MIN_64x64 && result <= MAX_64x64);
      return int128 (result);
    }
  }

  /**
   * Calculate x - y.  Revert on overflow.
   *
   * @param x signed 64.64-bit fixed point number
   * @param y signed 64.64-bit fixed point number
   * @return signed 64.64-bit fixed point number
   */
  function sub (int128 x, int128 y) internal pure returns (int128) {
    unchecked {
      int256 result = int256(x) - y;
      require (result >= MIN_64x64 && result <= MAX_64x64);
      return int128 (result);
    }
  }

  /**
   * Calculate x * y rounding down.  Revert on overflow.
   *
   * @param x signed 64.64-bit fixed point number
   * @param y signed 64.64-bit fixed point number
   * @return signed 64.64-bit fixed point number
   */
  function mul (int128 x, int128 y) internal pure returns (int128) {
    unchecked {
      int256 result = int256(x) * y >> 64;
      require (result >= MIN_64x64 && result <= MAX_64x64);
      return int128 (result);
    }
  }

  /**
   * Calculate x * y rounding towards zero, where x is signed 64.64 fixed point
   * number and y is signed 256-bit integer number.  Revert on overflow.
   *
   * @param x signed 64.64 fixed point number
   * @param y signed 256-bit integer number
   * @return signed 256-bit integer number
   */
  function muli (int128 x, int256 y) internal pure returns (int256) {
    unchecked {
      if (x == MIN_64x64) {
        require (y >= -0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF &&
          y <= 0x1000000000000000000000000000000000000000000000000);
        return -y << 63;
      } else {
        bool negativeResult = false;
        if (x < 0) {
          x = -x;
          negativeResult = true;
        }
        if (y < 0) {
          y = -y; // We rely on overflow behavior here
          negativeResult = !negativeResult;
        }
        uint256 absoluteResult = mulu (x, uint256 (y));
        if (negativeResult) {
          require (absoluteResult <=
            0x8000000000000000000000000000000000000000000000000000000000000000);
          return -int256 (absoluteResult); // We rely on overflow behavior here
        } else {
          require (absoluteResult <=
            0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
          return int256 (absoluteResult);
        }
      }
    }
  }

  /**
   * Calculate x * y rounding down, where x is signed 64.64 fixed point number
   * and y is unsigned 256-bit integer number.  Revert on overflow.
   *
   * @param x signed 64.64 fixed point number
   * @param y unsigned 256-bit integer number
   * @return unsigned 256-bit integer number
   */
  function mulu (int128 x, uint256 y) internal pure returns (uint256) {
    unchecked {
      if (y == 0) return 0;

      require (x >= 0);

      uint256 lo = (uint256 (int256 (x)) * (y & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)) >> 64;
      uint256 hi = uint256 (int256 (x)) * (y >> 128);

      require (hi <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
      hi <<= 64;

      require (hi <=
        0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF - lo);
      return hi + lo;
    }
  }

  /**
   * Calculate x / y rounding towards zero.  Revert on overflow or when y is
   * zero.
   *
   * @param x signed 64.64-bit fixed point number
   * @param y signed 64.64-bit fixed point number
   * @return signed 64.64-bit fixed point number
   */
  function div (int128 x, int128 y) internal pure returns (int128) {
    unchecked {
      require (y != 0);
      int256 result = (int256 (x) << 64) / y;
      require (result >= MIN_64x64 && result <= MAX_64x64);
      return int128 (result);
    }
  }

  /**
   * Calculate x / y rounding towards zero, where x and y are signed 256-bit
   * integer numbers.  Revert on overflow or when y is zero.
   *
   * @param x signed 256-bit integer number
   * @param y signed 256-bit integer number
   * @return signed 64.64-bit fixed point number
   */
  function divi (int256 x, int256 y) internal pure returns (int128) {
    unchecked {
      require (y != 0);

      bool negativeResult = false;
      if (x < 0) {
        x = -x; // We rely on overflow behavior here
        negativeResult = true;
      }
      if (y < 0) {
        y = -y; // We rely on overflow behavior here
        negativeResult = !negativeResult;
      }
      uint128 absoluteResult = divuu (uint256 (x), uint256 (y));
      if (negativeResult) {
        require (absoluteResult <= 0x80000000000000000000000000000000);
        return -int128 (absoluteResult); // We rely on overflow behavior here
      } else {
        require (absoluteResult <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
        return int128 (absoluteResult); // We rely on overflow behavior here
      }
    }
  }

  /**
   * Calculate x / y rounding towards zero, where x and y are unsigned 256-bit
   * integer numbers.  Revert on overflow or when y is zero.
   *
   * @param x unsigned 256-bit integer number
   * @param y unsigned 256-bit integer number
   * @return signed 64.64-bit fixed point number
   */
  function divu (uint256 x, uint256 y) internal pure returns (int128) {
    unchecked {
      require (y != 0);
      uint128 result = divuu (x, y);
      require (result <= uint128 (MAX_64x64));
      return int128 (result);
    }
  }

  /**
   * Calculate -x.  Revert on overflow.
   *
   * @param x signed 64.64-bit fixed point number
   * @return signed 64.64-bit fixed point number
   */
  function neg (int128 x) internal pure returns (int128) {
    unchecked {
      require (x != MIN_64x64);
      return -x;
    }
  }

  /**
   * Calculate |x|.  Revert on overflow.
   *
   * @param x signed 64.64-bit fixed point number
   * @return signed 64.64-bit fixed point number
   */
  function abs (int128 x) internal pure returns (int128) {
    unchecked {
      require (x != MIN_64x64);
      return x < 0 ? -x : x;
    }
  }

  /**
   * Calculate 1 / x rounding towards zero.  Revert on overflow or when x is
   * zero.
   *
   * @param x signed 64.64-bit fixed point number
   * @return signed 64.64-bit fixed point number
   */
  function inv (int128 x) internal pure returns (int128) {
    unchecked {
      require (x != 0);
      int256 result = int256 (0x100000000000000000000000000000000) / x;
      require (result >= MIN_64x64 && result <= MAX_64x64);
      return int128 (result);
    }
  }

  /**
   * Calculate arithmetics average of x and y, i.e. (x + y) / 2 rounding down.
   *
   * @param x signed 64.64-bit fixed point number
   * @param y signed 64.64-bit fixed point number
   * @return signed 64.64-bit fixed point number
   */
  function avg (int128 x, int128 y) internal pure returns (int128) {
    unchecked {
      return int128 ((int256 (x) + int256 (y)) >> 1);
    }
  }

  /**
   * Calculate geometric average of x and y, i.e. sqrt (x * y) rounding down.
   * Revert on overflow or in case x * y is negative.
   *
   * @param x signed 64.64-bit fixed point number
   * @param y signed 64.64-bit fixed point number
   * @return signed 64.64-bit fixed point number
   */
  function gavg (int128 x, int128 y) internal pure returns (int128) {
    unchecked {
      int256 m = int256 (x) * int256 (y);
      require (m >= 0);
      require (m <
          0x4000000000000000000000000000000000000000000000000000000000000000);
      return int128 (sqrtu (uint256 (m)));
    }
  }

  /**
   * Calculate x^y assuming 0^0 is 1, where x is signed 64.64 fixed point number
   * and y is unsigned 256-bit integer number.  Revert on overflow.
   *
   * @param x signed 64.64-bit fixed point number
   * @param y uint256 value
   * @return signed 64.64-bit fixed point number
   */
  function pow (int128 x, uint256 y) internal pure returns (int128) {
    unchecked {
      bool negative = x < 0 && y & 1 == 1;

      uint256 absX = uint128 (x < 0 ? -x : x);
      uint256 absResult;
      absResult = 0x100000000000000000000000000000000;

      if (absX <= 0x10000000000000000) {
        absX <<= 63;
        while (y != 0) {
          if (y & 0x1 != 0) {
            absResult = absResult * absX >> 127;
          }
          absX = absX * absX >> 127;

          if (y & 0x2 != 0) {
            absResult = absResult * absX >> 127;
          }
          absX = absX * absX >> 127;

          if (y & 0x4 != 0) {
            absResult = absResult * absX >> 127;
          }
          absX = absX * absX >> 127;

          if (y & 0x8 != 0) {
            absResult = absResult * absX >> 127;
          }
          absX = absX * absX >> 127;

          y >>= 4;
        }

        absResult >>= 64;
      } else {
        uint256 absXShift = 63;
        if (absX < 0x1000000000000000000000000) { absX <<= 32; absXShift -= 32; }
        if (absX < 0x10000000000000000000000000000) { absX <<= 16; absXShift -= 16; }
        if (absX < 0x1000000000000000000000000000000) { absX <<= 8; absXShift -= 8; }
        if (absX < 0x10000000000000000000000000000000) { absX <<= 4; absXShift -= 4; }
        if (absX < 0x40000000000000000000000000000000) { absX <<= 2; absXShift -= 2; }
        if (absX < 0x80000000000000000000000000000000) { absX <<= 1; absXShift -= 1; }

        uint256 resultShift = 0;
        while (y != 0) {
          require (absXShift < 64);

          if (y & 0x1 != 0) {
            absResult = absResult * absX >> 127;
            resultShift += absXShift;
            if (absResult > 0x100000000000000000000000000000000) {
              absResult >>= 1;
              resultShift += 1;
            }
          }
          absX = absX * absX >> 127;
          absXShift <<= 1;
          if (absX >= 0x100000000000000000000000000000000) {
              absX >>= 1;
              absXShift += 1;
          }

          y >>= 1;
        }

        require (resultShift < 64);
        absResult >>= 64 - resultShift;
      }
      int256 result = negative ? -int256 (absResult) : int256 (absResult);
      require (result >= MIN_64x64 && result <= MAX_64x64);
      return int128 (result);
    }
  }

  /**
   * Calculate sqrt (x) rounding down.  Revert if x < 0.
   *
   * @param x signed 64.64-bit fixed point number
   * @return signed 64.64-bit fixed point number
   */
  function sqrt (int128 x) internal pure returns (int128) {
    unchecked {
      require (x >= 0);
      return int128 (sqrtu (uint256 (int256 (x)) << 64));
    }
  }

  /**
   * Calculate binary logarithm of x.  Revert if x <= 0.
   *
   * @param x signed 64.64-bit fixed point number
   * @return signed 64.64-bit fixed point number
   */
  function log_2 (int128 x) internal pure returns (int128) {
    unchecked {
      require (x > 0);

      int256 msb = 0;
      int256 xc = x;
      if (xc >= 0x10000000000000000) { xc >>= 64; msb += 64; }
      if (xc >= 0x100000000) { xc >>= 32; msb += 32; }
      if (xc >= 0x10000) { xc >>= 16; msb += 16; }
      if (xc >= 0x100) { xc >>= 8; msb += 8; }
      if (xc >= 0x10) { xc >>= 4; msb += 4; }
      if (xc >= 0x4) { xc >>= 2; msb += 2; }
      if (xc >= 0x2) msb += 1;  // No need to shift xc anymore

      int256 result = msb - 64 << 64;
      uint256 ux = uint256 (int256 (x)) << uint256 (127 - msb);
      for (int256 bit = 0x8000000000000000; bit > 0; bit >>= 1) {
        ux *= ux;
        uint256 b = ux >> 255;
        ux >>= 127 + b;
        result += bit * int256 (b);
      }

      return int128 (result);
    }
  }

  /**
   * Calculate natural logarithm of x.  Revert if x <= 0.
   *
   * @param x signed 64.64-bit fixed point number
   * @return signed 64.64-bit fixed point number
   */
  function ln (int128 x) internal pure returns (int128) {
    unchecked {
      require (x > 0);

      return int128 (int256 (
          uint256 (int256 (log_2 (x))) * 0xB17217F7D1CF79ABC9E3B39803F2F6AF >> 128));
    }
  }

  /**
   * Calculate binary exponent of x.  Revert on overflow.
   *
   * @param x signed 64.64-bit fixed point number
   * @return signed 64.64-bit fixed point number
   */
  function exp_2 (int128 x) internal pure returns (int128) {
    unchecked {
      require (x < 0x400000000000000000); // Overflow

      if (x < -0x400000000000000000) return 0; // Underflow

      uint256 result = 0x80000000000000000000000000000000;

      if (x & 0x8000000000000000 > 0)
        result = result * 0x16A09E667F3BCC908B2FB1366EA957D3E >> 128;
      if (x & 0x4000000000000000 > 0)
        result = result * 0x1306FE0A31B7152DE8D5A46305C85EDEC >> 128;
      if (x & 0x2000000000000000 > 0)
        result = result * 0x1172B83C7D517ADCDF7C8C50EB14A791F >> 128;
      if (x & 0x1000000000000000 > 0)
        result = result * 0x10B5586CF9890F6298B92B71842A98363 >> 128;
      if (x & 0x800000000000000 > 0)
        result = result * 0x1059B0D31585743AE7C548EB68CA417FD >> 128;
      if (x & 0x400000000000000 > 0)
        result = result * 0x102C9A3E778060EE6F7CACA4F7A29BDE8 >> 128;
      if (x & 0x200000000000000 > 0)
        result = result * 0x10163DA9FB33356D84A66AE336DCDFA3F >> 128;
      if (x & 0x100000000000000 > 0)
        result = result * 0x100B1AFA5ABCBED6129AB13EC11DC9543 >> 128;
      if (x & 0x80000000000000 > 0)
        result = result * 0x10058C86DA1C09EA1FF19D294CF2F679B >> 128;
      if (x & 0x40000000000000 > 0)
        result = result * 0x1002C605E2E8CEC506D21BFC89A23A00F >> 128;
      if (x & 0x20000000000000 > 0)
        result = result * 0x100162F3904051FA128BCA9C55C31E5DF >> 128;
      if (x & 0x10000000000000 > 0)
        result = result * 0x1000B175EFFDC76BA38E31671CA939725 >> 128;
      if (x & 0x8000000000000 > 0)
        result = result * 0x100058BA01FB9F96D6CACD4B180917C3D >> 128;
      if (x & 0x4000000000000 > 0)
        result = result * 0x10002C5CC37DA9491D0985C348C68E7B3 >> 128;
      if (x & 0x2000000000000 > 0)
        result = result * 0x1000162E525EE054754457D5995292026 >> 128;
      if (x & 0x1000000000000 > 0)
        result = result * 0x10000B17255775C040618BF4A4ADE83FC >> 128;
      if (x & 0x800000000000 > 0)
        result = result * 0x1000058B91B5BC9AE2EED81E9B7D4CFAB >> 128;
      if (x & 0x400000000000 > 0)
        result = result * 0x100002C5C89D5EC6CA4D7C8ACC017B7C9 >> 128;
      if (x & 0x200000000000 > 0)
        result = result * 0x10000162E43F4F831060E02D839A9D16D >> 128;
      if (x & 0x100000000000 > 0)
        result = result * 0x100000B1721BCFC99D9F890EA06911763 >> 128;
      if (x & 0x80000000000 > 0)
        result = result * 0x10000058B90CF1E6D97F9CA14DBCC1628 >> 128;
      if (x & 0x40000000000 > 0)
        result = result * 0x1000002C5C863B73F016468F6BAC5CA2B >> 128;
      if (x & 0x20000000000 > 0)
        result = result * 0x100000162E430E5A18F6119E3C02282A5 >> 128;
      if (x & 0x10000000000 > 0)
        result = result * 0x1000000B1721835514B86E6D96EFD1BFE >> 128;
      if (x & 0x8000000000 > 0)
        result = result * 0x100000058B90C0B48C6BE5DF846C5B2EF >> 128;
      if (x & 0x4000000000 > 0)
        result = result * 0x10000002C5C8601CC6B9E94213C72737A >> 128;
      if (x & 0x2000000000 > 0)
        result = result * 0x1000000162E42FFF037DF38AA2B219F06 >> 128;
      if (x & 0x1000000000 > 0)
        result = result * 0x10000000B17217FBA9C739AA5819F44F9 >> 128;
      if (x & 0x800000000 > 0)
        result = result * 0x1000000058B90BFCDEE5ACD3C1CEDC823 >> 128;
      if (x & 0x400000000 > 0)
        result = result * 0x100000002C5C85FE31F35A6A30DA1BE50 >> 128;
      if (x & 0x200000000 > 0)
        result = result * 0x10000000162E42FF0999CE3541B9FFFCF >> 128;
      if (x & 0x100000000 > 0)
        result = result * 0x100000000B17217F80F4EF5AADDA45554 >> 128;
      if (x & 0x80000000 > 0)
        result = result * 0x10000000058B90BFBF8479BD5A81B51AD >> 128;
      if (x & 0x40000000 > 0)
        result = result * 0x1000000002C5C85FDF84BD62AE30A74CC >> 128;
      if (x & 0x20000000 > 0)
        result = result * 0x100000000162E42FEFB2FED257559BDAA >> 128;
      if (x & 0x10000000 > 0)
        result = result * 0x1000000000B17217F7D5A7716BBA4A9AE >> 128;
      if (x & 0x8000000 > 0)
        result = result * 0x100000000058B90BFBE9DDBAC5E109CCE >> 128;
      if (x & 0x4000000 > 0)
        result = result * 0x10000000002C5C85FDF4B15DE6F17EB0D >> 128;
      if (x & 0x2000000 > 0)
        result = result * 0x1000000000162E42FEFA494F1478FDE05 >> 128;
      if (x & 0x1000000 > 0)
        result = result * 0x10000000000B17217F7D20CF927C8E94C >> 128;
      if (x & 0x800000 > 0)
        result = result * 0x1000000000058B90BFBE8F71CB4E4B33D >> 128;
      if (x & 0x400000 > 0)
        result = result * 0x100000000002C5C85FDF477B662B26945 >> 128;
      if (x & 0x200000 > 0)
        result = result * 0x10000000000162E42FEFA3AE53369388C >> 128;
      if (x & 0x100000 > 0)
        result = result * 0x100000000000B17217F7D1D351A389D40 >> 128;
      if (x & 0x80000 > 0)
        result = result * 0x10000000000058B90BFBE8E8B2D3D4EDE >> 128;
      if (x & 0x40000 > 0)
        result = result * 0x1000000000002C5C85FDF4741BEA6E77E >> 128;
      if (x & 0x20000 > 0)
        result = result * 0x100000000000162E42FEFA39FE95583C2 >> 128;
      if (x & 0x10000 > 0)
        result = result * 0x1000000000000B17217F7D1CFB72B45E1 >> 128;
      if (x & 0x8000 > 0)
        result = result * 0x100000000000058B90BFBE8E7CC35C3F0 >> 128;
      if (x & 0x4000 > 0)
        result = result * 0x10000000000002C5C85FDF473E242EA38 >> 128;
      if (x & 0x2000 > 0)
        result = result * 0x1000000000000162E42FEFA39F02B772C >> 128;
      if (x & 0x1000 > 0)
        result = result * 0x10000000000000B17217F7D1CF7D83C1A >> 128;
      if (x & 0x800 > 0)
        result = result * 0x1000000000000058B90BFBE8E7BDCBE2E >> 128;
      if (x & 0x400 > 0)
        result = result * 0x100000000000002C5C85FDF473DEA871F >> 128;
      if (x & 0x200 > 0)
        result = result * 0x10000000000000162E42FEFA39EF44D91 >> 128;
      if (x & 0x100 > 0)
        result = result * 0x100000000000000B17217F7D1CF79E949 >> 128;
      if (x & 0x80 > 0)
        result = result * 0x10000000000000058B90BFBE8E7BCE544 >> 128;
      if (x & 0x40 > 0)
        result = result * 0x1000000000000002C5C85FDF473DE6ECA >> 128;
      if (x & 0x20 > 0)
        result = result * 0x100000000000000162E42FEFA39EF366F >> 128;
      if (x & 0x10 > 0)
        result = result * 0x1000000000000000B17217F7D1CF79AFA >> 128;
      if (x & 0x8 > 0)
        result = result * 0x100000000000000058B90BFBE8E7BCD6D >> 128;
      if (x & 0x4 > 0)
        result = result * 0x10000000000000002C5C85FDF473DE6B2 >> 128;
      if (x & 0x2 > 0)
        result = result * 0x1000000000000000162E42FEFA39EF358 >> 128;
      if (x & 0x1 > 0)
        result = result * 0x10000000000000000B17217F7D1CF79AB >> 128;

      result >>= uint256 (int256 (63 - (x >> 64)));
      require (result <= uint256 (int256 (MAX_64x64)));

      return int128 (int256 (result));
    }
  }

  /**
   * Calculate natural exponent of x.  Revert on overflow.
   *
   * @param x signed 64.64-bit fixed point number
   * @return signed 64.64-bit fixed point number
   */
  function exp (int128 x) internal pure returns (int128) {
    unchecked {
      require (x < 0x400000000000000000); // Overflow

      if (x < -0x400000000000000000) return 0; // Underflow

      return exp_2 (
          int128 (int256 (x) * 0x171547652B82FE1777D0FFDA0D23A7D12 >> 128));
    }
  }

  /**
   * Calculate x / y rounding towards zero, where x and y are unsigned 256-bit
   * integer numbers.  Revert on overflow or when y is zero.
   *
   * @param x unsigned 256-bit integer number
   * @param y unsigned 256-bit integer number
   * @return unsigned 64.64-bit fixed point number
   */
  function divuu (uint256 x, uint256 y) private pure returns (uint128) {
    unchecked {
      require (y != 0);

      uint256 result;

      if (x <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)
        result = (x << 64) / y;
      else {
        uint256 msb = 192;
        uint256 xc = x >> 192;
        if (xc >= 0x100000000) { xc >>= 32; msb += 32; }
        if (xc >= 0x10000) { xc >>= 16; msb += 16; }
        if (xc >= 0x100) { xc >>= 8; msb += 8; }
        if (xc >= 0x10) { xc >>= 4; msb += 4; }
        if (xc >= 0x4) { xc >>= 2; msb += 2; }
        if (xc >= 0x2) msb += 1;  // No need to shift xc anymore

        result = (x << 255 - msb) / ((y - 1 >> msb - 191) + 1);
        require (result <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);

        uint256 hi = result * (y >> 128);
        uint256 lo = result * (y & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);

        uint256 xh = x >> 192;
        uint256 xl = x << 64;

        if (xl < lo) xh -= 1;
        xl -= lo; // We rely on overflow behavior here
        lo = hi << 128;
        if (xl < lo) xh -= 1;
        xl -= lo; // We rely on overflow behavior here

        assert (xh == hi >> 128);

        result += xl / y;
      }

      require (result <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
      return uint128 (result);
    }
  }

  /**
   * Calculate sqrt (x) rounding down, where x is unsigned 256-bit integer
   * number.
   *
   * @param x unsigned 256-bit integer number
   * @return unsigned 128-bit integer number
   */
  function sqrtu (uint256 x) private pure returns (uint128) {
    unchecked {
      if (x == 0) return 0;
      else {
        uint256 xx = x;
        uint256 r = 1;
        if (xx >= 0x100000000000000000000000000000000) { xx >>= 128; r <<= 64; }
        if (xx >= 0x10000000000000000) { xx >>= 64; r <<= 32; }
        if (xx >= 0x100000000) { xx >>= 32; r <<= 16; }
        if (xx >= 0x10000) { xx >>= 16; r <<= 8; }
        if (xx >= 0x100) { xx >>= 8; r <<= 4; }
        if (xx >= 0x10) { xx >>= 4; r <<= 2; }
        if (xx >= 0x4) { r <<= 1; }
        r = (r + x / r) >> 1;
        r = (r + x / r) >> 1;
        r = (r + x / r) >> 1;
        r = (r + x / r) >> 1;
        r = (r + x / r) >> 1;
        r = (r + x / r) >> 1;
        r = (r + x / r) >> 1; // Seven iterations should be enough
        uint256 r1 = x / r;
        return uint128 (r < r1 ? r : r1);
      }
    }
  }
}

File 7 of 13 : IERC165.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (interfaces/IERC165.sol)

pragma solidity ^0.8.0;

import "../utils/introspection/IERC165.sol";

File 8 of 13 : ERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.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.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How
 * to implement supply mechanisms].
 *
 * 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}.
     *
     * The default value of {decimals} is 18. To select a different value for
     * {decimals} you should overload it.
     *
     * 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 value {ERC20} uses, unless this function is
     * 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;
        }
        _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;
        _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;
        }
        _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 {}
}

File 9 of 13 : Math.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.10;

import "abdk-libraries-solidity/ABDKMath64x64.sol";

library Math {
    function min(uint256 a, uint256 b) external pure returns (uint256) {
        if (a > b) return b;
        return a;
    }

    function max(uint256 a, uint256 b) external pure returns (uint256) {
        if (a > b) return a;
        return b;
    }

    function logX64(uint256 x) external pure returns (int128) {
        return ABDKMath64x64.log_2(ABDKMath64x64.fromUInt(x));
    }
}

File 10 of 13 : Context.sol
// 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;
    }
}

File 11 of 13 : IERC20Metadata.sol
// 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);
}

File 12 of 13 : IERC20.sol
// SPDX-License-Identifier: MIT
// 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 13 of 13 : IERC165.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC165 standard, as defined in the
 * https://eips.ethereum.org/EIPS/eip-165[EIP].
 *
 * Implementers can declare support of contract interfaces, which can then be
 * queried by others ({ERC165Checker}).
 *
 * For an implementation, see {ERC165}.
 */
interface IERC165 {
    /**
     * @dev Returns true if this contract implements the interface defined by
     * `interfaceId`. See the corresponding
     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
     * to learn more about how these ids are created.
     *
     * This function call must use less than 30 000 gas.
     */
    function supportsInterface(bytes4 interfaceId) external view returns (bool);
}

Settings
{
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "abi"
      ]
    }
  },
  "libraries": {
    "contracts/Math.sol": {
      "Math": "0xbdf6b32fe4fb7c9bed3bb04ac9b7ac6bb404a1d6"
    }
  }
}

Contract Security Audit

Contract ABI

[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"rewardAmount","type":"uint256"}],"name":"MintClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"term","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"rank","type":"uint256"}],"name":"RankClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"term","type":"uint256"}],"name":"Staked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"reward","type":"uint256"}],"name":"Withdrawn","type":"event"},{"inputs":[],"name":"AUTHORS","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DAYS_IN_YEAR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"EAA_PM_START","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"EAA_PM_STEP","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"EAA_RANK_STEP","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"GENESIS_RANK","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_PENALTY_PCT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_TERM_END","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_TERM_START","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MIN_TERM","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"REWARD_AMPLIFIER_END","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"REWARD_AMPLIFIER_START","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SECONDS_IN_DAY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"START_TIMESTAMP","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TERM_AMPLIFIER","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TERM_AMPLIFIER_THRESHOLD","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"WITHDRAWAL_WINDOW_DAYS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"XEN_APY_DAYS_STEP","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"XEN_APY_END","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"XEN_APY_START","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"XEN_MIN_BURN","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"XEN_MIN_STAKE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"activeMinters","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"activeStakes","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"claimMintReward","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"other","type":"address"},{"internalType":"uint256","name":"pct","type":"uint256"}],"name":"claimMintRewardAndShare","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"pct","type":"uint256"},{"internalType":"uint256","name":"term","type":"uint256"}],"name":"claimMintRewardAndStake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"term","type":"uint256"}],"name":"claimRank","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"genesisTs","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCurrentAMP","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCurrentAPY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCurrentEAAR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCurrentMaxTerm","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"rankDelta","type":"uint256"},{"internalType":"uint256","name":"amplifier","type":"uint256"},{"internalType":"uint256","name":"term","type":"uint256"},{"internalType":"uint256","name":"eaa","type":"uint256"}],"name":"getGrossReward","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getUserMint","outputs":[{"components":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"term","type":"uint256"},{"internalType":"uint256","name":"maturityTs","type":"uint256"},{"internalType":"uint256","name":"rank","type":"uint256"},{"internalType":"uint256","name":"amplifier","type":"uint256"},{"internalType":"uint256","name":"eaaRate","type":"uint256"}],"internalType":"struct XENCrypto.MintInfo","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getUserStake","outputs":[{"components":[{"internalType":"uint256","name":"term","type":"uint256"},{"internalType":"uint256","name":"maturityTs","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"apy","type":"uint256"}],"internalType":"struct XENCrypto.StakeInfo","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"globalRank","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"term","type":"uint256"}],"name":"stake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalXenStaked","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"userBurns","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"userMints","outputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"term","type":"uint256"},{"internalType":"uint256","name":"maturityTs","type":"uint256"},{"internalType":"uint256","name":"rank","type":"uint256"},{"internalType":"uint256","name":"amplifier","type":"uint256"},{"internalType":"uint256","name":"eaaRate","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"userStakes","outputs":[{"internalType":"uint256","name":"term","type":"uint256"},{"internalType":"uint256","name":"maturityTs","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"apy","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]

60a060405260016005553480156200001657600080fd5b50604080518082018252600f81526e0b0cadc40dccce840ccdee440c4def608b1b6020808301918252835180850190945260058452642127ac22a760d91b9084015281519192916200006b9160039162000092565b5080516200008190600490602084019062000092565b505063634edb906080525062000175565b828054620000a09062000138565b90600052602060002090601f016020900481019282620000c457600085556200010f565b82601f10620000df57805160ff19168380011785556200010f565b828001600101855582156200010f579182015b828111156200010f578251825591602001919060010190620000f2565b506200011d92915062000121565b5090565b5b808211156200011d576000815560010162000122565b600181811c908216806200014d57607f821691505b602082108114156200016f57634e487b7160e01b600052602260045260246000fd5b50919050565b608051612a786200019f600039600081816107210152818161232b015261238c0152612a786000f3fe608060405234801561001057600080fd5b506004361061035d5760003560e01c80637b0472f0116101d3578063b4800cdc11610104578063df282331116100a2578063ed2f23691161007c578063ed2f23691461074c578063f060482914610755578063f340faed1461075d578063fed742691461076757600080fd5b8063df28233114610698578063e3af6d0a1461071c578063e81917b41461074357600080fd5b8063c0c65259116100de578063c0c6525914610655578063c56f0bab1461065d578063ce653d5f14610665578063dd62ed3e1461068557600080fd5b8063b4800cdc14610644578063ba3ec7411461064d578063bcfe394f1461043857600080fd5b80639920245411610171578063a457c2d71161014b578063a457c2d714610602578063a9059cbb14610615578063b0fd1fc214610628578063b21d35f21461063b57600080fd5b806399202454146105d45780639dc29fac146105dc5780639ff054df146105ef57600080fd5b80638da7ad23116101ad5780638da7ad2314610567578063909a2ff6146105bc57806395d89b41146105c4578063962ca496146105cc57600080fd5b80637b0472f0146105445780637e7aa62e146105575780638979c87c1461055f57600080fd5b80632a62d966116102ad578063543d36521161024b5780637010d7a1116102255780637010d7a1146104b057806370a082311461050857806372475f9414610531578063781cd99d1461053957600080fd5b8063543d3652146104385780635bccb4c41461049557806361a52a36146104a857600080fd5b80633950935111610287578063395093511461046a5780633ccfd60b1461047d578063451257151461048557806352c7f8dc1461048d57600080fd5b80632a62d966146103cf578063313ce5671461045357806332870fda1461046257600080fd5b8063110d7fc21161031a5780631c244082116102f45780631c2440821461041a5780631c560305146104235780631c6f212e1461043857806323b872dd1461044057600080fd5b8063110d7fc2146103cf57806316f9c8fd146103d757806318160ddd1461041257600080fd5b80630237893214610362578063069612a51461037e57806306fdde0314610387578063095ea7b31461039c5780630bfae56b146103bf5780630f2e1228146103c7575b600080fd5b61036b61016d81565b6040519081526020015b60405180910390f35b61036b60085481565b61038f61076f565b60405161037591906126e3565b6103af6103aa366004612754565b610801565b6040519015158152602001610375565b61036b610819565b61036b606381565b61036b600081565b6103df610828565b60405161037591908151815260208083015190820152604080830151908201526060918201519181019190915260800190565b60025461036b565b61036b60055481565b610436610431366004612754565b610899565b005b61036b600181565b6103af61044e36600461277e565b610afa565b60405160128152602001610375565b61036b605a81565b6103af610478366004612754565b610b1e565b610436610b40565b61036b610c94565b610436610ca3565b6104366104a33660046127ba565b610dc6565b61036b603c81565b6104b8611115565b604051610375919081516001600160a01b031681526020808301519082015260408083015190820152606080830151908201526080808301519082015260a0918201519181019190915260c00190565b61036b6105163660046127dc565b6001600160a01b031660009081526020819052604090205490565b61036b600f81565b61036b63634edb9081565b6104366105523660046127ba565b6111ba565b61036b600281565b61036b6113d0565b61059c6105753660046127dc565b600a6020526000908152604090208054600182015460028301546003909301549192909184565b604080519485526020850193909352918301526060820152608001610375565b61036b606481565b61038f6113da565b61036b6113e9565b61036b6113f3565b6104366105ea366004612754565b6113fd565b6104366105fd3660046127f7565b6115af565b6103af610610366004612754565b61186d565b6103af610623366004612754565b6118e8565b61036b610636366004612810565b6118f6565b61036b61138881565b61036b60065481565b61038f611986565b61036b6119a2565b61036b600781565b61036b6106733660046127dc565b600b6020526000908152604090205481565b61036b610693366004612842565b6119af565b6106e56106a63660046127dc565b6009602052600090815260409020805460018201546002830154600384015460048501546005909501546001600160a01b039094169492939192909186565b604080516001600160a01b0390971687526020870195909552938501929092526060840152608083015260a082015260c001610375565b61036b7f000000000000000000000000000000000000000000000000000000000000000081565b61036b610bb881565b61036b60075481565b61036b6119da565b61036b620186a081565b61036b601481565b60606003805461077e90612875565b80601f01602080910402602001604051908101604052809291908181526020018280546107aa90612875565b80156107f75780601f106107cc576101008083540402835291602001916107f7565b820191906000526020600020905b8154815290600101906020018083116107da57829003601f168201915b5050505050905090565b60003361080f8185856119f1565b5060019392505050565b610825603c60646128c6565b81565b6108536040518060800160405280600081526020016000815260200160008152602001600081525090565b50336000908152600a6020908152604091829020825160808101845281548152600182015492810192909252600281015492820192909252600390910154606082015290565b33600090815260096020908152604091829020825160c08101845281546001600160a01b03908116825260018301549382019390935260028201549381019390935260038101546060840152600481015460808401526005015460a083015283166109595760405162461bcd60e51b815260206004820152602560248201527f4352616e6b3a2043616e6e6f742073686172652077697468207a65726f206164604482015264647265737360d81b60648201526084015b60405180910390fd5b600082116109a95760405162461bcd60e51b815260206004820181905260248201527f4352616e6b3a2043616e6e6f74207368617265207a65726f2070657263656e746044820152606401610950565b606582106109f95760405162461bcd60e51b815260206004820181905260248201527f4352616e6b3a2043616e6e6f74207368617265203130302b2070657263656e746044820152606401610950565b6000816060015111610a1d5760405162461bcd60e51b8152600401610950906128e5565b80604001514211610a405760405162461bcd60e51b815260040161095090612914565b6000610a6382606001518360200151846040015185608001518660a00151611b16565b610a7590670de0b6b3a76400006128c6565b905060006064610a8585846128c6565b610a8f919061295f565b90506000610a9d8284612981565b9050610aaa335b82611c14565b610ab48683611c14565b610abc611cf3565b60405183815233907fd74752b13281df13701575f3a507e9b1242e0b5fb040143211c481c1fce573a6906020015b60405180910390a2505050505050565b600033610b08858285611d47565b610b13858585611dc1565b506001949350505050565b60003361080f818585610b3183836119af565b610b3b9190612998565b6119f1565b336000908152600a6020908152604091829020825160808101845281548152600182015492810192909252600281015492820183905260030154606082015290610bc35760405162461bcd60e51b815260206004820152601460248201527358454e3a206e6f207374616b652065786973747360601b6044820152606401610950565b6000610be18260400151836000015184602001518560600151611f8f565b600780549192506000610bf3836129b0565b9190505550816040015160086000828254610c0e9190612981565b90915550610c2d905033828460400151610c289190612998565b611c14565b60408083015181519081526020810183905233917f92ccf450a286a957af52509bc1c9939d1a6a481783e142e41e2499f0bb66ebc6910160405180910390a25050336000908152600a60205260408120818155600181018290556002810182905560030155565b6000610c9e611fed565b905090565b33600090815260096020908152604091829020825160c08101845281546001600160a01b031681526001820154928101929092526002810154928201929092526003820154606082018190526004830154608083015260059092015460a082015290610d215760405162461bcd60e51b8152600401610950906128e5565b80604001514211610d445760405162461bcd60e51b815260040161095090612914565b6000610d6782606001518360200151846040015185608001518660a00151611b16565b610d7990670de0b6b3a76400006128c6565b9050610d8433610aa4565b610d8c611cf3565b60405181815233907fd74752b13281df13701575f3a507e9b1242e0b5fb040143211c481c1fce573a6906020015b60405180910390a25050565b33600090815260096020908152604091829020825160c08101845281546001600160a01b03168152600182015492810192909252600281015492820192909252600382015460608201526004820154608082015260059091015460a082015260658310610e755760405162461bcd60e51b815260206004820181905260248201527f4352616e6b3a2043616e6e6f74207368617265203e3130302070657263656e746044820152606401610950565b6000816060015111610e995760405162461bcd60e51b8152600401610950906128e5565b80604001514211610ebc5760405162461bcd60e51b815260040161095090612914565b6000610edf82606001518360200151846040015185608001518660a00151611b16565b610ef190670de0b6b3a76400006128c6565b905060006064610f0186846128c6565b610f0b919061295f565b90506000610f198284612981565b9050610f2433610aa4565b610f2c611cf3565b60405183815233907fd74752b13281df13701575f3a507e9b1242e0b5fb040143211c481c1fce573a69060200160405180910390a260008211610fa85760405162461bcd60e51b815260206004820152601460248201527358454e3a2042656c6f77206d696e207374616b6560601b6044820152606401610950565b6001610fb5603c826128c6565b610fbf9190612981565b610fca603c876128c6565b116110135760405162461bcd60e51b815260206004820152601960248201527858454e3a2042656c6f77206d696e207374616b65207465726d60381b6044820152606401610950565b611020603c6103e86128c6565b61102b906001612998565b611036603c876128c6565b1061107f5760405162461bcd60e51b815260206004820152601960248201527858454e3a2041626f7665206d6178207374616b65207465726d60381b6044820152606401610950565b336000908152600a6020526040902060020154156110d35760405162461bcd60e51b815260206004820152601160248201527058454e3a207374616b652065786973747360781b6044820152606401610950565b6110dd82866120ec565b604080518381526020810187905233917f1449c6dd7851abc30abf37f57715f492010519147cc2652fbc38202c18a6ee909101610aea565b6111576040518060c0016040528060006001600160a01b0316815260200160008152602001600081526020016000815260200160008152602001600081525090565b5033600090815260096020908152604091829020825160c08101845281546001600160a01b03168152600182015492810192909252600281015492820192909252600382015460608201526004820154608082015260059091015460a082015290565b816111c433610516565b10156112125760405162461bcd60e51b815260206004820152601760248201527f58454e3a206e6f7420656e6f7567682062616c616e63650000000000000000006044820152606401610950565b600082116112595760405162461bcd60e51b815260206004820152601460248201527358454e3a2042656c6f77206d696e207374616b6560601b6044820152606401610950565b6001611266603c826128c6565b6112709190612981565b61127b603c836128c6565b116112c45760405162461bcd60e51b815260206004820152601960248201527858454e3a2042656c6f77206d696e207374616b65207465726d60381b6044820152606401610950565b6112d1603c6103e86128c6565b6112dc906001612998565b6112e7603c836128c6565b106113305760405162461bcd60e51b815260206004820152601960248201527858454e3a2041626f7665206d6178207374616b65207465726d60381b6044820152606401610950565b336000908152600a6020526040902060020154156113845760405162461bcd60e51b815260206004820152601160248201527058454e3a207374616b652065786973747360781b6044820152606401610950565b61138e338361218d565b61139882826120ec565b604080518381526020810183905233917f1449c6dd7851abc30abf37f57715f492010519147cc2652fbc38202c18a6ee909101610dba565b6000610c9e6122d3565b60606004805461077e90612875565b6000610c9e612317565b6000610c9e612382565b600081116114455760405162461bcd60e51b8152602060048201526015602482015274109d5c9b8e8810995b1bddc81b5a5b881b1a5b5a5d605a1b6044820152606401610950565b336040516301ffc9a760e01b815263543746b160e01b60048201526001600160a01b0391909116906301ffc9a790602401602060405180830381865afa158015611493573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114b791906129c7565b6115035760405162461bcd60e51b815260206004820152601e60248201527f4275726e3a206e6f74206120737570706f7274656420636f6e747261637400006044820152606401610950565b61150e823383611d47565b611518828261218d565b6001600160a01b0382166000908152600b602052604081208054839290611540908490612998565b9091555033905060405163543746b160e01b81526001600160a01b03848116600483015260248201849052919091169063543746b190604401600060405180830381600087803b15801561159357600080fd5b505af11580156115a7573d6000803e3d6000fd5b505050505050565b63634edb904210156115f85760405162461bcd60e51b815260206004820152601260248201527110d4985b9ace88139bdd081cdd185c9d195960721b6044820152606401610950565b6000611605603c836128c6565b90506001611614603c826128c6565b61161e9190612981565b811161166c5760405162461bcd60e51b815260206004820152601960248201527f4352616e6b3a205465726d206c657373207468616e206d696e000000000000006044820152606401610950565b611674611fed565b61167f906001612998565b81106116dc5760405162461bcd60e51b815260206004820152602660248201527f4352616e6b3a205465726d206d6f7265207468616e2063757272656e74206d6160448201526578207465726d60d01b6064820152608401610950565b336000908152600960205260409020600301541561173c5760405162461bcd60e51b815260206004820152601f60248201527f4352616e6b3a204d696e7420616c726561647920696e2070726f6772657373006044820152606401610950565b60006040518060c001604052806117503390565b6001600160a01b031681526020810185905260400161176f8442612998565b81526020016005548152602001611784612382565b81526020016117916122d3565b9052336000908152600960209081526040808320845181546001600160a01b0319166001600160a01b039091161781559184015160018301558301516002820155606083015160038201556080830151600482015560a08301516005909101556006805492935090611802836129e9565b919050555061180e3390565b6001600160a01b03167fe9149e1b5059238baed02fa659dbf4bd932fbcf760a431330df4d934bc942f37846005600081548092919061184c906129e9565b909155506040805192835260208301919091520160405180910390a2505050565b6000338161187b82866119af565b9050838110156118db5760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b6064820152608401610950565b610b1382868684036119f1565b60003361080f818585611dc1565b60008061190d6119058761245c565b600f0b61247a565b9050600061194961191d8561245c565b6119406119298861245c565b6119406119358b61245c565b600f88900b9061255e565b600f0b9061255e565b905061196f61196761195c6103e861245c565b600f84900b9061259c565b600f0b6125f4565b67ffffffffffffffff16925050505b949350505050565b604051806060016040528060258152602001612a1e6025913981565b610825603c6103e86128c6565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b60016119e7603c826128c6565b6108259190612981565b6001600160a01b038316611a535760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b6064820152608401610950565b6001600160a01b038216611ab45760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b6064820152608401610950565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b600080611b238542612981565b90506000611b3082612610565b9050600073bdf6b32fe4fb7c9bed3bb04ac9b7ac6bb404a1d6636d5433e68a600554611b5c9190612981565b6040516001600160e01b031960e084901b168152600481019190915260026024820152604401602060405180830381865af4158015611b9f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bc39190612a04565b90506000611bd3866103e8612998565b90506000611be383898c856118f6565b90506064611bf18582612981565b611bfb90836128c6565b611c05919061295f565b9b9a5050505050505050505050565b6001600160a01b038216611c6a5760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610950565b8060026000828254611c7c9190612998565b90915550506001600160a01b03821660009081526020819052604081208054839290611ca9908490612998565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b33600090815260096020526040812080546001600160a01b0319168155600181018290556002810182905560038101829055600481018290556005018190556006805491611d40836129b0565b9190505550565b6000611d5384846119af565b90506000198114611dbb5781811015611dae5760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610950565b611dbb84848484036119f1565b50505050565b6001600160a01b038316611e255760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b6064820152608401610950565b6001600160a01b038216611e875760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b6064820152608401610950565b6001600160a01b03831660009081526020819052604090205481811015611eff5760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b6064820152608401610950565b6001600160a01b03808516600090815260208190526040808220858503905591851681529081208054849290611f36908490612998565b92505081905550826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051611f8291815260200190565b60405180910390a3611dbb565b600082421115611fe257600061016d611fa886856128c6565b611fb590620f42406128c6565b611fbf919061295f565b90506305f5e100611fd082886128c6565b611fda919061295f565b91505061197e565b506000949350505050565b600061138860055411156120e057600061201b61196761200d600f61245c565b61194061190560055461245c565b67ffffffffffffffff1690506000612034603c836128c6565b612040603c60646128c6565b61204a9190612998565b905073bdf6b32fe4fb7c9bed3bb04ac9b7ac6bb404a1d6637ae2b5c782612074603c6103e86128c6565b6040516001600160e01b031960e085901b16815260048101929092526024820152604401602060405180830381865af41580156120b5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120d99190612a04565b9250505090565b610c9e603c60646128c6565b6040518060800160405280828152602001603c8361210a91906128c6565b6121149042612998565b8152602001838152602001612127612317565b9052336000908152600a60209081526040808320845181559184015160018301558301516002820155606090920151600390920191909155600780549161216d836129e9565b919050555081600860008282546121849190612998565b90915550505050565b6001600160a01b0382166121ed5760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b6064820152608401610950565b6001600160a01b038216600090815260208190526040902054818110156122615760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b6064820152608401610950565b6001600160a01b0383166000908152602081905260408120838303905560028054849290612290908490612981565b90915550506040518281526000906001600160a01b038516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001611b09565b600080620186a060055460016122e991906128c6565b6122f3919061295f565b9050606481111561230657600091505090565b612311816064612981565b91505090565b600080612326605a603c6128c6565b6123507f000000000000000000000000000000000000000000000000000000000000000042612981565b61235a919061295f565b90508061236960026014612981565b101561237757600291505090565b612311816014612981565b600080603c6123b17f000000000000000000000000000000000000000000000000000000000000000042612981565b6123bb919061295f565b9050610bb88110156124545773bdf6b32fe4fb7c9bed3bb04ac9b7ac6bb404a1d6636d5433e66123ed83610bb8612981565b6040516001600160e01b031960e084901b168152600481019190915260016024820152604401602060405180830381865af4158015612430573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123119190612a04565b600191505090565b6000677fffffffffffffff82111561247357600080fd5b5060401b90565b60008082600f0b1361248b57600080fd5b6000600f83900b6801000000000000000081126124aa576040918201911d5b64010000000081126124be576020918201911d5b6201000081126124d0576010918201911d5b61010081126124e1576008918201911d5b601081126124f1576004918201911d5b60048112612501576002918201911d5b60028112612510576001820191505b603f19820160401b600f85900b607f8490031b6780000000000000005b60008113156125535790800260ff81901c8281029390930192607f011c9060011d61252d565b509095945050505050565b6000600f83810b9083900b0260401d60016001607f1b0319811280159061258c575060016001607f1b038113155b61259557600080fd5b9392505050565b600081600f0b600014156125af57600080fd5b600082600f0b604085600f0b901b816125ca576125ca612949565b05905060016001607f1b0319811280159061258c575060016001607f1b0381131561259557600080fd5b60008082600f0b121561260657600080fd5b50600f0b60401d90565b60008061261e603c8461295f565b905061262c60016007612981565b81111561263c5750606392915050565b60006001600761264d846003612998565b6001901b61265b919061295f565b6126659190612981565b604051637ae2b5c760e01b8152600481018290526063602482015290915073bdf6b32fe4fb7c9bed3bb04ac9b7ac6bb404a1d690637ae2b5c790604401602060405180830381865af41580156126bf573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061197e9190612a04565b600060208083528351808285015260005b81811015612710578581018301518582016040015282016126f4565b81811115612722576000604083870101525b50601f01601f1916929092016040019392505050565b80356001600160a01b038116811461274f57600080fd5b919050565b6000806040838503121561276757600080fd5b61277083612738565b946020939093013593505050565b60008060006060848603121561279357600080fd5b61279c84612738565b92506127aa60208501612738565b9150604084013590509250925092565b600080604083850312156127cd57600080fd5b50508035926020909101359150565b6000602082840312156127ee57600080fd5b61259582612738565b60006020828403121561280957600080fd5b5035919050565b6000806000806080858703121561282657600080fd5b5050823594602084013594506040840135936060013592509050565b6000806040838503121561285557600080fd5b61285e83612738565b915061286c60208401612738565b90509250929050565b600181811c9082168061288957607f821691505b602082108114156128aa57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b60008160001904831182151516156128e0576128e06128b0565b500290565b6020808252601590820152744352616e6b3a204e6f206d696e742065786973747360581b604082015260600190565b6020808252818101527f4352616e6b3a204d696e74206d61747572697479206e6f742072656163686564604082015260600190565b634e487b7160e01b600052601260045260246000fd5b60008261297c57634e487b7160e01b600052601260045260246000fd5b500490565b600082821015612993576129936128b0565b500390565b600082198211156129ab576129ab6128b0565b500190565b6000816129bf576129bf6128b0565b506000190190565b6000602082840312156129d957600080fd5b8151801515811461259557600080fd5b60006000198214156129fd576129fd6128b0565b5060010190565b600060208284031215612a1657600080fd5b505191905056fe404d724a61636b4c6576696e20406c62656c79616576206661697263727970746f2e6f7267a2646970667358221220e9aa281b097a35b40cd7836484ad9b58749efd8cd4c4c1ea4cddde499d78e96c64736f6c634300080a0033

Deployed Bytecode

0x608060405234801561001057600080fd5b506004361061035d5760003560e01c80637b0472f0116101d3578063b4800cdc11610104578063df282331116100a2578063ed2f23691161007c578063ed2f23691461074c578063f060482914610755578063f340faed1461075d578063fed742691461076757600080fd5b8063df28233114610698578063e3af6d0a1461071c578063e81917b41461074357600080fd5b8063c0c65259116100de578063c0c6525914610655578063c56f0bab1461065d578063ce653d5f14610665578063dd62ed3e1461068557600080fd5b8063b4800cdc14610644578063ba3ec7411461064d578063bcfe394f1461043857600080fd5b80639920245411610171578063a457c2d71161014b578063a457c2d714610602578063a9059cbb14610615578063b0fd1fc214610628578063b21d35f21461063b57600080fd5b806399202454146105d45780639dc29fac146105dc5780639ff054df146105ef57600080fd5b80638da7ad23116101ad5780638da7ad2314610567578063909a2ff6146105bc57806395d89b41146105c4578063962ca496146105cc57600080fd5b80637b0472f0146105445780637e7aa62e146105575780638979c87c1461055f57600080fd5b80632a62d966116102ad578063543d36521161024b5780637010d7a1116102255780637010d7a1146104b057806370a082311461050857806372475f9414610531578063781cd99d1461053957600080fd5b8063543d3652146104385780635bccb4c41461049557806361a52a36146104a857600080fd5b80633950935111610287578063395093511461046a5780633ccfd60b1461047d578063451257151461048557806352c7f8dc1461048d57600080fd5b80632a62d966146103cf578063313ce5671461045357806332870fda1461046257600080fd5b8063110d7fc21161031a5780631c244082116102f45780631c2440821461041a5780631c560305146104235780631c6f212e1461043857806323b872dd1461044057600080fd5b8063110d7fc2146103cf57806316f9c8fd146103d757806318160ddd1461041257600080fd5b80630237893214610362578063069612a51461037e57806306fdde0314610387578063095ea7b31461039c5780630bfae56b146103bf5780630f2e1228146103c7575b600080fd5b61036b61016d81565b6040519081526020015b60405180910390f35b61036b60085481565b61038f61076f565b60405161037591906126e3565b6103af6103aa366004612754565b610801565b6040519015158152602001610375565b61036b610819565b61036b606381565b61036b600081565b6103df610828565b60405161037591908151815260208083015190820152604080830151908201526060918201519181019190915260800190565b60025461036b565b61036b60055481565b610436610431366004612754565b610899565b005b61036b600181565b6103af61044e36600461277e565b610afa565b60405160128152602001610375565b61036b605a81565b6103af610478366004612754565b610b1e565b610436610b40565b61036b610c94565b610436610ca3565b6104366104a33660046127ba565b610dc6565b61036b603c81565b6104b8611115565b604051610375919081516001600160a01b031681526020808301519082015260408083015190820152606080830151908201526080808301519082015260a0918201519181019190915260c00190565b61036b6105163660046127dc565b6001600160a01b031660009081526020819052604090205490565b61036b600f81565b61036b63634edb9081565b6104366105523660046127ba565b6111ba565b61036b600281565b61036b6113d0565b61059c6105753660046127dc565b600a6020526000908152604090208054600182015460028301546003909301549192909184565b604080519485526020850193909352918301526060820152608001610375565b61036b606481565b61038f6113da565b61036b6113e9565b61036b6113f3565b6104366105ea366004612754565b6113fd565b6104366105fd3660046127f7565b6115af565b6103af610610366004612754565b61186d565b6103af610623366004612754565b6118e8565b61036b610636366004612810565b6118f6565b61036b61138881565b61036b60065481565b61038f611986565b61036b6119a2565b61036b600781565b61036b6106733660046127dc565b600b6020526000908152604090205481565b61036b610693366004612842565b6119af565b6106e56106a63660046127dc565b6009602052600090815260409020805460018201546002830154600384015460048501546005909501546001600160a01b039094169492939192909186565b604080516001600160a01b0390971687526020870195909552938501929092526060840152608083015260a082015260c001610375565b61036b7f00000000000000000000000000000000000000000000000000000000634edb9081565b61036b610bb881565b61036b60075481565b61036b6119da565b61036b620186a081565b61036b601481565b60606003805461077e90612875565b80601f01602080910402602001604051908101604052809291908181526020018280546107aa90612875565b80156107f75780601f106107cc576101008083540402835291602001916107f7565b820191906000526020600020905b8154815290600101906020018083116107da57829003601f168201915b5050505050905090565b60003361080f8185856119f1565b5060019392505050565b610825603c60646128c6565b81565b6108536040518060800160405280600081526020016000815260200160008152602001600081525090565b50336000908152600a6020908152604091829020825160808101845281548152600182015492810192909252600281015492820192909252600390910154606082015290565b33600090815260096020908152604091829020825160c08101845281546001600160a01b03908116825260018301549382019390935260028201549381019390935260038101546060840152600481015460808401526005015460a083015283166109595760405162461bcd60e51b815260206004820152602560248201527f4352616e6b3a2043616e6e6f742073686172652077697468207a65726f206164604482015264647265737360d81b60648201526084015b60405180910390fd5b600082116109a95760405162461bcd60e51b815260206004820181905260248201527f4352616e6b3a2043616e6e6f74207368617265207a65726f2070657263656e746044820152606401610950565b606582106109f95760405162461bcd60e51b815260206004820181905260248201527f4352616e6b3a2043616e6e6f74207368617265203130302b2070657263656e746044820152606401610950565b6000816060015111610a1d5760405162461bcd60e51b8152600401610950906128e5565b80604001514211610a405760405162461bcd60e51b815260040161095090612914565b6000610a6382606001518360200151846040015185608001518660a00151611b16565b610a7590670de0b6b3a76400006128c6565b905060006064610a8585846128c6565b610a8f919061295f565b90506000610a9d8284612981565b9050610aaa335b82611c14565b610ab48683611c14565b610abc611cf3565b60405183815233907fd74752b13281df13701575f3a507e9b1242e0b5fb040143211c481c1fce573a6906020015b60405180910390a2505050505050565b600033610b08858285611d47565b610b13858585611dc1565b506001949350505050565b60003361080f818585610b3183836119af565b610b3b9190612998565b6119f1565b336000908152600a6020908152604091829020825160808101845281548152600182015492810192909252600281015492820183905260030154606082015290610bc35760405162461bcd60e51b815260206004820152601460248201527358454e3a206e6f207374616b652065786973747360601b6044820152606401610950565b6000610be18260400151836000015184602001518560600151611f8f565b600780549192506000610bf3836129b0565b9190505550816040015160086000828254610c0e9190612981565b90915550610c2d905033828460400151610c289190612998565b611c14565b60408083015181519081526020810183905233917f92ccf450a286a957af52509bc1c9939d1a6a481783e142e41e2499f0bb66ebc6910160405180910390a25050336000908152600a60205260408120818155600181018290556002810182905560030155565b6000610c9e611fed565b905090565b33600090815260096020908152604091829020825160c08101845281546001600160a01b031681526001820154928101929092526002810154928201929092526003820154606082018190526004830154608083015260059092015460a082015290610d215760405162461bcd60e51b8152600401610950906128e5565b80604001514211610d445760405162461bcd60e51b815260040161095090612914565b6000610d6782606001518360200151846040015185608001518660a00151611b16565b610d7990670de0b6b3a76400006128c6565b9050610d8433610aa4565b610d8c611cf3565b60405181815233907fd74752b13281df13701575f3a507e9b1242e0b5fb040143211c481c1fce573a6906020015b60405180910390a25050565b33600090815260096020908152604091829020825160c08101845281546001600160a01b03168152600182015492810192909252600281015492820192909252600382015460608201526004820154608082015260059091015460a082015260658310610e755760405162461bcd60e51b815260206004820181905260248201527f4352616e6b3a2043616e6e6f74207368617265203e3130302070657263656e746044820152606401610950565b6000816060015111610e995760405162461bcd60e51b8152600401610950906128e5565b80604001514211610ebc5760405162461bcd60e51b815260040161095090612914565b6000610edf82606001518360200151846040015185608001518660a00151611b16565b610ef190670de0b6b3a76400006128c6565b905060006064610f0186846128c6565b610f0b919061295f565b90506000610f198284612981565b9050610f2433610aa4565b610f2c611cf3565b60405183815233907fd74752b13281df13701575f3a507e9b1242e0b5fb040143211c481c1fce573a69060200160405180910390a260008211610fa85760405162461bcd60e51b815260206004820152601460248201527358454e3a2042656c6f77206d696e207374616b6560601b6044820152606401610950565b6001610fb5603c826128c6565b610fbf9190612981565b610fca603c876128c6565b116110135760405162461bcd60e51b815260206004820152601960248201527858454e3a2042656c6f77206d696e207374616b65207465726d60381b6044820152606401610950565b611020603c6103e86128c6565b61102b906001612998565b611036603c876128c6565b1061107f5760405162461bcd60e51b815260206004820152601960248201527858454e3a2041626f7665206d6178207374616b65207465726d60381b6044820152606401610950565b336000908152600a6020526040902060020154156110d35760405162461bcd60e51b815260206004820152601160248201527058454e3a207374616b652065786973747360781b6044820152606401610950565b6110dd82866120ec565b604080518381526020810187905233917f1449c6dd7851abc30abf37f57715f492010519147cc2652fbc38202c18a6ee909101610aea565b6111576040518060c0016040528060006001600160a01b0316815260200160008152602001600081526020016000815260200160008152602001600081525090565b5033600090815260096020908152604091829020825160c08101845281546001600160a01b03168152600182015492810192909252600281015492820192909252600382015460608201526004820154608082015260059091015460a082015290565b816111c433610516565b10156112125760405162461bcd60e51b815260206004820152601760248201527f58454e3a206e6f7420656e6f7567682062616c616e63650000000000000000006044820152606401610950565b600082116112595760405162461bcd60e51b815260206004820152601460248201527358454e3a2042656c6f77206d696e207374616b6560601b6044820152606401610950565b6001611266603c826128c6565b6112709190612981565b61127b603c836128c6565b116112c45760405162461bcd60e51b815260206004820152601960248201527858454e3a2042656c6f77206d696e207374616b65207465726d60381b6044820152606401610950565b6112d1603c6103e86128c6565b6112dc906001612998565b6112e7603c836128c6565b106113305760405162461bcd60e51b815260206004820152601960248201527858454e3a2041626f7665206d6178207374616b65207465726d60381b6044820152606401610950565b336000908152600a6020526040902060020154156113845760405162461bcd60e51b815260206004820152601160248201527058454e3a207374616b652065786973747360781b6044820152606401610950565b61138e338361218d565b61139882826120ec565b604080518381526020810183905233917f1449c6dd7851abc30abf37f57715f492010519147cc2652fbc38202c18a6ee909101610dba565b6000610c9e6122d3565b60606004805461077e90612875565b6000610c9e612317565b6000610c9e612382565b600081116114455760405162461bcd60e51b8152602060048201526015602482015274109d5c9b8e8810995b1bddc81b5a5b881b1a5b5a5d605a1b6044820152606401610950565b336040516301ffc9a760e01b815263543746b160e01b60048201526001600160a01b0391909116906301ffc9a790602401602060405180830381865afa158015611493573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114b791906129c7565b6115035760405162461bcd60e51b815260206004820152601e60248201527f4275726e3a206e6f74206120737570706f7274656420636f6e747261637400006044820152606401610950565b61150e823383611d47565b611518828261218d565b6001600160a01b0382166000908152600b602052604081208054839290611540908490612998565b9091555033905060405163543746b160e01b81526001600160a01b03848116600483015260248201849052919091169063543746b190604401600060405180830381600087803b15801561159357600080fd5b505af11580156115a7573d6000803e3d6000fd5b505050505050565b63634edb904210156115f85760405162461bcd60e51b815260206004820152601260248201527110d4985b9ace88139bdd081cdd185c9d195960721b6044820152606401610950565b6000611605603c836128c6565b90506001611614603c826128c6565b61161e9190612981565b811161166c5760405162461bcd60e51b815260206004820152601960248201527f4352616e6b3a205465726d206c657373207468616e206d696e000000000000006044820152606401610950565b611674611fed565b61167f906001612998565b81106116dc5760405162461bcd60e51b815260206004820152602660248201527f4352616e6b3a205465726d206d6f7265207468616e2063757272656e74206d6160448201526578207465726d60d01b6064820152608401610950565b336000908152600960205260409020600301541561173c5760405162461bcd60e51b815260206004820152601f60248201527f4352616e6b3a204d696e7420616c726561647920696e2070726f6772657373006044820152606401610950565b60006040518060c001604052806117503390565b6001600160a01b031681526020810185905260400161176f8442612998565b81526020016005548152602001611784612382565b81526020016117916122d3565b9052336000908152600960209081526040808320845181546001600160a01b0319166001600160a01b039091161781559184015160018301558301516002820155606083015160038201556080830151600482015560a08301516005909101556006805492935090611802836129e9565b919050555061180e3390565b6001600160a01b03167fe9149e1b5059238baed02fa659dbf4bd932fbcf760a431330df4d934bc942f37846005600081548092919061184c906129e9565b909155506040805192835260208301919091520160405180910390a2505050565b6000338161187b82866119af565b9050838110156118db5760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b6064820152608401610950565b610b1382868684036119f1565b60003361080f818585611dc1565b60008061190d6119058761245c565b600f0b61247a565b9050600061194961191d8561245c565b6119406119298861245c565b6119406119358b61245c565b600f88900b9061255e565b600f0b9061255e565b905061196f61196761195c6103e861245c565b600f84900b9061259c565b600f0b6125f4565b67ffffffffffffffff16925050505b949350505050565b604051806060016040528060258152602001612a1e6025913981565b610825603c6103e86128c6565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b60016119e7603c826128c6565b6108259190612981565b6001600160a01b038316611a535760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b6064820152608401610950565b6001600160a01b038216611ab45760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b6064820152608401610950565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b600080611b238542612981565b90506000611b3082612610565b9050600073bdf6b32fe4fb7c9bed3bb04ac9b7ac6bb404a1d6636d5433e68a600554611b5c9190612981565b6040516001600160e01b031960e084901b168152600481019190915260026024820152604401602060405180830381865af4158015611b9f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bc39190612a04565b90506000611bd3866103e8612998565b90506000611be383898c856118f6565b90506064611bf18582612981565b611bfb90836128c6565b611c05919061295f565b9b9a5050505050505050505050565b6001600160a01b038216611c6a5760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610950565b8060026000828254611c7c9190612998565b90915550506001600160a01b03821660009081526020819052604081208054839290611ca9908490612998565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b33600090815260096020526040812080546001600160a01b0319168155600181018290556002810182905560038101829055600481018290556005018190556006805491611d40836129b0565b9190505550565b6000611d5384846119af565b90506000198114611dbb5781811015611dae5760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610950565b611dbb84848484036119f1565b50505050565b6001600160a01b038316611e255760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b6064820152608401610950565b6001600160a01b038216611e875760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b6064820152608401610950565b6001600160a01b03831660009081526020819052604090205481811015611eff5760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b6064820152608401610950565b6001600160a01b03808516600090815260208190526040808220858503905591851681529081208054849290611f36908490612998565b92505081905550826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051611f8291815260200190565b60405180910390a3611dbb565b600082421115611fe257600061016d611fa886856128c6565b611fb590620f42406128c6565b611fbf919061295f565b90506305f5e100611fd082886128c6565b611fda919061295f565b91505061197e565b506000949350505050565b600061138860055411156120e057600061201b61196761200d600f61245c565b61194061190560055461245c565b67ffffffffffffffff1690506000612034603c836128c6565b612040603c60646128c6565b61204a9190612998565b905073bdf6b32fe4fb7c9bed3bb04ac9b7ac6bb404a1d6637ae2b5c782612074603c6103e86128c6565b6040516001600160e01b031960e085901b16815260048101929092526024820152604401602060405180830381865af41580156120b5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120d99190612a04565b9250505090565b610c9e603c60646128c6565b6040518060800160405280828152602001603c8361210a91906128c6565b6121149042612998565b8152602001838152602001612127612317565b9052336000908152600a60209081526040808320845181559184015160018301558301516002820155606090920151600390920191909155600780549161216d836129e9565b919050555081600860008282546121849190612998565b90915550505050565b6001600160a01b0382166121ed5760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b6064820152608401610950565b6001600160a01b038216600090815260208190526040902054818110156122615760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b6064820152608401610950565b6001600160a01b0383166000908152602081905260408120838303905560028054849290612290908490612981565b90915550506040518281526000906001600160a01b038516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001611b09565b600080620186a060055460016122e991906128c6565b6122f3919061295f565b9050606481111561230657600091505090565b612311816064612981565b91505090565b600080612326605a603c6128c6565b6123507f00000000000000000000000000000000000000000000000000000000634edb9042612981565b61235a919061295f565b90508061236960026014612981565b101561237757600291505090565b612311816014612981565b600080603c6123b17f00000000000000000000000000000000000000000000000000000000634edb9042612981565b6123bb919061295f565b9050610bb88110156124545773bdf6b32fe4fb7c9bed3bb04ac9b7ac6bb404a1d6636d5433e66123ed83610bb8612981565b6040516001600160e01b031960e084901b168152600481019190915260016024820152604401602060405180830381865af4158015612430573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123119190612a04565b600191505090565b6000677fffffffffffffff82111561247357600080fd5b5060401b90565b60008082600f0b1361248b57600080fd5b6000600f83900b6801000000000000000081126124aa576040918201911d5b64010000000081126124be576020918201911d5b6201000081126124d0576010918201911d5b61010081126124e1576008918201911d5b601081126124f1576004918201911d5b60048112612501576002918201911d5b60028112612510576001820191505b603f19820160401b600f85900b607f8490031b6780000000000000005b60008113156125535790800260ff81901c8281029390930192607f011c9060011d61252d565b509095945050505050565b6000600f83810b9083900b0260401d60016001607f1b0319811280159061258c575060016001607f1b038113155b61259557600080fd5b9392505050565b600081600f0b600014156125af57600080fd5b600082600f0b604085600f0b901b816125ca576125ca612949565b05905060016001607f1b0319811280159061258c575060016001607f1b0381131561259557600080fd5b60008082600f0b121561260657600080fd5b50600f0b60401d90565b60008061261e603c8461295f565b905061262c60016007612981565b81111561263c5750606392915050565b60006001600761264d846003612998565b6001901b61265b919061295f565b6126659190612981565b604051637ae2b5c760e01b8152600481018290526063602482015290915073bdf6b32fe4fb7c9bed3bb04ac9b7ac6bb404a1d690637ae2b5c790604401602060405180830381865af41580156126bf573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061197e9190612a04565b600060208083528351808285015260005b81811015612710578581018301518582016040015282016126f4565b81811115612722576000604083870101525b50601f01601f1916929092016040019392505050565b80356001600160a01b038116811461274f57600080fd5b919050565b6000806040838503121561276757600080fd5b61277083612738565b946020939093013593505050565b60008060006060848603121561279357600080fd5b61279c84612738565b92506127aa60208501612738565b9150604084013590509250925092565b600080604083850312156127cd57600080fd5b50508035926020909101359150565b6000602082840312156127ee57600080fd5b61259582612738565b60006020828403121561280957600080fd5b5035919050565b6000806000806080858703121561282657600080fd5b5050823594602084013594506040840135936060013592509050565b6000806040838503121561285557600080fd5b61285e83612738565b915061286c60208401612738565b90509250929050565b600181811c9082168061288957607f821691505b602082108114156128aa57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b60008160001904831182151516156128e0576128e06128b0565b500290565b6020808252601590820152744352616e6b3a204e6f206d696e742065786973747360581b604082015260600190565b6020808252818101527f4352616e6b3a204d696e74206d61747572697479206e6f742072656163686564604082015260600190565b634e487b7160e01b600052601260045260246000fd5b60008261297c57634e487b7160e01b600052601260045260246000fd5b500490565b600082821015612993576129936128b0565b500390565b600082198211156129ab576129ab6128b0565b500190565b6000816129bf576129bf6128b0565b506000190190565b6000602082840312156129d957600080fd5b8151801515811461259557600080fd5b60006000198214156129fd576129fd6128b0565b5060010190565b600060208284031215612a1657600080fd5b505191905056fe404d724a61636b4c6576696e20406c62656c79616576206661697263727970746f2e6f7267a2646970667358221220e9aa281b097a35b40cd7836484ad9b58749efd8cd4c4c1ea4cddde499d78e96c64736f6c634300080a0033

Deployed Bytecode Sourcemap

418:14424:8:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1111:42;;1150:3;1111:42;;;;;160:25:13;;;148:2;133:18;1111:42:8;;;;;;;;2466:29;;;;;;2156:98:1;;;:::i;:::-;;;;;;;:::i;4433:197::-;;;;;;:::i;:::-;;:::i;:::-;;;1400:14:13;;1393:22;1375:41;;1363:2;1348:18;4433:197:1;1235:187:13;1270:61:8;;;:::i;1831:44::-;;1873:2;1831:44;;1930:40;;1969:1;1930:40;;7406:113;;;:::i;:::-;;;;;;1646:13:13;;1628:32;;1716:4;1704:17;;;1698:24;1676:20;;;1669:54;1779:4;1767:17;;;1761:24;1739:20;;;1732:54;1842:4;1830:17;;;1824:24;1802:20;;;1795:54;;;;1615:3;1600:19;;1427:428;3244:106:1;3331:12;;3244:106;;2353:40:8;;;;;;10155:1052;;;;;;:::i;:::-;;:::i;:::-;;1160:40;;1199:1;1160:40;;5192:286:1;;;;;;:::i;:::-;;:::i;3093:91::-;;;3175:2;2335:36:13;;2323:2;2308:18;3093:91:1;2193:184:13;2025:46:8;;2069:2;2025:46;;5873:234:1;;;;;;:::i;:::-;;:::i;13632:617:8:-;;;:::i;8049:104::-;;;:::i;9311:649::-;;;:::i;11378:1457::-;;;;;;:::i;:::-;;:::i;1062:43::-;;1103:2;1062:43;;7200:110;;;:::i;:::-;;;;;;2856:13:13;;-1:-1:-1;;;;;2852:39:13;2834:58;;2948:4;2936:17;;;2930:24;2908:20;;;2901:54;3011:4;2999:17;;;2993:24;2971:20;;;2964:54;3074:4;3062:17;;;3056:24;3034:20;;;3027:54;3137:4;3125:17;;;3119:24;3097:20;;;3090:54;2879:3;3188:17;;;3182:24;3160:20;;;3153:54;;;;2821:3;2806:19;;2635:578;3408:125:1;;;;;;:::i;:::-;-1:-1:-1;;;;;3508:18:1;3482:7;3508:18;;;;;;;;;;;;3408:125;1404:43:8;;1445:2;1404:43;;2202:52;;2244:10;2202:52;;12917:627;;;;;;:::i;:::-;;:::i;2077:39::-;;2115:1;2077:39;;7740:101;;;:::i;2627:47::-;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3640:25:13;;;3696:2;3681:18;;3674:34;;;;3724:18;;;3717:34;3782:2;3767:18;;3760:34;3627:3;3612:19;2627:47:8;3409:391:13;1629:42:8;;1668:3;1629:42;;2367:102:1;;;:::i;7895:96:8:-;;;:::i;7573:108::-;;;:::i;14371:469::-;;;;;;:::i;:::-;;:::i;8307:880::-;;;;;;:::i;:::-;;:::i;6594:427:1:-;;;;;;:::i;:::-;;:::i;3729:189::-;;;;;;:::i;:::-;;:::i;6718:386:8:-;;;;;;:::i;:::-;;:::i;1453:56::-;;1504:5;1453:56;;2399:28;;;;;;2123:72;;;:::i;1337:61::-;;;:::i;1775:50::-;;1824:1;1775:50;;2719:44;;;;;;:::i;:::-;;;;;;;;;;;;;;3976:149:1;;;;;;:::i;:::-;;:::i;2538:45:8:-;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;2538:45:8;;;;;;;;;;;;;;;;-1:-1:-1;;;;;4950:32:13;;;4932:51;;5014:2;4999:18;;4992:34;;;;5042:18;;;5035:34;;;;5100:2;5085:18;;5078:34;5143:3;5128:19;;5121:35;4970:3;5172:19;;5165:35;4919:3;4904:19;2538:45:8;4645:561:13;2313:34:8;;;;;1515:54;;1564:5;1515:54;;2433:27;;;;;;1207:57;;;:::i;1722:47::-;;1762:7;1722:47;;1977:42;;2017:2;1977:42;;2156:98:1;2210:13;2242:5;2235:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2156:98;:::o;4433:197::-;4516:4;719:10:4;4570:32:1;719:10:4;4586:7:1;4595:6;4570:8;:32::i;:::-;-1:-1:-1;4619:4:1;;4433:197;-1:-1:-1;;;4433:197:1:o;1270:61:8:-;1311:20;1103:2;1311:3;:20;:::i;:::-;1270:61;:::o;7406:113::-;7453:16;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;7453:16:8;-1:-1:-1;719:10:4;7488:24:8;;;;:10;:24;;;;;;;;;7481:31;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;7406:113::o;10155:1052::-;719:10:4;10235:24:8;10262:23;;;:9;:23;;;;;;;;;10235:50;;;;;;;;;-1:-1:-1;;;;;10235:50:8;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;10303:19;;10295:69;;;;-1:-1:-1;;;10295:69:8;;6103:2:13;10295:69:8;;;6085:21:13;6142:2;6122:18;;;6115:30;6181:34;6161:18;;;6154:62;-1:-1:-1;;;6232:18:13;;;6225:35;6277:19;;10295:69:8;;;;;;;;;10388:1;10382:3;:7;10374:52;;;;-1:-1:-1;;;10374:52:8;;6509:2:13;10374:52:8;;;6491:21:13;;;6528:18;;;6521:30;6587:34;6567:18;;;6560:62;6639:18;;10374:52:8;6307:356:13;10374:52:8;10450:3;10444;:9;10436:54;;;;-1:-1:-1;;;10436:54:8;;6870:2:13;10436:54:8;;;6852:21:13;;;6889:18;;;6882:30;6948:34;6928:18;;;6921:62;7000:18;;10436:54:8;6668:356:13;10436:54:8;10524:1;10508:8;:13;;;:17;10500:51;;;;-1:-1:-1;;;10500:51:8;;;;;;;:::i;:::-;10587:8;:19;;;10569:15;:37;10561:82;;;;-1:-1:-1;;;10561:82:8;;;;;;;:::i;:::-;10682:20;10705:179;10739:8;:13;;;10766:8;:13;;;10793:8;:19;;;10826:8;:18;;;10858:8;:16;;;10705:20;:179::i;:::-;:189;;10887:7;10705:189;:::i;:::-;10682:212;-1:-1:-1;10904:20:8;10950:3;10928:18;10943:3;10682:212;10928:18;:::i;:::-;10927:26;;;;:::i;:::-;10904:49;-1:-1:-1;10963:17:8;10983:27;10904:49;10983:12;:27;:::i;:::-;10963:47;-1:-1:-1;11051:30:8;719:10:4;11057:12:8;11071:9;11051:5;:30::i;:::-;11091:26;11097:5;11104:12;11091:5;:26::i;:::-;11128:18;:16;:18::i;:::-;11161:39;;160:25:13;;;719:10:4;;11161:39:8;;148:2:13;133:18;11161:39:8;;;;;;;;10225:982;;;;10155:1052;;:::o;5192:286:1:-;5319:4;719:10:4;5375:38:1;5391:4;719:10:4;5406:6:1;5375:15;:38::i;:::-;5423:27;5433:4;5439:2;5443:6;5423:9;:27::i;:::-;-1:-1:-1;5467:4:1;;5192:286;-1:-1:-1;;;;5192:286:1:o;5873:234::-;5961:4;719:10:4;6015:64:1;719:10:4;6031:7:1;6068:10;6040:25;719:10:4;6031:7:1;6040:9;:25::i;:::-;:38;;;;:::i;:::-;6015:8;:64::i;13632:617:8:-;719:10:4;13671:26:8;13700:24;;;:10;:24;;;;;;;;;13671:53;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;13734;;;;-1:-1:-1;;;13734:53:8;;8559:2:13;13734:53:8;;;8541:21:13;8598:2;8578:18;;;8571:30;-1:-1:-1;;;8617:18:13;;;8610:50;8677:18;;13734:53:8;8357:344:13;13734:53:8;13798:17;13818:150;13853:9;:16;;;13883:9;:14;;;13911:9;:20;;;13945:9;:13;;;13818:21;:150::i;:::-;13978:12;:14;;13798:170;;-1:-1:-1;13978:12:8;:14;;;:::i;:::-;;;;;;14020:9;:16;;;14002:14;;:34;;;;;;;:::i;:::-;;;;-1:-1:-1;14085:49:8;;-1:-1:-1;719:10:4;14124:9:8;14105;:16;;;:28;;;;:::i;:::-;14085:5;:49::i;:::-;14173:16;;;;;14149:52;;9021:25:13;;;9077:2;9062:18;;9055:34;;;719:10:4;;14149:52:8;;8994:18:13;14149:52:8;;;;;;;-1:-1:-1;;719:10:4;14218:24:8;;;;:10;:24;;;;;14211:31;;;;;;;;;;;;;;;;;;13632:617::o;8049:104::-;8101:7;8127:19;:17;:19::i;:::-;8120:26;;8049:104;:::o;9311:649::-;719:10:4;9357:24:8;9384:23;;;:9;:23;;;;;;;;;9357:50;;;;;;;;;-1:-1:-1;;;;;9357:50:8;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;9417:51;;;;-1:-1:-1;;;9417:51:8;;;;;;;:::i;:::-;9504:8;:19;;;9486:15;:37;9478:82;;;;-1:-1:-1;;;9478:82:8;;;;;;;:::i;:::-;9615:20;9638:179;9672:8;:13;;;9699:8;:13;;;9726:8;:19;;;9759:8;:18;;;9791:8;:16;;;9638:20;:179::i;:::-;:189;;9820:7;9638:189;:::i;:::-;9615:212;-1:-1:-1;9837:33:8;719:10:4;9843:12:8;640:96:4;9837:33:8;9881:18;:16;:18::i;:::-;9914:39;;160:25:13;;;719:10:4;;9914:39:8;;148:2:13;133:18;9914:39:8;;;;;;;;9347:613;;9311:649::o;11378:1457::-;719:10:4;11457:24:8;11484:23;;;:9;:23;;;;;;;;;11457:50;;;;;;;;;-1:-1:-1;;;;;11457:50:8;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;11596:3;11590:9;;11582:54;;;;-1:-1:-1;;;11582:54:8;;9302:2:13;11582:54:8;;;9284:21:13;;;9321:18;;;9314:30;9380:34;9360:18;;;9353:62;9432:18;;11582:54:8;9100:356:13;11582:54:8;11670:1;11654:8;:13;;;:17;11646:51;;;;-1:-1:-1;;;11646:51:8;;;;;;;:::i;:::-;11733:8;:19;;;11715:15;:37;11707:82;;;;-1:-1:-1;;;11707:82:8;;;;;;;:::i;:::-;11828:20;11851:179;11885:8;:13;;;11912:8;:13;;;11939:8;:19;;;11972:8;:18;;;12004:8;:16;;;11851:20;:179::i;:::-;:189;;12033:7;11851:189;:::i;:::-;11828:212;-1:-1:-1;12050:20:8;12096:3;12074:18;12089:3;11828:212;12074:18;:::i;:::-;12073:26;;;;:::i;:::-;12050:49;-1:-1:-1;12109:17:8;12129:27;12050:49;12129:12;:27;:::i;:::-;12109:47;-1:-1:-1;12202:30:8;719:10:4;12208:12:8;640:96:4;12202:30:8;12242:18;:16;:18::i;:::-;12275:39;;160:25:13;;;719:10:4;;12275:39:8;;148:2:13;133:18;12275:39:8;;;;;;;1922:1;12433:12;:28;12425:61;;;;-1:-1:-1;;;12425:61:8;;9663:2:13;12425:61:8;;;9645:21:13;9702:2;9682:18;;;9675:30;-1:-1:-1;;;9721:18:13;;;9714:50;9781:18;;12425:61:8;9461:344:13;12425:61:8;1263:1;1242:18;1103:2;1263:1;1242:18;:::i;:::-;:22;;;;:::i;:::-;12504:21;1103:2;12504:4;:21;:::i;:::-;:32;12496:70;;;;-1:-1:-1;;;12496:70:8;;10012:2:13;12496:70:8;;;9994:21:13;10051:2;10031:18;;;10024:30;-1:-1:-1;;;10070:18:13;;;10063:55;10135:18;;12496:70:8;9810:349:13;12496:70:8;1376:22;1103:2;1376:5;:22;:::i;:::-;12608:16;;12623:1;12608:16;:::i;:::-;12584:21;1103:2;12584:4;:21;:::i;:::-;:40;12576:78;;;;-1:-1:-1;;;12576:78:8;;10366:2:13;12576:78:8;;;10348:21:13;10405:2;10385:18;;;10378:30;-1:-1:-1;;;10424:18:13;;;10417:55;10489:18;;12576:78:8;10164:349:13;12576:78:8;719:10:4;12672:24:8;;;;:10;:24;;;;;:31;;;:36;12664:66;;;;-1:-1:-1;;;12664:66:8;;10720:2:13;12664:66:8;;;10702:21:13;10759:2;10739:18;;;10732:30;-1:-1:-1;;;10778:18:13;;;10771:47;10835:18;;12664:66:8;10518:341:13;12664:66:8;12741:32;12754:12;12768:4;12741:12;:32::i;:::-;12788:40;;;9021:25:13;;;9077:2;9062:18;;9055:34;;;719:10:4;;12788:40:8;;8994:18:13;12788:40:8;8847:248:13;7200:110:8;7246:15;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;7246:15:8;-1:-1:-1;719:10:4;7280:23:8;;;;:9;:23;;;;;;;;;7273:30;;;;;;;;;-1:-1:-1;;;;;7273:30:8;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;7200:110::o;12917:627::-;13016:6;12989:23;719:10:4;12999:12:8;640:96:4;12989:23:8;:33;;12981:69;;;;-1:-1:-1;;;12981:69:8;;11066:2:13;12981:69:8;;;11048:21:13;11105:2;11085:18;;;11078:30;11144:25;11124:18;;;11117:53;11187:18;;12981:69:8;10864:347:13;12981:69:8;1922:1;13068:6;:22;13060:55;;;;-1:-1:-1;;;13060:55:8;;9663:2:13;13060:55:8;;;9645:21:13;9702:2;9682:18;;;9675:30;-1:-1:-1;;;9721:18:13;;;9714:50;9781:18;;13060:55:8;9461:344:13;13060:55:8;1263:1;1242:18;1103:2;1263:1;1242:18;:::i;:::-;:22;;;;:::i;:::-;13133:21;1103:2;13133:4;:21;:::i;:::-;:32;13125:70;;;;-1:-1:-1;;;13125:70:8;;10012:2:13;13125:70:8;;;9994:21:13;10051:2;10031:18;;;10024:30;-1:-1:-1;;;10070:18:13;;;10063:55;10135:18;;13125:70:8;9810:349:13;13125:70:8;1376:22;1103:2;1376:5;:22;:::i;:::-;13237:16;;13252:1;13237:16;:::i;:::-;13213:21;1103:2;13213:4;:21;:::i;:::-;:40;13205:78;;;;-1:-1:-1;;;13205:78:8;;10366:2:13;13205:78:8;;;10348:21:13;10405:2;10385:18;;;10378:30;-1:-1:-1;;;10424:18:13;;;10417:55;10489:18;;13205:78:8;10164:349:13;13205:78:8;719:10:4;13301:24:8;;;;:10;:24;;;;;:31;;;:36;13293:66;;;;-1:-1:-1;;;13293:66:8;;10720:2:13;13293:66:8;;;10702:21:13;10759:2;10739:18;;;10732:30;-1:-1:-1;;;10778:18:13;;;10771:47;10835:18;;13293:66:8;10518:341:13;13293:66:8;13397:27;719:10:4;13417:6:8;13397:5;:27::i;:::-;13462:26;13475:6;13483:4;13462:12;:26::i;:::-;13503:34;;;9021:25:13;;;9077:2;9062:18;;9055:34;;;719:10:4;;13503:34:8;;8994:18:13;13503:34:8;8847:248:13;7740:101:8;7789:7;7815:19;:17;:19::i;2367:102:1:-;2423:13;2455:7;2448:14;;;;;:::i;7895:96:8:-;7943:7;7969:15;:13;:15::i;7573:108::-;7621:7;7647:27;:25;:27::i;14371:469::-;1969:1;14440:6;:21;14432:55;;;;-1:-1:-1;;;14432:55:8;;11418:2:13;14432:55:8;;;11400:21:13;11457:2;11437:18;;;11430:30;-1:-1:-1;;;11476:18:13;;;11469:51;11537:18;;14432:55:8;11216:345:13;14432:55:8;719:10:4;14518:74:8;;-1:-1:-1;;;14518:74:8;;-1:-1:-1;;;14518:74:8;;;11710:52:13;-1:-1:-1;;;;;14518:39:8;;;;;;;11683:18:13;;14518:74:8;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;14497:151;;;;-1:-1:-1;;;14497:151:8;;12257:2:13;14497:151:8;;;12239:21:13;12296:2;12276:18;;;12269:30;12335:32;12315:18;;;12308:60;12385:18;;14497:151:8;12055:354:13;14497:151:8;14659:43;14675:4;719:10:4;14695:6:8;14659:15;:43::i;:::-;14712:19;14718:4;14724:6;14712:5;:19::i;:::-;-1:-1:-1;;;;;14741:15:8;;;;;;:9;:15;;;;;:25;;14760:6;;14741:15;:25;;14760:6;;14741:25;:::i;:::-;;;;-1:-1:-1;719:10:4;;-1:-1:-1;14776:57:8;;-1:-1:-1;;;14776:57:8;;-1:-1:-1;;;;;12606:32:13;;;14776:57:8;;;12588:51:13;12655:18;;;12648:34;;;14776:43:8;;;;;;;12561:18:13;;14776:57:8;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;14371:469;;:::o;8307:880::-;2244:10;8367:15;:34;;8359:65;;;;-1:-1:-1;;;8359:65:8;;12895:2:13;8359:65:8;;;12877:21:13;12934:2;12914:18;;;12907:30;-1:-1:-1;;;12953:18:13;;;12946:48;13011:18;;8359:65:8;12693:342:13;8359:65:8;8434:15;8452:21;1103:2;8452:4;:21;:::i;:::-;8434:39;-1:-1:-1;1263:1:8;1242:18;1103:2;1263:1;1242:18;:::i;:::-;:22;;;;:::i;:::-;8491:7;:18;8483:56;;;;-1:-1:-1;;;8483:56:8;;13242:2:13;8483:56:8;;;13224:21:13;13281:2;13261:18;;;13254:30;13320:27;13300:18;;;13293:55;13365:18;;8483:56:8;13040:349:13;8483:56:8;8567:19;:17;:19::i;:::-;:23;;8589:1;8567:23;:::i;:::-;8557:7;:33;8549:84;;;;-1:-1:-1;;;8549:84:8;;13596:2:13;8549:84:8;;;13578:21:13;13635:2;13615:18;;;13608:30;13674:34;13654:18;;;13647:62;-1:-1:-1;;;13725:18:13;;;13718:36;13771:19;;8549:84:8;13394:402:13;8549:84:8;719:10:4;8651:23:8;;;;:9;:23;;;;;:28;;;:33;8643:77;;;;-1:-1:-1;;;8643:77:8;;14003:2:13;8643:77:8;;;13985:21:13;14042:2;14022:18;;;14015:30;14081:33;14061:18;;;14054:61;14132:18;;8643:77:8;13801:355:13;8643:77:8;8772:24;8799:251;;;;;;;;8828:12;719:10:4;;640:96;8828:12:8;-1:-1:-1;;;;;8799:251:8;;;;;;;;;;;8890:25;8908:7;8890:15;:25;:::i;:::-;8799:251;;;;8935:10;;8799:251;;;;8970:27;:25;:27::i;:::-;8799:251;;;;9020:19;:17;:19::i;:::-;8799:251;;719:10:4;9060:23:8;;;;:9;:23;;;;;;;;:34;;;;-1:-1:-1;;;;;;9060:34:8;-1:-1:-1;;;;;9060:34:8;;;;;;;;;;-1:-1:-1;9060:34:8;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;9104:13;:15;;9060:34;;-1:-1:-1;9104:13:8;:15;;;:::i;:::-;;;;;;9147:12;719:10:4;;640:96;9147:12:8;-1:-1:-1;;;;;9135:45:8;;9161:4;9167:10;;:12;;;;;;;;;:::i;:::-;;;;-1:-1:-1;9135:45:8;;;9021:25:13;;;9077:2;9062:18;;9055:34;;;;8994:18;9135:45:8;;;;;;;8349:838;;8307:880;:::o;6594:427:1:-;6687:4;719:10:4;6687:4:1;6768:25;719:10:4;6785:7:1;6768:9;:25::i;:::-;6741:52;;6831:15;6811:16;:35;;6803:85;;;;-1:-1:-1;;;6803:85:1;;14503:2:13;6803:85:1;;;14485:21:13;14542:2;14522:18;;;14515:30;14581:34;14561:18;;;14554:62;-1:-1:-1;;;14632:18:13;;;14625:35;14677:19;;6803:85:1;14301:401:13;6803:85:1;6922:60;6931:5;6938:7;6966:15;6947:16;:34;6922:8;:60::i;3729:189::-;3808:4;719:10:4;3862:28:1;719:10:4;3879:2:1;3883:6;3862:9;:28::i;6718:386:8:-;6866:7;6885:13;6901:28;:20;:9;:18;:20::i;:::-;:26;;;:28::i;:::-;6885:44;;6939:16;6958:73;7016:14;:3;:12;:14::i;:::-;6958:53;6995:15;:4;:13;:15::i;:::-;6958:32;6969:20;:9;:18;:20::i;:::-;6958:10;;;;;;:32::i;:::-;:36;;;;:53::i;:73::-;6939:92;;7048:49;:40;7062:25;7070:5;7062:23;:25::i;:::-;7048:13;;;;;;:40::i;:::-;:47;;;:49::i;:::-;7041:56;;;;;;6718:386;;;;;;;:::o;2123:72::-;;;;;;;;;;;;;;;;;;;:::o;1337:61::-;1376:22;1103:2;1376:5;:22;:::i;3976:149:1:-;-1:-1:-1;;;;;4091:18:1;;;4065:7;4091:18;;;:11;:18;;;;;;;;:27;;;;;;;;;;;;;3976:149::o;1207:57:8:-;1263:1;1242:18;1103:2;1263:1;1242:18;:::i;:::-;:22;;;;:::i;10110:370:1:-;-1:-1:-1;;;;;10241:19:1;;10233:68;;;;-1:-1:-1;;;10233:68:1;;14909:2:13;10233:68:1;;;14891:21:13;14948:2;14928:18;;;14921:30;14987:34;14967:18;;;14960:62;-1:-1:-1;;;15038:18:13;;;15031:34;15082:19;;10233:68:1;14707:400:13;10233:68:1;-1:-1:-1;;;;;10319:21:1;;10311:68;;;;-1:-1:-1;;;10311:68:1;;15314:2:13;10311:68:1;;;15296:21:13;15353:2;15333:18;;;15326:30;15392:34;15372:18;;;15365:62;-1:-1:-1;;;15443:18:13;;;15436:32;15485:19;;10311:68:1;15112:398:13;10311:68:1;-1:-1:-1;;;;;10390:18:1;;;;;;;:11;:18;;;;;;;;:27;;;;;;;;;;;;;:36;;;10441:32;;160:25:13;;;10441:32:1;;133:18:13;10441:32:1;;;;;;;;10110:370;;;:::o;3956:527:8:-;4139:7;;4177:28;4195:10;4177:15;:28;:::i;:::-;4158:47;;4215:15;4233:18;4242:8;4233;:18::i;:::-;4215:36;;4261:17;4281:4;:8;4303:5;4290:10;;:18;;;;:::i;:::-;4281:31;;-1:-1:-1;;;;;;4281:31:8;;;;;;;;;;9021:25:13;;;;4310:1:8;9062:18:13;;;9055:34;8994:18;;4281:31:8;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;4261:51;-1:-1:-1;4322:11:8;4337:15;4345:7;4337:5;:15;:::i;:::-;4322:31;;4363:14;4380:47;4395:9;4406;4417:4;4423:3;4380:14;:47::i;:::-;4363:64;-1:-1:-1;4473:3:8;4455:13;4461:7;4473:3;4455:13;:::i;:::-;4445:24;;:6;:24;:::i;:::-;4444:32;;;;:::i;:::-;4437:39;3956:527;-1:-1:-1;;;;;;;;;;;3956:527:8:o;8402:389:1:-;-1:-1:-1;;;;;8485:21:1;;8477:65;;;;-1:-1:-1;;;8477:65:1;;16175:2:13;8477:65:1;;;16157:21:13;16214:2;16194:18;;;16187:30;16253:33;16233:18;;;16226:61;16304:18;;8477:65:1;15973:355:13;8477:65:1;8629:6;8613:12;;:22;;;;;;;:::i;:::-;;;;-1:-1:-1;;;;;;;8645:18:1;;:9;:18;;;;;;;;;;:28;;8667:6;;8645:9;:28;;8667:6;;8645:28;:::i;:::-;;;;-1:-1:-1;;8688:37:1;;160:25:13;;;-1:-1:-1;;;;;8688:37:1;;;8705:1;;8688:37;;148:2:13;133:18;8688:37:1;;;;;;;8402:389;;:::o;4570:108:8:-;719:10:4;4623:23:8;;;;:9;:23;;;;;4616:30;;-1:-1:-1;;;;;;4616:30:8;;;-1:-1:-1;4616:30:8;;;;;;;;;;;;;;;;;;;;;;;;;;;;4656:13;:15;;;;;;:::i;:::-;;;;;;4570:108::o;10761:441:1:-;10891:24;10918:25;10928:5;10935:7;10918:9;:25::i;:::-;10891:52;;-1:-1:-1;;10957:16:1;:37;10953:243;;11038:6;11018:16;:26;;11010:68;;;;-1:-1:-1;;;11010:68:1;;16535:2:13;11010:68:1;;;16517:21:13;16574:2;16554:18;;;16547:30;16613:31;16593:18;;;16586:59;16662:18;;11010:68:1;16333:353:13;11010:68:1;11120:51;11129:5;11136:7;11164:6;11145:16;:25;11120:8;:51::i;:::-;10881:321;10761:441;;;:::o;7475:651::-;-1:-1:-1;;;;;7601:18:1;;7593:68;;;;-1:-1:-1;;;7593:68:1;;16893:2:13;7593:68:1;;;16875:21:13;16932:2;16912:18;;;16905:30;16971:34;16951:18;;;16944:62;-1:-1:-1;;;17022:18:13;;;17015:35;17067:19;;7593:68:1;16691:401:13;7593:68:1;-1:-1:-1;;;;;7679:16:1;;7671:64;;;;-1:-1:-1;;;7671:64:1;;17299:2:13;7671:64:1;;;17281:21:13;17338:2;17318:18;;;17311:30;17377:34;17357:18;;;17350:62;-1:-1:-1;;;17428:18:13;;;17421:33;17471:19;;7671:64:1;17097:399:13;7671:64:1;-1:-1:-1;;;;;7817:15:1;;7795:19;7817:15;;;;;;;;;;;7850:21;;;;7842:72;;;;-1:-1:-1;;;7842:72:1;;17703:2:13;7842:72:1;;;17685:21:13;17742:2;17722:18;;;17715:30;17781:34;17761:18;;;17754:62;-1:-1:-1;;;17832:18:13;;;17825:36;17878:19;;7842:72:1;17501:402:13;7842:72:1;-1:-1:-1;;;;;7948:15:1;;;:9;:15;;;;;;;;;;;7966:20;;;7948:38;;8006:13;;;;;;;;:23;;7980:6;;7948:9;8006:23;;7980:6;;8006:23;:::i;:::-;;;;;;;;8060:2;-1:-1:-1;;;;;8045:26:1;8054:4;-1:-1:-1;;;;;8045:26:1;;8064:6;8045:26;;;;160:25:13;;148:2;133:18;;14:177;8045:26:1;;;;;;;;8082:37;9111:576;4740:360:8;4894:7;4935:10;4917:15;:28;4913:163;;;4961:12;1150:3;4977:10;4983:4;4977:3;:10;:::i;:::-;:22;;4990:9;4977:22;:::i;:::-;4976:39;;;;:::i;:::-;4961:54;-1:-1:-1;5054:11:8;5037:13;4961:54;5037:6;:13;:::i;:::-;5036:29;;;;:::i;:::-;5029:36;;;;;4913:163;-1:-1:-1;5092:1:8;4740:360;;;;;;:::o;3020:381::-;3071:7;1504:5;3094:10;;:37;3090:274;;;3147:13;3163:69;:60;3197:25;1445:2;3197:23;:25::i;:::-;3163:29;:21;:10;;:19;:21::i;:69::-;3147:85;;;-1:-1:-1;3246:14:8;3280:22;1103:2;3147:85;3280:22;:::i;:::-;1311:20;1103:2;1311:3;:20;:::i;:::-;3263:39;;;;:::i;:::-;3246:56;-1:-1:-1;3323:4:8;:8;3246:56;1376:22;1103:2;1376:5;:22;:::i;:::-;3323:30;;-1:-1:-1;;;;;;3323:30:8;;;;;;;;;;9021:25:13;;;;9062:18;;;9055:34;8994:18;;3323:30:8;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;3316:37;;;;3020:381;:::o;3090:274::-;1311:20;1103:2;1311:3;:20;:::i;6286:334::-;6383:172;;;;;;;;6413:4;6383:172;;;;1103:2;6461:4;:21;;;;:::i;:::-;6443:39;;:15;:39;:::i;:::-;6383:172;;;;6504:6;6383:172;;;;6529:15;:13;:15::i;:::-;6383:172;;719:10:4;6356:24:8;;;;:10;:24;;;;;;;;:199;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6565:12;:14;;;;;;:::i;:::-;;;;;;6607:6;6589:14;;:24;;;;;;;:::i;:::-;;;;-1:-1:-1;;;;6286:334:8:o;9111:576:1:-;-1:-1:-1;;;;;9194:21:1;;9186:67;;;;-1:-1:-1;;;9186:67:1;;18371:2:13;9186:67:1;;;18353:21:13;18410:2;18390:18;;;18383:30;18449:34;18429:18;;;18422:62;-1:-1:-1;;;18500:18:13;;;18493:31;18541:19;;9186:67:1;18169:397:13;9186:67:1;-1:-1:-1;;;;;9349:18:1;;9324:22;9349:18;;;;;;;;;;;9385:24;;;;9377:71;;;;-1:-1:-1;;;9377:71:1;;18773:2:13;9377:71:1;;;18755:21:13;18812:2;18792:18;;;18785:30;18851:34;18831:18;;;18824:62;-1:-1:-1;;;18902:18:13;;;18895:32;18944:19;;9377:71:1;18571:398:13;9377:71:1;-1:-1:-1;;;;;9482:18:1;;:9;:18;;;;;;;;;;9503:23;;;9482:44;;9546:12;:22;;9520:6;;9482:9;9546:22;;9520:6;;9546:22;:::i;:::-;;;;-1:-1:-1;;9584:37:1;;160:25:13;;;9610:1:1;;-1:-1:-1;;;;;9584:37:1;;;;;148:2:13;133:18;9584:37:1;14:177:13;5679:225:8;5730:7;5749:16;1762:7;5783:10;;1715:1;5769:24;;;;:::i;:::-;5768:42;;;;:::i;:::-;5749:61;;1668:3;5824:8;:23;5820:37;;;5856:1;5849:8;;;5679:225;:::o;5820:37::-;5874:23;5889:8;1668:3;5874:23;:::i;:::-;5867:30;;;5679:225;:::o;5960:273::-;6007:7;;6078:34;2069:2;1103;6078:34;:::i;:::-;6046:27;6064:9;6046:15;:27;:::i;:::-;6045:68;;;;:::i;:::-;6026:87;-1:-1:-1;6026:87:8;6127:27;2115:1;2017:2;6127:27;:::i;:::-;:38;6123:62;;;2115:1;6167:18;;;5960:273;:::o;6123:62::-;6202:24;6218:8;2017:2;6202:24;:::i;5162:380::-;5221:7;;1103:2;5269:27;5287:9;5269:15;:27;:::i;:::-;5268:46;;;;:::i;:::-;5240:74;;1564:5;5328:17;:42;5324:212;;;5393:4;:8;5402:42;5427:17;1564:5;5402:42;:::i;:::-;5393:74;;-1:-1:-1;;;;;;5393:74:8;;;;;;;;;;9021:25:13;;;;1622:1:8;9062:18:13;;;9055:34;8994:18;;5393:74:8;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;5324:212::-;1622:1;5498:27;;;5162:380;:::o;1958:169:6:-;2011:6;2057:18;2052:1;:23;;2043:33;;;;;;-1:-1:-1;2112:2:6;2107:7;;1958:169::o;14134:838::-;14183:6;14228:1;14224;:5;;;14215:15;;;;;;14239:10;14261:13;;;;14292:19;14286:25;;14282:56;;14322:2;14326:9;;;;14315;14282:56;14355:11;14349:2;:17;14345:48;;14377:2;14381:9;;;;14370;14345:48;14410:7;14404:2;:13;14400:44;;14428:2;14432:9;;;;14421;14400:44;14461:5;14455:2;:11;14451:40;;14477:1;14480:8;;;;14470;14451:40;14508:4;14502:2;:10;14498:39;;14523:1;14526:8;;;;14516;14498:39;14554:3;14548:2;:9;14544:38;;14568:1;14571:8;;;;14561;14544:38;14599:3;14593:2;:9;14589:23;;14611:1;14604:8;;;;14589:23;-1:-1:-1;;14669:8:6;;14681:2;14669:14;14713:10;;;;14737:3;:9;;;14704:43;14773:18;14755:176;14799:1;14793:3;:7;14755:176;;;14823:8;;;14859:3;14853:9;;;14906:16;;;14896:26;;;;;14879:3;:7;14872:14;;14810:1;14802:9;14755:176;;;-1:-1:-1;14954:6:6;;14134:838;-1:-1:-1;;;;;14134:838:6:o;4395:225::-;4452:6;4500:13;:9;;;:13;;;;;4517:2;4500:19;-1:-1:-1;;;;;;4536:19:6;;;;;:42;;-1:-1:-1;;;;;;4559:19:6;;;4536:42;4527:52;;;;;;4602:6;4395:225;-1:-1:-1;;;4395:225:6:o;7038:252::-;7095:6;7136:1;:6;;7141:1;7136:6;;7127:16;;;;;;7151:13;7188:1;7167:22;;7182:2;7176:1;7168:10;;:16;;7167:22;;;;;:::i;:::-;;;-1:-1:-1;;;;;;;7206:19:6;;;;;:42;;-1:-1:-1;;;;;;7229:19:6;;;7197:52;;;;;2365:150;2415:6;2461:1;2456;:6;;;;2447:16;;;;;;-1:-1:-1;2495:7:6;;2500:2;2495:7;;2365:150::o;3487:385:8:-;3545:7;;3627:25;1103:2;3627:8;:25;:::i;:::-;3608:44;-1:-1:-1;3677:26:8;3702:1;1824;3677:26;:::i;:::-;3666:8;:37;3662:65;;;-1:-1:-1;1873:2:8;;3487:385;-1:-1:-1;;3487:385:8:o;3662:65::-;3737:15;3813:1;1824;3771:12;:8;3782:1;3771:12;:::i;:::-;3764:1;3756:28;;3755:55;;;;:::i;:::-;:59;;;;:::i;:::-;3831:34;;-1:-1:-1;;;3831:34:8;;;;;9021:25:13;;;1873:2:8;9062:18:13;;;9055:34;3737:77:8;;-1:-1:-1;3831:4:8;;:8;;8994:18:13;;3831:34:8;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;196:597:13:-;308:4;337:2;366;355:9;348:21;398:6;392:13;441:6;436:2;425:9;421:18;414:34;466:1;476:140;490:6;487:1;484:13;476:140;;;585:14;;;581:23;;575:30;551:17;;;570:2;547:26;540:66;505:10;;476:140;;;634:6;631:1;628:13;625:91;;;704:1;699:2;690:6;679:9;675:22;671:31;664:42;625:91;-1:-1:-1;777:2:13;756:15;-1:-1:-1;;752:29:13;737:45;;;;784:2;733:54;;196:597;-1:-1:-1;;;196:597:13:o;798:173::-;866:20;;-1:-1:-1;;;;;915:31:13;;905:42;;895:70;;961:1;958;951:12;895:70;798:173;;;:::o;976:254::-;1044:6;1052;1105:2;1093:9;1084:7;1080:23;1076:32;1073:52;;;1121:1;1118;1111:12;1073:52;1144:29;1163:9;1144:29;:::i;:::-;1134:39;1220:2;1205:18;;;;1192:32;;-1:-1:-1;;;976:254:13:o;1860:328::-;1937:6;1945;1953;2006:2;1994:9;1985:7;1981:23;1977:32;1974:52;;;2022:1;2019;2012:12;1974:52;2045:29;2064:9;2045:29;:::i;:::-;2035:39;;2093:38;2127:2;2116:9;2112:18;2093:38;:::i;:::-;2083:48;;2178:2;2167:9;2163:18;2150:32;2140:42;;1860:328;;;;;:::o;2382:248::-;2450:6;2458;2511:2;2499:9;2490:7;2486:23;2482:32;2479:52;;;2527:1;2524;2517:12;2479:52;-1:-1:-1;;2550:23:13;;;2620:2;2605:18;;;2592:32;;-1:-1:-1;2382:248:13:o;3218:186::-;3277:6;3330:2;3318:9;3309:7;3305:23;3301:32;3298:52;;;3346:1;3343;3336:12;3298:52;3369:29;3388:9;3369:29;:::i;3805:180::-;3864:6;3917:2;3905:9;3896:7;3892:23;3888:32;3885:52;;;3933:1;3930;3923:12;3885:52;-1:-1:-1;3956:23:13;;3805:180;-1:-1:-1;3805:180:13:o;3990:385::-;4076:6;4084;4092;4100;4153:3;4141:9;4132:7;4128:23;4124:33;4121:53;;;4170:1;4167;4160:12;4121:53;-1:-1:-1;;4193:23:13;;;4263:2;4248:18;;4235:32;;-1:-1:-1;4314:2:13;4299:18;;4286:32;;4365:2;4350:18;4337:32;;-1:-1:-1;3990:385:13;-1:-1:-1;3990:385:13:o;4380:260::-;4448:6;4456;4509:2;4497:9;4488:7;4484:23;4480:32;4477:52;;;4525:1;4522;4515:12;4477:52;4548:29;4567:9;4548:29;:::i;:::-;4538:39;;4596:38;4630:2;4619:9;4615:18;4596:38;:::i;:::-;4586:48;;4380:260;;;;;:::o;5211:380::-;5290:1;5286:12;;;;5333;;;5354:61;;5408:4;5400:6;5396:17;5386:27;;5354:61;5461:2;5453:6;5450:14;5430:18;5427:38;5424:161;;;5507:10;5502:3;5498:20;5495:1;5488:31;5542:4;5539:1;5532:15;5570:4;5567:1;5560:15;5424:161;;5211:380;;;:::o;5596:127::-;5657:10;5652:3;5648:20;5645:1;5638:31;5688:4;5685:1;5678:15;5712:4;5709:1;5702:15;5728:168;5768:7;5834:1;5830;5826:6;5822:14;5819:1;5816:21;5811:1;5804:9;5797:17;5793:45;5790:71;;;5841:18;;:::i;:::-;-1:-1:-1;5881:9:13;;5728:168::o;7029:345::-;7231:2;7213:21;;;7270:2;7250:18;;;7243:30;-1:-1:-1;;;7304:2:13;7289:18;;7282:51;7365:2;7350:18;;7029:345::o;7379:356::-;7581:2;7563:21;;;7600:18;;;7593:30;7659:34;7654:2;7639:18;;7632:62;7726:2;7711:18;;7379:356::o;7740:127::-;7801:10;7796:3;7792:20;7789:1;7782:31;7832:4;7829:1;7822:15;7856:4;7853:1;7846:15;7872:217;7912:1;7938;7928:132;;7982:10;7977:3;7973:20;7970:1;7963:31;8017:4;8014:1;8007:15;8045:4;8042:1;8035:15;7928:132;-1:-1:-1;8074:9:13;;7872:217::o;8094:125::-;8134:4;8162:1;8159;8156:8;8153:34;;;8167:18;;:::i;:::-;-1:-1:-1;8204:9:13;;8094:125::o;8224:128::-;8264:3;8295:1;8291:6;8288:1;8285:13;8282:39;;;8301:18;;:::i;:::-;-1:-1:-1;8337:9:13;;8224:128::o;8706:136::-;8745:3;8773:5;8763:39;;8782:18;;:::i;:::-;-1:-1:-1;;;8818:18:13;;8706:136::o;11773:277::-;11840:6;11893:2;11881:9;11872:7;11868:23;11864:32;11861:52;;;11909:1;11906;11899:12;11861:52;11941:9;11935:16;11994:5;11987:13;11980:21;11973:5;11970:32;11960:60;;12016:1;12013;12006:12;14161:135;14200:3;-1:-1:-1;;14221:17:13;;14218:43;;;14241:18;;:::i;:::-;-1:-1:-1;14288:1:13;14277:13;;14161:135::o;15784:184::-;15854:6;15907:2;15895:9;15886:7;15882:23;15878:32;15875:52;;;15923:1;15920;15913:12;15875:52;-1:-1:-1;15946:16:13;;15784:184;-1:-1:-1;15784:184:13:o

Swarm Source

ipfs://e9aa281b097a35b40cd7836484ad9b58749efd8cd4c4c1ea4cddde499d78e96c
Loading...
Loading
Loading...
Loading
[ Download: CSV Export  ]
[ Download: CSV Export  ]

A token is a representation of an on-chain or off-chain asset. The token page shows information such as price, total supply, holders, transfers and social links. Learn more about this page in our Knowledge Base.