ETH Price: $3,269.66 (-4.13%)
Gas: 8 Gwei

Token

Crypto Monkey King (CMK)
 

Overview

Max Total Supply

3,382 CMK

Holders

392

Market

Volume (24H)

N/A

Min Price (24H)

N/A

Max Price (24H)

N/A
Filtered by Token Holder
zivka.eth
Balance
1 CMK
0x56f9f1efa72e1e4ba56e74574d45c5a43624960a
Loading...
Loading
Loading...
Loading
Loading...
Loading

Click here to update the token information / general information
# Exchange Pair Price  24H Volume % Volume

Contract Source Code Verified (Exact Match)

Contract Name:
CryptoMonkeyKing

Compiler Version
v0.8.4+commit.c7e474f2

Optimization Enabled:
No with 200 runs

Other Settings:
default evmVersion, GNU LGPLv3 license

Contract Source Code (Solidity Multiple files format)

File 3 of 15: crypto-monkey-king.sol
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.4;
pragma experimental ABIEncoderV2;

import "./erc721-metadata.sol";
import "./nf-token-enumerable.sol";
import "./ownable.sol";
import "./address-utils.sol";
import "./cmk-utils.sol";
import "./datetime-library.sol";

contract CryptoMonkeyKing is
    NFTokenEnumerable,
    Ownable,
    CmkUtils,
    ERC721Metadata
{
    using AddressUtils for address;

    /************************************struct********************************/
    struct NFT {
        uint256 id;
        bool isSelling;
        uint256 priceInWei;
        address owner;
    }

    struct MintedInfo {
        uint256 lastYear;
        uint256 lastMonth;
        uint256 lastDay;
        uint256 lastCount;
        uint256 minted;
    }

    /************************************error********************************/
    string constant NOT_VALID_NFT_ID = "004001";
    string constant NOT_RESERVE = "004002";
    string constant NOT_NORMAL = "004003";
    string constant IN_SELLING = "004004";
    string constant NO_SELLING = "004005";
    string constant NFT_HAS_NO_OWNER = "004006";
    string constant NFT_HAS_OWNER = "004007";
    string constant IS_NFT_OWNER = "004008";
    string constant NOT_NFT_OWNER = "004009";
    string constant NOT_AIRDROP_ACCOUNT = "004010";
    string constant NOT_ENOUGH_BALANCE = "004011";
    string constant OUT_OF_MAX_PAGE_SIZE = "004012";
    string constant OUT_OF_MINT_MAX_PER_TIME = "004013";
    string constant OUT_OF_MINT_MAX_PER_DAY = "004014";
    string constant SENDER_MINTED = "004015";

    /************************************variable********************************/
    string private baseURI;
    address private airdropAccount;
    uint256 private maxSupply;
    uint256 private maxPageSize;
    uint256 private maxMintPerTime;
    uint256 private mintMaxPerDay;
    uint256 private mintPrice;
    MintedInfo mintedInfo;
    mapping(address => bool) private addressToMinted;

    /************************************validator********************************/
    modifier onlyAirdrop() {
        require(msg.sender == airdropAccount, NOT_AIRDROP_ACCOUNT);
        _;
    }

    modifier validNFTId(uint256 _id) {
        require(_id >= 0 && _id <= maxSupply - 1, NOT_VALID_NFT_ID);
        _;
    }

    /************************************helps********************************/
    function isReserve(uint256 _id) internal pure returns (bool) {
        return _id >= 7000 && _id < 10000;
    }

    function isNormal(uint256 _id) internal pure returns (bool) {
        return _id >= 0 && _id < 7000;
    }

    /************************************business********************************/
    /***contructor***/
    constructor() {
        baseURI = "https://cryptomonkeyking.com/token";
        airdropAccount = 0x251d42b900973eD14D7Ea82Ce9310D34534f75EC;
        maxSupply = 10000;
        maxPageSize = 1000;
        maxMintPerTime = 5;
        mintMaxPerDay = 200;
    }

    /***ERC721Metadata***/
    function name() external pure override returns (string memory _name) {
        return "Crypto Monkey King";
    }

    function symbol() external pure override returns (string memory _symbol) {
        return "CMK";
    }

    function tokenURI(uint256 _id)
        external
        view
        override
        returns (string memory)
    {
        return strConcat(baseURI, "/", uint2str(_id));
    }

    /***onlyOwner***/
    function setBaseURI(string memory _baseURI) public onlyOwner {
        baseURI = _baseURI;
    }

    function getBaseURI() public view onlyOwner returns (string memory) {
        return baseURI;
    }

    function setAirdropAccount(address _airdropAccount) public onlyOwner {
        airdropAccount = _airdropAccount;
    }

    function getAirdropAccount() public view onlyOwner returns (address) {
        return airdropAccount;
    }

    function setMintPrice(uint256 _mintPrice) public onlyOwner {
        mintPrice = _mintPrice;
    }

    function getMintPrice() public view returns (uint256) {
        return mintPrice;
    }

    function setMaxMintPerTime(uint256 _maxMintPerTime) public onlyOwner {
        maxMintPerTime = _maxMintPerTime;
    }

    function getMaxMintPerTime() public view returns (uint256) {
        return maxMintPerTime;
    }

    function setMintMaxPerDay(uint256 _mintMaxPerDay) public onlyOwner {
        mintMaxPerDay = _mintMaxPerDay;
    }

    function getMintMaxPerDay() public view returns (uint256) {
        return mintMaxPerDay;
    }

    /***business***/
    function getMaxSupply() public view returns (uint256) {
        return maxSupply;
    }

    function getMaxPageSize() public view returns (uint256) {
        return maxPageSize;
    }

    function getMintableRemaining() public view returns (uint256) {
        return 7000 - mintedInfo.minted;
    }

    function getPagedNFTs(uint256 pageSize, uint256 pageIndex)
        public
        view
        returns (NFT[] memory)
    {
        require(pageSize <= maxPageSize, OUT_OF_MAX_PAGE_SIZE);

        uint256 start = pageSize * pageIndex;
        uint256 end = start + pageSize - 1;

        if (start > maxSupply - 1) {
            start = maxSupply - 1;
        }

        if (end > maxSupply - 1) {
            end = maxSupply - 1;
        }

        NFT[] memory NFTs = new NFT[](pageSize);
        for (uint256 i = start; i <= end; i++) {
            address owner = idToOwner[i];
            NFT memory nft = NFT(i, false, 0, owner);
            NFTs[i - start] = nft;
        }
        return NFTs;
    }

    function getMintedCountToday() public view returns(uint256){
        (uint256 year, uint256 month, uint256 day) = BokkyPooBahsDateTimeLibrary
            .timestampToDate(block.timestamp);
        uint count=0;
        if (
            mintedInfo.lastYear == year &&
            mintedInfo.lastMonth == month &&
            mintedInfo.lastDay == day
        ) {
            count = mintedInfo.lastCount;
        } else {
            count = 0;
        }
        return count;
    }

    function getMintableCountToday() public view returns (uint256) {
        (uint256 year, uint256 month, uint256 day) = BokkyPooBahsDateTimeLibrary
            .timestampToDate(block.timestamp);

        uint256 count = 0;
        uint256 remainToday = CmkUtils.getMin(7000 - mintedInfo.minted, mintMaxPerDay);
        if (
            mintedInfo.lastYear == year &&
            mintedInfo.lastMonth == month &&
            mintedInfo.lastDay == day
        ) {
            count = remainToday - mintedInfo.lastCount;
        } else {
            count = remainToday;
        }

        if (count < 0) {
            count = 0;
        }

        return count;
    }

    function isMinted(address _addr) public view returns (bool) {
        return addressToMinted[_addr];
    }

    function mintNFTs(uint256[] memory _ids) public payable {
        // 需要未领过
        require(!addressToMinted[msg.sender], SENDER_MINTED);
        // 不要超过当日可领上限
        require(
            _ids.length <= getMintableCountToday(),
            OUT_OF_MINT_MAX_PER_DAY
        );
        // 不要超过每次可领上限
        require(_ids.length <= maxMintPerTime, OUT_OF_MINT_MAX_PER_TIME);

        uint256 total = _ids.length * mintPrice;
        require(total <= msg.value, NOT_ENOUGH_BALANCE);

        for (uint256 i = 0; i < _ids.length; i++) {
            uint256 _id = _ids[i];
            require(isNormal(_id), NOT_NORMAL);
            require(idToOwner[_id] == address(0), NFT_HAS_OWNER);

            _mint(msg.sender, _id);
        }

        // 更新当日领取数
        (uint256 year, uint256 month, uint256 day) = BokkyPooBahsDateTimeLibrary
            .timestampToDate(block.timestamp);

        if (
            mintedInfo.lastYear == year &&
            mintedInfo.lastMonth == month &&
            mintedInfo.lastDay == day
        ) {
            mintedInfo.lastCount += _ids.length;
        } else {
            mintedInfo.lastCount = _ids.length;
        }

        // 更新最近领取时间
        mintedInfo.lastYear = year;
        mintedInfo.lastMonth = month;
        mintedInfo.lastDay = day;

        // 更新累计已领
        mintedInfo.minted += _ids.length;

        // 标记已领取
        addressToMinted[msg.sender] = true;

        // 收款
        if (mintPrice > 0) {
            payable(owner).transfer(msg.value);
        }
    }

    function airdropNFT(address _to, uint256 _id)
        public
        onlyAirdrop
        validNFTId(_id)
    {
        require(isReserve(_id), NOT_RESERVE);
        require(idToOwner[_id] == address(0), NFT_HAS_OWNER);

        _mint(_to, _id);
    }

    function airdropNFTs(address _to, uint256[] memory _ids) public {
        for (uint256 i = 0; i < _ids.length; i++) {
            uint256 id = _ids[i];
            airdropNFT(_to, id);
        }
    }

    function giveNFT(address _to, uint256 _id) public validNFTId(_id) {
        require(this.ownerOf(_id) == msg.sender, NOT_NFT_OWNER);

        _transfer(_to, _id);
    }

    function giveNFTs(address _to, uint256[] memory _ids) public {
        for (uint256 i = 0; i < _ids.length; i++) {
            uint256 id = _ids[i];
            giveNFT(_to, id);
        }
    }
}

File 1 of 15: address-utils.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

/**
 * @dev Utility library of inline functions on addresses.
 * @notice Based on:
 * https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/Address.sol
 * Requires EIP-1052.
 */
library AddressUtils
{

  /**
   * @dev Returns whether the target address is a contract.
   * @param _addr Address to check.
   * @return addressCheck True if _addr is a contract, false if not.
   */
  function isContract(
    address _addr
  )
    internal
    view
    returns (bool addressCheck)
  {
    // This method relies in extcodesize, which returns 0 for contracts in
    // construction, since the code is only stored at the end of the
    // constructor execution.

    // According to EIP-1052, 0x0 is the value returned for not-yet created accounts
    // and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned
    // for accounts without code, i.e. `keccak256('')`
    bytes32 codehash;
    bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;
    assembly { codehash := extcodehash(_addr) } // solhint-disable-line
    addressCheck = (codehash != 0x0 && codehash != accountHash);
  }

}

File 2 of 15: cmk-utils.sol
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.4;

contract CmkUtils {
    function getMin(uint256 a,uint256 b) internal pure returns(uint256){
        if(a>b) return b;
        else return a;
    }

    function uint2str(uint256 _i) internal pure returns (string memory str) {
        if (_i == 0) {
            return "0";
        }
        uint256 j = _i;
        uint256 length;
        while (j != 0) {
            length++;
            j /= 10;
        }
        bytes memory bstr = new bytes(length);
        uint256 k = length;
        j = _i;
        while (j != 0) {
            bstr[--k] = bytes1(uint8(48 + (j % 10)));
            j /= 10;
        }
        str = string(bstr);
    }

    function strConcat(string memory _a, string memory _b)
        internal
        pure
        returns (string memory _concatenatedString)
    {
        return strConcat(_a, _b, "", "", "");
    }

    function strConcat(
        string memory _a,
        string memory _b,
        string memory _c
    ) internal pure returns (string memory _concatenatedString) {
        return strConcat(_a, _b, _c, "", "");
    }

    function strConcat(
        string memory _a,
        string memory _b,
        string memory _c,
        string memory _d
    ) internal pure returns (string memory _concatenatedString) {
        return strConcat(_a, _b, _c, _d, "");
    }

    function strConcat(
        string memory _a,
        string memory _b,
        string memory _c,
        string memory _d,
        string memory _e
    ) internal pure returns (string memory _concatenatedString) {
        bytes memory _ba = bytes(_a);
        bytes memory _bb = bytes(_b);
        bytes memory _bc = bytes(_c);
        bytes memory _bd = bytes(_d);
        bytes memory _be = bytes(_e);
        string memory abcde = new string(
            _ba.length + _bb.length + _bc.length + _bd.length + _be.length
        );
        bytes memory babcde = bytes(abcde);
        uint256 k = 0;
        uint256 i = 0;
        for (i = 0; i < _ba.length; i++) {
            babcde[k++] = _ba[i];
        }
        for (i = 0; i < _bb.length; i++) {
            babcde[k++] = _bb[i];
        }
        for (i = 0; i < _bc.length; i++) {
            babcde[k++] = _bc[i];
        }
        for (i = 0; i < _bd.length; i++) {
            babcde[k++] = _bd[i];
        }
        for (i = 0; i < _be.length; i++) {
            babcde[k++] = _be[i];
        }
        return string(babcde);
    }
}

File 4 of 15: datetime-library.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

// ----------------------------------------------------------------------------
// BokkyPooBah's DateTime Library v1.01
//
// A gas-efficient Solidity date and time library
//
// https://github.com/bokkypoobah/BokkyPooBahsDateTimeLibrary
//
// Tested date range 1970/01/01 to 2345/12/31
//
// Conventions:
// Unit      | Range         | Notes
// :-------- |:-------------:|:-----
// timestamp | >= 0          | Unix timestamp, number of seconds since 1970/01/01 00:00:00 UTC
// year      | 1970 ... 2345 |
// month     | 1 ... 12      |
// day       | 1 ... 31      |
// hour      | 0 ... 23      |
// minute    | 0 ... 59      |
// second    | 0 ... 59      |
// dayOfWeek | 1 ... 7       | 1 = Monday, ..., 7 = Sunday
//
//
// Enjoy. (c) BokkyPooBah / Bok Consulting Pty Ltd 2018-2019. The MIT Licence.
// ----------------------------------------------------------------------------

library BokkyPooBahsDateTimeLibrary {

    uint constant SECONDS_PER_DAY = 24 * 60 * 60;
    uint constant SECONDS_PER_HOUR = 60 * 60;
    uint constant SECONDS_PER_MINUTE = 60;
    int constant OFFSET19700101 = 2440588;

    uint constant DOW_MON = 1;
    uint constant DOW_TUE = 2;
    uint constant DOW_WED = 3;
    uint constant DOW_THU = 4;
    uint constant DOW_FRI = 5;
    uint constant DOW_SAT = 6;
    uint constant DOW_SUN = 7;

    // ------------------------------------------------------------------------
    // Calculate the number of days from 1970/01/01 to year/month/day using
    // the date conversion algorithm from
    //   http://aa.usno.navy.mil/faq/docs/JD_Formula.php
    // and subtracting the offset 2440588 so that 1970/01/01 is day 0
    //
    // days = day
    //      - 32075
    //      + 1461 * (year + 4800 + (month - 14) / 12) / 4
    //      + 367 * (month - 2 - (month - 14) / 12 * 12) / 12
    //      - 3 * ((year + 4900 + (month - 14) / 12) / 100) / 4
    //      - offset
    // ------------------------------------------------------------------------
    function _daysFromDate(uint year, uint month, uint day) internal pure returns (uint _days) {
        require(year >= 1970);
        int _year = int(year);
        int _month = int(month);
        int _day = int(day);

        int __days = _day
          - 32075
          + 1461 * (_year + 4800 + (_month - 14) / 12) / 4
          + 367 * (_month - 2 - (_month - 14) / 12 * 12) / 12
          - 3 * ((_year + 4900 + (_month - 14) / 12) / 100) / 4
          - OFFSET19700101;

        _days = uint(__days);
    }

    // ------------------------------------------------------------------------
    // Calculate year/month/day from the number of days since 1970/01/01 using
    // the date conversion algorithm from
    //   http://aa.usno.navy.mil/faq/docs/JD_Formula.php
    // and adding the offset 2440588 so that 1970/01/01 is day 0
    //
    // int L = days + 68569 + offset
    // int N = 4 * L / 146097
    // L = L - (146097 * N + 3) / 4
    // year = 4000 * (L + 1) / 1461001
    // L = L - 1461 * year / 4 + 31
    // month = 80 * L / 2447
    // dd = L - 2447 * month / 80
    // L = month / 11
    // month = month + 2 - 12 * L
    // year = 100 * (N - 49) + year + L
    // ------------------------------------------------------------------------
    function _daysToDate(uint _days) internal pure returns (uint year, uint month, uint day) {
        int __days = int(_days);

        int L = __days + 68569 + OFFSET19700101;
        int N = 4 * L / 146097;
        L = L - (146097 * N + 3) / 4;
        int _year = 4000 * (L + 1) / 1461001;
        L = L - 1461 * _year / 4 + 31;
        int _month = 80 * L / 2447;
        int _day = L - 2447 * _month / 80;
        L = _month / 11;
        _month = _month + 2 - 12 * L;
        _year = 100 * (N - 49) + _year + L;

        year = uint(_year);
        month = uint(_month);
        day = uint(_day);
    }

    function timestampFromDate(uint year, uint month, uint day) internal pure returns (uint timestamp) {
        timestamp = _daysFromDate(year, month, day) * SECONDS_PER_DAY;
    }
    function timestampFromDateTime(uint year, uint month, uint day, uint hour, uint minute, uint second) internal pure returns (uint timestamp) {
        timestamp = _daysFromDate(year, month, day) * SECONDS_PER_DAY + hour * SECONDS_PER_HOUR + minute * SECONDS_PER_MINUTE + second;
    }
    function timestampToDate(uint timestamp) internal pure returns (uint year, uint month, uint day) {
        (year, month, day) = _daysToDate(timestamp / SECONDS_PER_DAY);
    }
    function timestampToDateTime(uint timestamp) internal pure returns (uint year, uint month, uint day, uint hour, uint minute, uint second) {
        (year, month, day) = _daysToDate(timestamp / SECONDS_PER_DAY);
        uint secs = timestamp % SECONDS_PER_DAY;
        hour = secs / SECONDS_PER_HOUR;
        secs = secs % SECONDS_PER_HOUR;
        minute = secs / SECONDS_PER_MINUTE;
        second = secs % SECONDS_PER_MINUTE;
    }

    function isValidDate(uint year, uint month, uint day) internal pure returns (bool valid) {
        if (year >= 1970 && month > 0 && month <= 12) {
            uint daysInMonth = _getDaysInMonth(year, month);
            if (day > 0 && day <= daysInMonth) {
                valid = true;
            }
        }
    }
    function isValidDateTime(uint year, uint month, uint day, uint hour, uint minute, uint second) internal pure returns (bool valid) {
        if (isValidDate(year, month, day)) {
            if (hour < 24 && minute < 60 && second < 60) {
                valid = true;
            }
        }
    }
    function isLeapYear(uint timestamp) internal pure returns (bool leapYear) {
        (uint year,,) = _daysToDate(timestamp / SECONDS_PER_DAY);
        leapYear = _isLeapYear(year);
    }
    function _isLeapYear(uint year) internal pure returns (bool leapYear) {
        leapYear = ((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0);
    }
    function isWeekDay(uint timestamp) internal pure returns (bool weekDay) {
        weekDay = getDayOfWeek(timestamp) <= DOW_FRI;
    }
    function isWeekEnd(uint timestamp) internal pure returns (bool weekEnd) {
        weekEnd = getDayOfWeek(timestamp) >= DOW_SAT;
    }
    function getDaysInMonth(uint timestamp) internal pure returns (uint daysInMonth) {
        (uint year, uint month,) = _daysToDate(timestamp / SECONDS_PER_DAY);
        daysInMonth = _getDaysInMonth(year, month);
    }
    function _getDaysInMonth(uint year, uint month) internal pure returns (uint daysInMonth) {
        if (month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12) {
            daysInMonth = 31;
        } else if (month != 2) {
            daysInMonth = 30;
        } else {
            daysInMonth = _isLeapYear(year) ? 29 : 28;
        }
    }
    // 1 = Monday, 7 = Sunday
    function getDayOfWeek(uint timestamp) internal pure returns (uint dayOfWeek) {
        uint _days = timestamp / SECONDS_PER_DAY;
        dayOfWeek = (_days + 3) % 7 + 1;
    }

    function getYear(uint timestamp) internal pure returns (uint year) {
        (year,,) = _daysToDate(timestamp / SECONDS_PER_DAY);
    }
    function getMonth(uint timestamp) internal pure returns (uint month) {
        (,month,) = _daysToDate(timestamp / SECONDS_PER_DAY);
    }
    function getDay(uint timestamp) internal pure returns (uint day) {
        (,,day) = _daysToDate(timestamp / SECONDS_PER_DAY);
    }
    function getHour(uint timestamp) internal pure returns (uint hour) {
        uint secs = timestamp % SECONDS_PER_DAY;
        hour = secs / SECONDS_PER_HOUR;
    }
    function getMinute(uint timestamp) internal pure returns (uint minute) {
        uint secs = timestamp % SECONDS_PER_HOUR;
        minute = secs / SECONDS_PER_MINUTE;
    }
    function getSecond(uint timestamp) internal pure returns (uint second) {
        second = timestamp % SECONDS_PER_MINUTE;
    }

    function addYears(uint timestamp, uint _years) internal pure returns (uint newTimestamp) {
        (uint year, uint month, uint day) = _daysToDate(timestamp / SECONDS_PER_DAY);
        year += _years;
        uint daysInMonth = _getDaysInMonth(year, month);
        if (day > daysInMonth) {
            day = daysInMonth;
        }
        newTimestamp = _daysFromDate(year, month, day) * SECONDS_PER_DAY + timestamp % SECONDS_PER_DAY;
        require(newTimestamp >= timestamp);
    }
    function addMonths(uint timestamp, uint _months) internal pure returns (uint newTimestamp) {
        (uint year, uint month, uint day) = _daysToDate(timestamp / SECONDS_PER_DAY);
        month += _months;
        year += (month - 1) / 12;
        month = (month - 1) % 12 + 1;
        uint daysInMonth = _getDaysInMonth(year, month);
        if (day > daysInMonth) {
            day = daysInMonth;
        }
        newTimestamp = _daysFromDate(year, month, day) * SECONDS_PER_DAY + timestamp % SECONDS_PER_DAY;
        require(newTimestamp >= timestamp);
    }
    function addDays(uint timestamp, uint _days) internal pure returns (uint newTimestamp) {
        newTimestamp = timestamp + _days * SECONDS_PER_DAY;
        require(newTimestamp >= timestamp);
    }
    function addHours(uint timestamp, uint _hours) internal pure returns (uint newTimestamp) {
        newTimestamp = timestamp + _hours * SECONDS_PER_HOUR;
        require(newTimestamp >= timestamp);
    }
    function addMinutes(uint timestamp, uint _minutes) internal pure returns (uint newTimestamp) {
        newTimestamp = timestamp + _minutes * SECONDS_PER_MINUTE;
        require(newTimestamp >= timestamp);
    }
    function addSeconds(uint timestamp, uint _seconds) internal pure returns (uint newTimestamp) {
        newTimestamp = timestamp + _seconds;
        require(newTimestamp >= timestamp);
    }

    function subYears(uint timestamp, uint _years) internal pure returns (uint newTimestamp) {
        (uint year, uint month, uint day) = _daysToDate(timestamp / SECONDS_PER_DAY);
        year -= _years;
        uint daysInMonth = _getDaysInMonth(year, month);
        if (day > daysInMonth) {
            day = daysInMonth;
        }
        newTimestamp = _daysFromDate(year, month, day) * SECONDS_PER_DAY + timestamp % SECONDS_PER_DAY;
        require(newTimestamp <= timestamp);
    }
    function subMonths(uint timestamp, uint _months) internal pure returns (uint newTimestamp) {
        (uint year, uint month, uint day) = _daysToDate(timestamp / SECONDS_PER_DAY);
        uint yearMonth = year * 12 + (month - 1) - _months;
        year = yearMonth / 12;
        month = yearMonth % 12 + 1;
        uint daysInMonth = _getDaysInMonth(year, month);
        if (day > daysInMonth) {
            day = daysInMonth;
        }
        newTimestamp = _daysFromDate(year, month, day) * SECONDS_PER_DAY + timestamp % SECONDS_PER_DAY;
        require(newTimestamp <= timestamp);
    }
    function subDays(uint timestamp, uint _days) internal pure returns (uint newTimestamp) {
        newTimestamp = timestamp - _days * SECONDS_PER_DAY;
        require(newTimestamp <= timestamp);
    }
    function subHours(uint timestamp, uint _hours) internal pure returns (uint newTimestamp) {
        newTimestamp = timestamp - _hours * SECONDS_PER_HOUR;
        require(newTimestamp <= timestamp);
    }
    function subMinutes(uint timestamp, uint _minutes) internal pure returns (uint newTimestamp) {
        newTimestamp = timestamp - _minutes * SECONDS_PER_MINUTE;
        require(newTimestamp <= timestamp);
    }
    function subSeconds(uint timestamp, uint _seconds) internal pure returns (uint newTimestamp) {
        newTimestamp = timestamp - _seconds;
        require(newTimestamp <= timestamp);
    }

    function diffYears(uint fromTimestamp, uint toTimestamp) internal pure returns (uint _years) {
        require(fromTimestamp <= toTimestamp);
        (uint fromYear,,) = _daysToDate(fromTimestamp / SECONDS_PER_DAY);
        (uint toYear,,) = _daysToDate(toTimestamp / SECONDS_PER_DAY);
        _years = toYear - fromYear;
    }
    function diffMonths(uint fromTimestamp, uint toTimestamp) internal pure returns (uint _months) {
        require(fromTimestamp <= toTimestamp);
        (uint fromYear, uint fromMonth,) = _daysToDate(fromTimestamp / SECONDS_PER_DAY);
        (uint toYear, uint toMonth,) = _daysToDate(toTimestamp / SECONDS_PER_DAY);
        _months = toYear * 12 + toMonth - fromYear * 12 - fromMonth;
    }
    function diffDays(uint fromTimestamp, uint toTimestamp) internal pure returns (uint _days) {
        require(fromTimestamp <= toTimestamp);
        _days = (toTimestamp - fromTimestamp) / SECONDS_PER_DAY;
    }
    function diffHours(uint fromTimestamp, uint toTimestamp) internal pure returns (uint _hours) {
        require(fromTimestamp <= toTimestamp);
        _hours = (toTimestamp - fromTimestamp) / SECONDS_PER_HOUR;
    }
    function diffMinutes(uint fromTimestamp, uint toTimestamp) internal pure returns (uint _minutes) {
        require(fromTimestamp <= toTimestamp);
        _minutes = (toTimestamp - fromTimestamp) / SECONDS_PER_MINUTE;
    }
    function diffSeconds(uint fromTimestamp, uint toTimestamp) internal pure returns (uint _seconds) {
        require(fromTimestamp <= toTimestamp);
        _seconds = toTimestamp - fromTimestamp;
    }
}

File 5 of 15: erc165.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

/**
 * @dev A standard for detecting smart contract interfaces. 
 * See: https://eips.ethereum.org/EIPS/eip-165.
 */
interface ERC165
{

  /**
   * @dev Checks if the smart contract includes a specific interface.
   * This function uses less than 30,000 gas.
   * @param _interfaceID The interface identifier, as specified in ERC-165.
   * @return True if _interfaceID is supported, false otherwise.
   */
  function supportsInterface(
    bytes4 _interfaceID
  )
    external
    view
    returns (bool);
    
}

File 6 of 15: erc721-enumerable.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

/**
 * @dev Optional enumeration extension for ERC-721 non-fungible token standard.
 * See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md.
 */
interface ERC721Enumerable
{

  /**
   * @dev Returns a count of valid NFTs tracked by this contract, where each one of them has an
   * assigned and queryable owner not equal to the zero address.
   * @return Total supply of NFTs.
   */
  function totalSupply()
    external
    view
    returns (uint256);

  /**
   * @dev Returns the token identifier for the `_index`th NFT. Sort order is not specified.
   * @param _index A counter less than `totalSupply()`.
   * @return Token id.
   */
  function tokenByIndex(
    uint256 _index
  )
    external
    view
    returns (uint256);

  /**
   * @dev Returns the token identifier for the `_index`th NFT assigned to `_owner`. Sort order is
   * not specified. It throws if `_index` >= `balanceOf(_owner)` or if `_owner` is the zero address,
   * representing invalid NFTs.
   * @param _owner An address where we are interested in NFTs owned by them.
   * @param _index A counter less than `balanceOf(_owner)`.
   * @return Token id.
   */
  function tokenOfOwnerByIndex(
    address _owner,
    uint256 _index
  )
    external
    view
    returns (uint256);

}

File 7 of 15: erc721-metadata.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

/**
 * @dev Optional metadata extension for ERC-721 non-fungible token standard.
 * See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md.
 */
interface ERC721Metadata
{

  /**
   * @dev Returns a descriptive name for a collection of NFTs in this contract.
   * @return _name Representing name.
   */
  function name()
    external
    view
    returns (string memory _name);

  /**
   * @dev Returns a abbreviated name for a collection of NFTs in this contract.
   * @return _symbol Representing symbol.
   */
  function symbol()
    external
    view
    returns (string memory _symbol);

  /**
   * @dev Returns a distinct Uniform Resource Identifier (URI) for a given asset. It Throws if
   * `_tokenId` is not a valid NFT. URIs are defined in RFC3986. The URI may point to a JSON file
   * that conforms to the "ERC721 Metadata JSON Schema".
   * @return URI of _tokenId.
   */
  function tokenURI(uint256 _tokenId)
    external
    view
    returns (string memory);

}

File 8 of 15: erc721-token-receiver.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

/**
 * @dev ERC-721 interface for accepting safe transfers.
 * See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md.
 */
interface ERC721TokenReceiver
{

  /**
   * @dev Handle the receipt of a NFT. The ERC721 smart contract calls this function on the
   * recipient after a `transfer`. This function MAY throw to revert and reject the transfer. Return
   * of other than the magic value MUST result in the transaction being reverted.
   * Returns `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))` unless throwing.
   * @notice The contract address is always the message sender. A wallet/broker/auction application
   * MUST implement the wallet interface if it will accept safe transfers.
   * @param _operator The address which called `safeTransferFrom` function.
   * @param _from The address which previously owned the token.
   * @param _tokenId The NFT identifier which is being transferred.
   * @param _data Additional data with no specified format.
   * @return Returns `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`.
   */
  function onERC721Received(
    address _operator,
    address _from,
    uint256 _tokenId,
    bytes calldata _data
  )
    external
    returns(bytes4);

}

File 9 of 15: erc721.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

/**
 * @dev ERC-721 non-fungible token standard.
 * See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md.
 */
interface ERC721
{

  /**
   * @dev Emits when ownership of any NFT changes by any mechanism. This event emits when NFTs are
   * created (`from` == 0) and destroyed (`to` == 0). Exception: during contract creation, any
   * number of NFTs may be created and assigned without emitting Transfer. At the time of any
   * transfer, the approved address for that NFT (if any) is reset to none.
   */
  event Transfer(
    address indexed _from,
    address indexed _to,
    uint256 indexed _tokenId
  );

  /**
   * @dev This emits when the approved address for an NFT is changed or reaffirmed. The zero
   * address indicates there is no approved address. When a Transfer event emits, this also
   * indicates that the approved address for that NFT (if any) is reset to none.
   */
  event Approval(
    address indexed _owner,
    address indexed _approved,
    uint256 indexed _tokenId
  );

  /**
   * @dev This emits when an operator is enabled or disabled for an owner. The operator can manage
   * all NFTs of the owner.
   */
  event ApprovalForAll(
    address indexed _owner,
    address indexed _operator,
    bool _approved
  );

  /**
   * @dev Transfers the ownership of an NFT from one address to another address.
   * @notice Throws unless `msg.sender` is the current owner, an authorized operator, or the
   * approved address for this NFT. Throws if `_from` is not the current owner. Throws if `_to` is
   * the zero address. Throws if `_tokenId` is not a valid NFT. When transfer is complete, this
   * function checks if `_to` is a smart contract (code size > 0). If so, it calls
   * `onERC721Received` on `_to` and throws if the return value is not
   * `bytes4(keccak256("onERC721Received(address,uint256,bytes)"))`.
   * @param _from The current owner of the NFT.
   * @param _to The new owner.
   * @param _tokenId The NFT to transfer.
   * @param _data Additional data with no specified format, sent in call to `_to`.
   */
  function safeTransferFrom(
    address _from,
    address _to,
    uint256 _tokenId,
    bytes calldata _data
  )
    external;

  /**
   * @dev Transfers the ownership of an NFT from one address to another address.
   * @notice This works identically to the other function with an extra data parameter, except this
   * function just sets data to ""
   * @param _from The current owner of the NFT.
   * @param _to The new owner.
   * @param _tokenId The NFT to transfer.
   */
  function safeTransferFrom(
    address _from,
    address _to,
    uint256 _tokenId
  )
    external;

  /**
   * @dev Throws unless `msg.sender` is the current owner, an authorized operator, or the approved
   * address for this NFT. Throws if `_from` is not the current owner. Throws if `_to` is the zero
   * address. Throws if `_tokenId` is not a valid NFT.
   * @notice The caller is responsible to confirm that `_to` is capable of receiving NFTs or else
   * they may be permanently lost.
   * @param _from The current owner of the NFT.
   * @param _to The new owner.
   * @param _tokenId The NFT to transfer.
   */
  function transferFrom(
    address _from,
    address _to,
    uint256 _tokenId
  )
    external;

  /**
   * @dev Set or reaffirm the approved address for an NFT.
   * @notice The zero address indicates there is no approved address. Throws unless `msg.sender` is
   * the current NFT owner, or an authorized operator of the current owner.
   * @param _approved The new approved NFT controller.
   * @param _tokenId The NFT to approve.
   */
  function approve(
    address _approved,
    uint256 _tokenId
  )
    external;

  /**
   * @dev Enables or disables approval for a third party ("operator") to manage all of
   * `msg.sender`'s assets. It also emits the ApprovalForAll event.
   * @notice The contract MUST allow multiple operators per owner.
   * @param _operator Address to add to the set of authorized operators.
   * @param _approved True if the operators is approved, false to revoke approval.
   */
  function setApprovalForAll(
    address _operator,
    bool _approved
  )
    external;

  /**
   * @dev Returns the number of NFTs owned by `_owner`. NFTs assigned to the zero address are
   * considered invalid, and this function throws for queries about the zero address.
   * @param _owner Address for whom to query the balance.
   * @return Balance of _owner.
   */
  function balanceOf(
    address _owner
  )
    external
    view
    returns (uint256);

  /**
   * @dev Returns the address of the owner of the NFT. NFTs assigned to the zero address are
   * considered invalid, and queries about them do throw.
   * @param _tokenId The identifier for an NFT.
   * @return Address of _tokenId owner.
   */
  function ownerOf(
    uint256 _tokenId
  )
    external
    view
    returns (address);

  /**
   * @dev Get the approved address for a single NFT.
   * @notice Throws if `_tokenId` is not a valid NFT.
   * @param _tokenId The NFT to find the approved address for.
   * @return Address that _tokenId is approved for.
   */
  function getApproved(
    uint256 _tokenId
  )
    external
    view
    returns (address);

  /**
   * @dev Returns true if `_operator` is an approved operator for `_owner`, false otherwise.
   * @param _owner The address that owns the NFTs.
   * @param _operator The address that acts on behalf of the owner.
   * @return True if approved for all, false otherwise.
   */
  function isApprovedForAll(
    address _owner,
    address _operator
  )
    external
    view
    returns (bool);

}

File 10 of 15: Migrations.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.4.22 <0.9.0;

contract Migrations {
  address public owner = msg.sender;
  uint public last_completed_migration;

  modifier restricted() {
    require(
      msg.sender == owner,
      "This function is restricted to the contract's owner"
    );
    _;
  }

  function setCompleted(uint completed) public restricted {
    last_completed_migration = completed;
  }
}

File 11 of 15: nf-token-enumerable.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

import "./nf-token.sol";
import "./erc721-enumerable.sol";

/**
 * @dev Optional enumeration implementation for ERC-721 non-fungible token standard.
 */
contract NFTokenEnumerable is
  NFToken,
  ERC721Enumerable
{

  /**
   * @dev List of revert message codes. Implementing dApp should handle showing the correct message.
   * Based on 0xcert framework error codes.
   */
  string constant INVALID_INDEX = "005007";

  /**
   * @dev Array of all NFT IDs.
   */
  uint256[] internal tokens;

  /**
   * @dev Mapping from token ID to its index in global tokens array.
   */
  mapping(uint256 => uint256) internal idToIndex;

  /**
   * @dev Mapping from owner to list of owned NFT IDs.
   */
  mapping(address => uint256[]) internal ownerToIds;

  /**
   * @dev Mapping from NFT ID to its index in the owner tokens list.
   */
  mapping(uint256 => uint256) internal idToOwnerIndex;

  /**
   * @dev Contract constructor.
   */
  constructor()
  {
    supportedInterfaces[0x780e9d63] = true; // ERC721Enumerable
  }

  /**
   * @dev Returns the count of all existing NFTokens.
   * @return Total supply of NFTs.
   */
  function totalSupply()
    external
    override
    view
    returns (uint256)
  {
    return tokens.length;
  }

  /**
   * @dev Returns NFT ID by its index.
   * @param _index A counter less than `totalSupply()`.
   * @return Token id.
   */
  function tokenByIndex(
    uint256 _index
  )
    external
    override
    view
    returns (uint256)
  {
    require(_index < tokens.length, INVALID_INDEX);
    return tokens[_index];
  }

  /**
   * @dev returns the n-th NFT ID from a list of owner's tokens.
   * @param _owner Token owner's address.
   * @param _index Index number representing n-th token in owner's list of tokens.
   * @return Token id.
   */
  function tokenOfOwnerByIndex(
    address _owner,
    uint256 _index
  )
    external
    override
    view
    returns (uint256)
  {
    require(_index < ownerToIds[_owner].length, INVALID_INDEX);
    return ownerToIds[_owner][_index];
  }

  /**
   * @dev Mints a new NFT.
   * @notice This is an internal function which should be called from user-implemented external
   * mint function. Its purpose is to show and properly initialize data structures when using this
   * implementation.
   * @param _to The address that will own the minted NFT.
   * @param _tokenId of the NFT to be minted by the msg.sender.
   */
  function _mint(
    address _to,
    uint256 _tokenId
  )
    internal
    override
    virtual
  {
    super._mint(_to, _tokenId);
    tokens.push(_tokenId);
    idToIndex[_tokenId] = tokens.length - 1;
  }

  /**
   * @dev Burns a NFT.
   * @notice This is an internal function which should be called from user-implemented external
   * burn function. Its purpose is to show and properly initialize data structures when using this
   * implementation. Also, note that this burn implementation allows the minter to re-mint a burned
   * NFT.
   * @param _tokenId ID of the NFT to be burned.
   */
  function _burn(
    uint256 _tokenId
  )
    internal
    override
    virtual
  {
    super._burn(_tokenId);

    uint256 tokenIndex = idToIndex[_tokenId];
    uint256 lastTokenIndex = tokens.length - 1;
    uint256 lastToken = tokens[lastTokenIndex];

    tokens[tokenIndex] = lastToken;

    tokens.pop();
    // This wastes gas if you are burning the last token but saves a little gas if you are not.
    idToIndex[lastToken] = tokenIndex;
    idToIndex[_tokenId] = 0;
  }

  /**
   * @dev Removes a NFT from an address.
   * @notice Use and override this function with caution. Wrong usage can have serious consequences.
   * @param _from Address from wich we want to remove the NFT.
   * @param _tokenId Which NFT we want to remove.
   */
  function _removeNFToken(
    address _from,
    uint256 _tokenId
  )
    internal
    override
    virtual
  {
    require(idToOwner[_tokenId] == _from, NOT_OWNER);
    delete idToOwner[_tokenId];

    uint256 tokenToRemoveIndex = idToOwnerIndex[_tokenId];
    uint256 lastTokenIndex = ownerToIds[_from].length - 1;

    if (lastTokenIndex != tokenToRemoveIndex)
    {
      uint256 lastToken = ownerToIds[_from][lastTokenIndex];
      ownerToIds[_from][tokenToRemoveIndex] = lastToken;
      idToOwnerIndex[lastToken] = tokenToRemoveIndex;
    }

    ownerToIds[_from].pop();
  }

  /**
   * @dev Assigns a new NFT to an address.
   * @notice Use and override this function with caution. Wrong usage can have serious consequences.
   * @param _to Address to wich we want to add the NFT.
   * @param _tokenId Which NFT we want to add.
   */
  function _addNFToken(
    address _to,
    uint256 _tokenId
  )
    internal
    override
    virtual
  {
    require(idToOwner[_tokenId] == address(0), NFT_ALREADY_EXISTS);
    idToOwner[_tokenId] = _to;

    ownerToIds[_to].push(_tokenId);
    idToOwnerIndex[_tokenId] = ownerToIds[_to].length - 1;
  }

  /**
   * @dev Helper function that gets NFT count of owner. This is needed for overriding in enumerable
   * extension to remove double storage(gas optimization) of owner NFT count.
   * @param _owner Address for whom to query the count.
   * @return Number of _owner NFTs.
   */
  function _getOwnerNFTCount(
    address _owner
  )
    internal
    override
    virtual
    view
    returns (uint256)
  {
    return ownerToIds[_owner].length;
  }
}

File 12 of 15: nf-token-metadata.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

import "./nf-token.sol";
import "./erc721-metadata.sol";

/**
 * @dev Optional metadata implementation for ERC-721 non-fungible token standard.
 */
contract NFTokenMetadata is
  NFToken,
  ERC721Metadata
{

  /**
   * @dev A descriptive name for a collection of NFTs.
   */
  string internal nftName;

  /**
   * @dev An abbreviated name for NFTokens.
   */
  string internal nftSymbol;

  /**
   * @dev Mapping from NFT ID to metadata uri.
   */
  mapping (uint256 => string) internal idToUri;

  /**
   * @dev Contract constructor.
   * @notice When implementing this contract don't forget to set nftName and nftSymbol.
   */
  constructor()
  {
    supportedInterfaces[0x5b5e139f] = true; // ERC721Metadata
  }

  /**
   * @dev Returns a descriptive name for a collection of NFTokens.
   * @return _name Representing name.
   */
  function name()
    external
    override
    view
    returns (string memory _name)
  {
    _name = nftName;
  }

  /**
   * @dev Returns an abbreviated name for NFTokens.
   * @return _symbol Representing symbol.
   */
  function symbol()
    external
    override
    view
    returns (string memory _symbol)
  {
    _symbol = nftSymbol;
  }

  /**
   * @dev A distinct URI (RFC 3986) for a given NFT.
   * @param _tokenId Id for which we want uri.
   * @return URI of _tokenId.
   */
  function tokenURI(
    uint256 _tokenId
  )
    external
    override
    view
    validNFToken(_tokenId)
    returns (string memory)
  {
    return idToUri[_tokenId];
  }

  /**
   * @dev Burns a NFT.
   * @notice This is an internal function which should be called from user-implemented external
   * burn function. Its purpose is to show and properly initialize data structures when using this
   * implementation. Also, note that this burn implementation allows the minter to re-mint a burned
   * NFT.
   * @param _tokenId ID of the NFT to be burned.
   */
  function _burn(
    uint256 _tokenId
  )
    internal
    override
    virtual
  {
    super._burn(_tokenId);

    if (bytes(idToUri[_tokenId]).length != 0)
    {
      delete idToUri[_tokenId];
    }
  }

  /**
   * @dev Set a distinct URI (RFC 3986) for a given NFT ID.
   * @notice This is an internal function which should be called from user-implemented external
   * function. Its purpose is to show and properly initialize data structures when using this
   * implementation.
   * @param _tokenId Id for which we want URI.
   * @param _uri String representing RFC 3986 URI.
   */
  function _setTokenUri(
    uint256 _tokenId,
    string memory _uri
  )
    internal
    validNFToken(_tokenId)
  {
    idToUri[_tokenId] = _uri;
  }

}

File 13 of 15: nf-token.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

import "./erc721.sol";
import "./erc721-token-receiver.sol";
import "./supports-interface.sol";
import "./address-utils.sol";

/**
 * @dev Implementation of ERC-721 non-fungible token standard.
 */
contract NFToken is
  ERC721,
  SupportsInterface
{
  using AddressUtils for address;

  /**
   * @dev List of revert message codes. Implementing dApp should handle showing the correct message.
   * Based on 0xcert framework error codes.
   */
  string constant ZERO_ADDRESS = "003001";
  string constant NOT_VALID_NFT = "003002";
  string constant NOT_OWNER_OR_OPERATOR = "003003";
  string constant NOT_OWNER_APPROVED_OR_OPERATOR = "003004";
  string constant NOT_ABLE_TO_RECEIVE_NFT = "003005";
  string constant NFT_ALREADY_EXISTS = "003006";
  string constant NOT_OWNER = "003007";
  string constant IS_OWNER = "003008";

  /**
   * @dev Magic value of a smart contract that can receive NFT.
   * Equal to: bytes4(keccak256("onERC721Received(address,address,uint256,bytes)")).
   */
  bytes4 internal constant MAGIC_ON_ERC721_RECEIVED = 0x150b7a02;

  /**
   * @dev A mapping from NFT ID to the address that owns it.
   */
  mapping (uint256 => address) internal idToOwner;

  /**
   * @dev Mapping from NFT ID to approved address.
   */
  mapping (uint256 => address) internal idToApproval;

   /**
   * @dev Mapping from owner address to count of his tokens.
   */
  mapping (address => uint256) private ownerToNFTokenCount;

  /**
   * @dev Mapping from owner address to mapping of operator addresses.
   */
  mapping (address => mapping (address => bool)) internal ownerToOperators;

  /**
   * @dev Guarantees that the msg.sender is an owner or operator of the given NFT.
   * @param _tokenId ID of the NFT to validate.
   */
  modifier canOperate(
    uint256 _tokenId
  )
  {
    address tokenOwner = idToOwner[_tokenId];
    require(
      tokenOwner == msg.sender || ownerToOperators[tokenOwner][msg.sender],
      NOT_OWNER_OR_OPERATOR
    );
    _;
  }

  /**
   * @dev Guarantees that the msg.sender is allowed to transfer NFT.
   * @param _tokenId ID of the NFT to transfer.
   */
  modifier canTransfer(
    uint256 _tokenId
  )
  {
    address tokenOwner = idToOwner[_tokenId];
    require(
      tokenOwner == msg.sender
      || idToApproval[_tokenId] == msg.sender
      || ownerToOperators[tokenOwner][msg.sender],
      NOT_OWNER_APPROVED_OR_OPERATOR
    );
    _;
  }

  /**
   * @dev Guarantees that _tokenId is a valid Token.
   * @param _tokenId ID of the NFT to validate.
   */
  modifier validNFToken(
    uint256 _tokenId
  )
  {
    require(idToOwner[_tokenId] != address(0), NOT_VALID_NFT);
    _;
  }

  /**
   * @dev Contract constructor.
   */
  constructor()
  {
    supportedInterfaces[0x80ac58cd] = true; // ERC721
  }

  /**
   * @dev Transfers the ownership of an NFT from one address to another address. This function can
   * be changed to payable.
   * @notice Throws unless `msg.sender` is the current owner, an authorized operator, or the
   * approved address for this NFT. Throws if `_from` is not the current owner. Throws if `_to` is
   * the zero address. Throws if `_tokenId` is not a valid NFT. When transfer is complete, this
   * function checks if `_to` is a smart contract (code size > 0). If so, it calls
   * `onERC721Received` on `_to` and throws if the return value is not
   * `bytes4(keccak256("onERC721Received(address,uint256,bytes)"))`.
   * @param _from The current owner of the NFT.
   * @param _to The new owner.
   * @param _tokenId The NFT to transfer.
   * @param _data Additional data with no specified format, sent in call to `_to`.
   */
  function safeTransferFrom(
    address _from,
    address _to,
    uint256 _tokenId,
    bytes calldata _data
  )
    external
    override
  {
    _safeTransferFrom(_from, _to, _tokenId, _data);
  }

  /**
   * @dev Transfers the ownership of an NFT from one address to another address. This function can
   * be changed to payable.
   * @notice This works identically to the other function with an extra data parameter, except this
   * function just sets data to ""
   * @param _from The current owner of the NFT.
   * @param _to The new owner.
   * @param _tokenId The NFT to transfer.
   */
  function safeTransferFrom(
    address _from,
    address _to,
    uint256 _tokenId
  )
    external
    override
  {
    _safeTransferFrom(_from, _to, _tokenId, "");
  }

  /**
   * @dev Throws unless `msg.sender` is the current owner, an authorized operator, or the approved
   * address for this NFT. Throws if `_from` is not the current owner. Throws if `_to` is the zero
   * address. Throws if `_tokenId` is not a valid NFT. This function can be changed to payable.
   * @notice The caller is responsible to confirm that `_to` is capable of receiving NFTs or else
   * they may be permanently lost.
   * @param _from The current owner of the NFT.
   * @param _to The new owner.
   * @param _tokenId The NFT to transfer.
   */
  function transferFrom(
    address _from,
    address _to,
    uint256 _tokenId
  )
    external
    override
    canTransfer(_tokenId)
    validNFToken(_tokenId)
  {
    address tokenOwner = idToOwner[_tokenId];
    require(tokenOwner == _from, NOT_OWNER);
    require(_to != address(0), ZERO_ADDRESS);

    _transfer(_to, _tokenId);
  }

  /**
   * @dev Set or reaffirm the approved address for an NFT. This function can be changed to payable.
   * @notice The zero address indicates there is no approved address. Throws unless `msg.sender` is
   * the current NFT owner, or an authorized operator of the current owner.
   * @param _approved Address to be approved for the given NFT ID.
   * @param _tokenId ID of the token to be approved.
   */
  function approve(
    address _approved,
    uint256 _tokenId
  )
    external
    override
    canOperate(_tokenId)
    validNFToken(_tokenId)
  {
    address tokenOwner = idToOwner[_tokenId];
    require(_approved != tokenOwner, IS_OWNER);

    idToApproval[_tokenId] = _approved;
    emit Approval(tokenOwner, _approved, _tokenId);
  }

  /**
   * @dev Enables or disables approval for a third party ("operator") to manage all of
   * `msg.sender`'s assets. It also emits the ApprovalForAll event.
   * @notice This works even if sender doesn't own any tokens at the time.
   * @param _operator Address to add to the set of authorized operators.
   * @param _approved True if the operators is approved, false to revoke approval.
   */
  function setApprovalForAll(
    address _operator,
    bool _approved
  )
    external
    override
  {
    ownerToOperators[msg.sender][_operator] = _approved;
    emit ApprovalForAll(msg.sender, _operator, _approved);
  }

  /**
   * @dev Returns the number of NFTs owned by `_owner`. NFTs assigned to the zero address are
   * considered invalid, and this function throws for queries about the zero address.
   * @param _owner Address for whom to query the balance.
   * @return Balance of _owner.
   */
  function balanceOf(
    address _owner
  )
    external
    override
    view
    returns (uint256)
  {
    require(_owner != address(0), ZERO_ADDRESS);
    return _getOwnerNFTCount(_owner);
  }

  /**
   * @dev Returns the address of the owner of the NFT. NFTs assigned to the zero address are
   * considered invalid, and queries about them do throw.
   * @param _tokenId The identifier for an NFT.
   * @return _owner Address of _tokenId owner.
   */
  function ownerOf(
    uint256 _tokenId
  )
    external
    override
    view
    returns (address _owner)
  {
    _owner = idToOwner[_tokenId];
    require(_owner != address(0), NOT_VALID_NFT);
  }

  /**
   * @dev Get the approved address for a single NFT.
   * @notice Throws if `_tokenId` is not a valid NFT.
   * @param _tokenId ID of the NFT to query the approval of.
   * @return Address that _tokenId is approved for.
   */
  function getApproved(
    uint256 _tokenId
  )
    external
    override
    view
    validNFToken(_tokenId)
    returns (address)
  {
    return idToApproval[_tokenId];
  }

  /**
   * @dev Checks if `_operator` is an approved operator for `_owner`.
   * @param _owner The address that owns the NFTs.
   * @param _operator The address that acts on behalf of the owner.
   * @return True if approved for all, false otherwise.
   */
  function isApprovedForAll(
    address _owner,
    address _operator
  )
    external
    override
    view
    returns (bool)
  {
    return ownerToOperators[_owner][_operator];
  }

  /**
   * @dev Actually performs the transfer.
   * @notice Does NO checks.
   * @param _to Address of a new owner.
   * @param _tokenId The NFT that is being transferred.
   */
  function _transfer(
    address _to,
    uint256 _tokenId
  )
    internal
  {
    address from = idToOwner[_tokenId];
    _clearApproval(_tokenId);

    _removeNFToken(from, _tokenId);
    _addNFToken(_to, _tokenId);

    emit Transfer(from, _to, _tokenId);
  }

  /**
   * @dev Mints a new NFT.
   * @notice This is an internal function which should be called from user-implemented external
   * mint function. Its purpose is to show and properly initialize data structures when using this
   * implementation.
   * @param _to The address that will own the minted NFT.
   * @param _tokenId of the NFT to be minted by the msg.sender.
   */
  function _mint(
    address _to,
    uint256 _tokenId
  )
    internal
    virtual
  {
    require(_to != address(0), ZERO_ADDRESS);
    require(idToOwner[_tokenId] == address(0), NFT_ALREADY_EXISTS);

    _addNFToken(_to, _tokenId);

    emit Transfer(address(0), _to, _tokenId);
  }

  /**
   * @dev Burns a NFT.
   * @notice This is an internal function which should be called from user-implemented external burn
   * function. Its purpose is to show and properly initialize data structures when using this
   * implementation. Also, note that this burn implementation allows the minter to re-mint a burned
   * NFT.
   * @param _tokenId ID of the NFT to be burned.
   */
  function _burn(
    uint256 _tokenId
  )
    internal
    virtual
    validNFToken(_tokenId)
  {
    address tokenOwner = idToOwner[_tokenId];
    _clearApproval(_tokenId);
    _removeNFToken(tokenOwner, _tokenId);
    emit Transfer(tokenOwner, address(0), _tokenId);
  }

  /**
   * @dev Removes a NFT from owner.
   * @notice Use and override this function with caution. Wrong usage can have serious consequences.
   * @param _from Address from which we want to remove the NFT.
   * @param _tokenId Which NFT we want to remove.
   */
  function _removeNFToken(
    address _from,
    uint256 _tokenId
  )
    internal
    virtual
  {
    require(idToOwner[_tokenId] == _from, NOT_OWNER);
    ownerToNFTokenCount[_from] = ownerToNFTokenCount[_from] - 1;
    delete idToOwner[_tokenId];
  }

  /**
   * @dev Assigns a new NFT to owner.
   * @notice Use and override this function with caution. Wrong usage can have serious consequences.
   * @param _to Address to which we want to add the NFT.
   * @param _tokenId Which NFT we want to add.
   */
  function _addNFToken(
    address _to,
    uint256 _tokenId
  )
    internal
    virtual
  {
    require(idToOwner[_tokenId] == address(0), NFT_ALREADY_EXISTS);

    idToOwner[_tokenId] = _to;
    ownerToNFTokenCount[_to] = ownerToNFTokenCount[_to] + 1;
  }

  /**
   * @dev Helper function that gets NFT count of owner. This is needed for overriding in enumerable
   * extension to remove double storage (gas optimization) of owner NFT count.
   * @param _owner Address for whom to query the count.
   * @return Number of _owner NFTs.
   */
  function _getOwnerNFTCount(
    address _owner
  )
    internal
    virtual
    view
    returns (uint256)
  {
    return ownerToNFTokenCount[_owner];
  }

  /**
   * @dev Actually perform the safeTransferFrom.
   * @param _from The current owner of the NFT.
   * @param _to The new owner.
   * @param _tokenId The NFT to transfer.
   * @param _data Additional data with no specified format, sent in call to `_to`.
   */
  function _safeTransferFrom(
    address _from,
    address _to,
    uint256 _tokenId,
    bytes memory _data
  )
    private
    canTransfer(_tokenId)
    validNFToken(_tokenId)
  {
    address tokenOwner = idToOwner[_tokenId];
    require(tokenOwner == _from, NOT_OWNER);
    require(_to != address(0), ZERO_ADDRESS);

    _transfer(_to, _tokenId);

    if (_to.isContract())
    {
      bytes4 retval = ERC721TokenReceiver(_to).onERC721Received(msg.sender, _from, _tokenId, _data);
      require(retval == MAGIC_ON_ERC721_RECEIVED, NOT_ABLE_TO_RECEIVE_NFT);
    }
  }

  /**
   * @dev Clears the current approval of a given NFT ID.
   * @param _tokenId ID of the NFT to be transferred.
   */
  function _clearApproval(
    uint256 _tokenId
  )
    private
  {
    if (idToApproval[_tokenId] != address(0))
    {
      delete idToApproval[_tokenId];
    }
  }

}

File 14 of 15: ownable.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

/**
 * @dev The contract has an owner address, and provides basic authorization control whitch
 * simplifies the implementation of user permissions. This contract is based on the source code at:
 * https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/contracts/ownership/Ownable.sol
 */
contract Ownable
{

  /**
   * @dev Error constants.
   */
  string public constant NOT_CURRENT_OWNER = "018001";
  string public constant CANNOT_TRANSFER_TO_ZERO_ADDRESS = "018002";

  /**
   * @dev Current owner address.
   */
  address public owner;

  /**
   * @dev An event which is triggered when the owner is changed.
   * @param previousOwner The address of the previous owner.
   * @param newOwner The address of the new owner.
   */
  event OwnershipTransferred(
    address indexed previousOwner,
    address indexed newOwner
  );

  /**
   * @dev The constructor sets the original `owner` of the contract to the sender account.
   */
  constructor()
  {
    owner = msg.sender;
  }

  /**
   * @dev Throws if called by any account other than the owner.
   */
  modifier onlyOwner()
  {
    require(msg.sender == owner, NOT_CURRENT_OWNER);
    _;
  }

  /**
   * @dev Allows the current owner to transfer control of the contract to a newOwner.
   * @param _newOwner The address to transfer ownership to.
   */
  function transferOwnership(
    address _newOwner
  )
    public
    onlyOwner
  {
    require(_newOwner != address(0), CANNOT_TRANSFER_TO_ZERO_ADDRESS);
    emit OwnershipTransferred(owner, _newOwner);
    owner = _newOwner;
  }

}

File 15 of 15: supports-interface.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

import "./erc165.sol";

/**
 * @dev Implementation of standard for detect smart contract interfaces.
 */
contract SupportsInterface is
  ERC165
{

  /**
   * @dev Mapping of supported intefraces. You must not set element 0xffffffff to true.
   */
  mapping(bytes4 => bool) internal supportedInterfaces;

  /**
   * @dev Contract constructor.
   */
  constructor()
  {
    supportedInterfaces[0x01ffc9a7] = true; // ERC165
  }

  /**
   * @dev Function to check which interfaces are suported by this contract.
   * @param _interfaceID Id of the interface.
   * @return True if _interfaceID is supported, false otherwise.
   */
  function supportsInterface(
    bytes4 _interfaceID
  )
    external
    override
    view
    returns (bool)
  {
    return supportedInterfaces[_interfaceID];
  }

}

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":"_approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_owner","type":"address"},{"indexed":true,"internalType":"address","name":"_operator","type":"address"},{"indexed":false,"internalType":"bool","name":"_approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_from","type":"address"},{"indexed":true,"internalType":"address","name":"_to","type":"address"},{"indexed":true,"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"CANNOT_TRANSFER_TO_ZERO_ADDRESS","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"NOT_CURRENT_OWNER","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_id","type":"uint256"}],"name":"airdropNFT","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256[]","name":"_ids","type":"uint256[]"}],"name":"airdropNFTs","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_approved","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAirdropAccount","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getBaseURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getMaxMintPerTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getMaxPageSize","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getMaxSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getMintMaxPerDay","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getMintPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getMintableCountToday","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getMintableRemaining","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getMintedCountToday","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"pageSize","type":"uint256"},{"internalType":"uint256","name":"pageIndex","type":"uint256"}],"name":"getPagedNFTs","outputs":[{"components":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bool","name":"isSelling","type":"bool"},{"internalType":"uint256","name":"priceInWei","type":"uint256"},{"internalType":"address","name":"owner","type":"address"}],"internalType":"struct CryptoMonkeyKing.NFT[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_id","type":"uint256"}],"name":"giveNFT","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256[]","name":"_ids","type":"uint256[]"}],"name":"giveNFTs","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address","name":"_operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_addr","type":"address"}],"name":"isMinted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_ids","type":"uint256[]"}],"name":"mintNFTs","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"_name","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"_owner","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_airdropAccount","type":"address"}],"name":"setAirdropAccount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_operator","type":"address"},{"internalType":"bool","name":"_approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_baseURI","type":"string"}],"name":"setBaseURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxMintPerTime","type":"uint256"}],"name":"setMaxMintPerTime","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_mintMaxPerDay","type":"uint256"}],"name":"setMintMaxPerDay","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_mintPrice","type":"uint256"}],"name":"setMintPrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"_interfaceID","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"_symbol","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"_index","type":"uint256"}],"name":"tokenByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"uint256","name":"_index","type":"uint256"}],"name":"tokenOfOwnerByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_id","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}]

60806040523480156200001157600080fd5b5060016000806301ffc9a760e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060006101000a81548160ff02191690831515021790555060016000806380ac58cd60e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060006101000a81548160ff021916908315150217905550600160008063780e9d6360e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060006101000a81548160ff02191690831515021790555033600960006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060405180606001604052806022815260200162005f5560229139600a908051906020019062000177929190620001f5565b5073251d42b900973ed14d7ea82ce9310d34534f75ec600b60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550612710600c819055506103e8600d819055506005600e8190555060c8600f819055506200030a565b8280546200020390620002a5565b90600052602060002090601f01602090048101928262000227576000855562000273565b82601f106200024257805160ff191683800117855562000273565b8280016001018555821562000273579182015b828111156200027257825182559160200191906001019062000255565b5b50905062000282919062000286565b5090565b5b80821115620002a157600081600090555060010162000287565b5090565b60006002820490506001821680620002be57607f821691505b60208210811415620002d557620002d4620002db565b5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b615c3b806200031a6000396000f3fe6080604052600436106102515760003560e01c8063860d248a11610139578063bc99ca98116100b6578063cefca5da1161007a578063cefca5da146108cb578063e985e9c5146108f4578063f2fde38b14610931578063f3fe3bc31461095a578063f4a0a52814610985578063f9f2a7ce146109ae57610251565b8063bc99ca98146107e6578063bea06d2a1461080f578063c24108ae14610838578063c6b326ca14610863578063c87b56dd1461088e57610251565b8063a3eccf5b116100fd578063a3eccf5b14610701578063a7f93ebd1461072a578063a8e5fd0714610755578063b51c003814610792578063b88d4fde146107bd57610251565b8063860d248a1461062c5780638da5cb5b1461065757806392613a7c1461068257806395d89b41146106ad578063a22cb465146106d857610251565b806337e36f79116101d25780634c0f38c2116101965780634c0f38c2146104f65780634f6ccce71461052157806355f804b31461055e5780636352211e1461058757806370a08231146105c4578063714c53981461060157610251565b806337e36f7914610432578063387c5e671461045b57806342842e0e1461048657806342f56b92146104af57806343760078146104da57610251565b80630db2a867116102195780630db2a8671461034d57806318160ddd1461037657806323b872dd146103a157806327c03803146103ca5780632f745c59146103f557610251565b806301ffc9a7146102565780630316ae231461029357806306fdde03146102bc578063081812fc146102e7578063095ea7b314610324575b600080fd5b34801561026257600080fd5b5061027d600480360381019061027891906150f4565b6109eb565b60405161028a919061540c565b60405180910390f35b34801561029f57600080fd5b506102ba60048036038101906102b59190614e8a565b610a52565b005b3480156102c857600080fd5b506102d1610b5f565b6040516102de9190615427565b60405180910390f35b3480156102f357600080fd5b5061030e60048036038101906103099190615187565b610b9c565b60405161031b9190615383565b60405180910390f35b34801561033057600080fd5b5061034b60048036038101906103469190615077565b610cb7565b005b34801561035957600080fd5b50610374600480360381019061036f9190614fe7565b61109a565b005b34801561038257600080fd5b5061038b61110e565b6040516103989190615449565b60405180910390f35b3480156103ad57600080fd5b506103c860048036038101906103c39190614f18565b61111b565b005b3480156103d657600080fd5b506103df61156d565b6040516103ec9190615449565b60405180910390f35b34801561040157600080fd5b5061041c60048036038101906104179190615077565b611577565b6040516104299190615449565b60405180910390f35b34801561043e57600080fd5b5061045960048036038101906104549190615077565b6116c0565b005b34801561046757600080fd5b5061047061198c565b60405161047d9190615449565b60405180910390f35b34801561049257600080fd5b506104ad60048036038101906104a89190614f18565b6119ec565b005b3480156104bb57600080fd5b506104c4611a0c565b6040516104d19190615449565b60405180910390f35b6104f460048036038101906104ef91906150b3565b611aa6565b005b34801561050257600080fd5b5061050b612048565b6040516105189190615449565b60405180910390f35b34801561052d57600080fd5b5061054860048036038101906105439190615187565b612052565b6040516105559190615449565b60405180910390f35b34801561056a57600080fd5b5061058560048036038101906105809190615146565b612120565b005b34801561059357600080fd5b506105ae60048036038101906105a99190615187565b612203565b6040516105bb9190615383565b60405180910390f35b3480156105d057600080fd5b506105eb60048036038101906105e69190614e8a565b6122e9565b6040516105f89190615449565b60405180910390f35b34801561060d57600080fd5b506106166123a3565b6040516106239190615427565b60405180910390f35b34801561063857600080fd5b506106416124fe565b60405161064e9190615427565b60405180910390f35b34801561066357600080fd5b5061066c612537565b6040516106799190615383565b60405180910390f35b34801561068e57600080fd5b5061069761255d565b6040516106a49190615449565b60405180910390f35b3480156106b957600080fd5b506106c2612567565b6040516106cf9190615427565b60405180910390f35b3480156106e457600080fd5b506106ff60048036038101906106fa919061503b565b6125a4565b005b34801561070d57600080fd5b5061072860048036038101906107239190615187565b6126a1565b005b34801561073657600080fd5b5061073f612774565b60405161074c9190615449565b60405180910390f35b34801561076157600080fd5b5061077c600480360381019061077791906151b0565b61277e565b60405161078991906153ea565b60405180910390f35b34801561079e57600080fd5b506107a76129ee565b6040516107b49190615449565b60405180910390f35b3480156107c957600080fd5b506107e460048036038101906107df9190614f67565b612a08565b005b3480156107f257600080fd5b5061080d60048036038101906108089190614fe7565b612a5f565b005b34801561081b57600080fd5b5061083660048036038101906108319190615187565b612ad3565b005b34801561084457600080fd5b5061084d612ba6565b60405161085a9190615383565b60405180910390f35b34801561086f57600080fd5b50610878612c99565b6040516108859190615449565b60405180910390f35b34801561089a57600080fd5b506108b560048036038101906108b09190615187565b612ca3565b6040516108c29190615427565b60405180910390f35b3480156108d757600080fd5b506108f260048036038101906108ed9190615077565b612d7e565b005b34801561090057600080fd5b5061091b60048036038101906109169190614edc565b612f54565b604051610928919061540c565b60405180910390f35b34801561093d57600080fd5b5061095860048036038101906109539190614e8a565b612fe8565b005b34801561096657600080fd5b5061096f61321a565b60405161097c9190615427565b60405180910390f35b34801561099157600080fd5b506109ac60048036038101906109a79190615187565b613253565b005b3480156109ba57600080fd5b506109d560048036038101906109d09190614e8a565b613326565b6040516109e2919061540c565b60405180910390f35b6000806000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060009054906101000a900460ff169050919050565b600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146040518060400160405280600681526020017f303138303031000000000000000000000000000000000000000000000000000081525090610b1a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b119190615427565b60405180910390fd5b5080600b60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b60606040518060400160405280601281526020017f43727970746f204d6f6e6b6579204b696e670000000000000000000000000000815250905090565b600081600073ffffffffffffffffffffffffffffffffffffffff166001600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614156040518060400160405280600681526020017f303033303032000000000000000000000000000000000000000000000000000081525090610c7a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c719190615427565b60405180910390fd5b506002600084815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16915050919050565b8060006001600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690503373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161480610db05750600460008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff165b6040518060400160405280600681526020017f303033303033000000000000000000000000000000000000000000000000000081525090610e27576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e1e9190615427565b60405180910390fd5b5082600073ffffffffffffffffffffffffffffffffffffffff166001600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614156040518060400160405280600681526020017f303033303032000000000000000000000000000000000000000000000000000081525090610f04576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610efb9190615427565b60405180910390fd5b5060006001600086815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508073ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1614156040518060400160405280600681526020017f303033303038000000000000000000000000000000000000000000000000000081525090610fe4576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610fdb9190615427565b60405180910390fd5b50856002600087815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550848673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a4505050505050565b60005b81518110156111095760008282815181106110e1577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b602002602001015190506110f58482612d7e565b50808061110190615a62565b91505061109d565b505050565b6000600580549050905090565b8060006001600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690503373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614806111ec57503373ffffffffffffffffffffffffffffffffffffffff166002600084815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16145b8061127d5750600460008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff165b6040518060400160405280600681526020017f3030333030340000000000000000000000000000000000000000000000000000815250906112f4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112eb9190615427565b60405180910390fd5b5082600073ffffffffffffffffffffffffffffffffffffffff166001600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614156040518060400160405280600681526020017f3030333030320000000000000000000000000000000000000000000000000000815250906113d1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016113c89190615427565b60405180910390fd5b5060006001600086815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508673ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146040518060400160405280600681526020017f3030333030370000000000000000000000000000000000000000000000000000815250906114b0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016114a79190615427565b60405180910390fd5b50600073ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1614156040518060400160405280600681526020017f303033303031000000000000000000000000000000000000000000000000000081525090611559576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016115509190615427565b60405180910390fd5b50611564868661337c565b50505050505050565b6000600f54905090565b6000600760008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054905082106040518060400160405280600681526020017f303035303037000000000000000000000000000000000000000000000000000081525090611635576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161162c9190615427565b60405180910390fd5b50600760008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002082815481106116ad577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b9060005260206000200154905092915050565b600b60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146040518060400160405280600681526020017f303034303130000000000000000000000000000000000000000000000000000081525090611788576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161177f9190615427565b60405180910390fd5b5080600081101580156117a957506001600c546117a591906158e1565b8111155b6040518060400160405280600681526020017f303034303031000000000000000000000000000000000000000000000000000081525090611820576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016118179190615427565b60405180910390fd5b5061182a82613431565b6040518060400160405280600681526020017f3030343030320000000000000000000000000000000000000000000000000000815250906118a1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016118989190615427565b60405180910390fd5b50600073ffffffffffffffffffffffffffffffffffffffff166001600084815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146040518060400160405280600681526020017f30303430303700000000000000000000000000000000000000000000000000008152509061197c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016119739190615427565b60405180910390fd5b50611987838361344d565b505050565b60008060008061199b426134ad565b9250925092506000836011600001541480156119bb575082601160010154145b80156119cb575081601160020154145b156119dd5760116003015490506119e2565b600090505b8094505050505090565b611a07838383604051806020016040528060008152506134dc565b505050565b600080600080611a1b426134ad565b925092509250600080611a42601160040154611b58611a3a91906158e1565b600f54613aaa565b905084601160000154148015611a5c575083601160010154145b8015611a6c575082601160020154145b15611a895760116003015481611a8291906158e1565b9150611a8d565b8091505b6000821015611a9b57600091505b819550505050505090565b601660003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16156040518060400160405280600681526020017f303034303135000000000000000000000000000000000000000000000000000081525090611b6b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b629190615427565b60405180910390fd5b50611b74611a0c565b815111156040518060400160405280600681526020017f303034303134000000000000000000000000000000000000000000000000000081525090611bef576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611be69190615427565b60405180910390fd5b50600e54815111156040518060400160405280600681526020017f303034303133000000000000000000000000000000000000000000000000000081525090611c6e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c659190615427565b60405180910390fd5b5060006010548251611c8091906157f3565b9050348111156040518060400160405280600681526020017f303034303131000000000000000000000000000000000000000000000000000081525090611cfd576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611cf49190615427565b60405180910390fd5b5060005b8251811015611ec9576000838281518110611d45577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60200260200101519050611d5881613ac6565b6040518060400160405280600681526020017f303034303033000000000000000000000000000000000000000000000000000081525090611dcf576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611dc69190615427565b60405180910390fd5b50600073ffffffffffffffffffffffffffffffffffffffff166001600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146040518060400160405280600681526020017f303034303037000000000000000000000000000000000000000000000000000081525090611eaa576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ea19190615427565b60405180910390fd5b50611eb5338261344d565b508080611ec190615a62565b915050611d01565b506000806000611ed8426134ad565b92509250925082601160000154148015611ef6575081601160010154145b8015611f06575080601160020154145b15611f2d57845160116003016000828254611f2191906155eb565b92505081905550611f39565b84516011600301819055505b826011600001819055508160116001018190555080601160020181905550845160116004016000828254611f6d91906155eb565b925050819055506001601660003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055506000601054111561204157600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc349081150290604051600060405180830381858888f1935050505015801561203f573d6000803e3d6000fd5b505b5050505050565b6000600c54905090565b600060058054905082106040518060400160405280600681526020017f3030353030370000000000000000000000000000000000000000000000000000815250906120d3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016120ca9190615427565b60405180910390fd5b506005828154811061210e577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90600052602060002001549050919050565b600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146040518060400160405280600681526020017f3031383030310000000000000000000000000000000000000000000000000000815250906121e8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016121df9190615427565b60405180910390fd5b5080600a90805190602001906121ff929190614be1565b5050565b60006001600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156040518060400160405280600681526020017f3030333030320000000000000000000000000000000000000000000000000000815250906122e3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016122da9190615427565b60405180910390fd5b50919050565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614156040518060400160405280600681526020017f303033303031000000000000000000000000000000000000000000000000000081525090612392576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016123899190615427565b60405180910390fd5b5061239c82613ae0565b9050919050565b6060600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146040518060400160405280600681526020017f30313830303100000000000000000000000000000000000000000000000000008152509061246d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016124649190615427565b60405180910390fd5b50600a805461247b906159ff565b80601f01602080910402602001604051908101604052809291908181526020018280546124a7906159ff565b80156124f45780601f106124c9576101008083540402835291602001916124f4565b820191906000526020600020905b8154815290600101906020018083116124d757829003601f168201915b5050505050905090565b6040518060400160405280600681526020017f303138303032000000000000000000000000000000000000000000000000000081525081565b600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000600e54905090565b60606040518060400160405280600381526020017f434d4b0000000000000000000000000000000000000000000000000000000000815250905090565b80600460003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3183604051612695919061540c565b60405180910390a35050565b600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146040518060400160405280600681526020017f303138303031000000000000000000000000000000000000000000000000000081525090612769576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016127609190615427565b60405180910390fd5b5080600f8190555050565b6000601054905090565b6060600d548311156040518060400160405280600681526020017f3030343031320000000000000000000000000000000000000000000000000000815250906127fd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016127f49190615427565b60405180910390fd5b506000828461280c91906157f3565b905060006001858361281e91906155eb565b61282891906158e1565b90506001600c5461283991906158e1565b821115612852576001600c5461284f91906158e1565b91505b6001600c5461286191906158e1565b81111561287a576001600c5461287791906158e1565b90505b60008567ffffffffffffffff8111156128bc577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040519080825280602002602001820160405280156128f557816020015b6128e2614c67565b8152602001906001900390816128da5790505b50905060008390505b8281116129e15760006001600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905060006040518060800160405280848152602001600015158152602001600081526020018373ffffffffffffffffffffffffffffffffffffffff1681525090508084878561298a91906158e1565b815181106129c1577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6020026020010181905250505080806129d990615a62565b9150506128fe565b5080935050505092915050565b6000601160040154611b58612a0391906158e1565b905090565b612a5885858585858080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050506134dc565b5050505050565b60005b8151811015612ace576000828281518110612aa6577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60200260200101519050612aba84826116c0565b508080612ac690615a62565b915050612a62565b505050565b600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146040518060400160405280600681526020017f303138303031000000000000000000000000000000000000000000000000000081525090612b9b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612b929190615427565b60405180910390fd5b5080600e8190555050565b6000600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146040518060400160405280600681526020017f303138303031000000000000000000000000000000000000000000000000000081525090612c70576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612c679190615427565b60405180910390fd5b50600b60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6000600d54905090565b6060612d77600a8054612cb5906159ff565b80601f0160208091040260200160405190810160405280929190818152602001828054612ce1906159ff565b8015612d2e5780601f10612d0357610100808354040283529160200191612d2e565b820191906000526020600020905b815481529060010190602001808311612d1157829003601f168201915b50505050506040518060400160405280600181526020017f2f00000000000000000000000000000000000000000000000000000000000000815250612d7285613b2c565b613cdf565b9050919050565b8060008110158015612d9e57506001600c54612d9a91906158e1565b8111155b6040518060400160405280600681526020017f303034303031000000000000000000000000000000000000000000000000000081525090612e15576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612e0c9190615427565b60405180910390fd5b503373ffffffffffffffffffffffffffffffffffffffff163073ffffffffffffffffffffffffffffffffffffffff16636352211e846040518263ffffffff1660e01b8152600401612e669190615449565b60206040518083038186803b158015612e7e57600080fd5b505afa158015612e92573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612eb69190614eb3565b73ffffffffffffffffffffffffffffffffffffffff16146040518060400160405280600681526020017f303034303039000000000000000000000000000000000000000000000000000081525090612f44576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612f3b9190615427565b60405180910390fd5b50612f4f838361337c565b505050565b6000600460008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146040518060400160405280600681526020017f3031383030310000000000000000000000000000000000000000000000000000815250906130b0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016130a79190615427565b60405180910390fd5b50600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156040518060400160405280600681526020017f303138303032000000000000000000000000000000000000000000000000000081525090613159576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016131509190615427565b60405180910390fd5b508073ffffffffffffffffffffffffffffffffffffffff16600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a380600960006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6040518060400160405280600681526020017f303138303031000000000000000000000000000000000000000000000000000081525081565b600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146040518060400160405280600681526020017f30313830303100000000000000000000000000000000000000000000000000008152509061331b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016133129190615427565b60405180910390fd5b508060108190555050565b6000601660008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff169050919050565b60006001600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690506133bd82613d15565b6133c78183613db6565b6133d183836140ef565b818373ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4505050565b6000611b588210158015613446575061271082105b9050919050565b61345782826142ec565b6005819080600181540180825580915050600190039060005260206000200160009091909190915055600160058054905061349291906158e1565b60066000838152602001908152602001600020819055505050565b60008060006134c962015180856134c491906156ab565b6144da565b8093508194508295505050509193909250565b8160006001600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690503373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614806135ad57503373ffffffffffffffffffffffffffffffffffffffff166002600084815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16145b8061363e5750600460008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff165b6040518060400160405280600681526020017f3030333030340000000000000000000000000000000000000000000000000000815250906136b5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016136ac9190615427565b60405180910390fd5b5083600073ffffffffffffffffffffffffffffffffffffffff166001600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614156040518060400160405280600681526020017f303033303032000000000000000000000000000000000000000000000000000081525090613792576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016137899190615427565b60405180910390fd5b5060006001600087815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508773ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146040518060400160405280600681526020017f303033303037000000000000000000000000000000000000000000000000000081525090613871576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016138689190615427565b60405180910390fd5b50600073ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff1614156040518060400160405280600681526020017f30303330303100000000000000000000000000000000000000000000000000008152509061391a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016139119190615427565b60405180910390fd5b50613925878761337c565b6139448773ffffffffffffffffffffffffffffffffffffffff16614679565b15613aa05760008773ffffffffffffffffffffffffffffffffffffffff1663150b7a02338b8a8a6040518563ffffffff1660e01b815260040161398a949392919061539e565b602060405180830381600087803b1580156139a457600080fd5b505af11580156139b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139dc919061511d565b905063150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916146040518060400160405280600681526020017f303033303035000000000000000000000000000000000000000000000000000081525090613a9d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613a949190615427565b60405180910390fd5b50505b5050505050505050565b600081831115613abc57819050613ac0565b8290505b92915050565b6000808210158015613ad95750611b5882105b9050919050565b6000600760008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805490509050919050565b60606000821415613b74576040518060400160405280600181526020017f30000000000000000000000000000000000000000000000000000000000000008152509050613cda565b600082905060005b60008214613ba6578080613b8f90615a62565b915050600a82613b9f91906156ab565b9150613b7c565b60008167ffffffffffffffff811115613be8577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040519080825280601f01601f191660200182016040528015613c1a5781602001600182028036833780820191505090505b50905060008290508593505b60008414613cd257600a84613c3b9190615aab565b6030613c4791906155eb565b60f81b8282613c55906159d5565b92508281518110613c8f577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600a84613ccb91906156ab565b9350613c26565b819450505050505b919050565b6060613d0c84848460405180602001604052806000815250604051806020016040528060008152506146c4565b90509392505050565b600073ffffffffffffffffffffffffffffffffffffffff166002600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614613db3576002600082815260200190815260200160002060006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690555b50565b8173ffffffffffffffffffffffffffffffffffffffff166001600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146040518060400160405280600681526020017f303033303037000000000000000000000000000000000000000000000000000081525090613e8f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613e869190615427565b60405180910390fd5b506001600082815260200190815260200160002060006101000a81549073ffffffffffffffffffffffffffffffffffffffff021916905560006008600083815260200190815260200160002054905060006001600760008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080549050613f2f91906158e1565b905081811461405e576000600760008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208281548110613fb1577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b9060005260206000200154905080600760008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208481548110614036577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b9060005260206000200181905550826008600083815260200190815260200160002081905550505b600760008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054806140d3577f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b6001900381819060005260206000200160009055905550505050565b600073ffffffffffffffffffffffffffffffffffffffff166001600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146040518060400160405280600681526020017f3030333030360000000000000000000000000000000000000000000000000000815250906141c9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016141c09190615427565b60405180910390fd5b50816001600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600760008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190806001815401808255809150506001900390600052602060002001600090919091909150556001600760008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805490506142d191906158e1565b60086000838152602001908152602001600020819055505050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614156040518060400160405280600681526020017f303033303031000000000000000000000000000000000000000000000000000081525090614394576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161438b9190615427565b60405180910390fd5b50600073ffffffffffffffffffffffffffffffffffffffff166001600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146040518060400160405280600681526020017f30303330303600000000000000000000000000000000000000000000000000008152509061446f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016144669190615427565b60405180910390fd5b5061447a82826140ef565b808273ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a45050565b600080600080849050600062253d8c62010bd9836144f89190615557565b6145029190615557565b9050600062023ab182600461451791906156dc565b6145219190615641565b9050600460038262023ab161453691906156dc565b6145409190615557565b61454a9190615641565b82614555919061584d565b9150600062164b0960018461456a9190615557565b610fa061457791906156dc565b6145819190615641565b9050601f6004826105b561459591906156dc565b61459f9190615641565b846145aa919061584d565b6145b49190615557565b9250600061098f8460506145c891906156dc565b6145d29190615641565b9050600060508261098f6145e691906156dc565b6145f09190615641565b856145fb919061584d565b9050600b8261460a9190615641565b945084600c61461991906156dc565b6002836146269190615557565b614630919061584d565b91508483603186614641919061584d565b606461464d91906156dc565b6146579190615557565b6146619190615557565b92508298508197508096505050505050509193909250565b60008060007fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47060001b9050833f91506000801b82141580156146bb5750808214155b92505050919050565b6060600086905060008690506000869050600086905060008690506000815183518551875189516146f591906155eb565b6146ff91906155eb565b61470991906155eb565b61471391906155eb565b67ffffffffffffffff811115614752577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040519080825280601f01601f1916602001820160405280156147845781602001600182028036833780820191505090505b5090506000819050600080600090505b8851811015614868578881815181106147d6577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b602001015160f81c60f81b8383806147ed90615a62565b945081518110614826577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350808061486090615a62565b915050614794565b600090505b8751811015614941578781815181106148af577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b602001015160f81c60f81b8383806148c690615a62565b9450815181106148ff577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350808061493990615a62565b91505061486d565b600090505b8651811015614a1a57868181518110614988577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b602001015160f81c60f81b83838061499f90615a62565b9450815181106149d8577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508080614a1290615a62565b915050614946565b600090505b8551811015614af357858181518110614a61577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b602001015160f81c60f81b838380614a7890615a62565b945081518110614ab1577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508080614aeb90615a62565b915050614a1f565b600090505b8451811015614bcc57848181518110614b3a577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b602001015160f81c60f81b838380614b5190615a62565b945081518110614b8a577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508080614bc490615a62565b915050614af8565b82995050505050505050505095945050505050565b828054614bed906159ff565b90600052602060002090601f016020900481019282614c0f5760008555614c56565b82601f10614c2857805160ff1916838001178555614c56565b82800160010185558215614c56579182015b82811115614c55578251825591602001919060010190614c3a565b5b509050614c639190614ca7565b5090565b60405180608001604052806000815260200160001515815260200160008152602001600073ffffffffffffffffffffffffffffffffffffffff1681525090565b5b80821115614cc0576000816000905550600101614ca8565b5090565b6000614cd7614cd284615489565b615464565b90508083825260208201905082856020860282011115614cf657600080fd5b60005b85811015614d265781614d0c8882614e75565b845260208401935060208301925050600181019050614cf9565b5050509392505050565b6000614d43614d3e846154b5565b615464565b905082815260208101848484011115614d5b57600080fd5b614d66848285615993565b509392505050565b600081359050614d7d81615ba9565b92915050565b600081519050614d9281615ba9565b92915050565b600082601f830112614da957600080fd5b8135614db9848260208601614cc4565b91505092915050565b600081359050614dd181615bc0565b92915050565b600081359050614de681615bd7565b92915050565b600081519050614dfb81615bd7565b92915050565b60008083601f840112614e1357600080fd5b8235905067ffffffffffffffff811115614e2c57600080fd5b602083019150836001820283011115614e4457600080fd5b9250929050565b600082601f830112614e5c57600080fd5b8135614e6c848260208601614d30565b91505092915050565b600081359050614e8481615bee565b92915050565b600060208284031215614e9c57600080fd5b6000614eaa84828501614d6e565b91505092915050565b600060208284031215614ec557600080fd5b6000614ed384828501614d83565b91505092915050565b60008060408385031215614eef57600080fd5b6000614efd85828601614d6e565b9250506020614f0e85828601614d6e565b9150509250929050565b600080600060608486031215614f2d57600080fd5b6000614f3b86828701614d6e565b9350506020614f4c86828701614d6e565b9250506040614f5d86828701614e75565b9150509250925092565b600080600080600060808688031215614f7f57600080fd5b6000614f8d88828901614d6e565b9550506020614f9e88828901614d6e565b9450506040614faf88828901614e75565b935050606086013567ffffffffffffffff811115614fcc57600080fd5b614fd888828901614e01565b92509250509295509295909350565b60008060408385031215614ffa57600080fd5b600061500885828601614d6e565b925050602083013567ffffffffffffffff81111561502557600080fd5b61503185828601614d98565b9150509250929050565b6000806040838503121561504e57600080fd5b600061505c85828601614d6e565b925050602061506d85828601614dc2565b9150509250929050565b6000806040838503121561508a57600080fd5b600061509885828601614d6e565b92505060206150a985828601614e75565b9150509250929050565b6000602082840312156150c557600080fd5b600082013567ffffffffffffffff8111156150df57600080fd5b6150eb84828501614d98565b91505092915050565b60006020828403121561510657600080fd5b600061511484828501614dd7565b91505092915050565b60006020828403121561512f57600080fd5b600061513d84828501614dec565b91505092915050565b60006020828403121561515857600080fd5b600082013567ffffffffffffffff81111561517257600080fd5b61517e84828501614e4b565b91505092915050565b60006020828403121561519957600080fd5b60006151a784828501614e75565b91505092915050565b600080604083850312156151c357600080fd5b60006151d185828601614e75565b92505060206151e285828601614e75565b9150509250929050565b60006151f88383615310565b60808301905092915050565b61520d81615915565b82525050565b61521c81615915565b82525050565b600061522d826154f6565b6152378185615524565b9350615242836154e6565b8060005b8381101561527357815161525a88826151ec565b975061526583615517565b925050600181019050615246565b5085935050505092915050565b61528981615927565b82525050565b61529881615927565b82525050565b60006152a982615501565b6152b38185615535565b93506152c38185602086016159a2565b6152cc81615b98565b840191505092915050565b60006152e28261550c565b6152ec8185615546565b93506152fc8185602086016159a2565b61530581615b98565b840191505092915050565b6080820160008201516153266000850182615365565b5060208201516153396020850182615280565b50604082015161534c6040850182615365565b50606082015161535f6060850182615204565b50505050565b61536e81615989565b82525050565b61537d81615989565b82525050565b60006020820190506153986000830184615213565b92915050565b60006080820190506153b36000830187615213565b6153c06020830186615213565b6153cd6040830185615374565b81810360608301526153df818461529e565b905095945050505050565b600060208201905081810360008301526154048184615222565b905092915050565b6000602082019050615421600083018461528f565b92915050565b6000602082019050818103600083015261544181846152d7565b905092915050565b600060208201905061545e6000830184615374565b92915050565b600061546e61547f565b905061547a8282615a31565b919050565b6000604051905090565b600067ffffffffffffffff8211156154a4576154a3615b69565b5b602082029050602081019050919050565b600067ffffffffffffffff8211156154d0576154cf615b69565b5b6154d982615b98565b9050602081019050919050565b6000819050602082019050919050565b600081519050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b600082825260208201905092915050565b600082825260208201905092915050565b600082825260208201905092915050565b60006155628261595f565b915061556d8361595f565b9250817f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff038313600083121516156155a8576155a7615adc565b5b817f80000000000000000000000000000000000000000000000000000000000000000383126000831216156155e0576155df615adc565b5b828201905092915050565b60006155f682615989565b915061560183615989565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0382111561563657615635615adc565b5b828201905092915050565b600061564c8261595f565b91506156578361595f565b92508261566757615666615b0b565b5b600160000383147f8000000000000000000000000000000000000000000000000000000000000000831416156156a05761569f615adc565b5b828205905092915050565b60006156b682615989565b91506156c183615989565b9250826156d1576156d0615b0b565b5b828204905092915050565b60006156e78261595f565b91506156f28361595f565b9250827f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048211600084136000841316161561573157615730615adc565b5b817f8000000000000000000000000000000000000000000000000000000000000000058312600084126000841316161561576e5761576d615adc565b5b827f800000000000000000000000000000000000000000000000000000000000000005821260008413600084121616156157ab576157aa615adc565b5b827f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff05821260008412600084121616156157e8576157e7615adc565b5b828202905092915050565b60006157fe82615989565b915061580983615989565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561584257615841615adc565b5b828202905092915050565b60006158588261595f565b91506158638361595f565b9250827f80000000000000000000000000000000000000000000000000000000000000000182126000841215161561589e5761589d615adc565b5b827f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0182136000841216156158d6576158d5615adc565b5b828203905092915050565b60006158ec82615989565b91506158f783615989565b92508282101561590a57615909615adc565b5b828203905092915050565b600061592082615969565b9050919050565b60008115159050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b6000819050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b82818337600083830152505050565b60005b838110156159c05780820151818401526020810190506159a5565b838111156159cf576000848401525b50505050565b60006159e082615989565b915060008214156159f4576159f3615adc565b5b600182039050919050565b60006002820490506001821680615a1757607f821691505b60208210811415615a2b57615a2a615b3a565b5b50919050565b615a3a82615b98565b810181811067ffffffffffffffff82111715615a5957615a58615b69565b5b80604052505050565b6000615a6d82615989565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821415615aa057615a9f615adc565b5b600182019050919050565b6000615ab682615989565b9150615ac183615989565b925082615ad157615ad0615b0b565b5b828206905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000601f19601f8301169050919050565b615bb281615915565b8114615bbd57600080fd5b50565b615bc981615927565b8114615bd457600080fd5b50565b615be081615933565b8114615beb57600080fd5b50565b615bf781615989565b8114615c0257600080fd5b5056fea2646970667358221220e7168e71313d50a51c8a8164e260779e4b759679ea2685197c8bf7d4f8222ad764736f6c6343000804003368747470733a2f2f63727970746f6d6f6e6b65796b696e672e636f6d2f746f6b656e

Deployed Bytecode

0x6080604052600436106102515760003560e01c8063860d248a11610139578063bc99ca98116100b6578063cefca5da1161007a578063cefca5da146108cb578063e985e9c5146108f4578063f2fde38b14610931578063f3fe3bc31461095a578063f4a0a52814610985578063f9f2a7ce146109ae57610251565b8063bc99ca98146107e6578063bea06d2a1461080f578063c24108ae14610838578063c6b326ca14610863578063c87b56dd1461088e57610251565b8063a3eccf5b116100fd578063a3eccf5b14610701578063a7f93ebd1461072a578063a8e5fd0714610755578063b51c003814610792578063b88d4fde146107bd57610251565b8063860d248a1461062c5780638da5cb5b1461065757806392613a7c1461068257806395d89b41146106ad578063a22cb465146106d857610251565b806337e36f79116101d25780634c0f38c2116101965780634c0f38c2146104f65780634f6ccce71461052157806355f804b31461055e5780636352211e1461058757806370a08231146105c4578063714c53981461060157610251565b806337e36f7914610432578063387c5e671461045b57806342842e0e1461048657806342f56b92146104af57806343760078146104da57610251565b80630db2a867116102195780630db2a8671461034d57806318160ddd1461037657806323b872dd146103a157806327c03803146103ca5780632f745c59146103f557610251565b806301ffc9a7146102565780630316ae231461029357806306fdde03146102bc578063081812fc146102e7578063095ea7b314610324575b600080fd5b34801561026257600080fd5b5061027d600480360381019061027891906150f4565b6109eb565b60405161028a919061540c565b60405180910390f35b34801561029f57600080fd5b506102ba60048036038101906102b59190614e8a565b610a52565b005b3480156102c857600080fd5b506102d1610b5f565b6040516102de9190615427565b60405180910390f35b3480156102f357600080fd5b5061030e60048036038101906103099190615187565b610b9c565b60405161031b9190615383565b60405180910390f35b34801561033057600080fd5b5061034b60048036038101906103469190615077565b610cb7565b005b34801561035957600080fd5b50610374600480360381019061036f9190614fe7565b61109a565b005b34801561038257600080fd5b5061038b61110e565b6040516103989190615449565b60405180910390f35b3480156103ad57600080fd5b506103c860048036038101906103c39190614f18565b61111b565b005b3480156103d657600080fd5b506103df61156d565b6040516103ec9190615449565b60405180910390f35b34801561040157600080fd5b5061041c60048036038101906104179190615077565b611577565b6040516104299190615449565b60405180910390f35b34801561043e57600080fd5b5061045960048036038101906104549190615077565b6116c0565b005b34801561046757600080fd5b5061047061198c565b60405161047d9190615449565b60405180910390f35b34801561049257600080fd5b506104ad60048036038101906104a89190614f18565b6119ec565b005b3480156104bb57600080fd5b506104c4611a0c565b6040516104d19190615449565b60405180910390f35b6104f460048036038101906104ef91906150b3565b611aa6565b005b34801561050257600080fd5b5061050b612048565b6040516105189190615449565b60405180910390f35b34801561052d57600080fd5b5061054860048036038101906105439190615187565b612052565b6040516105559190615449565b60405180910390f35b34801561056a57600080fd5b5061058560048036038101906105809190615146565b612120565b005b34801561059357600080fd5b506105ae60048036038101906105a99190615187565b612203565b6040516105bb9190615383565b60405180910390f35b3480156105d057600080fd5b506105eb60048036038101906105e69190614e8a565b6122e9565b6040516105f89190615449565b60405180910390f35b34801561060d57600080fd5b506106166123a3565b6040516106239190615427565b60405180910390f35b34801561063857600080fd5b506106416124fe565b60405161064e9190615427565b60405180910390f35b34801561066357600080fd5b5061066c612537565b6040516106799190615383565b60405180910390f35b34801561068e57600080fd5b5061069761255d565b6040516106a49190615449565b60405180910390f35b3480156106b957600080fd5b506106c2612567565b6040516106cf9190615427565b60405180910390f35b3480156106e457600080fd5b506106ff60048036038101906106fa919061503b565b6125a4565b005b34801561070d57600080fd5b5061072860048036038101906107239190615187565b6126a1565b005b34801561073657600080fd5b5061073f612774565b60405161074c9190615449565b60405180910390f35b34801561076157600080fd5b5061077c600480360381019061077791906151b0565b61277e565b60405161078991906153ea565b60405180910390f35b34801561079e57600080fd5b506107a76129ee565b6040516107b49190615449565b60405180910390f35b3480156107c957600080fd5b506107e460048036038101906107df9190614f67565b612a08565b005b3480156107f257600080fd5b5061080d60048036038101906108089190614fe7565b612a5f565b005b34801561081b57600080fd5b5061083660048036038101906108319190615187565b612ad3565b005b34801561084457600080fd5b5061084d612ba6565b60405161085a9190615383565b60405180910390f35b34801561086f57600080fd5b50610878612c99565b6040516108859190615449565b60405180910390f35b34801561089a57600080fd5b506108b560048036038101906108b09190615187565b612ca3565b6040516108c29190615427565b60405180910390f35b3480156108d757600080fd5b506108f260048036038101906108ed9190615077565b612d7e565b005b34801561090057600080fd5b5061091b60048036038101906109169190614edc565b612f54565b604051610928919061540c565b60405180910390f35b34801561093d57600080fd5b5061095860048036038101906109539190614e8a565b612fe8565b005b34801561096657600080fd5b5061096f61321a565b60405161097c9190615427565b60405180910390f35b34801561099157600080fd5b506109ac60048036038101906109a79190615187565b613253565b005b3480156109ba57600080fd5b506109d560048036038101906109d09190614e8a565b613326565b6040516109e2919061540c565b60405180910390f35b6000806000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060009054906101000a900460ff169050919050565b600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146040518060400160405280600681526020017f303138303031000000000000000000000000000000000000000000000000000081525090610b1a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b119190615427565b60405180910390fd5b5080600b60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b60606040518060400160405280601281526020017f43727970746f204d6f6e6b6579204b696e670000000000000000000000000000815250905090565b600081600073ffffffffffffffffffffffffffffffffffffffff166001600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614156040518060400160405280600681526020017f303033303032000000000000000000000000000000000000000000000000000081525090610c7a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c719190615427565b60405180910390fd5b506002600084815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16915050919050565b8060006001600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690503373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161480610db05750600460008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff165b6040518060400160405280600681526020017f303033303033000000000000000000000000000000000000000000000000000081525090610e27576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e1e9190615427565b60405180910390fd5b5082600073ffffffffffffffffffffffffffffffffffffffff166001600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614156040518060400160405280600681526020017f303033303032000000000000000000000000000000000000000000000000000081525090610f04576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610efb9190615427565b60405180910390fd5b5060006001600086815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508073ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1614156040518060400160405280600681526020017f303033303038000000000000000000000000000000000000000000000000000081525090610fe4576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610fdb9190615427565b60405180910390fd5b50856002600087815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550848673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a4505050505050565b60005b81518110156111095760008282815181106110e1577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b602002602001015190506110f58482612d7e565b50808061110190615a62565b91505061109d565b505050565b6000600580549050905090565b8060006001600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690503373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614806111ec57503373ffffffffffffffffffffffffffffffffffffffff166002600084815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16145b8061127d5750600460008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff165b6040518060400160405280600681526020017f3030333030340000000000000000000000000000000000000000000000000000815250906112f4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112eb9190615427565b60405180910390fd5b5082600073ffffffffffffffffffffffffffffffffffffffff166001600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614156040518060400160405280600681526020017f3030333030320000000000000000000000000000000000000000000000000000815250906113d1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016113c89190615427565b60405180910390fd5b5060006001600086815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508673ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146040518060400160405280600681526020017f3030333030370000000000000000000000000000000000000000000000000000815250906114b0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016114a79190615427565b60405180910390fd5b50600073ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1614156040518060400160405280600681526020017f303033303031000000000000000000000000000000000000000000000000000081525090611559576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016115509190615427565b60405180910390fd5b50611564868661337c565b50505050505050565b6000600f54905090565b6000600760008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054905082106040518060400160405280600681526020017f303035303037000000000000000000000000000000000000000000000000000081525090611635576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161162c9190615427565b60405180910390fd5b50600760008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002082815481106116ad577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b9060005260206000200154905092915050565b600b60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146040518060400160405280600681526020017f303034303130000000000000000000000000000000000000000000000000000081525090611788576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161177f9190615427565b60405180910390fd5b5080600081101580156117a957506001600c546117a591906158e1565b8111155b6040518060400160405280600681526020017f303034303031000000000000000000000000000000000000000000000000000081525090611820576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016118179190615427565b60405180910390fd5b5061182a82613431565b6040518060400160405280600681526020017f3030343030320000000000000000000000000000000000000000000000000000815250906118a1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016118989190615427565b60405180910390fd5b50600073ffffffffffffffffffffffffffffffffffffffff166001600084815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146040518060400160405280600681526020017f30303430303700000000000000000000000000000000000000000000000000008152509061197c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016119739190615427565b60405180910390fd5b50611987838361344d565b505050565b60008060008061199b426134ad565b9250925092506000836011600001541480156119bb575082601160010154145b80156119cb575081601160020154145b156119dd5760116003015490506119e2565b600090505b8094505050505090565b611a07838383604051806020016040528060008152506134dc565b505050565b600080600080611a1b426134ad565b925092509250600080611a42601160040154611b58611a3a91906158e1565b600f54613aaa565b905084601160000154148015611a5c575083601160010154145b8015611a6c575082601160020154145b15611a895760116003015481611a8291906158e1565b9150611a8d565b8091505b6000821015611a9b57600091505b819550505050505090565b601660003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16156040518060400160405280600681526020017f303034303135000000000000000000000000000000000000000000000000000081525090611b6b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b629190615427565b60405180910390fd5b50611b74611a0c565b815111156040518060400160405280600681526020017f303034303134000000000000000000000000000000000000000000000000000081525090611bef576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611be69190615427565b60405180910390fd5b50600e54815111156040518060400160405280600681526020017f303034303133000000000000000000000000000000000000000000000000000081525090611c6e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c659190615427565b60405180910390fd5b5060006010548251611c8091906157f3565b9050348111156040518060400160405280600681526020017f303034303131000000000000000000000000000000000000000000000000000081525090611cfd576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611cf49190615427565b60405180910390fd5b5060005b8251811015611ec9576000838281518110611d45577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60200260200101519050611d5881613ac6565b6040518060400160405280600681526020017f303034303033000000000000000000000000000000000000000000000000000081525090611dcf576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611dc69190615427565b60405180910390fd5b50600073ffffffffffffffffffffffffffffffffffffffff166001600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146040518060400160405280600681526020017f303034303037000000000000000000000000000000000000000000000000000081525090611eaa576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ea19190615427565b60405180910390fd5b50611eb5338261344d565b508080611ec190615a62565b915050611d01565b506000806000611ed8426134ad565b92509250925082601160000154148015611ef6575081601160010154145b8015611f06575080601160020154145b15611f2d57845160116003016000828254611f2191906155eb565b92505081905550611f39565b84516011600301819055505b826011600001819055508160116001018190555080601160020181905550845160116004016000828254611f6d91906155eb565b925050819055506001601660003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055506000601054111561204157600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc349081150290604051600060405180830381858888f1935050505015801561203f573d6000803e3d6000fd5b505b5050505050565b6000600c54905090565b600060058054905082106040518060400160405280600681526020017f3030353030370000000000000000000000000000000000000000000000000000815250906120d3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016120ca9190615427565b60405180910390fd5b506005828154811061210e577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90600052602060002001549050919050565b600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146040518060400160405280600681526020017f3031383030310000000000000000000000000000000000000000000000000000815250906121e8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016121df9190615427565b60405180910390fd5b5080600a90805190602001906121ff929190614be1565b5050565b60006001600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156040518060400160405280600681526020017f3030333030320000000000000000000000000000000000000000000000000000815250906122e3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016122da9190615427565b60405180910390fd5b50919050565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614156040518060400160405280600681526020017f303033303031000000000000000000000000000000000000000000000000000081525090612392576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016123899190615427565b60405180910390fd5b5061239c82613ae0565b9050919050565b6060600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146040518060400160405280600681526020017f30313830303100000000000000000000000000000000000000000000000000008152509061246d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016124649190615427565b60405180910390fd5b50600a805461247b906159ff565b80601f01602080910402602001604051908101604052809291908181526020018280546124a7906159ff565b80156124f45780601f106124c9576101008083540402835291602001916124f4565b820191906000526020600020905b8154815290600101906020018083116124d757829003601f168201915b5050505050905090565b6040518060400160405280600681526020017f303138303032000000000000000000000000000000000000000000000000000081525081565b600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000600e54905090565b60606040518060400160405280600381526020017f434d4b0000000000000000000000000000000000000000000000000000000000815250905090565b80600460003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3183604051612695919061540c565b60405180910390a35050565b600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146040518060400160405280600681526020017f303138303031000000000000000000000000000000000000000000000000000081525090612769576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016127609190615427565b60405180910390fd5b5080600f8190555050565b6000601054905090565b6060600d548311156040518060400160405280600681526020017f3030343031320000000000000000000000000000000000000000000000000000815250906127fd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016127f49190615427565b60405180910390fd5b506000828461280c91906157f3565b905060006001858361281e91906155eb565b61282891906158e1565b90506001600c5461283991906158e1565b821115612852576001600c5461284f91906158e1565b91505b6001600c5461286191906158e1565b81111561287a576001600c5461287791906158e1565b90505b60008567ffffffffffffffff8111156128bc577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040519080825280602002602001820160405280156128f557816020015b6128e2614c67565b8152602001906001900390816128da5790505b50905060008390505b8281116129e15760006001600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905060006040518060800160405280848152602001600015158152602001600081526020018373ffffffffffffffffffffffffffffffffffffffff1681525090508084878561298a91906158e1565b815181106129c1577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6020026020010181905250505080806129d990615a62565b9150506128fe565b5080935050505092915050565b6000601160040154611b58612a0391906158e1565b905090565b612a5885858585858080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050506134dc565b5050505050565b60005b8151811015612ace576000828281518110612aa6577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60200260200101519050612aba84826116c0565b508080612ac690615a62565b915050612a62565b505050565b600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146040518060400160405280600681526020017f303138303031000000000000000000000000000000000000000000000000000081525090612b9b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612b929190615427565b60405180910390fd5b5080600e8190555050565b6000600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146040518060400160405280600681526020017f303138303031000000000000000000000000000000000000000000000000000081525090612c70576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612c679190615427565b60405180910390fd5b50600b60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6000600d54905090565b6060612d77600a8054612cb5906159ff565b80601f0160208091040260200160405190810160405280929190818152602001828054612ce1906159ff565b8015612d2e5780601f10612d0357610100808354040283529160200191612d2e565b820191906000526020600020905b815481529060010190602001808311612d1157829003601f168201915b50505050506040518060400160405280600181526020017f2f00000000000000000000000000000000000000000000000000000000000000815250612d7285613b2c565b613cdf565b9050919050565b8060008110158015612d9e57506001600c54612d9a91906158e1565b8111155b6040518060400160405280600681526020017f303034303031000000000000000000000000000000000000000000000000000081525090612e15576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612e0c9190615427565b60405180910390fd5b503373ffffffffffffffffffffffffffffffffffffffff163073ffffffffffffffffffffffffffffffffffffffff16636352211e846040518263ffffffff1660e01b8152600401612e669190615449565b60206040518083038186803b158015612e7e57600080fd5b505afa158015612e92573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612eb69190614eb3565b73ffffffffffffffffffffffffffffffffffffffff16146040518060400160405280600681526020017f303034303039000000000000000000000000000000000000000000000000000081525090612f44576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612f3b9190615427565b60405180910390fd5b50612f4f838361337c565b505050565b6000600460008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146040518060400160405280600681526020017f3031383030310000000000000000000000000000000000000000000000000000815250906130b0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016130a79190615427565b60405180910390fd5b50600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156040518060400160405280600681526020017f303138303032000000000000000000000000000000000000000000000000000081525090613159576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016131509190615427565b60405180910390fd5b508073ffffffffffffffffffffffffffffffffffffffff16600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a380600960006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6040518060400160405280600681526020017f303138303031000000000000000000000000000000000000000000000000000081525081565b600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146040518060400160405280600681526020017f30313830303100000000000000000000000000000000000000000000000000008152509061331b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016133129190615427565b60405180910390fd5b508060108190555050565b6000601660008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff169050919050565b60006001600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690506133bd82613d15565b6133c78183613db6565b6133d183836140ef565b818373ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4505050565b6000611b588210158015613446575061271082105b9050919050565b61345782826142ec565b6005819080600181540180825580915050600190039060005260206000200160009091909190915055600160058054905061349291906158e1565b60066000838152602001908152602001600020819055505050565b60008060006134c962015180856134c491906156ab565b6144da565b8093508194508295505050509193909250565b8160006001600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690503373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614806135ad57503373ffffffffffffffffffffffffffffffffffffffff166002600084815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16145b8061363e5750600460008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff165b6040518060400160405280600681526020017f3030333030340000000000000000000000000000000000000000000000000000815250906136b5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016136ac9190615427565b60405180910390fd5b5083600073ffffffffffffffffffffffffffffffffffffffff166001600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614156040518060400160405280600681526020017f303033303032000000000000000000000000000000000000000000000000000081525090613792576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016137899190615427565b60405180910390fd5b5060006001600087815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508773ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146040518060400160405280600681526020017f303033303037000000000000000000000000000000000000000000000000000081525090613871576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016138689190615427565b60405180910390fd5b50600073ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff1614156040518060400160405280600681526020017f30303330303100000000000000000000000000000000000000000000000000008152509061391a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016139119190615427565b60405180910390fd5b50613925878761337c565b6139448773ffffffffffffffffffffffffffffffffffffffff16614679565b15613aa05760008773ffffffffffffffffffffffffffffffffffffffff1663150b7a02338b8a8a6040518563ffffffff1660e01b815260040161398a949392919061539e565b602060405180830381600087803b1580156139a457600080fd5b505af11580156139b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139dc919061511d565b905063150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916146040518060400160405280600681526020017f303033303035000000000000000000000000000000000000000000000000000081525090613a9d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613a949190615427565b60405180910390fd5b50505b5050505050505050565b600081831115613abc57819050613ac0565b8290505b92915050565b6000808210158015613ad95750611b5882105b9050919050565b6000600760008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805490509050919050565b60606000821415613b74576040518060400160405280600181526020017f30000000000000000000000000000000000000000000000000000000000000008152509050613cda565b600082905060005b60008214613ba6578080613b8f90615a62565b915050600a82613b9f91906156ab565b9150613b7c565b60008167ffffffffffffffff811115613be8577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040519080825280601f01601f191660200182016040528015613c1a5781602001600182028036833780820191505090505b50905060008290508593505b60008414613cd257600a84613c3b9190615aab565b6030613c4791906155eb565b60f81b8282613c55906159d5565b92508281518110613c8f577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600a84613ccb91906156ab565b9350613c26565b819450505050505b919050565b6060613d0c84848460405180602001604052806000815250604051806020016040528060008152506146c4565b90509392505050565b600073ffffffffffffffffffffffffffffffffffffffff166002600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614613db3576002600082815260200190815260200160002060006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690555b50565b8173ffffffffffffffffffffffffffffffffffffffff166001600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146040518060400160405280600681526020017f303033303037000000000000000000000000000000000000000000000000000081525090613e8f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613e869190615427565b60405180910390fd5b506001600082815260200190815260200160002060006101000a81549073ffffffffffffffffffffffffffffffffffffffff021916905560006008600083815260200190815260200160002054905060006001600760008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080549050613f2f91906158e1565b905081811461405e576000600760008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208281548110613fb1577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b9060005260206000200154905080600760008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208481548110614036577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b9060005260206000200181905550826008600083815260200190815260200160002081905550505b600760008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054806140d3577f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b6001900381819060005260206000200160009055905550505050565b600073ffffffffffffffffffffffffffffffffffffffff166001600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146040518060400160405280600681526020017f3030333030360000000000000000000000000000000000000000000000000000815250906141c9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016141c09190615427565b60405180910390fd5b50816001600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600760008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190806001815401808255809150506001900390600052602060002001600090919091909150556001600760008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805490506142d191906158e1565b60086000838152602001908152602001600020819055505050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614156040518060400160405280600681526020017f303033303031000000000000000000000000000000000000000000000000000081525090614394576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161438b9190615427565b60405180910390fd5b50600073ffffffffffffffffffffffffffffffffffffffff166001600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146040518060400160405280600681526020017f30303330303600000000000000000000000000000000000000000000000000008152509061446f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016144669190615427565b60405180910390fd5b5061447a82826140ef565b808273ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a45050565b600080600080849050600062253d8c62010bd9836144f89190615557565b6145029190615557565b9050600062023ab182600461451791906156dc565b6145219190615641565b9050600460038262023ab161453691906156dc565b6145409190615557565b61454a9190615641565b82614555919061584d565b9150600062164b0960018461456a9190615557565b610fa061457791906156dc565b6145819190615641565b9050601f6004826105b561459591906156dc565b61459f9190615641565b846145aa919061584d565b6145b49190615557565b9250600061098f8460506145c891906156dc565b6145d29190615641565b9050600060508261098f6145e691906156dc565b6145f09190615641565b856145fb919061584d565b9050600b8261460a9190615641565b945084600c61461991906156dc565b6002836146269190615557565b614630919061584d565b91508483603186614641919061584d565b606461464d91906156dc565b6146579190615557565b6146619190615557565b92508298508197508096505050505050509193909250565b60008060007fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47060001b9050833f91506000801b82141580156146bb5750808214155b92505050919050565b6060600086905060008690506000869050600086905060008690506000815183518551875189516146f591906155eb565b6146ff91906155eb565b61470991906155eb565b61471391906155eb565b67ffffffffffffffff811115614752577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040519080825280601f01601f1916602001820160405280156147845781602001600182028036833780820191505090505b5090506000819050600080600090505b8851811015614868578881815181106147d6577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b602001015160f81c60f81b8383806147ed90615a62565b945081518110614826577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350808061486090615a62565b915050614794565b600090505b8751811015614941578781815181106148af577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b602001015160f81c60f81b8383806148c690615a62565b9450815181106148ff577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350808061493990615a62565b91505061486d565b600090505b8651811015614a1a57868181518110614988577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b602001015160f81c60f81b83838061499f90615a62565b9450815181106149d8577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508080614a1290615a62565b915050614946565b600090505b8551811015614af357858181518110614a61577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b602001015160f81c60f81b838380614a7890615a62565b945081518110614ab1577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508080614aeb90615a62565b915050614a1f565b600090505b8451811015614bcc57848181518110614b3a577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b602001015160f81c60f81b838380614b5190615a62565b945081518110614b8a577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508080614bc490615a62565b915050614af8565b82995050505050505050505095945050505050565b828054614bed906159ff565b90600052602060002090601f016020900481019282614c0f5760008555614c56565b82601f10614c2857805160ff1916838001178555614c56565b82800160010185558215614c56579182015b82811115614c55578251825591602001919060010190614c3a565b5b509050614c639190614ca7565b5090565b60405180608001604052806000815260200160001515815260200160008152602001600073ffffffffffffffffffffffffffffffffffffffff1681525090565b5b80821115614cc0576000816000905550600101614ca8565b5090565b6000614cd7614cd284615489565b615464565b90508083825260208201905082856020860282011115614cf657600080fd5b60005b85811015614d265781614d0c8882614e75565b845260208401935060208301925050600181019050614cf9565b5050509392505050565b6000614d43614d3e846154b5565b615464565b905082815260208101848484011115614d5b57600080fd5b614d66848285615993565b509392505050565b600081359050614d7d81615ba9565b92915050565b600081519050614d9281615ba9565b92915050565b600082601f830112614da957600080fd5b8135614db9848260208601614cc4565b91505092915050565b600081359050614dd181615bc0565b92915050565b600081359050614de681615bd7565b92915050565b600081519050614dfb81615bd7565b92915050565b60008083601f840112614e1357600080fd5b8235905067ffffffffffffffff811115614e2c57600080fd5b602083019150836001820283011115614e4457600080fd5b9250929050565b600082601f830112614e5c57600080fd5b8135614e6c848260208601614d30565b91505092915050565b600081359050614e8481615bee565b92915050565b600060208284031215614e9c57600080fd5b6000614eaa84828501614d6e565b91505092915050565b600060208284031215614ec557600080fd5b6000614ed384828501614d83565b91505092915050565b60008060408385031215614eef57600080fd5b6000614efd85828601614d6e565b9250506020614f0e85828601614d6e565b9150509250929050565b600080600060608486031215614f2d57600080fd5b6000614f3b86828701614d6e565b9350506020614f4c86828701614d6e565b9250506040614f5d86828701614e75565b9150509250925092565b600080600080600060808688031215614f7f57600080fd5b6000614f8d88828901614d6e565b9550506020614f9e88828901614d6e565b9450506040614faf88828901614e75565b935050606086013567ffffffffffffffff811115614fcc57600080fd5b614fd888828901614e01565b92509250509295509295909350565b60008060408385031215614ffa57600080fd5b600061500885828601614d6e565b925050602083013567ffffffffffffffff81111561502557600080fd5b61503185828601614d98565b9150509250929050565b6000806040838503121561504e57600080fd5b600061505c85828601614d6e565b925050602061506d85828601614dc2565b9150509250929050565b6000806040838503121561508a57600080fd5b600061509885828601614d6e565b92505060206150a985828601614e75565b9150509250929050565b6000602082840312156150c557600080fd5b600082013567ffffffffffffffff8111156150df57600080fd5b6150eb84828501614d98565b91505092915050565b60006020828403121561510657600080fd5b600061511484828501614dd7565b91505092915050565b60006020828403121561512f57600080fd5b600061513d84828501614dec565b91505092915050565b60006020828403121561515857600080fd5b600082013567ffffffffffffffff81111561517257600080fd5b61517e84828501614e4b565b91505092915050565b60006020828403121561519957600080fd5b60006151a784828501614e75565b91505092915050565b600080604083850312156151c357600080fd5b60006151d185828601614e75565b92505060206151e285828601614e75565b9150509250929050565b60006151f88383615310565b60808301905092915050565b61520d81615915565b82525050565b61521c81615915565b82525050565b600061522d826154f6565b6152378185615524565b9350615242836154e6565b8060005b8381101561527357815161525a88826151ec565b975061526583615517565b925050600181019050615246565b5085935050505092915050565b61528981615927565b82525050565b61529881615927565b82525050565b60006152a982615501565b6152b38185615535565b93506152c38185602086016159a2565b6152cc81615b98565b840191505092915050565b60006152e28261550c565b6152ec8185615546565b93506152fc8185602086016159a2565b61530581615b98565b840191505092915050565b6080820160008201516153266000850182615365565b5060208201516153396020850182615280565b50604082015161534c6040850182615365565b50606082015161535f6060850182615204565b50505050565b61536e81615989565b82525050565b61537d81615989565b82525050565b60006020820190506153986000830184615213565b92915050565b60006080820190506153b36000830187615213565b6153c06020830186615213565b6153cd6040830185615374565b81810360608301526153df818461529e565b905095945050505050565b600060208201905081810360008301526154048184615222565b905092915050565b6000602082019050615421600083018461528f565b92915050565b6000602082019050818103600083015261544181846152d7565b905092915050565b600060208201905061545e6000830184615374565b92915050565b600061546e61547f565b905061547a8282615a31565b919050565b6000604051905090565b600067ffffffffffffffff8211156154a4576154a3615b69565b5b602082029050602081019050919050565b600067ffffffffffffffff8211156154d0576154cf615b69565b5b6154d982615b98565b9050602081019050919050565b6000819050602082019050919050565b600081519050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b600082825260208201905092915050565b600082825260208201905092915050565b600082825260208201905092915050565b60006155628261595f565b915061556d8361595f565b9250817f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff038313600083121516156155a8576155a7615adc565b5b817f80000000000000000000000000000000000000000000000000000000000000000383126000831216156155e0576155df615adc565b5b828201905092915050565b60006155f682615989565b915061560183615989565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0382111561563657615635615adc565b5b828201905092915050565b600061564c8261595f565b91506156578361595f565b92508261566757615666615b0b565b5b600160000383147f8000000000000000000000000000000000000000000000000000000000000000831416156156a05761569f615adc565b5b828205905092915050565b60006156b682615989565b91506156c183615989565b9250826156d1576156d0615b0b565b5b828204905092915050565b60006156e78261595f565b91506156f28361595f565b9250827f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048211600084136000841316161561573157615730615adc565b5b817f8000000000000000000000000000000000000000000000000000000000000000058312600084126000841316161561576e5761576d615adc565b5b827f800000000000000000000000000000000000000000000000000000000000000005821260008413600084121616156157ab576157aa615adc565b5b827f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff05821260008412600084121616156157e8576157e7615adc565b5b828202905092915050565b60006157fe82615989565b915061580983615989565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561584257615841615adc565b5b828202905092915050565b60006158588261595f565b91506158638361595f565b9250827f80000000000000000000000000000000000000000000000000000000000000000182126000841215161561589e5761589d615adc565b5b827f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0182136000841216156158d6576158d5615adc565b5b828203905092915050565b60006158ec82615989565b91506158f783615989565b92508282101561590a57615909615adc565b5b828203905092915050565b600061592082615969565b9050919050565b60008115159050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b6000819050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b82818337600083830152505050565b60005b838110156159c05780820151818401526020810190506159a5565b838111156159cf576000848401525b50505050565b60006159e082615989565b915060008214156159f4576159f3615adc565b5b600182039050919050565b60006002820490506001821680615a1757607f821691505b60208210811415615a2b57615a2a615b3a565b5b50919050565b615a3a82615b98565b810181811067ffffffffffffffff82111715615a5957615a58615b69565b5b80604052505050565b6000615a6d82615989565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821415615aa057615a9f615adc565b5b600182019050919050565b6000615ab682615989565b9150615ac183615989565b925082615ad157615ad0615b0b565b5b828206905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000601f19601f8301169050919050565b615bb281615915565b8114615bbd57600080fd5b50565b615bc981615927565b8114615bd457600080fd5b50565b615be081615933565b8114615beb57600080fd5b50565b615bf781615989565b8114615c0257600080fd5b5056fea2646970667358221220e7168e71313d50a51c8a8164e260779e4b759679ea2685197c8bf7d4f8222ad764736f6c63430008040033

Deployed Bytecode Sourcemap

288:9321:3:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;715:172:14;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;3767:120:3;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;3103:115;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;8158:183:12;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;5943:352;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;9407:199:3;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;1227:120:10;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;5169:353:12;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;4576:97:3;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;1924:251:10;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;8747:259:3;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;5761:495;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;4414:179:12;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;6264:684:3;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;7072:1667;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;4703:89;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;1488:199:10;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;3552:98:3;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;7706:208:12;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;7232:204;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;3658:101:3;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;488:65:13;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;608:20;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;4345:99:3;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;3226:104;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;6706:232:12;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;4452:116:3;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;4120:89;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;5021:732;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;4901:112;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;3795:209:12;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;9014:205:3;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;4217:120;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;3895:109;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;4800:93;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;3338:183;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;9227:172;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;8610:192:12;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;1433:238:13;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;432:51;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;4012:100:3;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;6956:108;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;715:172:14;825:4;848:19;:33;868:12;848:33;;;;;;;;;;;;;;;;;;;;;;;;;;;841:40;;715:172;;;:::o;3767:120:3:-;1226:5:13;;;;;;;;;;;1212:19;;:10;:19;;;1233:17;;;;;;;;;;;;;;;;;1204:47;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;3864:15:3::1;3847:14;;:32;;;;;;;;;;;;;;;;;;3767:120:::0;:::o;3103:115::-;3151:19;3183:27;;;;;;;;;;;;;;;;;;;3103:115;:::o;8158:183:12:-;8287:7;8263:8;2758:1;2727:33;;:9;:19;2737:8;2727:19;;;;;;;;;;;;;;;;;;;;;:33;;;;2762:13;;;;;;;;;;;;;;;;;2719:57;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;8313:12:::1;:22;8326:8;8313:22;;;;;;;;;;;;;;;;;;;;;8306:29;;8158:183:::0;;;;:::o;5943:352::-;6056:8;1911:18;1932:9;:19;1942:8;1932:19;;;;;;;;;;;;;;;;;;;;;1911:40;;1988:10;1974:24;;:10;:24;;;:68;;;;2002:16;:28;2019:10;2002:28;;;;;;;;;;;;;;;:40;2031:10;2002:40;;;;;;;;;;;;;;;;;;;;;;;;;1974:68;2051:21;;;;;;;;;;;;;;;;;1958:121;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;6084:8:::1;2758:1;2727:33;;:9;:19;2737:8;2727:19;;;;;;;;;;;;;;;;;;;;;:33;;;;2762:13;;;;;;;;;;;;;;;;::::0;2719:57:::1;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;6104:18:::2;6125:9;:19;6135:8;6125:19;;;;;;;;;;;;;;;;;;;;;6104:40;;6172:10;6159:23;;:9;:23;;;;6184:8;;;;;;;;;;;;;;;;::::0;6151:42:::2;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;6227:9;6202:12;:22;6215:8;6202:22;;;;;;;;;;;;:34;;;;;;;;;;;;;;;;;;6280:8;6269:9;6248:41;;6257:10;6248:41;;;;;;;;;;;;2783:1;2086::::1;5943:352:::0;;;;:::o;9407:199:3:-;9484:9;9479:120;9503:4;:11;9499:1;:15;9479:120;;;9536:10;9549:4;9554:1;9549:7;;;;;;;;;;;;;;;;;;;;;;9536:20;;9571:16;9579:3;9584:2;9571:7;:16::i;:::-;9479:120;9516:3;;;;;:::i;:::-;;;;9479:120;;;;9407:199;;:::o;1227:120:10:-;1302:7;1328:6;:13;;;;1321:20;;1227:120;:::o;5169:353:12:-;5302:8;2291:18;2312:9;:19;2322:8;2312:19;;;;;;;;;;;;;;;;;;;;;2291:40;;2368:10;2354:24;;:10;:24;;;:71;;;;2415:10;2389:36;;:12;:22;2402:8;2389:22;;;;;;;;;;;;;;;;;;;;;:36;;;2354:71;:122;;;;2436:16;:28;2453:10;2436:28;;;;;;;;;;;;;;;:40;2465:10;2436:40;;;;;;;;;;;;;;;;;;;;;;;;;2354:122;2485:30;;;;;;;;;;;;;;;;;2338:184;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;5330:8:::1;2758:1;2727:33;;:9;:19;2737:8;2727:19;;;;;;;;;;;;;;;;;;;;;:33;;;;2762:13;;;;;;;;;;;;;;;;::::0;2719:57:::1;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;5350:18:::2;5371:9;:19;5381:8;5371:19;;;;;;;;;;;;;;;;;;;;;5350:40;;5419:5;5405:19;;:10;:19;;;5426:9;;;;;;;;;;;;;;;;::::0;5397:39:::2;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;5466:1;5451:17;;:3;:17;;;;5470:12;;;;;;;;;;;;;;;;::::0;5443:40:::2;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;5492:24;5502:3;5507:8;5492:9;:24::i;:::-;2783:1;2529::::1;5169:353:::0;;;;;:::o;4576:97:3:-;4625:7;4652:13;;4645:20;;4576:97;:::o;1924:251:10:-;2052:7;2088:10;:18;2099:6;2088:18;;;;;;;;;;;;;;;:25;;;;2079:6;:34;2115:13;;;;;;;;;;;;;;;;;2071:58;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;2143:10;:18;2154:6;2143:18;;;;;;;;;;;;;;;2162:6;2143:26;;;;;;;;;;;;;;;;;;;;;;;;2136:33;;1924:251;;;;:::o;8747:259:3:-;2181:14;;;;;;;;;;;2167:28;;:10;:28;;;2197:19;;;;;;;;;;;;;;;;;2159:58;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;8850:3:::1;2304:1;2297:3;:8;;:32;;;;;2328:1;2316:9;;:13;;;;:::i;:::-;2309:3;:20;;2297:32;2331:16;;;;;;;;;;;;;;;;::::0;2289:59:::1;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;8879:14:::2;8889:3;8879:9;:14::i;:::-;8895:11;;;;;;;;;;;;;;;;::::0;8871:36:::2;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;8952:1;8926:28;;:9;:14;8936:3;8926:14;;;;;;;;;;;;;;;;;;;;;:28;;;8956:13;;;;;;;;;;;;;;;;::::0;8918:52:::2;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;8983:15;8989:3;8994;8983:5;:15::i;:::-;2228:1:::1;8747:259:::0;;:::o;5761:495::-;5812:7;5832:12;5846:13;5861:11;5876:74;5934:15;5876:57;:74::i;:::-;5831:119;;;;;;5961:10;6025:4;6002:10;:19;;;:27;:73;;;;;6070:5;6046:10;:20;;;:29;6002:73;:115;;;;;6114:3;6092:10;:18;;;:25;6002:115;5984:242;;;6152:10;:20;;;6144:28;;5984:242;;;6213:1;6205:9;;5984:242;6243:5;6236:12;;;;;;5761:495;:::o;4414:179:12:-;4544:43;4562:5;4569:3;4574:8;4544:43;;;;;;;;;;;;:17;:43::i;:::-;4414:179;;;:::o;6264:684:3:-;6318:7;6339:12;6353:13;6368:11;6383:74;6441:15;6383:57;:74::i;:::-;6338:119;;;;;;6470:13;6498:19;6520:56;6543:10;:17;;;6536:4;:24;;;;:::i;:::-;6562:13;;6520:15;:56::i;:::-;6498:78;;6628:4;6605:10;:19;;;:27;:73;;;;;6673:5;6649:10;:20;;;:29;6605:73;:115;;;;;6717:3;6695:10;:18;;;:25;6605:115;6587:266;;;6769:10;:20;;;6755:11;:34;;;;:::i;:::-;6747:42;;6587:266;;;6830:11;6822:19;;6587:266;6877:1;6869:5;:9;6865:51;;;6903:1;6895:9;;6865:51;6935:5;6928:12;;;;;;;6264:684;:::o;7072:1667::-;7176:15;:27;7192:10;7176:27;;;;;;;;;;;;;;;;;;;;;;;;;7175:28;7205:13;;;;;;;;;;;;;;;;;7167:52;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;7310:23;:21;:23::i;:::-;7295:4;:11;:38;;7348:23;;;;;;;;;;;;;;;;;7273:109;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;7459:14;;7444:4;:11;:29;;7475:24;;;;;;;;;;;;;;;;;7436:64;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;7513:13;7543:9;;7529:4;:11;:23;;;;:::i;:::-;7513:39;;7580:9;7571:5;:18;;7591;;;;;;;;;;;;;;;;;7563:47;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;7628:9;7623:245;7647:4;:11;7643:1;:15;7623:245;;;7680:11;7694:4;7699:1;7694:7;;;;;;;;;;;;;;;;;;;;;;7680:21;;7724:13;7733:3;7724:8;:13::i;:::-;7739:10;;;;;;;;;;;;;;;;;7716:34;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;7799:1;7773:28;;:9;:14;7783:3;7773:14;;;;;;;;;;;;;;;;;;;;;:28;;;7803:13;;;;;;;;;;;;;;;;;7765:52;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;7834:22;7840:10;7852:3;7834:5;:22::i;:::-;7623:245;7660:3;;;;;:::i;:::-;;;;7623:245;;;;7915:12;7929:13;7944:11;7959:74;8017:15;7959:57;:74::i;:::-;7914:119;;;;;;8087:4;8064:10;:19;;;:27;:73;;;;;8132:5;8108:10;:20;;;:29;8064:73;:115;;;;;8176:3;8154:10;:18;;;:25;8064:115;8046:274;;;8230:4;:11;8206:10;:20;;;:35;;;;;;;:::i;:::-;;;;;;;;8046:274;;;8297:4;:11;8274:10;:20;;:34;;;;8046:274;8391:4;8369:10;:19;;:26;;;;8429:5;8406:10;:20;;:28;;;;8466:3;8445:10;:18;;:24;;;;8534:4;:11;8513:10;:17;;;:32;;;;;;;:::i;:::-;;;;;;;;8616:4;8586:15;:27;8602:10;8586:27;;;;;;;;;;;;;;;;:34;;;;;;;;;;;;;;;;;;8668:1;8656:9;;:13;8652:80;;;8694:5;;;;;;;;;;;8686:23;;:34;8710:9;8686:34;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8652:80;7072:1667;;;;;:::o;4703:89::-;4748:7;4775:9;;4768:16;;4703:89;:::o;1488:199:10:-;1588:7;1624:6;:13;;;;1615:6;:22;1639:13;;;;;;;;;;;;;;;;;1607:46;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;1667:6;1674;1667:14;;;;;;;;;;;;;;;;;;;;;;;;1660:21;;1488:199;;;:::o;3552:98:3:-;1226:5:13;;;;;;;;;;;1212:19;;:10;:19;;;1233:17;;;;;;;;;;;;;;;;;1204:47;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;3634:8:3::1;3624:7;:18;;;;;;;;;;;;:::i;:::-;;3552:98:::0;:::o;7706:208:12:-;7803:14;7838:9;:19;7848:8;7838:19;;;;;;;;;;;;;;;;;;;;;7829:28;;7890:1;7872:20;;:6;:20;;;;7894:13;;;;;;;;;;;;;;;;;7864:44;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;7706:208;;;:::o;7232:204::-;7329:7;7374:1;7356:20;;:6;:20;;;;7378:12;;;;;;;;;;;;;;;;;7348:43;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;7405:25;7423:6;7405:17;:25::i;:::-;7398:32;;7232:204;;;:::o;3658:101:3:-;3711:13;1226:5:13;;;;;;;;;;;1212:19;;:10;:19;;;1233:17;;;;;;;;;;;;;;;;;1204:47;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;3744:7:3::1;3737:14;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3658:101:::0;:::o;488:65:13:-;;;;;;;;;;;;;;;;;;;:::o;608:20::-;;;;;;;;;;;;;:::o;4345:99:3:-;4395:7;4422:14;;4415:21;;4345:99;:::o;3226:104::-;3276:21;3310:12;;;;;;;;;;;;;;;;;;;3226:104;:::o;6706:232:12:-;6863:9;6821:16;:28;6838:10;6821:28;;;;;;;;;;;;;;;:39;6850:9;6821:39;;;;;;;;;;;;;;;;:51;;;;;;;;;;;;;;;;;;6911:9;6884:48;;6899:10;6884:48;;;6922:9;6884:48;;;;;;:::i;:::-;;;;;;;;6706:232;;:::o;4452:116:3:-;1226:5:13;;;;;;;;;;;1212:19;;:10;:19;;;1233:17;;;;;;;;;;;;;;;;;1204:47;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;4546:14:3::1;4530:13;:30;;;;4452:116:::0;:::o;4120:89::-;4165:7;4192:9;;4185:16;;4120:89;:::o;5021:732::-;5128:12;5178:11;;5166:8;:23;;5191:20;;;;;;;;;;;;;;;;;5158:54;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;5225:13;5252:9;5241:8;:20;;;;:::i;:::-;5225:36;;5272:11;5305:1;5294:8;5286:5;:16;;;;:::i;:::-;:20;;;;:::i;:::-;5272:34;;5343:1;5331:9;;:13;;;;:::i;:::-;5323:5;:21;5319:75;;;5381:1;5369:9;;:13;;;;:::i;:::-;5361:21;;5319:75;5428:1;5416:9;;:13;;;;:::i;:::-;5410:3;:19;5406:71;;;5464:1;5452:9;;:13;;;;:::i;:::-;5446:19;;5406:71;5489:17;5519:8;5509:19;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;5489:39;;5544:9;5556:5;5544:17;;5539:185;5568:3;5563:1;:8;5539:185;;5593:13;5609:9;:12;5619:1;5609:12;;;;;;;;;;;;;;;;;;;;;5593:28;;5636:14;5653:23;;;;;;;;5657:1;5653:23;;;;5660:5;5653:23;;;;;;5667:1;5653:23;;;;5670:5;5653:23;;;;;5636:40;;5709:3;5691:4;5700:5;5696:1;:9;;;;:::i;:::-;5691:15;;;;;;;;;;;;;;;;;;;;;:21;;;;5539:185;;5573:3;;;;;:::i;:::-;;;;5539:185;;;;5741:4;5734:11;;;;;5021:732;;;;:::o;4901:112::-;4954:7;4988:10;:17;;;4981:4;:24;;;;:::i;:::-;4974:31;;4901:112;:::o;3795:209:12:-;3952:46;3970:5;3977:3;3982:8;3992:5;;3952:46;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:17;:46::i;:::-;3795:209;;;;;:::o;9014:205:3:-;9094:9;9089:123;9113:4;:11;9109:1;:15;9089:123;;;9146:10;9159:4;9164:1;9159:7;;;;;;;;;;;;;;;;;;;;;;9146:20;;9181:19;9192:3;9197:2;9181:10;:19::i;:::-;9089:123;9126:3;;;;;:::i;:::-;;;;9089:123;;;;9014:205;;:::o;4217:120::-;1226:5:13;;;;;;;;;;;1212:19;;:10;:19;;;1233:17;;;;;;;;;;;;;;;;;1204:47;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;4314:15:3::1;4297:14;:32;;;;4217:120:::0;:::o;3895:109::-;3955:7;1226:5:13;;;;;;;;;;;1212:19;;:10;:19;;;1233:17;;;;;;;;;;;;;;;;;1204:47;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;3982:14:3::1;;;;;;;;;;;3975:21;;3895:109:::0;:::o;4800:93::-;4847:7;4874:11;;4867:18;;4800:93;:::o;3338:183::-;3437:13;3475:38;3485:7;3475:38;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3499:13;3508:3;3499:8;:13::i;:::-;3475:9;:38::i;:::-;3468:45;;3338:183;;;:::o;9227:172::-;9288:3;2304:1;2297:3;:8;;:32;;;;;2328:1;2316:9;;:13;;;;:::i;:::-;2309:3;:20;;2297:32;2331:16;;;;;;;;;;;;;;;;;2289:59;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;9333:10:::1;9312:31;;:4;:12;;;9325:3;9312:17;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:31;;;9345:13;;;;;;;;;;;;;;;;::::0;9304:55:::1;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;9372:19;9382:3;9387;9372:9;:19::i;:::-;9227:172:::0;;;:::o;8610:192:12:-;8738:4;8761:16;:24;8778:6;8761:24;;;;;;;;;;;;;;;:35;8786:9;8761:35;;;;;;;;;;;;;;;;;;;;;;;;;8754:42;;8610:192;;;;:::o;1433:238:13:-;1226:5;;;;;;;;;;;1212:19;;:10;:19;;;1233:17;;;;;;;;;;;;;;;;;1204:47;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;1555:1:::1;1534:23;;:9;:23;;;;1559:31;;;;;;;;;;;;;;;;::::0;1526:65:::1;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;1631:9;1603:38;;1624:5;;;;;;;;;;;1603:38;;;;;;;;;;;;1656:9;1648:5;;:17;;;;;;;;;;;;;;;;;;1433:238:::0;:::o;432:51::-;;;;;;;;;;;;;;;;;;;:::o;4012:100:3:-;1226:5:13;;;;;;;;;;;1212:19;;:10;:19;;;1233:17;;;;;;;;;;;;;;;;;1204:47;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;4094:10:3::1;4082:9;:22;;;;4012:100:::0;:::o;6956:108::-;7010:4;7034:15;:22;7050:5;7034:22;;;;;;;;;;;;;;;;;;;;;;;;;7027:29;;6956:108;;;:::o;8993:275:12:-;9082:12;9097:9;:19;9107:8;9097:19;;;;;;;;;;;;;;;;;;;;;9082:34;;9123:24;9138:8;9123:14;:24::i;:::-;9156:30;9171:4;9177:8;9156:14;:30::i;:::-;9193:26;9205:3;9210:8;9193:11;:26::i;:::-;9253:8;9248:3;9233:29;;9242:4;9233:29;;;;;;;;;;;;8993:275;;;:::o;2457:113:3:-;2512:4;2543;2536:3;:11;;:26;;;;;2557:5;2551:3;:11;2536:26;2529:33;;2457:113;;;:::o;2566:218:10:-;2678:26;2690:3;2695:8;2678:11;:26::i;:::-;2711:6;2723:8;2711:21;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2777:1;2761:6;:13;;;;:17;;;;:::i;:::-;2739:9;:19;2749:8;2739:19;;;;;;;;;;;:39;;;;2566:218;;:::o;4502:177:4:-;4566:9;4577:10;4589:8;4631:40;1048:12;4643:9;:27;;;;:::i;:::-;4631:11;:40::i;:::-;4610:61;;;;;;;;;;;;4502:177;;;;;:::o;12450:590:12:-;12598:8;2291:18;2312:9;:19;2322:8;2312:19;;;;;;;;;;;;;;;;;;;;;2291:40;;2368:10;2354:24;;:10;:24;;;:71;;;;2415:10;2389:36;;:12;:22;2402:8;2389:22;;;;;;;;;;;;;;;;;;;;;:36;;;2354:71;:122;;;;2436:16;:28;2453:10;2436:28;;;;;;;;;;;;;;;:40;2465:10;2436:40;;;;;;;;;;;;;;;;;;;;;;;;;2354:122;2485:30;;;;;;;;;;;;;;;;;2338:184;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;12626:8:::1;2758:1;2727:33;;:9;:19;2737:8;2727:19;;;;;;;;;;;;;;;;;;;;;:33;;;;2762:13;;;;;;;;;;;;;;;;::::0;2719:57:::1;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;12646:18:::2;12667:9;:19;12677:8;12667:19;;;;;;;;;;;;;;;;;;;;;12646:40;;12715:5;12701:19;;:10;:19;;;12722:9;;;;;;;;;;;;;;;;::::0;12693:39:::2;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;12762:1;12747:17;;:3;:17;;;;12766:12;;;;;;;;;;;;;;;;::::0;12739:40:::2;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;12788:24;12798:3;12803:8;12788:9;:24::i;:::-;12825:16;:3;:14;;;:16::i;:::-;12821:214;;;12857:13;12893:3;12873:41;;;12915:10;12927:5;12934:8;12944:5;12873:77;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;12857:93;;1131:10;12977:24;;12967:34;;;:6;:34;;;;13003:23;;;;;;;;;;;;;;;;::::0;12959:68:::2;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;12821:214;;2783:1;2529::::1;12450:590:::0;;;;;;:::o;89:126:2:-;148:7;172:1;170;:3;167:40;;;182:1;175:8;;;;167:40;206:1;199:8;;89:126;;;;;:::o;2578:108:3:-;2632:4;2663:1;2656:3;:8;;:22;;;;;2674:4;2668:3;:10;2656:22;2649:29;;2578:108;;;:::o;5446:175:10:-;5564:7;5590:10;:18;5601:6;5590:18;;;;;;;;;;;;;;;:25;;;;5583:32;;5446:175;;;:::o;223:509:2:-;276:17;316:1;310:2;:7;306:50;;;334:10;;;;;;;;;;;;;;;;;;;;;306:50;366:9;378:2;366:14;;391;416:72;428:1;423;:6;416:72;;446:8;;;;;:::i;:::-;;;;474:2;469:7;;;;;:::i;:::-;;;416:72;;;498:17;528:6;518:17;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;498:37;;546:9;558:6;546:18;;579:2;575:6;;592:104;604:1;599;:6;592:104;;657:2;653:1;:6;;;;:::i;:::-;647:2;:13;;;;:::i;:::-;634:28;;622:4;627:3;;;;:::i;:::-;;;;622:9;;;;;;;;;;;;;;;;;;;:40;;;;;;;;;;;682:2;677:7;;;;;:::i;:::-;;;592:104;;;719:4;706:18;;223:509;;;;;;;;:::o;948:220::-;1078:33;1131:29;1141:2;1145;1149;1131:29;;;;;;;;;;;;;;;;;;;;;;;;:9;:29::i;:::-;1124:36;;948:220;;;;;:::o;13173:173:12:-;13286:1;13252:36;;:12;:22;13265:8;13252:22;;;;;;;;;;;;;;;;;;;;;:36;;;13248:93;;13311:12;:22;13324:8;13311:22;;;;;;;;;;;;13304:29;;;;;;;;;;;13248:93;13173:173;:::o;3961:602:10:-;4115:5;4092:28;;:9;:19;4102:8;4092:19;;;;;;;;;;;;;;;;;;;;;:28;;;4122:9;;;;;;;;;;;;;;;;;4084:48;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;4146:9;:19;4156:8;4146:19;;;;;;;;;;;;4139:26;;;;;;;;;;;4174;4203:14;:24;4218:8;4203:24;;;;;;;;;;;;4174:53;;4234:22;4286:1;4259:10;:17;4270:5;4259:17;;;;;;;;;;;;;;;:24;;;;:28;;;;:::i;:::-;4234:53;;4318:18;4300:14;:36;4296:230;;4352:17;4372:10;:17;4383:5;4372:17;;;;;;;;;;;;;;;4390:14;4372:33;;;;;;;;;;;;;;;;;;;;;;;;4352:53;;4454:9;4414:10;:17;4425:5;4414:17;;;;;;;;;;;;;;;4432:18;4414:37;;;;;;;;;;;;;;;;;;;;;;;:49;;;;4500:18;4472:14;:25;4487:9;4472:25;;;;;;;;;;;:46;;;;4296:230;;4534:10;:17;4545:5;4534:17;;;;;;;;;;;;;;;:23;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3961:602;;;;:::o;4834:317::-;4991:1;4960:33;;:9;:19;4970:8;4960:19;;;;;;;;;;;;;;;;;;;;;:33;;;4995:18;;;;;;;;;;;;;;;;;4952:62;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;5043:3;5021:9;:19;5031:8;5021:19;;;;;;;;;;;;:25;;;;;;;;;;;;;;;;;;5055:10;:15;5066:3;5055:15;;;;;;;;;;;;;;;5076:8;5055:30;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5144:1;5119:10;:15;5130:3;5119:15;;;;;;;;;;;;;;;:22;;;;:26;;;;:::i;:::-;5092:14;:24;5107:8;5092:24;;;;;;;;;;;:53;;;;4834:317;;:::o;9659:297:12:-;9780:1;9765:17;;:3;:17;;;;9784:12;;;;;;;;;;;;;;;;;9757:40;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;9843:1;9812:33;;:9;:19;9822:8;9812:19;;;;;;;;;;;;;;;;;;;;;:33;;;9847:18;;;;;;;;;;;;;;;;;9804:62;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;9875:26;9887:3;9892:8;9875:11;:26::i;:::-;9941:8;9936:3;9915:35;;9932:1;9915:35;;;;;;;;;;;;9659:297;;:::o;3396:622:4:-;3452:9;3463:10;3475:8;3496:10;3513:5;3496:23;;3532:5;1188:7;3549:5;3540:6;:14;;;;:::i;:::-;:31;;;;:::i;:::-;3532:39;;3582:5;3598:6;3594:1;3590;:5;;;;:::i;:::-;:14;;;;:::i;:::-;3582:22;;3642:1;3637;3633;3624:6;:10;;;;:::i;:::-;:14;;;;:::i;:::-;3623:20;;;;:::i;:::-;3619:1;:24;;;;:::i;:::-;3615:28;;3654:9;3683:7;3678:1;3674;:5;;;;:::i;:::-;3666:4;:14;;;;:::i;:::-;:24;;;;:::i;:::-;3654:36;;3728:2;3724:1;3716:5;3709:4;:12;;;;:::i;:::-;:16;;;;:::i;:::-;3705:1;:20;;;;:::i;:::-;:25;;;;:::i;:::-;3701:29;;3741:10;3763:4;3759:1;3754:2;:6;;;;:::i;:::-;:13;;;;:::i;:::-;3741:26;;3778:8;3809:2;3800:6;3793:4;:13;;;;:::i;:::-;:18;;;;:::i;:::-;3789:1;:22;;;;:::i;:::-;3778:33;;3835:2;3826:6;:11;;;;:::i;:::-;3822:15;;3875:1;3870:2;:6;;;;:::i;:::-;3866:1;3857:6;:10;;;;:::i;:::-;:19;;;;:::i;:::-;3848:28;;3920:1;3912:5;3906:2;3902:1;:6;;;;:::i;:::-;3895:3;:14;;;;:::i;:::-;:22;;;;:::i;:::-;:26;;;;:::i;:::-;3887:34;;3946:5;3934:18;;3976:6;3963:20;;4005:4;3994:16;;3396:622;;;;;;;;;;;:::o;484:780:1:-;567:17;1008:16;1031:19;1053:66;1031:88;;;;1161:5;1149:18;1137:30;;1227:3;1215:15;;:8;:15;;:42;;;;;1246:11;1234:8;:23;;1215:42;1199:59;;484:780;;;;;:::o;1431:1128:2:-;1615:33;1661:16;1686:2;1661:28;;1700:16;1725:2;1700:28;;1739:16;1764:2;1739:28;;1778:16;1803:2;1778:28;;1817:16;1842:2;1817:28;;1856:19;1955:3;:10;1942:3;:10;1929:3;:10;1916:3;:10;1903:3;:10;:23;;;;:::i;:::-;:36;;;;:::i;:::-;:49;;;;:::i;:::-;:62;;;;:::i;:::-;1878:98;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1856:120;;1987:19;2015:5;1987:34;;2032:9;2056;2089:1;2085:5;;2080:80;2096:3;:10;2092:1;:14;2080:80;;;2142:3;2146:1;2142:6;;;;;;;;;;;;;;;;;;;;;;;;2128;2135:3;;;;;:::i;:::-;;;2128:11;;;;;;;;;;;;;;;;;;;:20;;;;;;;;;;;2108:3;;;;;:::i;:::-;;;;2080:80;;;2179:1;2175:5;;2170:80;2186:3;:10;2182:1;:14;2170:80;;;2232:3;2236:1;2232:6;;;;;;;;;;;;;;;;;;;;;;;;2218;2225:3;;;;;:::i;:::-;;;2218:11;;;;;;;;;;;;;;;;;;;:20;;;;;;;;;;;2198:3;;;;;:::i;:::-;;;;2170:80;;;2269:1;2265:5;;2260:80;2276:3;:10;2272:1;:14;2260:80;;;2322:3;2326:1;2322:6;;;;;;;;;;;;;;;;;;;;;;;;2308;2315:3;;;;;:::i;:::-;;;2308:11;;;;;;;;;;;;;;;;;;;:20;;;;;;;;;;;2288:3;;;;;:::i;:::-;;;;2260:80;;;2359:1;2355:5;;2350:80;2366:3;:10;2362:1;:14;2350:80;;;2412:3;2416:1;2412:6;;;;;;;;;;;;;;;;;;;;;;;;2398;2405:3;;;;;:::i;:::-;;;2398:11;;;;;;;;;;;;;;;;;;;:20;;;;;;;;;;;2378:3;;;;;:::i;:::-;;;;2350:80;;;2449:1;2445:5;;2440:80;2456:3;:10;2452:1;:14;2440:80;;;2502:3;2506:1;2502:6;;;;;;;;;;;;;;;;;;;;;;;;2488;2495:3;;;;;:::i;:::-;;;2488:11;;;;;;;;;;;;;;;;;;;:20;;;;;;;;;;;2468:3;;;;;:::i;:::-;;;;2440:80;;;2544:6;2530:21;;;;;;;;;;;1431:1128;;;;;;;:::o;-1:-1:-1:-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;:::o;24:655:15:-;120:5;145:81;161:64;218:6;161:64;:::i;:::-;145:81;:::i;:::-;136:90;;246:5;275:6;268:5;261:21;309:4;302:5;298:16;291:23;;335:6;385:3;377:4;369:6;365:17;360:3;356:27;353:36;350:2;;;414:1;411;404:12;350:2;450:1;435:238;460:6;457:1;454:13;435:238;;;528:3;557:37;590:3;578:10;557:37;:::i;:::-;552:3;545:50;624:4;619:3;615:14;608:21;;658:4;653:3;649:14;642:21;;495:178;482:1;479;475:9;470:14;;435:238;;;439:14;126:553;;;;;;;:::o;685:345::-;763:5;788:66;804:49;846:6;804:49;:::i;:::-;788:66;:::i;:::-;779:75;;877:6;870:5;863:21;915:4;908:5;904:16;953:3;944:6;939:3;935:16;932:25;929:2;;;970:1;967;960:12;929:2;983:41;1017:6;1012:3;1007;983:41;:::i;:::-;769:261;;;;;;:::o;1036:139::-;1082:5;1120:6;1107:20;1098:29;;1136:33;1163:5;1136:33;:::i;:::-;1088:87;;;;:::o;1181:143::-;1238:5;1269:6;1263:13;1254:22;;1285:33;1312:5;1285:33;:::i;:::-;1244:80;;;;:::o;1347:303::-;1418:5;1467:3;1460:4;1452:6;1448:17;1444:27;1434:2;;1485:1;1482;1475:12;1434:2;1525:6;1512:20;1550:94;1640:3;1632:6;1625:4;1617:6;1613:17;1550:94;:::i;:::-;1541:103;;1424:226;;;;;:::o;1656:133::-;1699:5;1737:6;1724:20;1715:29;;1753:30;1777:5;1753:30;:::i;:::-;1705:84;;;;:::o;1795:137::-;1840:5;1878:6;1865:20;1856:29;;1894:32;1920:5;1894:32;:::i;:::-;1846:86;;;;:::o;1938:141::-;1994:5;2025:6;2019:13;2010:22;;2041:32;2067:5;2041:32;:::i;:::-;2000:79;;;;:::o;2098:351::-;2155:8;2165:6;2215:3;2208:4;2200:6;2196:17;2192:27;2182:2;;2233:1;2230;2223:12;2182:2;2269:6;2256:20;2246:30;;2299:18;2291:6;2288:30;2285:2;;;2331:1;2328;2321:12;2285:2;2368:4;2360:6;2356:17;2344:29;;2422:3;2414:4;2406:6;2402:17;2392:8;2388:32;2385:41;2382:2;;;2439:1;2436;2429:12;2382:2;2172:277;;;;;:::o;2469:273::-;2525:5;2574:3;2567:4;2559:6;2555:17;2551:27;2541:2;;2592:1;2589;2582:12;2541:2;2632:6;2619:20;2657:79;2732:3;2724:6;2717:4;2709:6;2705:17;2657:79;:::i;:::-;2648:88;;2531:211;;;;;:::o;2748:139::-;2794:5;2832:6;2819:20;2810:29;;2848:33;2875:5;2848:33;:::i;:::-;2800:87;;;;:::o;2893:262::-;2952:6;3001:2;2989:9;2980:7;2976:23;2972:32;2969:2;;;3017:1;3014;3007:12;2969:2;3060:1;3085:53;3130:7;3121:6;3110:9;3106:22;3085:53;:::i;:::-;3075:63;;3031:117;2959:196;;;;:::o;3161:284::-;3231:6;3280:2;3268:9;3259:7;3255:23;3251:32;3248:2;;;3296:1;3293;3286:12;3248:2;3339:1;3364:64;3420:7;3411:6;3400:9;3396:22;3364:64;:::i;:::-;3354:74;;3310:128;3238:207;;;;:::o;3451:407::-;3519:6;3527;3576:2;3564:9;3555:7;3551:23;3547:32;3544:2;;;3592:1;3589;3582:12;3544:2;3635:1;3660:53;3705:7;3696:6;3685:9;3681:22;3660:53;:::i;:::-;3650:63;;3606:117;3762:2;3788:53;3833:7;3824:6;3813:9;3809:22;3788:53;:::i;:::-;3778:63;;3733:118;3534:324;;;;;:::o;3864:552::-;3941:6;3949;3957;4006:2;3994:9;3985:7;3981:23;3977:32;3974:2;;;4022:1;4019;4012:12;3974:2;4065:1;4090:53;4135:7;4126:6;4115:9;4111:22;4090:53;:::i;:::-;4080:63;;4036:117;4192:2;4218:53;4263:7;4254:6;4243:9;4239:22;4218:53;:::i;:::-;4208:63;;4163:118;4320:2;4346:53;4391:7;4382:6;4371:9;4367:22;4346:53;:::i;:::-;4336:63;;4291:118;3964:452;;;;;:::o;4422:829::-;4519:6;4527;4535;4543;4551;4600:3;4588:9;4579:7;4575:23;4571:33;4568:2;;;4617:1;4614;4607:12;4568:2;4660:1;4685:53;4730:7;4721:6;4710:9;4706:22;4685:53;:::i;:::-;4675:63;;4631:117;4787:2;4813:53;4858:7;4849:6;4838:9;4834:22;4813:53;:::i;:::-;4803:63;;4758:118;4915:2;4941:53;4986:7;4977:6;4966:9;4962:22;4941:53;:::i;:::-;4931:63;;4886:118;5071:2;5060:9;5056:18;5043:32;5102:18;5094:6;5091:30;5088:2;;;5134:1;5131;5124:12;5088:2;5170:64;5226:7;5217:6;5206:9;5202:22;5170:64;:::i;:::-;5152:82;;;;5014:230;4558:693;;;;;;;;:::o;5257:550::-;5350:6;5358;5407:2;5395:9;5386:7;5382:23;5378:32;5375:2;;;5423:1;5420;5413:12;5375:2;5466:1;5491:53;5536:7;5527:6;5516:9;5512:22;5491:53;:::i;:::-;5481:63;;5437:117;5621:2;5610:9;5606:18;5593:32;5652:18;5644:6;5641:30;5638:2;;;5684:1;5681;5674:12;5638:2;5712:78;5782:7;5773:6;5762:9;5758:22;5712:78;:::i;:::-;5702:88;;5564:236;5365:442;;;;;:::o;5813:401::-;5878:6;5886;5935:2;5923:9;5914:7;5910:23;5906:32;5903:2;;;5951:1;5948;5941:12;5903:2;5994:1;6019:53;6064:7;6055:6;6044:9;6040:22;6019:53;:::i;:::-;6009:63;;5965:117;6121:2;6147:50;6189:7;6180:6;6169:9;6165:22;6147:50;:::i;:::-;6137:60;;6092:115;5893:321;;;;;:::o;6220:407::-;6288:6;6296;6345:2;6333:9;6324:7;6320:23;6316:32;6313:2;;;6361:1;6358;6351:12;6313:2;6404:1;6429:53;6474:7;6465:6;6454:9;6450:22;6429:53;:::i;:::-;6419:63;;6375:117;6531:2;6557:53;6602:7;6593:6;6582:9;6578:22;6557:53;:::i;:::-;6547:63;;6502:118;6303:324;;;;;:::o;6633:405::-;6717:6;6766:2;6754:9;6745:7;6741:23;6737:32;6734:2;;;6782:1;6779;6772:12;6734:2;6853:1;6842:9;6838:17;6825:31;6883:18;6875:6;6872:30;6869:2;;;6915:1;6912;6905:12;6869:2;6943:78;7013:7;7004:6;6993:9;6989:22;6943:78;:::i;:::-;6933:88;;6796:235;6724:314;;;;:::o;7044:260::-;7102:6;7151:2;7139:9;7130:7;7126:23;7122:32;7119:2;;;7167:1;7164;7157:12;7119:2;7210:1;7235:52;7279:7;7270:6;7259:9;7255:22;7235:52;:::i;:::-;7225:62;;7181:116;7109:195;;;;:::o;7310:282::-;7379:6;7428:2;7416:9;7407:7;7403:23;7399:32;7396:2;;;7444:1;7441;7434:12;7396:2;7487:1;7512:63;7567:7;7558:6;7547:9;7543:22;7512:63;:::i;:::-;7502:73;;7458:127;7386:206;;;;:::o;7598:375::-;7667:6;7716:2;7704:9;7695:7;7691:23;7687:32;7684:2;;;7732:1;7729;7722:12;7684:2;7803:1;7792:9;7788:17;7775:31;7833:18;7825:6;7822:30;7819:2;;;7865:1;7862;7855:12;7819:2;7893:63;7948:7;7939:6;7928:9;7924:22;7893:63;:::i;:::-;7883:73;;7746:220;7674:299;;;;:::o;7979:262::-;8038:6;8087:2;8075:9;8066:7;8062:23;8058:32;8055:2;;;8103:1;8100;8093:12;8055:2;8146:1;8171:53;8216:7;8207:6;8196:9;8192:22;8171:53;:::i;:::-;8161:63;;8117:117;8045:196;;;;:::o;8247:407::-;8315:6;8323;8372:2;8360:9;8351:7;8347:23;8343:32;8340:2;;;8388:1;8385;8378:12;8340:2;8431:1;8456:53;8501:7;8492:6;8481:9;8477:22;8456:53;:::i;:::-;8446:63;;8402:117;8558:2;8584:53;8629:7;8620:6;8609:9;8605:22;8584:53;:::i;:::-;8574:63;;8529:118;8330:324;;;;;:::o;8660:259::-;8769:10;8790:86;8872:3;8864:6;8790:86;:::i;:::-;8908:4;8903:3;8899:14;8885:28;;8780:139;;;;:::o;8925:108::-;9002:24;9020:5;9002:24;:::i;:::-;8997:3;8990:37;8980:53;;:::o;9039:118::-;9126:24;9144:5;9126:24;:::i;:::-;9121:3;9114:37;9104:53;;:::o;9233:892::-;9392:3;9421:74;9489:5;9421:74;:::i;:::-;9511:106;9610:6;9605:3;9511:106;:::i;:::-;9504:113;;9641:76;9711:5;9641:76;:::i;:::-;9740:7;9771:1;9756:344;9781:6;9778:1;9775:13;9756:344;;;9857:6;9851:13;9884:103;9983:3;9968:13;9884:103;:::i;:::-;9877:110;;10010:80;10083:6;10010:80;:::i;:::-;10000:90;;9816:284;9803:1;9800;9796:9;9791:14;;9756:344;;;9760:14;10116:3;10109:10;;9397:728;;;;;;;:::o;10131:99::-;10202:21;10217:5;10202:21;:::i;:::-;10197:3;10190:34;10180:50;;:::o;10236:109::-;10317:21;10332:5;10317:21;:::i;:::-;10312:3;10305:34;10295:50;;:::o;10351:360::-;10437:3;10465:38;10497:5;10465:38;:::i;:::-;10519:70;10582:6;10577:3;10519:70;:::i;:::-;10512:77;;10598:52;10643:6;10638:3;10631:4;10624:5;10620:16;10598:52;:::i;:::-;10675:29;10697:6;10675:29;:::i;:::-;10670:3;10666:39;10659:46;;10441:270;;;;;:::o;10717:364::-;10805:3;10833:39;10866:5;10833:39;:::i;:::-;10888:71;10952:6;10947:3;10888:71;:::i;:::-;10881:78;;10968:52;11013:6;11008:3;11001:4;10994:5;10990:16;10968:52;:::i;:::-;11045:29;11067:6;11045:29;:::i;:::-;11040:3;11036:39;11029:46;;10809:272;;;;;:::o;11153:839::-;11280:4;11275:3;11271:14;11365:4;11358:5;11354:16;11348:23;11384:63;11441:4;11436:3;11432:14;11418:12;11384:63;:::i;:::-;11295:162;11544:4;11537:5;11533:16;11527:23;11563:57;11614:4;11609:3;11605:14;11591:12;11563:57;:::i;:::-;11467:163;11718:4;11711:5;11707:16;11701:23;11737:63;11794:4;11789:3;11785:14;11771:12;11737:63;:::i;:::-;11640:170;11893:4;11886:5;11882:16;11876:23;11912:63;11969:4;11964:3;11960:14;11946:12;11912:63;:::i;:::-;11820:165;11249:743;;;:::o;11998:108::-;12075:24;12093:5;12075:24;:::i;:::-;12070:3;12063:37;12053:53;;:::o;12112:118::-;12199:24;12217:5;12199:24;:::i;:::-;12194:3;12187:37;12177:53;;:::o;12236:222::-;12329:4;12367:2;12356:9;12352:18;12344:26;;12380:71;12448:1;12437:9;12433:17;12424:6;12380:71;:::i;:::-;12334:124;;;;:::o;12464:640::-;12659:4;12697:3;12686:9;12682:19;12674:27;;12711:71;12779:1;12768:9;12764:17;12755:6;12711:71;:::i;:::-;12792:72;12860:2;12849:9;12845:18;12836:6;12792:72;:::i;:::-;12874;12942:2;12931:9;12927:18;12918:6;12874:72;:::i;:::-;12993:9;12987:4;12983:20;12978:2;12967:9;12963:18;12956:48;13021:76;13092:4;13083:6;13021:76;:::i;:::-;13013:84;;12664:440;;;;;;;:::o;13110:453::-;13293:4;13331:2;13320:9;13316:18;13308:26;;13380:9;13374:4;13370:20;13366:1;13355:9;13351:17;13344:47;13408:148;13551:4;13542:6;13408:148;:::i;:::-;13400:156;;13298:265;;;;:::o;13569:210::-;13656:4;13694:2;13683:9;13679:18;13671:26;;13707:65;13769:1;13758:9;13754:17;13745:6;13707:65;:::i;:::-;13661:118;;;;:::o;13785:313::-;13898:4;13936:2;13925:9;13921:18;13913:26;;13985:9;13979:4;13975:20;13971:1;13960:9;13956:17;13949:47;14013:78;14086:4;14077:6;14013:78;:::i;:::-;14005:86;;13903:195;;;;:::o;14104:222::-;14197:4;14235:2;14224:9;14220:18;14212:26;;14248:71;14316:1;14305:9;14301:17;14292:6;14248:71;:::i;:::-;14202:124;;;;:::o;14332:129::-;14366:6;14393:20;;:::i;:::-;14383:30;;14422:33;14450:4;14442:6;14422:33;:::i;:::-;14373:88;;;:::o;14467:75::-;14500:6;14533:2;14527:9;14517:19;;14507:35;:::o;14548:311::-;14625:4;14715:18;14707:6;14704:30;14701:2;;;14737:18;;:::i;:::-;14701:2;14787:4;14779:6;14775:17;14767:25;;14847:4;14841;14837:15;14829:23;;14630:229;;;:::o;14865:308::-;14927:4;15017:18;15009:6;15006:30;15003:2;;;15039:18;;:::i;:::-;15003:2;15077:29;15099:6;15077:29;:::i;:::-;15069:37;;15161:4;15155;15151:15;15143:23;;14932:241;;;:::o;15179:152::-;15266:4;15289:3;15281:11;;15319:4;15314:3;15310:14;15302:22;;15271:60;;;:::o;15337:134::-;15424:6;15458:5;15452:12;15442:22;;15431:40;;;:::o;15477:98::-;15528:6;15562:5;15556:12;15546:22;;15535:40;;;:::o;15581:99::-;15633:6;15667:5;15661:12;15651:22;;15640:40;;;:::o;15686:133::-;15776:4;15808;15803:3;15799:14;15791:22;;15781:38;;;:::o;15825:204::-;15944:11;15978:6;15973:3;15966:19;16018:4;16013:3;16009:14;15994:29;;15956:73;;;;:::o;16035:168::-;16118:11;16152:6;16147:3;16140:19;16192:4;16187:3;16183:14;16168:29;;16130:73;;;;:::o;16209:169::-;16293:11;16327:6;16322:3;16315:19;16367:4;16362:3;16358:14;16343:29;;16305:73;;;;:::o;16384:525::-;16423:3;16442:19;16459:1;16442:19;:::i;:::-;16437:24;;16475:19;16492:1;16475:19;:::i;:::-;16470:24;;16663:1;16595:66;16591:74;16588:1;16584:82;16579:1;16576;16572:9;16565:17;16561:106;16558:2;;;16670:18;;:::i;:::-;16558:2;16850:1;16782:66;16778:74;16775:1;16771:82;16767:1;16764;16760:9;16756:98;16753:2;;;16857:18;;:::i;:::-;16753:2;16901:1;16898;16894:9;16887:16;;16427:482;;;;:::o;16915:305::-;16955:3;16974:20;16992:1;16974:20;:::i;:::-;16969:25;;17008:20;17026:1;17008:20;:::i;:::-;17003:25;;17162:1;17094:66;17090:74;17087:1;17084:81;17081:2;;;17168:18;;:::i;:::-;17081:2;17212:1;17209;17205:9;17198:16;;16959:261;;;;:::o;17226:385::-;17265:1;17282:19;17299:1;17282:19;:::i;:::-;17277:24;;17315:19;17332:1;17315:19;:::i;:::-;17310:24;;17353:1;17343:2;;17358:18;;:::i;:::-;17343:2;17544:1;17541;17537:9;17534:1;17531:16;17450:66;17447:1;17444:73;17427:130;17424:2;;;17560:18;;:::i;:::-;17424:2;17603:1;17600;17595:10;17590:15;;17267:344;;;;:::o;17617:185::-;17657:1;17674:20;17692:1;17674:20;:::i;:::-;17669:25;;17708:20;17726:1;17708:20;:::i;:::-;17703:25;;17747:1;17737:2;;17752:18;;:::i;:::-;17737:2;17794:1;17791;17787:9;17782:14;;17659:143;;;;:::o;17808:991::-;17847:7;17870:19;17887:1;17870:19;:::i;:::-;17865:24;;17903:19;17920:1;17903:19;:::i;:::-;17898:24;;18104:1;18036:66;18032:74;18029:1;18026:81;18021:1;18018;18014:9;18010:1;18007;18003:9;17999:25;17995:113;17992:2;;;18111:18;;:::i;:::-;17992:2;18315:1;18247:66;18242:75;18239:1;18235:83;18230:1;18227;18223:9;18219:1;18216;18212:9;18208:25;18204:115;18201:2;;;18322:18;;:::i;:::-;18201:2;18526:1;18458:66;18453:75;18450:1;18446:83;18441:1;18438;18434:9;18430:1;18427;18423:9;18419:25;18415:115;18412:2;;;18533:18;;:::i;:::-;18412:2;18736:1;18668:66;18663:75;18660:1;18656:83;18651:1;18648;18644:9;18640:1;18637;18633:9;18629:25;18625:115;18622:2;;;18743:18;;:::i;:::-;18622:2;18791:1;18788;18784:9;18773:20;;17855:944;;;;:::o;18805:348::-;18845:7;18868:20;18886:1;18868:20;:::i;:::-;18863:25;;18902:20;18920:1;18902:20;:::i;:::-;18897:25;;19090:1;19022:66;19018:74;19015:1;19012:81;19007:1;19000:9;18993:17;18989:105;18986:2;;;19097:18;;:::i;:::-;18986:2;19145:1;19142;19138:9;19127:20;;18853:300;;;;:::o;19159:527::-;19198:4;19218:19;19235:1;19218:19;:::i;:::-;19213:24;;19251:19;19268:1;19251:19;:::i;:::-;19246:24;;19440:1;19372:66;19368:74;19365:1;19361:82;19356:1;19353;19349:9;19342:17;19338:106;19335:2;;;19447:18;;:::i;:::-;19335:2;19626:1;19558:66;19554:74;19551:1;19547:82;19543:1;19540;19536:9;19532:98;19529:2;;;19633:18;;:::i;:::-;19529:2;19678:1;19675;19671:9;19663:17;;19203:483;;;;:::o;19692:191::-;19732:4;19752:20;19770:1;19752:20;:::i;:::-;19747:25;;19786:20;19804:1;19786:20;:::i;:::-;19781:25;;19825:1;19822;19819:8;19816:2;;;19830:18;;:::i;:::-;19816:2;19875:1;19872;19868:9;19860:17;;19737:146;;;;:::o;19889:96::-;19926:7;19955:24;19973:5;19955:24;:::i;:::-;19944:35;;19934:51;;;:::o;19991:90::-;20025:7;20068:5;20061:13;20054:21;20043:32;;20033:48;;;:::o;20087:149::-;20123:7;20163:66;20156:5;20152:78;20141:89;;20131:105;;;:::o;20242:76::-;20278:7;20307:5;20296:16;;20286:32;;;:::o;20324:126::-;20361:7;20401:42;20394:5;20390:54;20379:65;;20369:81;;;:::o;20456:77::-;20493:7;20522:5;20511:16;;20501:32;;;:::o;20539:154::-;20623:6;20618:3;20613;20600:30;20685:1;20676:6;20671:3;20667:16;20660:27;20590:103;;;:::o;20699:307::-;20767:1;20777:113;20791:6;20788:1;20785:13;20777:113;;;20876:1;20871:3;20867:11;20861:18;20857:1;20852:3;20848:11;20841:39;20813:2;20810:1;20806:10;20801:15;;20777:113;;;20908:6;20905:1;20902:13;20899:2;;;20988:1;20979:6;20974:3;20970:16;20963:27;20899:2;20748:258;;;;:::o;21012:171::-;21051:3;21074:24;21092:5;21074:24;:::i;:::-;21065:33;;21120:4;21113:5;21110:15;21107:2;;;21128:18;;:::i;:::-;21107:2;21175:1;21168:5;21164:13;21157:20;;21055:128;;;:::o;21189:320::-;21233:6;21270:1;21264:4;21260:12;21250:22;;21317:1;21311:4;21307:12;21338:18;21328:2;;21394:4;21386:6;21382:17;21372:27;;21328:2;21456;21448:6;21445:14;21425:18;21422:38;21419:2;;;21475:18;;:::i;:::-;21419:2;21240:269;;;;:::o;21515:281::-;21598:27;21620:4;21598:27;:::i;:::-;21590:6;21586:40;21728:6;21716:10;21713:22;21692:18;21680:10;21677:34;21674:62;21671:2;;;21739:18;;:::i;:::-;21671:2;21779:10;21775:2;21768:22;21558:238;;;:::o;21802:233::-;21841:3;21864:24;21882:5;21864:24;:::i;:::-;21855:33;;21910:66;21903:5;21900:77;21897:2;;;21980:18;;:::i;:::-;21897:2;22027:1;22020:5;22016:13;22009:20;;21845:190;;;:::o;22041:176::-;22073:1;22090:20;22108:1;22090:20;:::i;:::-;22085:25;;22124:20;22142:1;22124:20;:::i;:::-;22119:25;;22163:1;22153:2;;22168:18;;:::i;:::-;22153:2;22209:1;22206;22202:9;22197:14;;22075:142;;;;:::o;22223:180::-;22271:77;22268:1;22261:88;22368:4;22365:1;22358:15;22392:4;22389:1;22382:15;22409:180;22457:77;22454:1;22447:88;22554:4;22551:1;22544:15;22578:4;22575:1;22568:15;22595:180;22643:77;22640:1;22633:88;22740:4;22737:1;22730:15;22764:4;22761:1;22754:15;22781:180;22829:77;22826:1;22819:88;22926:4;22923:1;22916:15;22950:4;22947:1;22940:15;22967:102;23008:6;23059:2;23055:7;23050:2;23043:5;23039:14;23035:28;23025:38;;23015:54;;;:::o;23075:122::-;23148:24;23166:5;23148:24;:::i;:::-;23141:5;23138:35;23128:2;;23187:1;23184;23177:12;23128:2;23118:79;:::o;23203:116::-;23273:21;23288:5;23273:21;:::i;:::-;23266:5;23263:32;23253:2;;23309:1;23306;23299:12;23253:2;23243:76;:::o;23325:120::-;23397:23;23414:5;23397:23;:::i;:::-;23390:5;23387:34;23377:2;;23435:1;23432;23425:12;23377:2;23367:78;:::o;23451:122::-;23524:24;23542:5;23524:24;:::i;:::-;23517:5;23514:35;23504:2;;23563:1;23560;23553:12;23504:2;23494:79;:::o

Swarm Source

ipfs://e7168e71313d50a51c8a8164e260779e4b759679ea2685197c8bf7d4f8222ad7
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.