ETH Price: $3,419.97 (-2.23%)
Gas: 5 Gwei

Token

Co-Bots 2.0 (CBTE)
 

Overview

Max Total Supply

139 CBTE

Holders

49

Market

Volume (24H)

N/A

Min Price (24H)

N/A

Max Price (24H)

N/A
Filtered by Token Holder
whenlambo.collab0x.eth
Balance
1 CBTE
0xafbdec0ba91fdff03a91cbdf07392e6d72d43712
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:
CoBotsV2

Compiler Version
v0.8.12+commit.f00d7308

Optimization Enabled:
Yes with 2000 runs

Other Settings:
default evmVersion
File 1 of 18 : CoBotsV2.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.12;

import "@chainlink/contracts/src/v0.8/interfaces/LinkTokenInterface.sol";
import "@chainlink/contracts/src/v0.8/interfaces/VRFCoordinatorV2Interface.sol";
import "@chainlink/contracts/src/v0.8/VRFConsumerBaseV2.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "erc721a/contracts/ERC721A.sol";
import {ICoBotsRendererV2, TokenData} from "../interfaces/ICoBotsRendererV2.sol";
import "./Schedule.sol";

error BatchLimitExceeded();
error WrongPrice(uint256 paidPrice, uint256 expectedPrice);
error TotalSupplyExceeded();
error AllocationExceeded();
error ToggleMettaCallerNotOwner();
error ChainlinkSubscriptionNotFound();
error TransferFailed();
error MysteryChallengeSenderDoesNotOwnENS();
error MysteryChallengeValueDoesNotMatch();
error FulfillmentAlreadyFulfilled();
error FulfillRequestForNonExistentContest();
error FulfillRequestWithTokenNotOwnedByWinner();
error FulfillRequestWithTokenOutOfBounds();
error RedeemTokenNotOwner();
error RedeemTokenAlreadyRedeemed();
error NoGiveawayToTrigger();
error InsufficientFunds();
error WithdrawalFailed();
error FailSafeWithdrawalNotEnabled();
error FulfillRequestRedrawn();
error NonexistentRenderer();

contract CoBotsV2 is
    ERC721A,
    VRFConsumerBaseV2,
    Ownable,
    ReentrancyGuard,
    Schedule
{
    // Events
    event RendererContractUpdated(address indexed renderer);
    event MettaToggled(uint256 indexed tokenId, bool isMetta);
    event CheckpointDrawn(uint256 indexed requestId, Prize prize);
    event CheckpointFulfilled(
        uint256 indexed requestId,
        Prize prize,
        Winner winner
    );
    event GiveawayFinished();
    event Withdrawal(uint256 amount);
    event DrawBeforeWithdrawal();

    // Data structures
    /** @dev The prize struct contains the data for one single giveaway prize
     *  @param checkpoint the number of minted bots required to unlock the give
     *  @param amount the amount of the prize to be won
     *  @param isContest flag to indicate if the prize is a contest (meme, twitter, etc) and to be drawn randomly
     */
    struct Prize {
        uint16 checkpoint;
        uint72 amount;
        bool isContest;
    }

    /** @dev The mystery challenge is a special giveaway that will not be drawn nor won after founders selection.
     *  It will require to take control of a given ENS name and to send a message to the contract with the address
     *  owning it.
     *  @param ensId the tokenId of the given ENS
     *  @param value the answer to the challenge
     *  @param prizeIndex the index of this prize in the global Prize[] array
     */
    struct MysteryChallenge {
        uint256 ensId;
        uint256 value;
        uint8 prizeIndex;
    }

    /** @dev Global parameters for the project. Non-standards uintN types to ensure struct fits in one slot (256 bits).
     *  @param cobotsV1Discount the discount given when redeeming a CoBot V1. This is a percentage of public price
     *  @param mintOutFoundersWithdrawalDelay the delay between mint out and possible failsafe withdrawal from the founders
     *  @param grandPrizeDelay the delay between mint out and the grand prize draw
     *  @param maxCobots the total supply of CoBots
     *  @param contestDuration after this time, all contest will be turned into random draws
     *  @param mintPublicPrice the public price of one single CoBot.
     */
    struct Parameters {
        uint16 mintOutFoundersWithdrawalDelay;
        uint16 grandPrizeDelay;
        uint16 maxCobots;
        uint24 contestDuration;
        uint72 mintPublicPrice;
        uint72 cobotsV1Discount;
    }

    // Constants
    uint8 public constant MINT_FOUNDERS = 3;
    uint8 public constant MINT_BATCH_LIMIT = 32;
    Parameters public PARAMETERS;
    Prize[] public PRIZES;
    MysteryChallenge private MYSTERY_CHALLENGE;
    IERC721 public immutable ENS;
    IERC721Enumerable public immutable COBOTS_V1;
    address public immutable COBOTS_V1_ADDRESS;

    ////////////////////////////////////////////////////////////////////////
    ////////////////////////// Token ///////////////////////////////////////
    ////////////////////////////////////////////////////////////////////////

    address public renderingContractAddress;
    ICoBotsRendererV2 public renderer;
    uint8[] public coBotsSeeds;
    mapping(uint256 => bool) public coBotsV1Redeemed;
    uint256 private _redeemedCount;

    function setRenderingContractAddress(address _renderingContractAddress)
        public
        onlyOwner
    {
        renderingContractAddress = _renderingContractAddress;
        renderer = ICoBotsRendererV2(renderingContractAddress);
        emit RendererContractUpdated(renderingContractAddress);
    }

    constructor(
        string memory name_,
        string memory symbol_,
        address _rendererAddress,
        address vrfCoordinator,
        address link,
        bytes32 keyHash,
        Parameters memory _parameters,
        Prize[] memory _prizes,
        address ens,
        address cobotsV1,
        MysteryChallenge memory _mysteryChallenge
    ) ERC721A(name_, symbol_) VRFConsumerBaseV2(vrfCoordinator) {
        setRenderingContractAddress(_rendererAddress);
        COORDINATOR = VRFCoordinatorV2Interface(vrfCoordinator);
        LINKTOKEN = LinkTokenInterface(link);
        gasKeyHash = keyHash;
        PARAMETERS = _parameters;
        uint256 _prizesLength = _prizes.length;
        for (uint256 i = 0; i < _prizesLength; ) {
            PRIZES.push(_prizes[i]);
            unchecked {
                ++i;
            }
        }
        ENS = IERC721(ens);
        COBOTS_V1_ADDRESS = cobotsV1;
        COBOTS_V1 = IERC721Enumerable(cobotsV1);
        MYSTERY_CHALLENGE = _mysteryChallenge;
    }

    function _mintCoBots(address to, uint256 quantity) internal {
        if (quantity > MINT_BATCH_LIMIT) revert BatchLimitExceeded();
        bytes32 seeds = keccak256(
            abi.encodePacked(
                quantity,
                msg.sender,
                msg.value,
                block.timestamp,
                block.difficulty
            )
        );
        for (uint256 i = 0; i < quantity; ) {
            coBotsSeeds.push(uint8(seeds[i]) << 1); // insure last digit is 0, used for Metta status
            unchecked {
                ++i;
            }
        }

        ERC721A._safeMint(to, quantity);

        if (_currentIndex == PARAMETERS.maxCobots) {
            mintedOutTimestamp = block.timestamp;
        }
    }

    modifier supplyAvailable(uint256 quantity) {
        if (_currentIndex + quantity > PARAMETERS.maxCobots)
            revert TotalSupplyExceeded();
        _;
    }

    /**
     * Mints a batch of Co-Bots to the sender.
     *
     * @dev The tokenIdsV1 parameter can be empty. The call will revert only if the sender pretends to own some
     *      Co-Bots V1 that they actually don't. However it accepts already redeemed token and just ignore them silently.
     *      This is to make it easier for people using etherscan to copy a bunch of token Ids without having to
     *      manually check if they are redeemed or not. However, it is optimal in terms of gas fees to only give
     *      tokenIds if they can actually be redeemed.
     * @param quantity The number of COBOTS to mint.
     * @param tokenIdsV1 A list of V1 Co-Bots token Ids owned by the sender, used to determine the discount.
     */
    function mintPublicSale(uint256 quantity, uint256[] memory tokenIdsV1)
        external
        payable
        whenPublicSaleOpen
        supplyAvailable(quantity)
        nonReentrant
    {
        uint256 price = PARAMETERS.mintPublicPrice * quantity;

        uint256 redeemed = 0;
        uint256 tokenIdsV1Length = tokenIdsV1.length;
        for (uint256 i = 0; i < tokenIdsV1Length; ) {
            if (COBOTS_V1.ownerOf(tokenIdsV1[i]) != _msgSender())
                revert RedeemTokenNotOwner();
            if (!coBotsV1Redeemed[tokenIdsV1[i]] && redeemed < quantity) {
                coBotsV1Redeemed[tokenIdsV1[i]] = true;
                redeemed++;
                price -=
                    PARAMETERS.mintPublicPrice /
                    PARAMETERS.cobotsV1Discount;
            }
            unchecked {
                ++i;
            }
        }
        _redeemedCount += redeemed;
        if (msg.value != price) revert WrongPrice(price, msg.value);

        _mintCoBots(_msgSender(), quantity);
    }

    function mintFounders(address to, uint256 quantity)
        external
        onlyOwner
        supplyAvailable(quantity)
    {
        if (quantity + _currentIndex > MINT_FOUNDERS)
            revert AllocationExceeded();

        _mintCoBots(to, quantity);
    }

    /** @notice Return true if the Co-Bot displays metta screen
     *   @param tokenId The Co-Bot token ID
     */
    function isMettaEnabled(uint256 tokenId) external view returns (bool) {
        return coBotsSeeds[tokenId] & 1 == 1;
    }

    function _toggleMetta(uint256 tokenId) internal {
        if (ERC721A.ownerOf(tokenId) != _msgSender())
            revert ToggleMettaCallerNotOwner();

        coBotsSeeds[tokenId] = coBotsSeeds[tokenId] ^ 1;
    }

    function toggleMetta(uint256[] calldata tokenIds) public nonReentrant {
        uint256 tokenIdsLength = tokenIds.length;
        for (uint256 i = 0; i < tokenIdsLength; ) {
            _toggleMetta(tokenIds[i]);
            unchecked {
                ++i;
            }
        }
    }

    function tokenURI(uint256 _tokenId)
        public
        view
        virtual
        override
        returns (string memory)
    {
        if (!_exists(_tokenId)) revert URIQueryForNonexistentToken();

        if (renderingContractAddress == address(0)) {
            return "";
        }

        return renderer.tokenURI(_tokenId, coBotsSeeds[_tokenId]);
    }

    function tokenData(uint256 _tokenId)
        public
        view
        returns (TokenData memory)
    {
        if (!_exists(_tokenId)) revert URIQueryForNonexistentToken();

        if (renderingContractAddress == address(0)) {
            revert NonexistentRenderer();
        }

        return renderer.tokenData(_tokenId, coBotsSeeds[_tokenId]);
    }

    function exists(uint256 _tokenId) external view returns (bool) {
        return _exists(_tokenId);
    }

    receive() external payable {}

    /** @notice At any point in time, founders can withdraw only up to the required balance to insure that the giveaways
     *          will be paid. We take a conservative approach considering that all the remaining discounted bots will be minted
     *          as soon as possible.
     */
    function withdraw() public onlyOwner {
        // Draw eventual remaining giveaways
        if (_shouldDraw()) {
            emit DrawBeforeWithdrawal();
            draw();
        }

        // Start with the current contract's balance
        uint256 balance = address(this).balance;

        // Correct amount with giveaways that are pending fulfillments, typically previously drawn random fulfillments
        uint256 requestIdsLength = requestIds.length;
        for (uint256 i = 0; i < requestIdsLength; ) {
            if (!fulfillments[requestIds[i]].fulfilled) {
                balance -= fulfillments[requestIds[i]].prize.amount;
            }
            unchecked {
                ++i;
            }
        }

        // Use the corrected balance as a base possible withdrawn value
        uint256 value = balance;
        if (value == 0) revert InsufficientFunds();

        // Compute number of remaining discount sales
        uint256 remainingVoucher = COBOTS_V1.totalSupply() - _redeemedCount;
        // Initialize the number of already minted bots for checkpoints
        uint256 previousCheckpoint = _currentIndex;

        // Loop over locked checkpoint to estimate funds and withdrawal capacities
        uint256 prizesLength = PRIZES.length;
        for (uint256 i = requestIds.length; i < prizesLength; ) {
            // to unlock the next checkpoint, remainingBots bots need to be minted
            uint256 remainingBots = PRIZES[i].checkpoint - previousCheckpoint;

            // They will top up the contract's balance, depending on the number of voucher
            if (remainingVoucher > remainingBots) {
                balance +=
                    remainingBots *
                    (PARAMETERS.mintPublicPrice / PARAMETERS.cobotsV1Discount);
                remainingVoucher -= remainingBots;
            } else {
                balance +=
                    remainingVoucher *
                    (PARAMETERS.mintPublicPrice / PARAMETERS.cobotsV1Discount) +
                    (remainingBots - remainingVoucher) *
                    PARAMETERS.mintPublicPrice;
                remainingVoucher = 0;
            }

            // Then the current prize will be paid
            balance -= PRIZES[i].amount;

            // If at some point in the future it's not possible to pay, then the withdraw tx is reverted
            if (balance < 1) {
                revert InsufficientFunds();
            }

            // The possible withdrawal amount is the minimum between the current balance and the contract's balance
            // after each giveaway.
            if (balance < value) {
                value = balance;
            }
            previousCheckpoint = PRIZES[i].checkpoint;

            unchecked {
                ++i;
            }
        }

        (bool success, ) = _msgSender().call{value: value}("");
        if (!success) revert WithdrawalFailed();
        emit Withdrawal(value);
    }

    /** @notice A very basic function to act as a failsafe if the contract has a bug somewhere in the fulfill functions.
     */
    function failsafeWithdraw() public onlyOwner whenMintedOut {
        if (
            block.timestamp <
            (mintedOutTimestamp + PARAMETERS.mintOutFoundersWithdrawalDelay)
        ) {
            revert FailSafeWithdrawalNotEnabled();
        }

        uint256 value = address(this).balance;
        (bool success, ) = _msgSender().call{value: value}("");
        if (!success) revert WithdrawalFailed();
        emit Withdrawal(value);
    }

    ////////////////////////////////////////////////////////////////////////
    ////////////////////////// Raffle //////////////////////////////////////
    ////////////////////////////////////////////////////////////////////////
    VRFCoordinatorV2Interface public immutable COORDINATOR;
    LinkTokenInterface public immutable LINKTOKEN;
    bytes32 public immutable gasKeyHash;
    uint64 public chainlinkSubscriptionId;

    function createSubscriptionAndFund(uint96 amount) external nonReentrant {
        if (chainlinkSubscriptionId == 0) {
            chainlinkSubscriptionId = COORDINATOR.createSubscription();
            COORDINATOR.addConsumer(chainlinkSubscriptionId, address(this));
        }
        LINKTOKEN.transferAndCall(
            address(COORDINATOR),
            amount,
            abi.encode(chainlinkSubscriptionId)
        );
    }

    function cancelSubscription() external onlyOwner {
        COORDINATOR.cancelSubscription(chainlinkSubscriptionId, _msgSender());
        chainlinkSubscriptionId = 0;
    }

    struct Winner {
        address winner;
        uint16 tokenId;
    }

    struct Fulfillment {
        Prize prize;
        bool fulfilled;
        Winner winner;
    }

    mapping(uint256 => Fulfillment) public fulfillments;
    uint256[] public requestIds;
    uint256 public drawnAmount;

    /** @notice Use this to retrieve the ordered list of winners with their corresponding prizes and token Id.
     *          Pending fulfillments are included (no winner drawn yet, probably waiting for Chainlink to fulfill).
     */
    function getOrderedFulfillments()
        external
        view
        returns (Fulfillment[] memory)
    {
        Fulfillment[] memory result = new Fulfillment[](requestIds.length);
        for (uint256 i = 0; i < requestIds.length; i++) {
            result[i] = fulfillments[requestIds[i]];
        }
        return result;
    }

    function _shouldDraw() internal view returns (bool) {
        if (requestIds.length == PRIZES.length) {
            return false;
        }
        if (
            (requestIds.length == PRIZES.length - 1) &&
            (block.timestamp < mintedOutTimestamp + PARAMETERS.grandPrizeDelay)
        ) {
            return false;
        }
        if (PRIZES[requestIds.length].checkpoint > _currentIndex) return false;
        return true;
    }

    /** @notice This function is a failsafe in case a Chainlink VRF request does not resolve
     *          (behaviour experimented on rinkeby).
     *          The new draws will override the previous ones.
     */
    function redrawPendingFulfillments() public nonReentrant {
        uint256 requestIdsLength = requestIds.length;
        for (uint256 i = 0; i < requestIdsLength; ) {
            if (
                !fulfillments[requestIds[i]].fulfilled &&
                (!fulfillments[requestIds[i]].prize.isContest ||
                    block.timestamp >
                    publicSaleStartTimestamp + PARAMETERS.contestDuration)
            ) {
                uint256 requestId = COORDINATOR.requestRandomWords(
                    gasKeyHash,
                    chainlinkSubscriptionId,
                    5, // requestConfirmations
                    500_000, // callbackGasLimit
                    1 // numWords
                );
                fulfillments[requestId] = Fulfillment(
                    fulfillments[requestIds[i]].prize,
                    false,
                    Winner(address(0), 0)
                );
                delete fulfillments[requestIds[i]];
                requestIds[i] = requestId;
            }

            unchecked {
                ++i;
            }
        }
    }

    /**
     * @notice This function can be called at any time by anyone to trigger the unlocked giveaways. It will
     *         revert if there is nothing to unlock to prevent anon from making useless tx. (Usually wallet, e.g.
     *         metamask, warn this before signing).
     *         Giveaways that use Chainlink VRF oracle will be fulfilled automatically by Chainlink. Giveaways that
     *         require founders to unlock will be fulfilled by the founders.
     */
    function draw() public nonReentrant {
        uint256 drawCounts = requestIds.length;
        if (chainlinkSubscriptionId == 0) {
            revert ChainlinkSubscriptionNotFound();
        }
        if (!_shouldDraw()) revert NoGiveawayToTrigger();
        while (PRIZES[drawCounts].checkpoint < _currentIndex + 1) {
            uint256 requestId;
            if (
                (PRIZES[drawCounts].isContest &&
                    block.timestamp <
                    publicSaleStartTimestamp + PARAMETERS.contestDuration) ||
                (drawCounts == MYSTERY_CHALLENGE.prizeIndex)
            ) {
                requestId = _computeRequestId(drawCounts);
            } else {
                requestId = COORDINATOR.requestRandomWords(
                    gasKeyHash,
                    chainlinkSubscriptionId,
                    5, // requestConfirmations
                    500_000, // callbackGasLimit
                    1 // numWords
                );
            }
            drawnAmount += PRIZES[drawCounts].amount;
            fulfillments[requestId] = Fulfillment(
                PRIZES[drawCounts],
                false,
                Winner(address(0), 0)
            );
            emit CheckpointDrawn(requestId, PRIZES[drawCounts]);
            drawCounts++;
            requestIds.push(requestId);
            if (
                (drawCounts == PRIZES.length - 1) &&
                (block.timestamp <
                    mintedOutTimestamp + PARAMETERS.grandPrizeDelay)
            ) {
                return;
            }
            if (drawCounts == PRIZES.length) {
                emit GiveawayFinished();
                return;
            }
        }
    }

    function _computeRequestId(uint256 id) private pure returns (uint256) {
        return
            uint256(keccak256(abi.encodePacked(uint8(id % type(uint8).max))));
    }

    function _fulfill(
        uint256 requestId,
        address winnerAddress,
        uint256 selectedToken
    ) internal {
        if (fulfillments[requestId].fulfilled) {
            revert FulfillmentAlreadyFulfilled();
        }
        if (fulfillments[requestId].prize.amount == 0)
            revert FulfillRequestForNonExistentContest();
        if (ERC721A.ownerOf(selectedToken) != winnerAddress) {
            revert FulfillRequestWithTokenNotOwnedByWinner();
        }
        if (selectedToken > fulfillments[requestId].prize.checkpoint - 1) {
            revert FulfillRequestWithTokenOutOfBounds();
        }
        fulfillments[requestId].fulfilled = true;
        Winner memory winner = Winner(winnerAddress, uint16(selectedToken));
        fulfillments[requestId].winner = winner;
        (bool success, ) = winnerAddress.call{
            value: fulfillments[requestId].prize.amount
        }("");
        if (!success) revert TransferFailed();
        emit CheckpointFulfilled(
            requestId,
            fulfillments[requestId].prize,
            winner
        );
    }

    function fulfillRandomWords(uint256 requestId, uint256[] memory randomWords)
        internal
        override
    {
        uint256 checkpoint = fulfillments[requestId].prize.checkpoint;
        if (checkpoint == 0) revert FulfillRequestRedrawn();
        uint256 selectedToken = randomWords[0] % checkpoint;
        address winner = ERC721A.ownerOf(selectedToken);
        _fulfill(requestId, winner, selectedToken);
    }

    /**
     * @notice This function lets the owner fulfill a giveaway. If the giveaway has not been unlocked, this will
     *         revert.
     * @param giveawayIndex The index of the giveaway to fulfill, 0 based (the first giveaway is index 0).
     * @param winner The selected winner address.
     * @param selectedToken The selected token to be displayed on the website.
     */
    function fulfillContest(
        uint256 giveawayIndex,
        address winner,
        uint256 selectedToken
    ) external nonReentrant onlyOwner {
        uint256 requestId = _computeRequestId(giveawayIndex);
        _fulfill(requestId, winner, selectedToken);
    }

    /**
     * @notice Call this when, you know, you probably know what you're doing here.
     *         revert.
     * @param value Word biggest mysteries are solved with this single value.
     * @param tokenId The selected token to be displayed on the website. This should be owned by the winner.
     */
    function TheAnswer(uint256 value, uint256 tokenId) external nonReentrant {
        if (ENS.ownerOf(MYSTERY_CHALLENGE.ensId) != _msgSender()) {
            revert MysteryChallengeSenderDoesNotOwnENS();
        }
        if (value != MYSTERY_CHALLENGE.value) {
            revert MysteryChallengeValueDoesNotMatch();
        }
        _fulfill(
            _computeRequestId(MYSTERY_CHALLENGE.prizeIndex),
            _msgSender(),
            tokenId
        );
    }
}

File 2 of 18 : LinkTokenInterface.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

interface LinkTokenInterface {
  function allowance(address owner, address spender) external view returns (uint256 remaining);

  function approve(address spender, uint256 value) external returns (bool success);

  function balanceOf(address owner) external view returns (uint256 balance);

  function decimals() external view returns (uint8 decimalPlaces);

  function decreaseApproval(address spender, uint256 addedValue) external returns (bool success);

  function increaseApproval(address spender, uint256 subtractedValue) external;

  function name() external view returns (string memory tokenName);

  function symbol() external view returns (string memory tokenSymbol);

  function totalSupply() external view returns (uint256 totalTokensIssued);

  function transfer(address to, uint256 value) external returns (bool success);

  function transferAndCall(
    address to,
    uint256 value,
    bytes calldata data
  ) external returns (bool success);

  function transferFrom(
    address from,
    address to,
    uint256 value
  ) external returns (bool success);
}

File 3 of 18 : VRFCoordinatorV2Interface.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

interface VRFCoordinatorV2Interface {
  /**
   * @notice Get configuration relevant for making requests
   * @return minimumRequestConfirmations global min for request confirmations
   * @return maxGasLimit global max for request gas limit
   * @return s_provingKeyHashes list of registered key hashes
   */
  function getRequestConfig()
    external
    view
    returns (
      uint16,
      uint32,
      bytes32[] memory
    );

  /**
   * @notice Request a set of random words.
   * @param keyHash - Corresponds to a particular oracle job which uses
   * that key for generating the VRF proof. Different keyHash's have different gas price
   * ceilings, so you can select a specific one to bound your maximum per request cost.
   * @param subId  - The ID of the VRF subscription. Must be funded
   * with the minimum subscription balance required for the selected keyHash.
   * @param minimumRequestConfirmations - How many blocks you'd like the
   * oracle to wait before responding to the request. See SECURITY CONSIDERATIONS
   * for why you may want to request more. The acceptable range is
   * [minimumRequestBlockConfirmations, 200].
   * @param callbackGasLimit - How much gas you'd like to receive in your
   * fulfillRandomWords callback. Note that gasleft() inside fulfillRandomWords
   * may be slightly less than this amount because of gas used calling the function
   * (argument decoding etc.), so you may need to request slightly more than you expect
   * to have inside fulfillRandomWords. The acceptable range is
   * [0, maxGasLimit]
   * @param numWords - The number of uint256 random values you'd like to receive
   * in your fulfillRandomWords callback. Note these numbers are expanded in a
   * secure way by the VRFCoordinator from a single random value supplied by the oracle.
   * @return requestId - A unique identifier of the request. Can be used to match
   * a request to a response in fulfillRandomWords.
   */
  function requestRandomWords(
    bytes32 keyHash,
    uint64 subId,
    uint16 minimumRequestConfirmations,
    uint32 callbackGasLimit,
    uint32 numWords
  ) external returns (uint256 requestId);

  /**
   * @notice Create a VRF subscription.
   * @return subId - A unique subscription id.
   * @dev You can manage the consumer set dynamically with addConsumer/removeConsumer.
   * @dev Note to fund the subscription, use transferAndCall. For example
   * @dev  LINKTOKEN.transferAndCall(
   * @dev    address(COORDINATOR),
   * @dev    amount,
   * @dev    abi.encode(subId));
   */
  function createSubscription() external returns (uint64 subId);

  /**
   * @notice Get a VRF subscription.
   * @param subId - ID of the subscription
   * @return balance - LINK balance of the subscription in juels.
   * @return reqCount - number of requests for this subscription, determines fee tier.
   * @return owner - owner of the subscription.
   * @return consumers - list of consumer address which are able to use this subscription.
   */
  function getSubscription(uint64 subId)
    external
    view
    returns (
      uint96 balance,
      uint64 reqCount,
      address owner,
      address[] memory consumers
    );

  /**
   * @notice Request subscription owner transfer.
   * @param subId - ID of the subscription
   * @param newOwner - proposed new owner of the subscription
   */
  function requestSubscriptionOwnerTransfer(uint64 subId, address newOwner) external;

  /**
   * @notice Request subscription owner transfer.
   * @param subId - ID of the subscription
   * @dev will revert if original owner of subId has
   * not requested that msg.sender become the new owner.
   */
  function acceptSubscriptionOwnerTransfer(uint64 subId) external;

  /**
   * @notice Add a consumer to a VRF subscription.
   * @param subId - ID of the subscription
   * @param consumer - New consumer which can use the subscription
   */
  function addConsumer(uint64 subId, address consumer) external;

  /**
   * @notice Remove a consumer from a VRF subscription.
   * @param subId - ID of the subscription
   * @param consumer - Consumer to remove from the subscription
   */
  function removeConsumer(uint64 subId, address consumer) external;

  /**
   * @notice Cancel a subscription
   * @param subId - ID of the subscription
   * @param to - Where to send the remaining LINK to
   */
  function cancelSubscription(uint64 subId, address to) external;
}

File 4 of 18 : VRFConsumerBaseV2.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

/** ****************************************************************************
 * @notice Interface for contracts using VRF randomness
 * *****************************************************************************
 * @dev PURPOSE
 *
 * @dev Reggie the Random Oracle (not his real job) wants to provide randomness
 * @dev to Vera the verifier in such a way that Vera can be sure he's not
 * @dev making his output up to suit himself. Reggie provides Vera a public key
 * @dev to which he knows the secret key. Each time Vera provides a seed to
 * @dev Reggie, he gives back a value which is computed completely
 * @dev deterministically from the seed and the secret key.
 *
 * @dev Reggie provides a proof by which Vera can verify that the output was
 * @dev correctly computed once Reggie tells it to her, but without that proof,
 * @dev the output is indistinguishable to her from a uniform random sample
 * @dev from the output space.
 *
 * @dev The purpose of this contract is to make it easy for unrelated contracts
 * @dev to talk to Vera the verifier about the work Reggie is doing, to provide
 * @dev simple access to a verifiable source of randomness. It ensures 2 things:
 * @dev 1. The fulfillment came from the VRFCoordinator
 * @dev 2. The consumer contract implements fulfillRandomWords.
 * *****************************************************************************
 * @dev USAGE
 *
 * @dev Calling contracts must inherit from VRFConsumerBase, and can
 * @dev initialize VRFConsumerBase's attributes in their constructor as
 * @dev shown:
 *
 * @dev   contract VRFConsumer {
 * @dev     constructor(<other arguments>, address _vrfCoordinator, address _link)
 * @dev       VRFConsumerBase(_vrfCoordinator) public {
 * @dev         <initialization with other arguments goes here>
 * @dev       }
 * @dev   }
 *
 * @dev The oracle will have given you an ID for the VRF keypair they have
 * @dev committed to (let's call it keyHash). Create subscription, fund it
 * @dev and your consumer contract as a consumer of it (see VRFCoordinatorInterface
 * @dev subscription management functions).
 * @dev Call requestRandomWords(keyHash, subId, minimumRequestConfirmations,
 * @dev callbackGasLimit, numWords),
 * @dev see (VRFCoordinatorInterface for a description of the arguments).
 *
 * @dev Once the VRFCoordinator has received and validated the oracle's response
 * @dev to your request, it will call your contract's fulfillRandomWords method.
 *
 * @dev The randomness argument to fulfillRandomWords is a set of random words
 * @dev generated from your requestId and the blockHash of the request.
 *
 * @dev If your contract could have concurrent requests open, you can use the
 * @dev requestId returned from requestRandomWords to track which response is associated
 * @dev with which randomness request.
 * @dev See "SECURITY CONSIDERATIONS" for principles to keep in mind,
 * @dev if your contract could have multiple requests in flight simultaneously.
 *
 * @dev Colliding `requestId`s are cryptographically impossible as long as seeds
 * @dev differ.
 *
 * *****************************************************************************
 * @dev SECURITY CONSIDERATIONS
 *
 * @dev A method with the ability to call your fulfillRandomness method directly
 * @dev could spoof a VRF response with any random value, so it's critical that
 * @dev it cannot be directly called by anything other than this base contract
 * @dev (specifically, by the VRFConsumerBase.rawFulfillRandomness method).
 *
 * @dev For your users to trust that your contract's random behavior is free
 * @dev from malicious interference, it's best if you can write it so that all
 * @dev behaviors implied by a VRF response are executed *during* your
 * @dev fulfillRandomness method. If your contract must store the response (or
 * @dev anything derived from it) and use it later, you must ensure that any
 * @dev user-significant behavior which depends on that stored value cannot be
 * @dev manipulated by a subsequent VRF request.
 *
 * @dev Similarly, both miners and the VRF oracle itself have some influence
 * @dev over the order in which VRF responses appear on the blockchain, so if
 * @dev your contract could have multiple VRF requests in flight simultaneously,
 * @dev you must ensure that the order in which the VRF responses arrive cannot
 * @dev be used to manipulate your contract's user-significant behavior.
 *
 * @dev Since the block hash of the block which contains the requestRandomness
 * @dev call is mixed into the input to the VRF *last*, a sufficiently powerful
 * @dev miner could, in principle, fork the blockchain to evict the block
 * @dev containing the request, forcing the request to be included in a
 * @dev different block with a different hash, and therefore a different input
 * @dev to the VRF. However, such an attack would incur a substantial economic
 * @dev cost. This cost scales with the number of blocks the VRF oracle waits
 * @dev until it calls responds to a request. It is for this reason that
 * @dev that you can signal to an oracle you'd like them to wait longer before
 * @dev responding to the request (however this is not enforced in the contract
 * @dev and so remains effective only in the case of unmodified oracle software).
 */
abstract contract VRFConsumerBaseV2 {
  error OnlyCoordinatorCanFulfill(address have, address want);
  address private immutable vrfCoordinator;

  /**
   * @param _vrfCoordinator address of VRFCoordinator contract
   */
  constructor(address _vrfCoordinator) {
    vrfCoordinator = _vrfCoordinator;
  }

  /**
   * @notice fulfillRandomness handles the VRF response. Your contract must
   * @notice implement it. See "SECURITY CONSIDERATIONS" above for important
   * @notice principles to keep in mind when implementing your fulfillRandomness
   * @notice method.
   *
   * @dev VRFConsumerBaseV2 expects its subcontracts to have a method with this
   * @dev signature, and will call it once it has verified the proof
   * @dev associated with the randomness. (It is triggered via a call to
   * @dev rawFulfillRandomness, below.)
   *
   * @param requestId The Id initially returned by requestRandomness
   * @param randomWords the VRF output expanded to the requested number of words
   */
  function fulfillRandomWords(uint256 requestId, uint256[] memory randomWords) internal virtual;

  // rawFulfillRandomness is called by VRFCoordinator when it receives a valid VRF
  // proof. rawFulfillRandomness then calls fulfillRandomness, after validating
  // the origin of the call
  function rawFulfillRandomWords(uint256 requestId, uint256[] memory randomWords) external {
    if (msg.sender != vrfCoordinator) {
      revert OnlyCoordinatorCanFulfill(msg.sender, vrfCoordinator);
    }
    fulfillRandomWords(requestId, randomWords);
  }
}

File 5 of 18 : ReentrancyGuard.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol)

pragma solidity ^0.8.0;

/**
 * @dev Contract module that helps prevent reentrant calls to a function.
 *
 * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
 * available, which can be applied to functions to make sure there are no nested
 * (reentrant) calls to them.
 *
 * Note that because there is a single `nonReentrant` guard, functions marked as
 * `nonReentrant` may not call one another. This can be worked around by making
 * those functions `private`, and then adding `external` `nonReentrant` entry
 * points to them.
 *
 * TIP: If you would like to learn more about reentrancy and alternative ways
 * to protect against it, check out our blog post
 * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
 */
abstract contract ReentrancyGuard {
    // Booleans are more expensive than uint256 or any type that takes up a full
    // word because each write operation emits an extra SLOAD to first read the
    // slot's contents, replace the bits taken up by the boolean, and then write
    // back. This is the compiler's defense against contract upgrades and
    // pointer aliasing, and it cannot be disabled.

    // The values being non-zero value makes deployment a bit more expensive,
    // but in exchange the refund on every call to nonReentrant will be lower in
    // amount. Since refunds are capped to a percentage of the total
    // transaction's gas, it is best to keep them low in cases like this one, to
    // increase the likelihood of the full refund coming into effect.
    uint256 private constant _NOT_ENTERED = 1;
    uint256 private constant _ENTERED = 2;

    uint256 private _status;

    constructor() {
        _status = _NOT_ENTERED;
    }

    /**
     * @dev Prevents a contract from calling itself, directly or indirectly.
     * Calling a `nonReentrant` function from another `nonReentrant`
     * function is not supported. It is possible to prevent this from happening
     * by making the `nonReentrant` function external, and making it call a
     * `private` function that does the actual work.
     */
    modifier nonReentrant() {
        // On the first call to nonReentrant, _notEntered will be true
        require(_status != _ENTERED, "ReentrancyGuard: reentrant call");

        // Any calls to nonReentrant after this point will fail
        _status = _ENTERED;

        _;

        // By storing the original value once again, a refund is triggered (see
        // https://eips.ethereum.org/EIPS/eip-2200)
        _status = _NOT_ENTERED;
    }
}

File 6 of 18 : Ownable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (access/Ownable.sol)

pragma solidity ^0.8.0;

import "../utils/Context.sol";

/**
 * @dev Contract module which provides a basic access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * By default, the owner account will be the one that deploys the contract. This
 * can later be changed with {transferOwnership}.
 *
 * This module is used through inheritance. It will make available the modifier
 * `onlyOwner`, which can be applied to your functions to restrict their use to
 * the owner.
 */
abstract contract Ownable is Context {
    address private _owner;

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    /**
     * @dev Initializes the contract setting the deployer as the initial owner.
     */
    constructor() {
        _transferOwnership(_msgSender());
    }

    /**
     * @dev Returns the address of the current owner.
     */
    function owner() public view virtual returns (address) {
        return _owner;
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        require(owner() == _msgSender(), "Ownable: caller is not the owner");
        _;
    }

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions anymore. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby removing any functionality that is only available to the owner.
     */
    function renounceOwnership() public virtual onlyOwner {
        _transferOwnership(address(0));
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        require(newOwner != address(0), "Ownable: new owner is the zero address");
        _transferOwnership(newOwner);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Internal function without access restriction.
     */
    function _transferOwnership(address newOwner) internal virtual {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}

File 7 of 18 : ERC721A.sol
// SPDX-License-Identifier: MIT
// Creator: Chiru Labs

pragma solidity ^0.8.4;

import '@openzeppelin/contracts/token/ERC721/IERC721.sol';
import '@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol';
import '@openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol';
import '@openzeppelin/contracts/token/ERC721/extensions/IERC721Enumerable.sol';
import '@openzeppelin/contracts/utils/Address.sol';
import '@openzeppelin/contracts/utils/Context.sol';
import '@openzeppelin/contracts/utils/Strings.sol';
import '@openzeppelin/contracts/utils/introspection/ERC165.sol';

error ApprovalCallerNotOwnerNorApproved();
error ApprovalQueryForNonexistentToken();
error ApproveToCaller();
error ApprovalToCurrentOwner();
error BalanceQueryForZeroAddress();
error MintedQueryForZeroAddress();
error BurnedQueryForZeroAddress();
error MintToZeroAddress();
error MintZeroQuantity();
error OwnerIndexOutOfBounds();
error OwnerQueryForNonexistentToken();
error TokenIndexOutOfBounds();
error TransferCallerNotOwnerNorApproved();
error TransferFromIncorrectOwner();
error TransferToNonERC721ReceiverImplementer();
error TransferToZeroAddress();
error URIQueryForNonexistentToken();

/**
 * @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including
 * the Metadata and Enumerable extension. Built to optimize for lower gas during batch mints.
 *
 * Assumes serials are sequentially minted starting at 0 (e.g. 0, 1, 2, 3..).
 *
 * Assumes that an owner cannot have more than 2**64 - 1 (max value of uint64) of supply.
 *
 * Assumes that the maximum token id cannot exceed 2**128 - 1 (max value of uint128).
 */
contract ERC721A is Context, ERC165, IERC721, IERC721Metadata, IERC721Enumerable {
    using Address for address;
    using Strings for uint256;

    // Compiler will pack this into a single 256bit word.
    struct TokenOwnership {
        // The address of the owner.
        address addr;
        // Keeps track of the start time of ownership with minimal overhead for tokenomics.
        uint64 startTimestamp;
        // Whether the token has been burned.
        bool burned;
    }

    // Compiler will pack this into a single 256bit word.
    struct AddressData {
        // Realistically, 2**64-1 is more than enough.
        uint64 balance;
        // Keeps track of mint count with minimal overhead for tokenomics.
        uint64 numberMinted;
        // Keeps track of burn count with minimal overhead for tokenomics.
        uint64 numberBurned;
    }

    // Compiler will pack the following 
    // _currentIndex and _burnCounter into a single 256bit word.
    
    // The tokenId of the next token to be minted.
    uint128 internal _currentIndex;

    // The number of tokens burned.
    uint128 internal _burnCounter;

    // Token name
    string private _name;

    // Token symbol
    string private _symbol;

    // Mapping from token ID to ownership details
    // An empty struct value does not necessarily mean the token is unowned. See ownershipOf implementation for details.
    mapping(uint256 => TokenOwnership) internal _ownerships;

    // Mapping owner address to address data
    mapping(address => AddressData) private _addressData;

    // Mapping from token ID to approved address
    mapping(uint256 => address) private _tokenApprovals;

    // Mapping from owner to operator approvals
    mapping(address => mapping(address => bool)) private _operatorApprovals;

    constructor(string memory name_, string memory symbol_) {
        _name = name_;
        _symbol = symbol_;
    }

    /**
     * @dev See {IERC721Enumerable-totalSupply}.
     */
    function totalSupply() public view override returns (uint256) {
        // Counter underflow is impossible as _burnCounter cannot be incremented
        // more than _currentIndex times
        unchecked {
            return _currentIndex - _burnCounter;    
        }
    }

    /**
     * @dev See {IERC721Enumerable-tokenByIndex}.
     * This read function is O(totalSupply). If calling from a separate contract, be sure to test gas first.
     * It may also degrade with extremely large collection sizes (e.g >> 10000), test for your use case.
     */
    function tokenByIndex(uint256 index) public view override returns (uint256) {
        uint256 numMintedSoFar = _currentIndex;
        uint256 tokenIdsIdx;

        // Counter overflow is impossible as the loop breaks when
        // uint256 i is equal to another uint256 numMintedSoFar.
        unchecked {
            for (uint256 i; i < numMintedSoFar; i++) {
                TokenOwnership memory ownership = _ownerships[i];
                if (!ownership.burned) {
                    if (tokenIdsIdx == index) {
                        return i;
                    }
                    tokenIdsIdx++;
                }
            }
        }
        revert TokenIndexOutOfBounds();
    }

    /**
     * @dev See {IERC721Enumerable-tokenOfOwnerByIndex}.
     * This read function is O(totalSupply). If calling from a separate contract, be sure to test gas first.
     * It may also degrade with extremely large collection sizes (e.g >> 10000), test for your use case.
     */
    function tokenOfOwnerByIndex(address owner, uint256 index) public view override returns (uint256) {
        if (index >= balanceOf(owner)) revert OwnerIndexOutOfBounds();
        uint256 numMintedSoFar = _currentIndex;
        uint256 tokenIdsIdx;
        address currOwnershipAddr;

        // Counter overflow is impossible as the loop breaks when
        // uint256 i is equal to another uint256 numMintedSoFar.
        unchecked {
            for (uint256 i; i < numMintedSoFar; i++) {
                TokenOwnership memory ownership = _ownerships[i];
                if (ownership.burned) {
                    continue;
                }
                if (ownership.addr != address(0)) {
                    currOwnershipAddr = ownership.addr;
                }
                if (currOwnershipAddr == owner) {
                    if (tokenIdsIdx == index) {
                        return i;
                    }
                    tokenIdsIdx++;
                }
            }
        }

        // Execution should never reach this point.
        revert();
    }

    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {
        return
            interfaceId == type(IERC721).interfaceId ||
            interfaceId == type(IERC721Metadata).interfaceId ||
            interfaceId == type(IERC721Enumerable).interfaceId ||
            super.supportsInterface(interfaceId);
    }

    /**
     * @dev See {IERC721-balanceOf}.
     */
    function balanceOf(address owner) public view override returns (uint256) {
        if (owner == address(0)) revert BalanceQueryForZeroAddress();
        return uint256(_addressData[owner].balance);
    }

    function _numberMinted(address owner) internal view returns (uint256) {
        if (owner == address(0)) revert MintedQueryForZeroAddress();
        return uint256(_addressData[owner].numberMinted);
    }

    function _numberBurned(address owner) internal view returns (uint256) {
        if (owner == address(0)) revert BurnedQueryForZeroAddress();
        return uint256(_addressData[owner].numberBurned);
    }

    /**
     * Gas spent here starts off proportional to the maximum mint batch size.
     * It gradually moves to O(1) as tokens get transferred around in the collection over time.
     */
    function ownershipOf(uint256 tokenId) internal view returns (TokenOwnership memory) {
        uint256 curr = tokenId;

        unchecked {
            if (curr < _currentIndex) {
                TokenOwnership memory ownership = _ownerships[curr];
                if (!ownership.burned) {
                    if (ownership.addr != address(0)) {
                        return ownership;
                    }
                    // Invariant: 
                    // There will always be an ownership that has an address and is not burned 
                    // before an ownership that does not have an address and is not burned.
                    // Hence, curr will not underflow.
                    while (true) {
                        curr--;
                        ownership = _ownerships[curr];
                        if (ownership.addr != address(0)) {
                            return ownership;
                        }
                    }
                }
            }
        }
        revert OwnerQueryForNonexistentToken();
    }

    /**
     * @dev See {IERC721-ownerOf}.
     */
    function ownerOf(uint256 tokenId) public view override returns (address) {
        return ownershipOf(tokenId).addr;
    }

    /**
     * @dev See {IERC721Metadata-name}.
     */
    function name() public view virtual override returns (string memory) {
        return _name;
    }

    /**
     * @dev See {IERC721Metadata-symbol}.
     */
    function symbol() public view virtual override returns (string memory) {
        return _symbol;
    }

    /**
     * @dev See {IERC721Metadata-tokenURI}.
     */
    function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
        if (!_exists(tokenId)) revert URIQueryForNonexistentToken();

        string memory baseURI = _baseURI();
        return bytes(baseURI).length != 0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : '';
    }

    /**
     * @dev Base URI for computing {tokenURI}. If set, the resulting URI for each
     * token will be the concatenation of the `baseURI` and the `tokenId`. Empty
     * by default, can be overriden in child contracts.
     */
    function _baseURI() internal view virtual returns (string memory) {
        return '';
    }

    /**
     * @dev See {IERC721-approve}.
     */
    function approve(address to, uint256 tokenId) public override {
        address owner = ERC721A.ownerOf(tokenId);
        if (to == owner) revert ApprovalToCurrentOwner();

        if (_msgSender() != owner && !isApprovedForAll(owner, _msgSender())) {
            revert ApprovalCallerNotOwnerNorApproved();
        }

        _approve(to, tokenId, owner);
    }

    /**
     * @dev See {IERC721-getApproved}.
     */
    function getApproved(uint256 tokenId) public view override returns (address) {
        if (!_exists(tokenId)) revert ApprovalQueryForNonexistentToken();

        return _tokenApprovals[tokenId];
    }

    /**
     * @dev See {IERC721-setApprovalForAll}.
     */
    function setApprovalForAll(address operator, bool approved) public override {
        if (operator == _msgSender()) revert ApproveToCaller();

        _operatorApprovals[_msgSender()][operator] = approved;
        emit ApprovalForAll(_msgSender(), operator, approved);
    }

    /**
     * @dev See {IERC721-isApprovedForAll}.
     */
    function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {
        return _operatorApprovals[owner][operator];
    }

    /**
     * @dev See {IERC721-transferFrom}.
     */
    function transferFrom(
        address from,
        address to,
        uint256 tokenId
    ) public virtual override {
        _transfer(from, to, tokenId);
    }

    /**
     * @dev See {IERC721-safeTransferFrom}.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId
    ) public virtual override {
        safeTransferFrom(from, to, tokenId, '');
    }

    /**
     * @dev See {IERC721-safeTransferFrom}.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId,
        bytes memory _data
    ) public virtual override {
        _transfer(from, to, tokenId);
        if (!_checkOnERC721Received(from, to, tokenId, _data)) {
            revert TransferToNonERC721ReceiverImplementer();
        }
    }

    /**
     * @dev Returns whether `tokenId` exists.
     *
     * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.
     *
     * Tokens start existing when they are minted (`_mint`),
     */
    function _exists(uint256 tokenId) internal view returns (bool) {
        return tokenId < _currentIndex && !_ownerships[tokenId].burned;
    }

    function _safeMint(address to, uint256 quantity) internal {
        _safeMint(to, quantity, '');
    }

    /**
     * @dev Safely mints `quantity` tokens and transfers them to `to`.
     *
     * Requirements:
     *
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called for each safe transfer.
     * - `quantity` must be greater than 0.
     *
     * Emits a {Transfer} event.
     */
    function _safeMint(
        address to,
        uint256 quantity,
        bytes memory _data
    ) internal {
        _mint(to, quantity, _data, true);
    }

    /**
     * @dev Mints `quantity` tokens and transfers them to `to`.
     *
     * Requirements:
     *
     * - `to` cannot be the zero address.
     * - `quantity` must be greater than 0.
     *
     * Emits a {Transfer} event.
     */
    function _mint(
        address to,
        uint256 quantity,
        bytes memory _data,
        bool safe
    ) internal {
        uint256 startTokenId = _currentIndex;
        if (to == address(0)) revert MintToZeroAddress();
        if (quantity == 0) revert MintZeroQuantity();

        _beforeTokenTransfers(address(0), to, startTokenId, quantity);

        // Overflows are incredibly unrealistic.
        // balance or numberMinted overflow if current value of either + quantity > 3.4e38 (2**128) - 1
        // updatedIndex overflows if _currentIndex + quantity > 3.4e38 (2**128) - 1
        unchecked {
            _addressData[to].balance += uint64(quantity);
            _addressData[to].numberMinted += uint64(quantity);

            _ownerships[startTokenId].addr = to;
            _ownerships[startTokenId].startTimestamp = uint64(block.timestamp);

            uint256 updatedIndex = startTokenId;

            for (uint256 i; i < quantity; i++) {
                emit Transfer(address(0), to, updatedIndex);
                if (safe && !_checkOnERC721Received(address(0), to, updatedIndex, _data)) {
                    revert TransferToNonERC721ReceiverImplementer();
                }
                updatedIndex++;
            }

            _currentIndex = uint128(updatedIndex);
        }
        _afterTokenTransfers(address(0), to, startTokenId, quantity);
    }

    /**
     * @dev Transfers `tokenId` from `from` to `to`.
     *
     * Requirements:
     *
     * - `to` cannot be the zero address.
     * - `tokenId` token must be owned by `from`.
     *
     * Emits a {Transfer} event.
     */
    function _transfer(
        address from,
        address to,
        uint256 tokenId
    ) private {
        TokenOwnership memory prevOwnership = ownershipOf(tokenId);

        bool isApprovedOrOwner = (_msgSender() == prevOwnership.addr ||
            isApprovedForAll(prevOwnership.addr, _msgSender()) ||
            getApproved(tokenId) == _msgSender());

        if (!isApprovedOrOwner) revert TransferCallerNotOwnerNorApproved();
        if (prevOwnership.addr != from) revert TransferFromIncorrectOwner();
        if (to == address(0)) revert TransferToZeroAddress();

        _beforeTokenTransfers(from, to, tokenId, 1);

        // Clear approvals from the previous owner
        _approve(address(0), tokenId, prevOwnership.addr);

        // Underflow of the sender's balance is impossible because we check for
        // ownership above and the recipient's balance can't realistically overflow.
        // Counter overflow is incredibly unrealistic as tokenId would have to be 2**128.
        unchecked {
            _addressData[from].balance -= 1;
            _addressData[to].balance += 1;

            _ownerships[tokenId].addr = to;
            _ownerships[tokenId].startTimestamp = uint64(block.timestamp);

            // If the ownership slot of tokenId+1 is not explicitly set, that means the transfer initiator owns it.
            // Set the slot of tokenId+1 explicitly in storage to maintain correctness for ownerOf(tokenId+1) calls.
            uint256 nextTokenId = tokenId + 1;
            if (_ownerships[nextTokenId].addr == address(0)) {
                // This will suffice for checking _exists(nextTokenId),
                // as a burned slot cannot contain the zero address.
                if (nextTokenId < _currentIndex) {
                    _ownerships[nextTokenId].addr = prevOwnership.addr;
                    _ownerships[nextTokenId].startTimestamp = prevOwnership.startTimestamp;
                }
            }
        }

        emit Transfer(from, to, tokenId);
        _afterTokenTransfers(from, to, tokenId, 1);
    }

    /**
     * @dev Destroys `tokenId`.
     * The approval is cleared when the token is burned.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     *
     * Emits a {Transfer} event.
     */
    function _burn(uint256 tokenId) internal virtual {
        TokenOwnership memory prevOwnership = ownershipOf(tokenId);

        _beforeTokenTransfers(prevOwnership.addr, address(0), tokenId, 1);

        // Clear approvals from the previous owner
        _approve(address(0), tokenId, prevOwnership.addr);

        // Underflow of the sender's balance is impossible because we check for
        // ownership above and the recipient's balance can't realistically overflow.
        // Counter overflow is incredibly unrealistic as tokenId would have to be 2**128.
        unchecked {
            _addressData[prevOwnership.addr].balance -= 1;
            _addressData[prevOwnership.addr].numberBurned += 1;

            // Keep track of who burned the token, and the timestamp of burning.
            _ownerships[tokenId].addr = prevOwnership.addr;
            _ownerships[tokenId].startTimestamp = uint64(block.timestamp);
            _ownerships[tokenId].burned = true;

            // If the ownership slot of tokenId+1 is not explicitly set, that means the burn initiator owns it.
            // Set the slot of tokenId+1 explicitly in storage to maintain correctness for ownerOf(tokenId+1) calls.
            uint256 nextTokenId = tokenId + 1;
            if (_ownerships[nextTokenId].addr == address(0)) {
                // This will suffice for checking _exists(nextTokenId),
                // as a burned slot cannot contain the zero address.
                if (nextTokenId < _currentIndex) {
                    _ownerships[nextTokenId].addr = prevOwnership.addr;
                    _ownerships[nextTokenId].startTimestamp = prevOwnership.startTimestamp;
                }
            }
        }

        emit Transfer(prevOwnership.addr, address(0), tokenId);
        _afterTokenTransfers(prevOwnership.addr, address(0), tokenId, 1);

        // Overflow not possible, as _burnCounter cannot be exceed _currentIndex times.
        unchecked { 
            _burnCounter++;
        }
    }

    /**
     * @dev Approve `to` to operate on `tokenId`
     *
     * Emits a {Approval} event.
     */
    function _approve(
        address to,
        uint256 tokenId,
        address owner
    ) private {
        _tokenApprovals[tokenId] = to;
        emit Approval(owner, to, tokenId);
    }

    /**
     * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.
     * The call is not executed if the target address is not a contract.
     *
     * @param from address representing the previous owner of the given token ID
     * @param to target address that will receive the tokens
     * @param tokenId uint256 ID of the token to be transferred
     * @param _data bytes optional data to send along with the call
     * @return bool whether the call correctly returned the expected magic value
     */
    function _checkOnERC721Received(
        address from,
        address to,
        uint256 tokenId,
        bytes memory _data
    ) private returns (bool) {
        if (to.isContract()) {
            try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, _data) returns (bytes4 retval) {
                return retval == IERC721Receiver(to).onERC721Received.selector;
            } catch (bytes memory reason) {
                if (reason.length == 0) {
                    revert TransferToNonERC721ReceiverImplementer();
                } else {
                    assembly {
                        revert(add(32, reason), mload(reason))
                    }
                }
            }
        } else {
            return true;
        }
    }

    /**
     * @dev Hook that is called before a set of serially-ordered token ids are about to be transferred. This includes minting.
     * And also called before burning one token.
     *
     * startTokenId - the first token id to be transferred
     * quantity - the amount to be transferred
     *
     * Calling conditions:
     *
     * - When `from` and `to` are both non-zero, `from`'s `tokenId` will be
     * transferred to `to`.
     * - When `from` is zero, `tokenId` will be minted for `to`.
     * - When `to` is zero, `tokenId` will be burned by `from`.
     * - `from` and `to` are never both zero.
     */
    function _beforeTokenTransfers(
        address from,
        address to,
        uint256 startTokenId,
        uint256 quantity
    ) internal virtual {}

    /**
     * @dev Hook that is called after a set of serially-ordered token ids have been transferred. This includes
     * minting.
     * And also called after one token has been burned.
     *
     * startTokenId - the first token id to be transferred
     * quantity - the amount to be transferred
     *
     * Calling conditions:
     *
     * - When `from` and `to` are both non-zero, `from`'s `tokenId` has been
     * transferred to `to`.
     * - When `from` is zero, `tokenId` has been minted for `to`.
     * - When `to` is zero, `tokenId` has been burned by `from`.
     * - `from` and `to` are never both zero.
     */
    function _afterTokenTransfers(
        address from,
        address to,
        uint256 startTokenId,
        uint256 quantity
    ) internal virtual {}
}

File 8 of 18 : ICoBotsRendererV2.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.12;

struct Attribute {
    string trait_type;
    string value;
}

struct TokenData {
    string image;
    string description;
    string name;
    Attribute[] attributes;
}

interface ICoBotsRendererV2 {
    function tokenURI(uint256 tokenId, uint8 seed)
        external
        view
        returns (string memory);

    function tokenData(uint256 tokenId, uint8 seed)
        external
        view
        returns (TokenData memory);
}

File 9 of 18 : Schedule.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.12;

import "@openzeppelin/contracts/access/Ownable.sol";

error PublicSaleOpen();
error PublicSaleNotOpen();
error TokenMintedOut();
error TokenNotMintedOut();

/** @dev This contract can be used to manage some basic scheduling of a token sale.
 *       To have the isMintedOut() function work, it is required to either update the mintedOutTimestamp
 *       or to override the function (using totalSupply() for instance).
 */
contract Schedule is Ownable {
    uint256 public publicSaleStartTimestamp;
    uint256 public mintedOutTimestamp;

    function openPublicSale() external onlyOwner whenPublicSaleClosed {
        publicSaleStartTimestamp = block.timestamp;
    }

    function isPublicSaleOpen() public view virtual returns (bool) {
        return
            publicSaleStartTimestamp != 0 &&
            block.timestamp > publicSaleStartTimestamp;
    }

    modifier whenPublicSaleOpen() {
        if (!isPublicSaleOpen()) revert PublicSaleNotOpen();
        _;
    }

    modifier whenPublicSaleClosed() {
        if (isPublicSaleOpen()) revert PublicSaleOpen();
        _;
    }

    function isMintedOut() public view virtual returns (bool) {
        return mintedOutTimestamp > 0;
    }

    modifier whenMintedOut() {
        if (!isMintedOut()) revert TokenNotMintedOut();
        _;
    }

    modifier whenNotMintedOut() {
        if (isMintedOut()) revert TokenMintedOut();
        _;
    }
}

File 10 of 18 : Context.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)

pragma solidity ^0.8.0;

/**
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
abstract contract Context {
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }
}

File 11 of 18 : IERC721.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC721/IERC721.sol)

pragma solidity ^0.8.0;

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

/**
 * @dev Required interface of an ERC721 compliant contract.
 */
interface IERC721 is IERC165 {
    /**
     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.
     */
    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);

    /**
     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
     */
    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);

    /**
     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.
     */
    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);

    /**
     * @dev Returns the number of tokens in ``owner``'s account.
     */
    function balanceOf(address owner) external view returns (uint256 balance);

    /**
     * @dev Returns the owner of the `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function ownerOf(uint256 tokenId) external view returns (address owner);

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
     * are aware of the ERC721 protocol to prevent tokens from being forever locked.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId
    ) external;

    /**
     * @dev Transfers `tokenId` token from `from` to `to`.
     *
     * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must be owned by `from`.
     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(
        address from,
        address to,
        uint256 tokenId
    ) external;

    /**
     * @dev Gives permission to `to` to transfer `tokenId` token to another account.
     * The approval is cleared when the token is transferred.
     *
     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.
     *
     * Requirements:
     *
     * - The caller must own the token or be an approved operator.
     * - `tokenId` must exist.
     *
     * Emits an {Approval} event.
     */
    function approve(address to, uint256 tokenId) external;

    /**
     * @dev Returns the account approved for `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function getApproved(uint256 tokenId) external view returns (address operator);

    /**
     * @dev Approve or remove `operator` as an operator for the caller.
     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.
     *
     * Requirements:
     *
     * - The `operator` cannot be the caller.
     *
     * Emits an {ApprovalForAll} event.
     */
    function setApprovalForAll(address operator, bool _approved) external;

    /**
     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
     *
     * See {setApprovalForAll}
     */
    function isApprovedForAll(address owner, address operator) external view returns (bool);

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId,
        bytes calldata data
    ) external;
}

File 12 of 18 : IERC721Receiver.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC721/IERC721Receiver.sol)

pragma solidity ^0.8.0;

/**
 * @title ERC721 token receiver interface
 * @dev Interface for any contract that wants to support safeTransfers
 * from ERC721 asset contracts.
 */
interface IERC721Receiver {
    /**
     * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}
     * by `operator` from `from`, this function is called.
     *
     * It must return its Solidity selector to confirm the token transfer.
     * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.
     *
     * The selector can be obtained in Solidity with `IERC721.onERC721Received.selector`.
     */
    function onERC721Received(
        address operator,
        address from,
        uint256 tokenId,
        bytes calldata data
    ) external returns (bytes4);
}

File 13 of 18 : IERC721Metadata.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)

pragma solidity ^0.8.0;

import "../IERC721.sol";

/**
 * @title ERC-721 Non-Fungible Token Standard, optional metadata extension
 * @dev See https://eips.ethereum.org/EIPS/eip-721
 */
interface IERC721Metadata is IERC721 {
    /**
     * @dev Returns the token collection name.
     */
    function name() external view returns (string memory);

    /**
     * @dev Returns the token collection symbol.
     */
    function symbol() external view returns (string memory);

    /**
     * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.
     */
    function tokenURI(uint256 tokenId) external view returns (string memory);
}

File 14 of 18 : IERC721Enumerable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC721/extensions/IERC721Enumerable.sol)

pragma solidity ^0.8.0;

import "../IERC721.sol";

/**
 * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension
 * @dev See https://eips.ethereum.org/EIPS/eip-721
 */
interface IERC721Enumerable is IERC721 {
    /**
     * @dev Returns the total amount of tokens stored by the contract.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns a token ID owned by `owner` at a given `index` of its token list.
     * Use along with {balanceOf} to enumerate all of ``owner``'s tokens.
     */
    function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256);

    /**
     * @dev Returns a token ID at a given `index` of all the tokens stored by the contract.
     * Use along with {totalSupply} to enumerate all tokens.
     */
    function tokenByIndex(uint256 index) external view returns (uint256);
}

File 15 of 18 : Address.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol)

pragma solidity ^0.8.1;

/**
 * @dev Collection of functions related to the address type
 */
library Address {
    /**
     * @dev Returns true if `account` is a contract.
     *
     * [IMPORTANT]
     * ====
     * It is unsafe to assume that an address for which this function returns
     * false is an externally-owned account (EOA) and not a contract.
     *
     * Among others, `isContract` will return false for the following
     * types of addresses:
     *
     *  - an externally-owned account
     *  - a contract in construction
     *  - an address where a contract will be created
     *  - an address where a contract lived, but was destroyed
     * ====
     *
     * [IMPORTANT]
     * ====
     * You shouldn't rely on `isContract` to protect against flash loan attacks!
     *
     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
     * constructor.
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // This method relies on extcodesize/address.code.length, which returns 0
        // for contracts in construction, since the code is only stored at the end
        // of the constructor execution.

        return account.code.length > 0;
    }

    /**
     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
     * `recipient`, forwarding all available gas and reverting on errors.
     *
     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
     * of certain opcodes, possibly making contracts go over the 2300 gas limit
     * imposed by `transfer`, making them unable to receive funds via
     * `transfer`. {sendValue} removes this limitation.
     *
     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
     *
     * IMPORTANT: because control is transferred to `recipient`, care must be
     * taken to not create reentrancy vulnerabilities. Consider using
     * {ReentrancyGuard} or the
     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
     */
    function sendValue(address payable recipient, uint256 amount) internal {
        require(address(this).balance >= amount, "Address: insufficient balance");

        (bool success, ) = recipient.call{value: amount}("");
        require(success, "Address: unable to send value, recipient may have reverted");
    }

    /**
     * @dev Performs a Solidity function call using a low level `call`. A
     * plain `call` is an unsafe replacement for a function call: use this
     * function instead.
     *
     * If `target` reverts with a revert reason, it is bubbled up by this
     * function (like regular Solidity function calls).
     *
     * Returns the raw returned data. To convert to the expected return value,
     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
     *
     * Requirements:
     *
     * - `target` must be a contract.
     * - calling `target` with `data` must not revert.
     *
     * _Available since v3.1._
     */
    function functionCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionCall(target, data, "Address: low-level call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
     * `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        return functionCallWithValue(target, data, 0, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but also transferring `value` wei to `target`.
     *
     * Requirements:
     *
     * - the calling contract must have an ETH balance of at least `value`.
     * - the called Solidity function must be `payable`.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value
    ) internal returns (bytes memory) {
        return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
    }

    /**
     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
     * with `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value,
        string memory errorMessage
    ) internal returns (bytes memory) {
        require(address(this).balance >= value, "Address: insufficient balance for call");
        require(isContract(target), "Address: call to non-contract");

        (bool success, bytes memory returndata) = target.call{value: value}(data);
        return verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
        return functionStaticCall(target, data, "Address: low-level static call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal view returns (bytes memory) {
        require(isContract(target), "Address: static call to non-contract");

        (bool success, bytes memory returndata) = target.staticcall(data);
        return verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionDelegateCall(target, data, "Address: low-level delegate call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        require(isContract(target), "Address: delegate call to non-contract");

        (bool success, bytes memory returndata) = target.delegatecall(data);
        return verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
     * revert reason using the provided one.
     *
     * _Available since v4.3._
     */
    function verifyCallResult(
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal pure returns (bytes memory) {
        if (success) {
            return returndata;
        } else {
            // Look for revert reason and bubble it up if present
            if (returndata.length > 0) {
                // The easiest way to bubble the revert reason is using memory via assembly

                assembly {
                    let returndata_size := mload(returndata)
                    revert(add(32, returndata), returndata_size)
                }
            } else {
                revert(errorMessage);
            }
        }
    }
}

File 16 of 18 : Strings.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Strings.sol)

pragma solidity ^0.8.0;

/**
 * @dev String operations.
 */
library Strings {
    bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef";

    /**
     * @dev Converts a `uint256` to its ASCII `string` decimal representation.
     */
    function toString(uint256 value) internal pure returns (string memory) {
        // Inspired by OraclizeAPI's implementation - MIT licence
        // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol

        if (value == 0) {
            return "0";
        }
        uint256 temp = value;
        uint256 digits;
        while (temp != 0) {
            digits++;
            temp /= 10;
        }
        bytes memory buffer = new bytes(digits);
        while (value != 0) {
            digits -= 1;
            buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
            value /= 10;
        }
        return string(buffer);
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
     */
    function toHexString(uint256 value) internal pure returns (string memory) {
        if (value == 0) {
            return "0x00";
        }
        uint256 temp = value;
        uint256 length = 0;
        while (temp != 0) {
            length++;
            temp >>= 8;
        }
        return toHexString(value, length);
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
     */
    function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
        bytes memory buffer = new bytes(2 * length + 2);
        buffer[0] = "0";
        buffer[1] = "x";
        for (uint256 i = 2 * length + 1; i > 1; --i) {
            buffer[i] = _HEX_SYMBOLS[value & 0xf];
            value >>= 4;
        }
        require(value == 0, "Strings: hex length insufficient");
        return string(buffer);
    }
}

File 17 of 18 : ERC165.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)

pragma solidity ^0.8.0;

import "./IERC165.sol";

/**
 * @dev Implementation of the {IERC165} interface.
 *
 * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check
 * for the additional interface id that will be supported. For example:
 *
 * ```solidity
 * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
 *     return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
 * }
 * ```
 *
 * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.
 */
abstract contract ERC165 is IERC165 {
    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
        return interfaceId == type(IERC165).interfaceId;
    }
}

File 18 of 18 : IERC165.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)

pragma solidity ^0.8.0;

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

Settings
{
  "optimizer": {
    "enabled": true,
    "runs": 2000,
    "details": {
      "yul": true,
      "yulDetails": {
        "stackAllocation": true,
        "optimizerSteps": "dhfoDgvulfnTUtnIf"
      }
    }
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "metadata": {
    "useLiteralContent": true
  },
  "libraries": {}
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"string","name":"name_","type":"string"},{"internalType":"string","name":"symbol_","type":"string"},{"internalType":"address","name":"_rendererAddress","type":"address"},{"internalType":"address","name":"vrfCoordinator","type":"address"},{"internalType":"address","name":"link","type":"address"},{"internalType":"bytes32","name":"keyHash","type":"bytes32"},{"components":[{"internalType":"uint16","name":"mintOutFoundersWithdrawalDelay","type":"uint16"},{"internalType":"uint16","name":"grandPrizeDelay","type":"uint16"},{"internalType":"uint16","name":"maxCobots","type":"uint16"},{"internalType":"uint24","name":"contestDuration","type":"uint24"},{"internalType":"uint72","name":"mintPublicPrice","type":"uint72"},{"internalType":"uint72","name":"cobotsV1Discount","type":"uint72"}],"internalType":"struct CoBotsV2.Parameters","name":"_parameters","type":"tuple"},{"components":[{"internalType":"uint16","name":"checkpoint","type":"uint16"},{"internalType":"uint72","name":"amount","type":"uint72"},{"internalType":"bool","name":"isContest","type":"bool"}],"internalType":"struct CoBotsV2.Prize[]","name":"_prizes","type":"tuple[]"},{"internalType":"address","name":"ens","type":"address"},{"internalType":"address","name":"cobotsV1","type":"address"},{"components":[{"internalType":"uint256","name":"ensId","type":"uint256"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint8","name":"prizeIndex","type":"uint8"}],"internalType":"struct CoBotsV2.MysteryChallenge","name":"_mysteryChallenge","type":"tuple"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AllocationExceeded","type":"error"},{"inputs":[],"name":"ApprovalCallerNotOwnerNorApproved","type":"error"},{"inputs":[],"name":"ApprovalQueryForNonexistentToken","type":"error"},{"inputs":[],"name":"ApprovalToCurrentOwner","type":"error"},{"inputs":[],"name":"ApproveToCaller","type":"error"},{"inputs":[],"name":"BalanceQueryForZeroAddress","type":"error"},{"inputs":[],"name":"BatchLimitExceeded","type":"error"},{"inputs":[],"name":"ChainlinkSubscriptionNotFound","type":"error"},{"inputs":[],"name":"FailSafeWithdrawalNotEnabled","type":"error"},{"inputs":[],"name":"FulfillRequestForNonExistentContest","type":"error"},{"inputs":[],"name":"FulfillRequestRedrawn","type":"error"},{"inputs":[],"name":"FulfillRequestWithTokenNotOwnedByWinner","type":"error"},{"inputs":[],"name":"FulfillRequestWithTokenOutOfBounds","type":"error"},{"inputs":[],"name":"FulfillmentAlreadyFulfilled","type":"error"},{"inputs":[],"name":"InsufficientFunds","type":"error"},{"inputs":[],"name":"MintToZeroAddress","type":"error"},{"inputs":[],"name":"MintZeroQuantity","type":"error"},{"inputs":[],"name":"MysteryChallengeSenderDoesNotOwnENS","type":"error"},{"inputs":[],"name":"MysteryChallengeValueDoesNotMatch","type":"error"},{"inputs":[],"name":"NoGiveawayToTrigger","type":"error"},{"inputs":[],"name":"NonexistentRenderer","type":"error"},{"inputs":[{"internalType":"address","name":"have","type":"address"},{"internalType":"address","name":"want","type":"address"}],"name":"OnlyCoordinatorCanFulfill","type":"error"},{"inputs":[],"name":"OwnerIndexOutOfBounds","type":"error"},{"inputs":[],"name":"OwnerQueryForNonexistentToken","type":"error"},{"inputs":[],"name":"PublicSaleNotOpen","type":"error"},{"inputs":[],"name":"PublicSaleOpen","type":"error"},{"inputs":[],"name":"RedeemTokenNotOwner","type":"error"},{"inputs":[],"name":"ToggleMettaCallerNotOwner","type":"error"},{"inputs":[],"name":"TokenIndexOutOfBounds","type":"error"},{"inputs":[],"name":"TokenNotMintedOut","type":"error"},{"inputs":[],"name":"TotalSupplyExceeded","type":"error"},{"inputs":[],"name":"TransferCallerNotOwnerNorApproved","type":"error"},{"inputs":[],"name":"TransferFailed","type":"error"},{"inputs":[],"name":"TransferFromIncorrectOwner","type":"error"},{"inputs":[],"name":"TransferToNonERC721ReceiverImplementer","type":"error"},{"inputs":[],"name":"TransferToZeroAddress","type":"error"},{"inputs":[],"name":"URIQueryForNonexistentToken","type":"error"},{"inputs":[],"name":"WithdrawalFailed","type":"error"},{"inputs":[{"internalType":"uint256","name":"paidPrice","type":"uint256"},{"internalType":"uint256","name":"expectedPrice","type":"uint256"}],"name":"WrongPrice","type":"error"},{"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":"uint256","name":"requestId","type":"uint256"},{"components":[{"internalType":"uint16","name":"checkpoint","type":"uint16"},{"internalType":"uint72","name":"amount","type":"uint72"},{"internalType":"bool","name":"isContest","type":"bool"}],"indexed":false,"internalType":"struct CoBotsV2.Prize","name":"prize","type":"tuple"}],"name":"CheckpointDrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"requestId","type":"uint256"},{"components":[{"internalType":"uint16","name":"checkpoint","type":"uint16"},{"internalType":"uint72","name":"amount","type":"uint72"},{"internalType":"bool","name":"isContest","type":"bool"}],"indexed":false,"internalType":"struct CoBotsV2.Prize","name":"prize","type":"tuple"},{"components":[{"internalType":"address","name":"winner","type":"address"},{"internalType":"uint16","name":"tokenId","type":"uint16"}],"indexed":false,"internalType":"struct CoBotsV2.Winner","name":"winner","type":"tuple"}],"name":"CheckpointFulfilled","type":"event"},{"anonymous":false,"inputs":[],"name":"DrawBeforeWithdrawal","type":"event"},{"anonymous":false,"inputs":[],"name":"GiveawayFinished","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"bool","name":"isMetta","type":"bool"}],"name":"MettaToggled","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":"renderer","type":"address"}],"name":"RendererContractUpdated","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"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Withdrawal","type":"event"},{"inputs":[],"name":"COBOTS_V1","outputs":[{"internalType":"contract IERC721Enumerable","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"COBOTS_V1_ADDRESS","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"COORDINATOR","outputs":[{"internalType":"contract VRFCoordinatorV2Interface","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ENS","outputs":[{"internalType":"contract IERC721","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"LINKTOKEN","outputs":[{"internalType":"contract LinkTokenInterface","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MINT_BATCH_LIMIT","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MINT_FOUNDERS","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PARAMETERS","outputs":[{"internalType":"uint16","name":"mintOutFoundersWithdrawalDelay","type":"uint16"},{"internalType":"uint16","name":"grandPrizeDelay","type":"uint16"},{"internalType":"uint16","name":"maxCobots","type":"uint16"},{"internalType":"uint24","name":"contestDuration","type":"uint24"},{"internalType":"uint72","name":"mintPublicPrice","type":"uint72"},{"internalType":"uint72","name":"cobotsV1Discount","type":"uint72"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"PRIZES","outputs":[{"internalType":"uint16","name":"checkpoint","type":"uint16"},{"internalType":"uint72","name":"amount","type":"uint72"},{"internalType":"bool","name":"isContest","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"TheAnswer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","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":"cancelSubscription","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"chainlinkSubscriptionId","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"coBotsSeeds","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"coBotsV1Redeemed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint96","name":"amount","type":"uint96"}],"name":"createSubscriptionAndFund","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"draw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"drawnAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"exists","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"failsafeWithdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"giveawayIndex","type":"uint256"},{"internalType":"address","name":"winner","type":"address"},{"internalType":"uint256","name":"selectedToken","type":"uint256"}],"name":"fulfillContest","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"fulfillments","outputs":[{"components":[{"internalType":"uint16","name":"checkpoint","type":"uint16"},{"internalType":"uint72","name":"amount","type":"uint72"},{"internalType":"bool","name":"isContest","type":"bool"}],"internalType":"struct CoBotsV2.Prize","name":"prize","type":"tuple"},{"internalType":"bool","name":"fulfilled","type":"bool"},{"components":[{"internalType":"address","name":"winner","type":"address"},{"internalType":"uint16","name":"tokenId","type":"uint16"}],"internalType":"struct CoBotsV2.Winner","name":"winner","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"gasKeyHash","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"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":"getOrderedFulfillments","outputs":[{"components":[{"components":[{"internalType":"uint16","name":"checkpoint","type":"uint16"},{"internalType":"uint72","name":"amount","type":"uint72"},{"internalType":"bool","name":"isContest","type":"bool"}],"internalType":"struct CoBotsV2.Prize","name":"prize","type":"tuple"},{"internalType":"bool","name":"fulfilled","type":"bool"},{"components":[{"internalType":"address","name":"winner","type":"address"},{"internalType":"uint16","name":"tokenId","type":"uint16"}],"internalType":"struct CoBotsV2.Winner","name":"winner","type":"tuple"}],"internalType":"struct CoBotsV2.Fulfillment[]","name":"","type":"tuple[]"}],"stateMutability":"view","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":"uint256","name":"tokenId","type":"uint256"}],"name":"isMettaEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isMintedOut","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isPublicSaleOpen","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"quantity","type":"uint256"}],"name":"mintFounders","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"quantity","type":"uint256"},{"internalType":"uint256[]","name":"tokenIdsV1","type":"uint256[]"}],"name":"mintPublicSale","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"mintedOutTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"openPublicSale","outputs":[],"stateMutability":"nonpayable","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":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"publicSaleStartTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"requestId","type":"uint256"},{"internalType":"uint256[]","name":"randomWords","type":"uint256[]"}],"name":"rawFulfillRandomWords","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"redrawPendingFulfillments","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renderer","outputs":[{"internalType":"contract ICoBotsRendererV2","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renderingContractAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"requestIds","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":"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":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_renderingContractAddress","type":"address"}],"name":"setRenderingContractAddress","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":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"name":"toggleMetta","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"tokenData","outputs":[{"components":[{"internalType":"string","name":"image","type":"string"},{"internalType":"string","name":"description","type":"string"},{"internalType":"string","name":"name","type":"string"},{"components":[{"internalType":"string","name":"trait_type","type":"string"},{"internalType":"string","name":"value","type":"string"}],"internalType":"struct Attribute[]","name":"attributes","type":"tuple[]"}],"internalType":"struct TokenData","name":"","type":"tuple"}],"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":"_tokenId","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"},{"inputs":[],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]

6101606040523480156200001257600080fd5b5060405162005d0238038062005d028339810160408190526200003591620007e6565b878b8b81600190805190602001906200005092919062000331565b5080516200006690600290602084019062000331565b5050506001600160a01b0316608052620000803362000253565b60016008556200009089620002a5565b6001600160a01b03808916610100528716610120526101408690528451600b80546020880151604089015160608a015160808b015160a08c01516001600160481b03908116600160901b02600160901b600160d81b03199190921669010000000000000000000216600160481b600160d81b031962ffffff90931666010000000000000262ffffff60301b1961ffff958616640100000000021664ffffffffff60201b19968616620100000263ffffffff199098169590991694909417959095179390931695909517179390931617919091179055835160005b818110156200020657600c8682815181106200018a576200018a62000947565b6020908102919091018101518254600181810185556000948552938390208251910180549383015160409093015115156b0100000000000000000000000260ff60581b196001600160481b0390941662010000026001600160581b031990951661ffff909316929092179390931791909116179055016200016a565b50506001600160a01b0392831660a052911660e081905260c0528051600d556020810151600e5560400151600f805460ff191660ff90921691909117905550620009df9650505050505050565b600780546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6007546001600160a01b03163314620002db5760405162461bcd60e51b8152600401620002d2906200095d565b60405180910390fd5b601080546001600160a01b0383166001600160a01b0319918216811790925560118054909116821790556040517f2926c01a1380ae82a404a8c554ad486a6842a4a320d80b770e2930d763825e4f90600090a250565b8280546200033f90620009ae565b90600052602060002090601f016020900481019282620003635760008555620003ae565b82601f106200037e57805160ff1916838001178555620003ae565b82800160010185558215620003ae579182015b82811115620003ae57825182559160200191906001019062000391565b50620003bc929150620003c0565b5090565b5b80821115620003bc5760008155600101620003c1565b634e487b7160e01b600052604160045260246000fd5b601f19601f83011681016001600160401b0381118282101715620004155762000415620003d7565b6040525050565b60006200042860405190565b9050620004368282620003ed565b919050565b60006001600160401b03821115620004575762000457620003d7565b601f19601f83011660200192915050565b60005b83811015620004855781810151838201526020016200046b565b8381111562000495576000848401525b50505050565b6000620004b2620004ac846200043b565b6200041c565b905082815260208101848484011115620004cf57620004cf600080fd5b620004dc84828562000468565b509392505050565b600082601f830112620004fa57620004fa600080fd5b81516200050c8482602086016200049b565b949350505050565b60006001600160a01b0382165b92915050565b620005328162000514565b81146200053e57600080fd5b50565b8051620005218162000527565b8062000532565b805162000521816200054e565b61ffff811662000532565b8051620005218162000562565b62ffffff811662000532565b805162000521816200057a565b6001600160481b03811662000532565b8051620005218162000593565b600060c08284031215620005c757620005c7600080fd5b620005d360c06200041c565b90506000620005e384846200056d565b908201526020620005f7848483016200056d565b9082015260406200060b848483016200056d565b9082015260606200061f8484830162000586565b9082015260806200063384848301620005a3565b9082015260a06200064784848301620005a3565b9082015292915050565b60006001600160401b038211156200066d576200066d620003d7565b5060209081020190565b80151562000532565b8051620005218162000677565b600060608284031215620006a457620006a4600080fd5b620006b060606200041c565b90506000620006c084846200056d565b908201526020620006d484848301620005a3565b908201526040620006478484830162000680565b6000620006f9620004ac8462000651565b838152905060208101606084028301858111156200071a576200071a600080fd5b835b8181101562000742576200073187826200068d565b83526020909201916060016200071c565b5050509392505050565b600082601f830112620007625762000762600080fd5b81516200050c848260208601620006e8565b60ff811662000532565b8051620005218162000774565b600060608284031215620007a257620007a2600080fd5b620007ae60606200041c565b90506000620007be848462000555565b908201526020620007d28484830162000555565b90820152604062000647848483016200077e565b60008060008060008060008060008060006102408c8e0312156200080d576200080d600080fd5b8b516001600160401b03811115620008285762000828600080fd5b620008368e828f01620004e4565b60208e0151909c5090506001600160401b03811115620008595762000859600080fd5b620008678e828f01620004e4565b9a505060406200087a8e828f0162000541565b99505060606200088d8e828f0162000541565b9850506080620008a08e828f0162000541565b97505060a0620008b38e828f0162000555565b96505060c0620008c68e828f01620005b0565b6101808e015190965090506001600160401b03811115620008ea57620008ea600080fd5b620008f88e828f016200074c565b9450506101a06200090c8e828f0162000541565b9350506101c0620009208e828f0162000541565b9250506101e0620009348e828f016200078b565b9150509295989b509295989b9093969950565b634e487b7160e01b600052603260045260246000fd5b60208082528181019081527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260408301526060820162000521565b634e487b7160e01b600052602260045260246000fd5b600281046001821680620009c357607f821691505b60208210811415620009d957620009d962000998565b50919050565b60805160a05160c05160e05161010051610120516101405161526d62000a9560003960008181610c680152818161125701526123ac0152600081816107860152612d8201526000818161069d0152818161122a0152818161191b0152818161237f01528181612c3601528181612d010152612dab01526000610b64015260008181610c3401528181611c050152612fbf0152600081816105550152610f680152600081816116bb01526116e3015261526d6000f3fe6080604052600436106103905760003560e01c80635a08cae5116101dc578063a9b5898f11610102578063d7822c99116100a0578063e985e9c51161006f578063e985e9c514610bb9578063f2fde38b14610c02578063fef490f314610c22578063ffae2b5614610c5657600080fd5b8063d7822c9914610b3c578063dce6c25914610b52578063dfc7e2c914610b86578063e10a64dd14610ba657600080fd5b8063b88d4fde116100dc578063b88d4fde14610abc578063c074f41214610adc578063c87b56dd14610afc578063cf62c8ab14610b1c57600080fd5b8063a9b5898f146109f6578063b4b5b48f14610a7a578063b585209b14610aa757600080fd5b806386758e711161017a57806395d89b411161014957806395d89b41146109895780639a14f79d1461099e578063a22cb465146109b4578063a715b15b146109d457600080fd5b806386758e711461090b5780638796ba8c1461092b5780638ada6b0f1461094b5780638da5cb5b1461096b57600080fd5b806370a08231116101b657806370a0823114610891578063715018a6146108b157806372c64f16146108c657806381870fd1146108f657600080fd5b80635a08cae5146107a85780636352211e1461085a57806368d99f7c1461087a57600080fd5b80631fd9d081116102c15780633b2bcbf11161025f5780634e02099f1161022e5780634e02099f146107145780634f558e79146107345780634f6ccce71461075457806355380dfb1461077457600080fd5b80633b2bcbf11461068b5780633ccfd60b146106bf57806342842e0e146106d457806349cae612146106f457600080fd5b806321e182081161029b57806321e182081461062157806323b872dd1461063657806324e9edb0146106565780632f745c591461066b57600080fd5b80631fd9d081146105a45780631fe543e3146105d357806320c5780c146105f357600080fd5b80630f8236081161032e57806318160ddd1161030857806318160ddd146104f25780631a6949e31461052e5780631d2e2cc4146105435780631fafadbc1461058457600080fd5b80630f8236081461049b57806312b40a9f146104bd578063143a3f92146104dd57600080fd5b8063081812fc1161036a578063081812fc14610417578063095ea7b3146104445780630badbd07146104665780630eecae211461048657600080fd5b806301ffc9a71461039c57806304035a92146103d257806306fdde03146103f557600080fd5b3661039757005b600080fd5b3480156103a857600080fd5b506103bc6103b7366004614054565b610c8a565b6040516103c9919061407f565b60405180910390f35b3480156103de57600080fd5b506103e8600a5481565b6040516103c99190614093565b34801561040157600080fd5b5061040a610d5b565b6040516103c991906140ff565b34801561042357600080fd5b50610437610432366004614128565b610ded565b6040516103c99190614163565b34801561045057600080fd5b5061046461045f366004614185565b610e4a565b005b34801561047257600080fd5b506104646104813660046141c2565b610f0a565b34801561049257600080fd5b50610464611082565b3480156104a757600080fd5b506104b0600381565b6040516103c991906141ed565b3480156104c957600080fd5b506104646104d83660046141fb565b61158a565b3480156104e957600080fd5b506104b0602081565b3480156104fe57600080fd5b506103e86000546001600160801b0370010000000000000000000000000000000082048116918116919091031690565b34801561053a57600080fd5b506103bc611617565b34801561054f57600080fd5b506105777f000000000000000000000000000000000000000000000000000000000000000081565b6040516103c9919061425e565b34801561059057600080fd5b506104b061059f366004614128565b611632565b3480156105b057600080fd5b506105c46105bf366004614128565b611666565b6040516103c993929190614287565b3480156105df57600080fd5b506104646105ee3660046143b4565b6116b0565b3480156105ff57600080fd5b506015546106149067ffffffffffffffff1681565b6040516103c99190614412565b34801561062d57600080fd5b50610464611744565b34801561064257600080fd5b50610464610651366004614420565b6118b3565b34801561066257600080fd5b506104646118be565b34801561067757600080fd5b506103e8610686366004614185565b6119a0565b34801561069757600080fd5b506105777f000000000000000000000000000000000000000000000000000000000000000081565b3480156106cb57600080fd5b50610464611ab6565b3480156106e057600080fd5b506104646106ef366004614420565b611f69565b34801561070057600080fd5b5061046461070f366004614470565b611f84565b34801561072057600080fd5b5061046461072f366004614185565b611ff9565b34801561074057600080fd5b506103bc61074f366004614128565b6120df565b34801561076057600080fd5b506103e861076f366004614128565b6120ea565b34801561078057600080fd5b506105777f000000000000000000000000000000000000000000000000000000000000000081565b3480156107b457600080fd5b5061084b6107c3366004614128565b6016602090815260009182526040918290208251606081018452815461ffff808216835268ffffffffffffffffff620100008304168386015260ff6b0100000000000000000000009092048216151583870152600184015486518088019097526002909401546001600160a01b0381168752600160a01b900416938501939093529291169083565b6040516103c9939291906144e5565b34801561086657600080fd5b50610437610875366004614128565b6121ae565b34801561088657600080fd5b50600a5415156103bc565b34801561089d57600080fd5b506103e86108ac3660046141fb565b6121c0565b3480156108bd57600080fd5b50610464612228565b3480156108d257600080fd5b506103bc6108e1366004614128565b60136020526000908152604090205460ff1681565b34801561090257600080fd5b5061046461225e565b34801561091757600080fd5b506103bc610926366004614128565b612636565b34801561093757600080fd5b506103e8610946366004614128565b612673565b34801561095757600080fd5b50601154610577906001600160a01b031681565b34801561097757600080fd5b506007546001600160a01b0316610437565b34801561099557600080fd5b5061040a612694565b3480156109aa57600080fd5b506103e860185481565b3480156109c057600080fd5b506104646109cf366004614520565b6126a3565b3480156109e057600080fd5b506109e9612755565b6040516103c991906145e3565b348015610a0257600080fd5b50600b54610a689061ffff808216916201000081048216916401000000008204169062ffffff66010000000000008204169068ffffffffffffffffff69010000000000000000008204811691720100000000000000000000000000000000000090041686565b6040516103c9969594939291906145ff565b348015610a8657600080fd5b50610a9a610a95366004614128565b6128e7565b6040516103c9919061476a565b348015610ab357600080fd5b50610464612a40565b348015610ac857600080fd5b50610464610ad7366004614812565b612aaf565b348015610ae857600080fd5b50601054610437906001600160a01b031681565b348015610b0857600080fd5b5061040a610b17366004614128565b612ae9565b348015610b2857600080fd5b50610464610b373660046148b0565b612bfb565b348015610b4857600080fd5b506103e860095481565b348015610b5e57600080fd5b506104377f000000000000000000000000000000000000000000000000000000000000000081565b348015610b9257600080fd5b50610464610ba1366004614923565b612e54565b610464610bb43660046143b4565b612eb1565b348015610bc557600080fd5b506103bc610bd436600461496b565b6001600160a01b03918216600090815260066020908152604080832093909416825291909152205460ff1690565b348015610c0e57600080fd5b50610464610c1d3660046141fb565b613205565b348015610c2e57600080fd5b506105777f000000000000000000000000000000000000000000000000000000000000000081565b348015610c6257600080fd5b506103e87f000000000000000000000000000000000000000000000000000000000000000081565b60006001600160e01b031982167f80ac58cd000000000000000000000000000000000000000000000000000000001480610ced57506001600160e01b031982167f5b5e139f00000000000000000000000000000000000000000000000000000000145b80610d2157506001600160e01b031982167f780e9d6300000000000000000000000000000000000000000000000000000000145b80610d5557507f01ffc9a7000000000000000000000000000000000000000000000000000000006001600160e01b03198316145b92915050565b606060018054610d6a906149b4565b80601f0160208091040260200160405190810160405280929190818152602001828054610d96906149b4565b8015610de35780601f10610db857610100808354040283529160200191610de3565b820191906000526020600020905b815481529060010190602001808311610dc657829003601f168201915b5050505050905090565b6000610df882613261565b610e2e576040517fcf4700e400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b506000908152600560205260409020546001600160a01b031690565b6000610e55826121ae565b9050806001600160a01b0316836001600160a01b03161415610ea3576040517f943f7b8c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b336001600160a01b03821614801590610ec35750610ec18133610bd4565b155b15610efa576040517fcfb3b94200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610f05838383613295565b505050565b60026008541415610f365760405162461bcd60e51b8152600401610f2d90614a0d565b60405180910390fd5b6002600855600d546040517f6352211e00000000000000000000000000000000000000000000000000000000815233917f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031691636352211e91610fa391600401614093565b602060405180830381865afa158015610fc0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fe49190614a28565b6001600160a01b031614611024576040517fb2c6179c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600e54821461105f576040517f8f6d9d6300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600f54611079906110729060ff166132fe565b3383613339565b50506001600855565b600260085414156110a55760405162461bcd60e51b8152600401610f2d90614a0d565b600260085560175460155467ffffffffffffffff166110f0576040517f15cd15ad00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6110f86135f9565b61112e576040517fc3a7d74d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600054611145906001600160801b03166001614a5f565b6001600160801b0316600c828154811061116157611161614a97565b60009182526020909120015461ffff161015611581576000600c828154811061118c5761118c614a97565b6000918252602090912001546b010000000000000000000000900460ff1680156111d35750600b546009546111d0916601000000000000900462ffffff1690614aad565b42105b806111e25750600f5460ff1682145b156111f7576111f0826132fe565b90506112dd565b6015546040517f5d3b1d300000000000000000000000000000000000000000000000000000000081526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001691635d3b1d3091611297917f00000000000000000000000000000000000000000000000000000000000000009167ffffffffffffffff909116906005906207a12090600190600401614aee565b6020604051808303816000875af11580156112b6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112da9190614b45565b90505b600c82815481106112f0576112f0614a97565b6000918252602082200154601880546201000090920468ffffffffffffffffff1692909161131f908490614aad565b925050819055506040518060600160405280600c848154811061134457611344614a97565b6000918252602080832060408051606081018252939091015461ffff80821685526201000080830468ffffffffffffffffff908116878701526b0100000000000000000000009384900460ff161515878601529588528785018790528351808501855287815280860188905297840197909752888652601684529482902087518051825482870151928601519189166affffffffffffffffffffff199091161791909616909702969096176bff00000000000000000000001916931515029290921784558481015160018501805460ff191691151591909117905593015180516002909301805491909401516001600160a01b0390931675ffffffffffffffffffffffffffffffffffffffffffff1990911617600160a01b9290911691909102179055600c805482917fb40531e03f8d4be5f5bb24f4d1811140fbead25a449a04cdb8e941384a810702918590811061149f5761149f614a97565b906000526020600020016040516114b69190614be8565b60405180910390a2816114c881614bf6565b60178054600181810183556000929092527fc624b66cc0138b8fabc209247f72d758e1cf3343756d543badbf24212bed8c1501849055600c5491945061150f925090614c11565b821480156115355750600b54600a546115329162010000900461ffff1690614aad565b42105b15611541575050611583565b600c5482141561157b576040517fc4f545db975f34de8f12b4353fa42dd295e802239df19ebbe5fd3c245dad0a5a90600090a15050611583565b5061112e565b505b6001600855565b6007546001600160a01b031633146115b45760405162461bcd60e51b8152600401610f2d90614c5c565b601080546001600160a01b03831673ffffffffffffffffffffffffffffffffffffffff19918216811790925560118054909116821790556040517f2926c01a1380ae82a404a8c554ad486a6842a4a320d80b770e2930d763825e4f90600090a250565b600060095460001415801561162d575060095442115b905090565b6012818154811061164257600080fd5b9060005260206000209060209182820401919006915054906101000a900460ff1681565b600c818154811061167657600080fd5b60009182526020909120015461ffff8116915062010000810468ffffffffffffffffff16906b010000000000000000000000900460ff1683565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461173657337f00000000000000000000000000000000000000000000000000000000000000006040517f1cf993f4000000000000000000000000000000000000000000000000000000008152600401610f2d929190614c6c565b6117408282613699565b5050565b6007546001600160a01b0316331461176e5760405162461bcd60e51b8152600401610f2d90614c5c565b600a546117a7576040517fe5b93aca00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600b54600a546117bb9161ffff1690614aad565b4210156117f4576040517f3e8e963c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040514790600090339083908381818185875af1925050503d8060008114611838576040519150601f19603f3d011682016040523d82523d6000602084013e61183d565b606091505b5050905080611878576040517f27fcd9d100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f4e70a604b23a8edee2b1d0a656e9b9c00b73ad8bb1afc2c59381ee9f69197de7826040516118a79190614093565b60405180910390a15050565b610f0583838361372c565b6007546001600160a01b031633146118e85760405162461bcd60e51b8152600401610f2d90614c5c565b6015546040517fd7ae1d300000000000000000000000000000000000000000000000000000000081526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169163d7ae1d309161195b9167ffffffffffffffff16903390600401614c87565b600060405180830381600087803b15801561197557600080fd5b505af1158015611989573d6000803e3d6000fd5b50506015805467ffffffffffffffff191690555050565b60006119ab836121c0565b82106119e3576040517f0ddac30e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080546001600160801b03169080805b83811015611ab057600081815260036020908152604091829020825160608101845290546001600160a01b0381168252600160a01b810467ffffffffffffffff1692820192909252600160e01b90910460ff161580159282019290925290611a5c5750611aa8565b80516001600160a01b031615611a7157805192505b876001600160a01b0316836001600160a01b03161415611aa65786841415611a9f57509350610d5592505050565b6001909301925b505b6001016119f4565b50600080fd5b6007546001600160a01b03163314611ae05760405162461bcd60e51b8152600401610f2d90614c5c565b611ae86135f9565b15611b1e576040517fa8ad87cbcccddb5ba11ee5851b9075d95af2c88adb9ad0ae9a4f40b810b74cb590600090a1611b1e611082565b601754479060005b81811015611bc5576016600060178381548110611b4557611b45614a97565b6000918252602080832090910154835282019290925260400190206001015460ff16611bbd576016600060178381548110611b8257611b82614a97565b60009182526020808320909101548352820192909252604001902054611bba9068ffffffffffffffffff620100009091041684614c11565b92505b600101611b26565b508180611bfe576040517f356680b700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006014547f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611c61573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c859190614b45565b611c8f9190614c11565b600054600c546017549293506001600160801b03909116915b81811015611ea657600083600c8381548110611cc657611cc6614a97565b600091825260209091200154611ce0919061ffff16614c11565b905080851115611d5957600b54611d279068ffffffffffffffffff720100000000000000000000000000000000000082048116916901000000000000000000900416614cab565b611d3c9068ffffffffffffffffff1682614cce565b611d469089614aad565b9750611d528186614c11565b9450611df5565b600b546901000000000000000000900468ffffffffffffffffff16611d7e8683614c11565b611d889190614cce565b600b54611dc59068ffffffffffffffffff720100000000000000000000000000000000000082048116916901000000000000000000900416614cab565b611dda9068ffffffffffffffffff1687614cce565b611de49190614aad565b611dee9089614aad565b9750600094505b600c8281548110611e0857611e08614a97565b600091825260209091200154611e2f9062010000900468ffffffffffffffffff1689614c11565b97506001881015611e6c576040517f356680b700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b85881015611e78578795505b600c8281548110611e8b57611e8b614a97565b60009182526020909120015461ffff16935050600101611ca8565b50604051600090339086908381818185875af1925050503d8060008114611ee9576040519150601f19603f3d011682016040523d82523d6000602084013e611eee565b606091505b5050905080611f29576040517f27fcd9d100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f4e70a604b23a8edee2b1d0a656e9b9c00b73ad8bb1afc2c59381ee9f69197de785604051611f589190614093565b60405180910390a150505050505050565b610f0583838360405180602001604052806000815250612aaf565b60026008541415611fa75760405162461bcd60e51b8152600401610f2d90614a0d565b60026008556007546001600160a01b03163314611fd65760405162461bcd60e51b8152600401610f2d90614c5c565b6000611fe1846132fe565b9050611fee818484613339565b505060016008555050565b6007546001600160a01b031633146120235760405162461bcd60e51b8152600401610f2d90614c5c565b600b546000548291640100000000900461ffff169061204c9083906001600160801b0316614aad565b1115612084576040517ffd59427a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005460039061209d906001600160801b031684614aad565b11156120d5576040517f74a5d1f500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610f058383613994565b6000610d5582613261565b600080546001600160801b031681805b8281101561217b57600081815260036020908152604091829020825160608101845290546001600160a01b0381168252600160a01b810467ffffffffffffffff1692820192909252600160e01b90910460ff16151591810182905290612172578583141561216b5750949350505050565b6001909201915b506001016120fa565b506040517fa723001c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006121b982613a9b565b5192915050565b60006001600160a01b038216612202576040517f8f4eb60400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b506001600160a01b031660009081526004602052604090205467ffffffffffffffff1690565b6007546001600160a01b031633146122525760405162461bcd60e51b8152600401610f2d90614c5c565b61225c6000613bd8565b565b600260085414156122815760405162461bcd60e51b8152600401610f2d90614a0d565b600260085560175460005b818110156110795760166000601783815481106122ab576122ab614a97565b6000918252602080832090910154835282019290925260400190206001015460ff16158015612344575060166000601783815481106122ec576122ec614a97565b6000918252602080832090910154835282019290925260400190205460ff6b0100000000000000000000009091041615806123445750600b54600954612341916601000000000000900462ffffff1690614aad565b42115b1561262e576015546040517f5d3b1d300000000000000000000000000000000000000000000000000000000081526000916001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001691635d3b1d30916123ea917f00000000000000000000000000000000000000000000000000000000000000009167ffffffffffffffff16906005906207a12090600190600401614aee565b6020604051808303816000875af1158015612409573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061242d9190614b45565b90506040518060600160405280601660006017868154811061245157612451614a97565b600091825260208083209190910154835282810193909352604091820181208251606081018452905461ffff80821683526201000080830468ffffffffffffffffff908116858901526b0100000000000000000000009384900460ff1615158588015293885287870185905285518087018752858152808801869052978601979097528884526016808752858520895180518254828b0151928a01519186166affffffffffffffffffffff199091161791909616909902989098176bff000000000000000000000019169315159092029290921786558685015160018701805460ff1916911515919091179055959092015180516002909501805491909401516001600160a01b0390951675ffffffffffffffffffffffffffffffffffffffffffff1990911617600160a01b9490921693909302179055601780548590811061259c5761259c614a97565b60009182526020808320909101548352820192909252604001902080547fffffffffffffffffffffffffffffffffffffffff00000000000000000000000016815560018101805460ff19169055600201805475ffffffffffffffffffffffffffffffffffffffffffff19169055601780548291908490811061262057612620614a97565b600091825260209091200155505b60010161228c565b60006012828154811061264b5761264b614a97565b6000918252602091829020918104909101546001601f9092166101000a900481161492915050565b6017818154811061268357600080fd5b600091825260209091200154905081565b606060028054610d6a906149b4565b6001600160a01b0382163314156126e6576040517fb06307db00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3360008181526006602090815260408083206001600160a01b038716808552925291829020805460ff191685151517905590519091907f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c319061274990859061407f565b60405180910390a35050565b60175460609060009067ffffffffffffffff811115612776576127766142af565b6040519080825280602002602001820160405280156127e657816020015b6040805160c0810182526000606082018181526080830182905260a083018290528252602080830182905283518085018552828152808201929092529282015282526000199092019101816127945790505b50905060005b6017548110156128e157601660006017838154811061280d5761280d614a97565b600091825260208083209091015483528281019390935260409182019020815160c081018352815461ffff8082166060840190815268ffffffffffffffffff62010000840416608085015260ff6b0100000000000000000000009093048316151560a085015283526001840154909116151582860152835180850185526002909301546001600160a01b0381168452600160a01b900416938201939093529082015282518390839081106128c3576128c3614a97565b602002602001018190525080806128d990614bf6565b9150506127ec565b50919050565b6129126040518060800160405280606081526020016060815260200160608152602001606081525090565b61291b82613261565b612951576040517fa14c4b5000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6010546001600160a01b0316612993576040517f38bdd72700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601154601280546001600160a01b03909216916344ec3631918591829081106129be576129be614a97565b90600052602060002090602091828204019190069054906101000a900460ff166040518363ffffffff1660e01b81526004016129fb929190614ced565b600060405180830381865afa158015612a18573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610d559190810190614f4e565b6007546001600160a01b03163314612a6a5760405162461bcd60e51b8152600401610f2d90614c5c565b612a72611617565b15612aa9576040517fd205ec1b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b42600955565b612aba84848461372c565b612ac684848484613c37565b612ae3576040516368d2bf6b60e11b815260040160405180910390fd5b50505050565b6060612af482613261565b612b2a576040517fa14c4b5000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6010546001600160a01b0316612b4e57505060408051602081019091526000815290565b601154601280546001600160a01b0390921691635cc518ba91859182908110612b7957612b79614a97565b90600052602060002090602091828204019190069054906101000a900460ff166040518363ffffffff1660e01b8152600401612bb6929190614ced565b600060405180830381865afa158015612bd3573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610d559190810190614f89565b60026008541415612c1e5760405162461bcd60e51b8152600401610f2d90614a0d565b600260085560155467ffffffffffffffff16612d72577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a21a23e46040518163ffffffff1660e01b81526004016020604051808303816000875af1158015612c94573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612cb89190614fdf565b6015805467ffffffffffffffff191667ffffffffffffffff9290921691821790556040517f7341c10c0000000000000000000000000000000000000000000000000000000081527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031691637341c10c91612d3f91903090600401614c87565b600060405180830381600087803b158015612d5957600080fd5b505af1158015612d6d573d6000803e3d6000fd5b505050505b6015546040516001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001691634000aea0917f0000000000000000000000000000000000000000000000000000000000000000918591612de49167ffffffffffffffff1690602001614412565b6040516020818303038152906040526040518463ffffffff1660e01b8152600401612e1193929190615023565b6020604051808303816000875af1158015612e30573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611079919061505b565b60026008541415612e775760405162461bcd60e51b8152600401610f2d90614a0d565b60026008558060005b81811015611fee57612ea9848483818110612e9d57612e9d614a97565b90506020020135613d69565b600101612e80565b612eb9611617565b612eef576040517f63a2de0f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600b546000548391640100000000900461ffff1690612f189083906001600160801b0316614aad565b1115612f50576040517ffd59427a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60026008541415612f735760405162461bcd60e51b8152600401610f2d90614a0d565b6002600855600b54600090612fa19085906901000000000000000000900468ffffffffffffffffff16614cce565b8351909150600090815b8181101561319957336001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636352211e888481518110612ffe57612ffe614a97565b60200260200101516040518263ffffffff1660e01b81526004016130229190614093565b602060405180830381865afa15801561303f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130639190614a28565b6001600160a01b0316146130a3576040517f5246352300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601360008783815181106130b9576130b9614a97565b60209081029190910181015182528101919091526040016000205460ff161580156130e357508683105b156131915760016013600088848151811061310057613100614a97565b6020026020010151815260200190815260200160002060006101000a81548160ff021916908315150217905550828061313890614bf6565b600b54909450613179915068ffffffffffffffffff720100000000000000000000000000000000000082048116916901000000000000000000900416614cab565b61318e9068ffffffffffffffffff1685614c11565b93505b600101612fab565b5081601460008282546131ac9190614aad565b90915550503483146131ee5782346040517f6871963e000000000000000000000000000000000000000000000000000000008152600401610f2d92919061507c565b6131f83387613994565b5050600160085550505050565b6007546001600160a01b0316331461322f5760405162461bcd60e51b8152600401610f2d90614c5c565b6001600160a01b0381166132555760405162461bcd60e51b8152600401610f2d90615097565b61325e81613bd8565b50565b600080546001600160801b031682108015610d55575050600090815260036020526040902054600160e01b900460ff161590565b600082815260056020526040808220805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0387811691821790925591518593918516917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a4505050565b600061330b60ff836150f8565b60405160200161331b9190615124565b60408051601f19818403018152919052805160209091012092915050565b60008381526016602052604090206001015460ff1615613385576040517f636d49d300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008381526016602052604090205462010000900468ffffffffffffffffff166133db576040517f8e1773d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b816001600160a01b03166133ee826121ae565b6001600160a01b03161461342e576040517f03e21ec200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008381526016602052604090205461344d9060019061ffff16615136565b61ffff1681111561348a576040517f518af55d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008381526016602081815260408084206001818101805460ff19169091179055815180830183526001600160a01b0380891680835261ffff808a168488019081528c8a529790965282516002850180549851909716600160a01b0275ffffffffffffffffffffffffffffffffffffffffffff19909816921691909117959095179093555490519193929168ffffffffffffffffff62010000909204919091169060006040518083038185875af1925050503d8060008114613568576040519150601f19603f3d011682016040523d82523d6000602084013e61356d565b606091505b50509050806135a8576040517f90b8ec1800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008581526016602052604090819020905186917f7d2db4ed55b360e8ea7d70390d6f63a1404136410fa6f3f94a41d1cf99488a7f916135ea91908690615144565b60405180910390a25050505050565b600c54601754600091141561360e5750600090565b600c5461361d90600190614c11565b6017541480156136455750600b54600a546136429162010000900461ffff1690614aad565b42105b156136505750600090565b600054601754600c80546001600160801b0390931692909190811061367757613677614a97565b60009182526020909120015461ffff1611156136935750600090565b50600190565b60008281526016602052604090205461ffff16806136e3576040517f018bd28900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600081836000815181106136f9576136f9614a97565b602002602001015161370b91906150f8565b90506000613718826121ae565b9050613725858284613339565b5050505050565b600061373782613a9b565b80519091506000906001600160a01b0316336001600160a01b03161480613765575081516137659033610bd4565b8061378057503361377584610ded565b6001600160a01b0316145b9050806137b9576040517f59c896be00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b846001600160a01b031682600001516001600160a01b031614613808576040517fa114810000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b038416613848576040517fea553b3400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6138586000848460000151613295565b6001600160a01b038581166000908152600460209081526040808320805467ffffffffffffffff1980821667ffffffffffffffff92831660001901831617909255898616808652838620805493841693831660019081018416949094179055898652600390945282852080546001600160e01b031916909417600160a01b42909216919091021790925590860180835291205490911661394d576000546001600160801b031681101561394d578251600082815260036020908152604090912080549186015167ffffffffffffffff16600160a01b026001600160e01b03199092166001600160a01b03909316929092171790555b5082846001600160a01b0316866001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4613725565b60208111156139cf576040517f359fd04400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600081333442446040516020016139ea959493929190615187565b60405160208183030381529060405280519060200120905060005b82811015613a635760126001838360208110613a2357613a23614a97565b83546001808201865560009586526020958690209582049095018054601f9092166101000a60ff818102199093169490931a90941b160217905501613a05565b50613a6e8383613e29565b600b5460005464010000000090910461ffff166001600160801b039091161415610f055742600a55505050565b60408051606081018252600080825260208201819052918101829052905482906001600160801b0316811015613ba657600081815260036020908152604091829020825160608101845290546001600160a01b0381168252600160a01b810467ffffffffffffffff1692820192909252600160e01b90910460ff16151591810182905290613ba45780516001600160a01b031615613b3a579392505050565b5060001901600081815260036020908152604091829020825160608101845290546001600160a01b038116808352600160a01b820467ffffffffffffffff1693830193909352600160e01b900460ff1615159281019290925215613b9f579392505050565b613b3a565b505b6040517fdf2d9b4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600780546001600160a01b0383811673ffffffffffffffffffffffffffffffffffffffff19831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60006001600160a01b0384163b15613d5d576040517f150b7a020000000000000000000000000000000000000000000000000000000081526001600160a01b0385169063150b7a0290613c949033908990889088906004016151d1565b6020604051808303816000875af1925050508015613ccf575060408051601f3d908101601f19168201909252613ccc91810190615216565b60015b613d2a573d808015613cfd576040519150601f19603f3d011682016040523d82523d6000602084013e613d02565b606091505b508051613d22576040516368d2bf6b60e11b815260040160405180910390fd5b805181602001fd5b6001600160e01b0319167f150b7a0200000000000000000000000000000000000000000000000000000000149050613d61565b5060015b949350505050565b33613d73826121ae565b6001600160a01b031614613db3576040517fff68d35d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60128181548110613dc657613dc6614a97565b90600052602060002090602091828204019190069054906101000a900460ff1660011860128281548110613dfc57613dfc614a97565b90600052602060002090602091828204019190066101000a81548160ff021916908360ff16021790555050565b611740828260405180602001604052806000815250610f0583838360016000546001600160801b03166001600160a01b038516613e92576040517f2e07630000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b83613ec9576040517fb562e8dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b038516600081815260046020908152604080832080547fffffffffffffffffffffffffffffffff00000000000000000000000000000000811667ffffffffffffffff8083168c0181169182176801000000000000000067ffffffffffffffff1990941690921783900481168c018116909202179091558584526003909252822080546001600160e01b031916909317600160a01b42909216919091021790915581905b85811015613ff45760405182906001600160a01b038916906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a4838015613fca5750613fc86000888488613c37565b155b15613fe8576040516368d2bf6b60e11b815260040160405180910390fd5b60019182019101613f73565b50600080547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166001600160801b0392909216919091179055613725565b6001600160e01b031981165b811461325e57600080fd5b8035610d5581614032565b60006020828403121561406957614069600080fd5b6000613d618484614049565b8015155b82525050565b60208101610d558284614075565b80614079565b60208101610d55828461408d565b60005b838110156140bc5781810151838201526020016140a4565b83811115612ae35750506000910152565b60006140d7825190565b8084526020840193506140ee8185602086016140a1565b601f01601f19169290920192915050565b6020808252810161411081846140cd565b9392505050565b8061403e565b8035610d5581614117565b60006020828403121561413d5761413d600080fd5b6000613d61848461411d565b60006001600160a01b038216610d55565b61407981614149565b60208101610d55828461415a565b61403e81614149565b8035610d5581614171565b6000806040838503121561419b5761419b600080fd5b60006141a7858561417a565b92505060206141b88582860161411d565b9150509250929050565b600080604083850312156141d8576141d8600080fd5b60006141a7858561411d565b60ff8116614079565b60208101610d5582846141e4565b60006020828403121561421057614210600080fd5b6000613d61848461417a565b6000610d556001600160a01b038316614233565b90565b6001600160a01b031690565b6000610d558261421c565b6000610d558261423f565b6140798161424a565b60208101610d558284614255565b61ffff8116614079565b68ffffffffffffffffff8116614079565b60608101614295828661426c565b6142a26020830185614276565b613d616040830184614075565b634e487b7160e01b600052604160045260246000fd5b601f19601f830116810181811067ffffffffffffffff821117156142eb576142eb6142af565b6040525050565b60006142fd60405190565b905061430982826142c5565b919050565b600067ffffffffffffffff821115614328576143286142af565b5060209081020190565b60006143456143408461430e565b6142f2565b8381529050602080820190840283018581111561436457614364600080fd5b835b8181101561438657614378878261411d565b835260209283019201614366565b5050509392505050565b600082601f8301126143a4576143a4600080fd5b8135613d61848260208601614332565b600080604083850312156143ca576143ca600080fd5b60006143d6858561411d565b925050602083013567ffffffffffffffff8111156143f6576143f6600080fd5b6141b885828601614390565b67ffffffffffffffff8116614079565b60208101610d558284614402565b60008060006060848603121561443857614438600080fd5b6000614444868661417a565b93505060206144558682870161417a565b92505060406144668682870161411d565b9150509250925092565b60008060006060848603121561448857614488600080fd5b6000614444868661411d565b80516144a0838261426c565b5060208101516144b36020840182614276565b506040810151610f056040840182614075565b80516144d2838261415a565b506020810151610f05602084018261426c565b60c081016144f38286614494565b6145006060830185614075565b613d6160808301846144c6565b80151561403e565b8035610d558161450d565b6000806040838503121561453657614536600080fd5b6000614542858561417a565b92505060206141b885828601614515565b805161455f8382614494565b5060208101516145726060840182614075565b506040810151610f0560808401826144c6565b61458f8282614553565b5060c00190565b60200190565b60006145a6825190565b808452602093840193830160005b828110156145d95781516145c88782614585565b9650506020820191506001016145b4565b5093949350505050565b60208082528101614110818461459c565b62ffffff8116614079565b60c0810161460d828961426c565b61461a602083018861426c565b614627604083018761426c565b61463460608301866145f4565b6146416080830185614276565b61464e60a0830184614276565b979650505050505050565b805160408084526000919084019061467182826140cd565b9150506020830151848203602086015261468b82826140cd565b95945050505050565b60006141108383614659565b60006146aa825190565b808452602084019350836020820285016146c48560200190565b60005b848110156146f857838303885281516146e08482614694565b935050602082016020989098019791506001016146c7565b50909695505050505050565b805160808084526000919084019061471c82826140cd565b9150506020830151848203602086015261473682826140cd565b9150506040830151848203604086015261475082826140cd565b9150506060830151848203606086015261468b82826146a0565b602080825281016141108184614704565b600067ffffffffffffffff821115614795576147956142af565b601f19601f83011660200192915050565b82818337506000910152565b60006147c06143408461477b565b9050828152602081018484840111156147db576147db600080fd5b6147e68482856147a6565b509392505050565b600082601f83011261480257614802600080fd5b8135613d618482602086016147b2565b6000806000806080858703121561482b5761482b600080fd5b6000614837878761417a565b94505060206148488782880161417a565b93505060406148598782880161411d565b925050606085013567ffffffffffffffff81111561487957614879600080fd5b614885878288016147ee565b91505092959194509250565b6bffffffffffffffffffffffff811661403e565b8035610d5581614891565b6000602082840312156148c5576148c5600080fd5b6000613d6184846148a5565b60008083601f8401126148e6576148e6600080fd5b50813567ffffffffffffffff81111561490157614901600080fd5b60208301915083602082028301111561491c5761491c600080fd5b9250929050565b6000806020838503121561493957614939600080fd5b823567ffffffffffffffff81111561495357614953600080fd5b61495f858286016148d1565b92509250509250929050565b6000806040838503121561498157614981600080fd5b600061498d858561417a565b92505060206141b88582860161417a565b634e487b7160e01b600052602260045260246000fd5b6002810460018216806149c857607f821691505b602082108114156128e1576128e161499e565b601f8152602081017f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0081529050614596565b60208082528101610d55816149db565b8051610d5581614171565b600060208284031215614a3d57614a3d600080fd5b6000613d618484614a1d565b634e487b7160e01b600052601160045260246000fd5b6001600160801b03811690506001600160801b03821691506000826001600160801b0303821115614a9257614a92614a49565b500190565b634e487b7160e01b600052603260045260246000fd5b60008219821115614a9257614a92614a49565b6000610d55825b61ffff1690565b61407981614ac0565b600063ffffffff8216610d55565b61407981614ad7565b60a08101614afc828861408d565b614b096020830187614402565b614b166040830186614ace565b614b236060830185614ae5565b614b306080830184614ae5565b9695505050505050565b8051610d5581614117565b600060208284031215614b5a57614b5a600080fd5b6000613d618484614b3a565b6000610d5582614ac7565b6000610d55614b808360101c90565b68ffffffffffffffffff1690565b6000610d55614b9d8360581c90565b60ff1690565b8054614bae81614b66565b614bb8848261426c565b50614bc281614b71565b614bcf6020850182614276565b50614bd981614b8e565b9050610f056040840182614075565b60608101610d558284614ba3565b6000600019821415614c0a57614c0a614a49565b5060010190565b815b9150600082821015614c2757614c27614a49565b500390565b60208082527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65729101908152614596565b60208082528101610d5581614c2c565b60408101614c7a828561415a565b614110602083018461415a565b60408101614c7a8285614402565b634e487b7160e01b600052601260045260246000fd5b68ffffffffffffffffff9182169116600082614cc957614cc9614c95565b500490565b6000816000190483118215151615614ce857614ce8614a49565b500290565b60408101614cfb828561408d565b61411060208301846141e4565b6000614d166143408461477b565b905082815260208101848484011115614d3157614d31600080fd5b6147e68482856140a1565b600082601f830112614d5057614d50600080fd5b8151613d61848260208601614d08565b600060408284031215614d7557614d75600080fd5b614d7f60406142f2565b825190915067ffffffffffffffff811115614d9c57614d9c600080fd5b614da884828501614d3c565b825250602082015167ffffffffffffffff811115614dc857614dc8600080fd5b614dd484828501614d3c565b60208301525092915050565b6000614dee6143408461430e565b83815290506020808201908402830185811115614e0d57614e0d600080fd5b835b8181101561438657805167ffffffffffffffff811115614e3157614e31600080fd5b8501614e3d8882614d60565b84525060209283019201614e0f565b600082601f830112614e6057614e60600080fd5b8151613d61848260208601614de0565b600060808284031215614e8557614e85600080fd5b614e8f60806142f2565b825190915067ffffffffffffffff811115614eac57614eac600080fd5b614eb884828501614d3c565b825250602082015167ffffffffffffffff811115614ed857614ed8600080fd5b614ee484828501614d3c565b602083015250604082015167ffffffffffffffff811115614f0757614f07600080fd5b614f1384828501614d3c565b604083015250606082015167ffffffffffffffff811115614f3657614f36600080fd5b614f4284828501614e4c565b60608301525092915050565b600060208284031215614f6357614f63600080fd5b815167ffffffffffffffff811115614f7d57614f7d600080fd5b613d6184828501614e70565b600060208284031215614f9e57614f9e600080fd5b815167ffffffffffffffff811115614fb857614fb8600080fd5b613d6184828501614d3c565b67ffffffffffffffff811661403e565b8051610d5581614fc4565b600060208284031215614ff457614ff4600080fd5b6000613d618484614fd4565b6000610d556142306bffffffffffffffffffffffff841681565b61407981615000565b60608101615031828661415a565b61503e602083018561501a565b818103604083015261468b81846140cd565b8051610d558161450d565b60006020828403121561507057615070600080fd5b6000613d618484615050565b6040810161508a828561408d565b614110602083018461408d565b60208082528101610d5581602681527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160208201527f6464726573730000000000000000000000000000000000000000000000000000604082015260600190565b60008261510757615107614c95565b500690565b6000610d558260f81b90565b61407960ff821661510c565b61512e8183615118565b600101919050565b61ffff908116908216614c13565b60a081016151528285614ba3565b61411060608301846144c6565b6000610d558260601b90565b6000610d558261515f565b61407961518282614149565b61516b565b615191818761408d565b60200161519e8186615176565b6014016151ab818561408d565b6020016151b8818461408d565b6020016151c5818361408d565b60200195945050505050565b608081016151df828761415a565b6151ec602083018661415a565b6151f9604083018561408d565b8181036060830152614b3081846140cd565b8051610d5581614032565b60006020828403121561522b5761522b600080fd5b6000613d61848461520b56fea26469706673582212207dd66c8d317298ce56e6a7158ceeab1e7aba2a50e9aee48f85e7c4089ad87e4864736f6c634300080c00330000000000000000000000000000000000000000000000000000000000000240000000000000000000000000000000000000000000000000000000000000028000000000000000000000000004af8975918169ae48b25da78d5145bd673b2b6e000000000000000000000000271682deb8c4e0901d1a1550ad2e64d568e69909000000000000000000000000514910771af9ca656af840dff83e8264ecf986ca9fe0eebf5e446e3c998ec9bb19951541aee00bb90ea201ae456421a2ded868050000000000000000000000000000000000000000000000000000000000001c200000000000000000000000000000000000000000000000000000000000000e100000000000000000000000000000000000000000000000000000000000002710000000000000000000000000000000000000000000000000000000000024ea0000000000000000000000000000000000000000000000000000b1a2bc2ec50000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000002c000000000000000000000000057f1887a8bf19b14fc0df6fd9b2acc9af147ea850000000000000000000000002efa2743b863f3bd6f624ac0d58445bc5fb62bf66f4b4baf771f79ee3db2afdf13c35c213ea9f36f199efb86410649ffdf1adb0e000000000000000000000000000000000000000000000000000000000000002a0000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000b436f2d426f747320322e3000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044342544500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001f00000000000000000000000000000000000000000000000000000000000000640000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c80000000000000000000000000000000000000000000000001bc16d674ec800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012c00000000000000000000000000000000000000000000000029a2241af62c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001900000000000000000000000000000000000000000000000003782dace9d900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001f40000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000001f40000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000001f40000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000001f40000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000001f40000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000002ee00000000000000000000000000000000000000000000000053444835ec580000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003e80000000000000000000000000000000000000000000000006124fee993bc0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005dc0000000000000000000000000000000000000000000000006f05b59d3b200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007d00000000000000000000000000000000000000000000000007ce66c50e284000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000bb80000000000000000000000000000000000000000000000001bc16d674ec8000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000bb80000000000000000000000000000000000000000000000001bc16d674ec8000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000bb80000000000000000000000000000000000000000000000001bc16d674ec8000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000bb80000000000000000000000000000000000000000000000001bc16d674ec8000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000bb80000000000000000000000000000000000000000000000001bc16d674ec8000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000fa0000000000000000000000000000000000000000000000000a688906bd8b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001388000000000000000000000000000000000000000000000000c249fdd32778000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001388000000000000000000000000000000000000000000000002b5e3af16b188000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000001770000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001b58000000000000000000000000000000000000000000000000f9ccd8a1c508000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001f400000000000000000000000000000000000000000000000003782dace9d90000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000001f400000000000000000000000000000000000000000000000003782dace9d90000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000001f400000000000000000000000000000000000000000000000003782dace9d90000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000001f400000000000000000000000000000000000000000000000003782dace9d90000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000001f400000000000000000000000000000000000000000000000003782dace9d90000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000002328000000000000000000000000000000000000000000000001314fb37062980000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000027100000000000000000000000000000000000000000000000014d1120d7b160000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002710000000000000000000000000000000000000000000000003bd913e6c1df400000000000000000000000000000000000000000000000000000000000000000000

Deployed Bytecode

0x6080604052600436106103905760003560e01c80635a08cae5116101dc578063a9b5898f11610102578063d7822c99116100a0578063e985e9c51161006f578063e985e9c514610bb9578063f2fde38b14610c02578063fef490f314610c22578063ffae2b5614610c5657600080fd5b8063d7822c9914610b3c578063dce6c25914610b52578063dfc7e2c914610b86578063e10a64dd14610ba657600080fd5b8063b88d4fde116100dc578063b88d4fde14610abc578063c074f41214610adc578063c87b56dd14610afc578063cf62c8ab14610b1c57600080fd5b8063a9b5898f146109f6578063b4b5b48f14610a7a578063b585209b14610aa757600080fd5b806386758e711161017a57806395d89b411161014957806395d89b41146109895780639a14f79d1461099e578063a22cb465146109b4578063a715b15b146109d457600080fd5b806386758e711461090b5780638796ba8c1461092b5780638ada6b0f1461094b5780638da5cb5b1461096b57600080fd5b806370a08231116101b657806370a0823114610891578063715018a6146108b157806372c64f16146108c657806381870fd1146108f657600080fd5b80635a08cae5146107a85780636352211e1461085a57806368d99f7c1461087a57600080fd5b80631fd9d081116102c15780633b2bcbf11161025f5780634e02099f1161022e5780634e02099f146107145780634f558e79146107345780634f6ccce71461075457806355380dfb1461077457600080fd5b80633b2bcbf11461068b5780633ccfd60b146106bf57806342842e0e146106d457806349cae612146106f457600080fd5b806321e182081161029b57806321e182081461062157806323b872dd1461063657806324e9edb0146106565780632f745c591461066b57600080fd5b80631fd9d081146105a45780631fe543e3146105d357806320c5780c146105f357600080fd5b80630f8236081161032e57806318160ddd1161030857806318160ddd146104f25780631a6949e31461052e5780631d2e2cc4146105435780631fafadbc1461058457600080fd5b80630f8236081461049b57806312b40a9f146104bd578063143a3f92146104dd57600080fd5b8063081812fc1161036a578063081812fc14610417578063095ea7b3146104445780630badbd07146104665780630eecae211461048657600080fd5b806301ffc9a71461039c57806304035a92146103d257806306fdde03146103f557600080fd5b3661039757005b600080fd5b3480156103a857600080fd5b506103bc6103b7366004614054565b610c8a565b6040516103c9919061407f565b60405180910390f35b3480156103de57600080fd5b506103e8600a5481565b6040516103c99190614093565b34801561040157600080fd5b5061040a610d5b565b6040516103c991906140ff565b34801561042357600080fd5b50610437610432366004614128565b610ded565b6040516103c99190614163565b34801561045057600080fd5b5061046461045f366004614185565b610e4a565b005b34801561047257600080fd5b506104646104813660046141c2565b610f0a565b34801561049257600080fd5b50610464611082565b3480156104a757600080fd5b506104b0600381565b6040516103c991906141ed565b3480156104c957600080fd5b506104646104d83660046141fb565b61158a565b3480156104e957600080fd5b506104b0602081565b3480156104fe57600080fd5b506103e86000546001600160801b0370010000000000000000000000000000000082048116918116919091031690565b34801561053a57600080fd5b506103bc611617565b34801561054f57600080fd5b506105777f00000000000000000000000057f1887a8bf19b14fc0df6fd9b2acc9af147ea8581565b6040516103c9919061425e565b34801561059057600080fd5b506104b061059f366004614128565b611632565b3480156105b057600080fd5b506105c46105bf366004614128565b611666565b6040516103c993929190614287565b3480156105df57600080fd5b506104646105ee3660046143b4565b6116b0565b3480156105ff57600080fd5b506015546106149067ffffffffffffffff1681565b6040516103c99190614412565b34801561062d57600080fd5b50610464611744565b34801561064257600080fd5b50610464610651366004614420565b6118b3565b34801561066257600080fd5b506104646118be565b34801561067757600080fd5b506103e8610686366004614185565b6119a0565b34801561069757600080fd5b506105777f000000000000000000000000271682deb8c4e0901d1a1550ad2e64d568e6990981565b3480156106cb57600080fd5b50610464611ab6565b3480156106e057600080fd5b506104646106ef366004614420565b611f69565b34801561070057600080fd5b5061046461070f366004614470565b611f84565b34801561072057600080fd5b5061046461072f366004614185565b611ff9565b34801561074057600080fd5b506103bc61074f366004614128565b6120df565b34801561076057600080fd5b506103e861076f366004614128565b6120ea565b34801561078057600080fd5b506105777f000000000000000000000000514910771af9ca656af840dff83e8264ecf986ca81565b3480156107b457600080fd5b5061084b6107c3366004614128565b6016602090815260009182526040918290208251606081018452815461ffff808216835268ffffffffffffffffff620100008304168386015260ff6b0100000000000000000000009092048216151583870152600184015486518088019097526002909401546001600160a01b0381168752600160a01b900416938501939093529291169083565b6040516103c9939291906144e5565b34801561086657600080fd5b50610437610875366004614128565b6121ae565b34801561088657600080fd5b50600a5415156103bc565b34801561089d57600080fd5b506103e86108ac3660046141fb565b6121c0565b3480156108bd57600080fd5b50610464612228565b3480156108d257600080fd5b506103bc6108e1366004614128565b60136020526000908152604090205460ff1681565b34801561090257600080fd5b5061046461225e565b34801561091757600080fd5b506103bc610926366004614128565b612636565b34801561093757600080fd5b506103e8610946366004614128565b612673565b34801561095757600080fd5b50601154610577906001600160a01b031681565b34801561097757600080fd5b506007546001600160a01b0316610437565b34801561099557600080fd5b5061040a612694565b3480156109aa57600080fd5b506103e860185481565b3480156109c057600080fd5b506104646109cf366004614520565b6126a3565b3480156109e057600080fd5b506109e9612755565b6040516103c991906145e3565b348015610a0257600080fd5b50600b54610a689061ffff808216916201000081048216916401000000008204169062ffffff66010000000000008204169068ffffffffffffffffff69010000000000000000008204811691720100000000000000000000000000000000000090041686565b6040516103c9969594939291906145ff565b348015610a8657600080fd5b50610a9a610a95366004614128565b6128e7565b6040516103c9919061476a565b348015610ab357600080fd5b50610464612a40565b348015610ac857600080fd5b50610464610ad7366004614812565b612aaf565b348015610ae857600080fd5b50601054610437906001600160a01b031681565b348015610b0857600080fd5b5061040a610b17366004614128565b612ae9565b348015610b2857600080fd5b50610464610b373660046148b0565b612bfb565b348015610b4857600080fd5b506103e860095481565b348015610b5e57600080fd5b506104377f0000000000000000000000002efa2743b863f3bd6f624ac0d58445bc5fb62bf681565b348015610b9257600080fd5b50610464610ba1366004614923565b612e54565b610464610bb43660046143b4565b612eb1565b348015610bc557600080fd5b506103bc610bd436600461496b565b6001600160a01b03918216600090815260066020908152604080832093909416825291909152205460ff1690565b348015610c0e57600080fd5b50610464610c1d3660046141fb565b613205565b348015610c2e57600080fd5b506105777f0000000000000000000000002efa2743b863f3bd6f624ac0d58445bc5fb62bf681565b348015610c6257600080fd5b506103e87f9fe0eebf5e446e3c998ec9bb19951541aee00bb90ea201ae456421a2ded8680581565b60006001600160e01b031982167f80ac58cd000000000000000000000000000000000000000000000000000000001480610ced57506001600160e01b031982167f5b5e139f00000000000000000000000000000000000000000000000000000000145b80610d2157506001600160e01b031982167f780e9d6300000000000000000000000000000000000000000000000000000000145b80610d5557507f01ffc9a7000000000000000000000000000000000000000000000000000000006001600160e01b03198316145b92915050565b606060018054610d6a906149b4565b80601f0160208091040260200160405190810160405280929190818152602001828054610d96906149b4565b8015610de35780601f10610db857610100808354040283529160200191610de3565b820191906000526020600020905b815481529060010190602001808311610dc657829003601f168201915b5050505050905090565b6000610df882613261565b610e2e576040517fcf4700e400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b506000908152600560205260409020546001600160a01b031690565b6000610e55826121ae565b9050806001600160a01b0316836001600160a01b03161415610ea3576040517f943f7b8c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b336001600160a01b03821614801590610ec35750610ec18133610bd4565b155b15610efa576040517fcfb3b94200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610f05838383613295565b505050565b60026008541415610f365760405162461bcd60e51b8152600401610f2d90614a0d565b60405180910390fd5b6002600855600d546040517f6352211e00000000000000000000000000000000000000000000000000000000815233917f00000000000000000000000057f1887a8bf19b14fc0df6fd9b2acc9af147ea856001600160a01b031691636352211e91610fa391600401614093565b602060405180830381865afa158015610fc0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fe49190614a28565b6001600160a01b031614611024576040517fb2c6179c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600e54821461105f576040517f8f6d9d6300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600f54611079906110729060ff166132fe565b3383613339565b50506001600855565b600260085414156110a55760405162461bcd60e51b8152600401610f2d90614a0d565b600260085560175460155467ffffffffffffffff166110f0576040517f15cd15ad00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6110f86135f9565b61112e576040517fc3a7d74d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600054611145906001600160801b03166001614a5f565b6001600160801b0316600c828154811061116157611161614a97565b60009182526020909120015461ffff161015611581576000600c828154811061118c5761118c614a97565b6000918252602090912001546b010000000000000000000000900460ff1680156111d35750600b546009546111d0916601000000000000900462ffffff1690614aad565b42105b806111e25750600f5460ff1682145b156111f7576111f0826132fe565b90506112dd565b6015546040517f5d3b1d300000000000000000000000000000000000000000000000000000000081526001600160a01b037f000000000000000000000000271682deb8c4e0901d1a1550ad2e64d568e699091691635d3b1d3091611297917f9fe0eebf5e446e3c998ec9bb19951541aee00bb90ea201ae456421a2ded868059167ffffffffffffffff909116906005906207a12090600190600401614aee565b6020604051808303816000875af11580156112b6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112da9190614b45565b90505b600c82815481106112f0576112f0614a97565b6000918252602082200154601880546201000090920468ffffffffffffffffff1692909161131f908490614aad565b925050819055506040518060600160405280600c848154811061134457611344614a97565b6000918252602080832060408051606081018252939091015461ffff80821685526201000080830468ffffffffffffffffff908116878701526b0100000000000000000000009384900460ff161515878601529588528785018790528351808501855287815280860188905297840197909752888652601684529482902087518051825482870151928601519189166affffffffffffffffffffff199091161791909616909702969096176bff00000000000000000000001916931515029290921784558481015160018501805460ff191691151591909117905593015180516002909301805491909401516001600160a01b0390931675ffffffffffffffffffffffffffffffffffffffffffff1990911617600160a01b9290911691909102179055600c805482917fb40531e03f8d4be5f5bb24f4d1811140fbead25a449a04cdb8e941384a810702918590811061149f5761149f614a97565b906000526020600020016040516114b69190614be8565b60405180910390a2816114c881614bf6565b60178054600181810183556000929092527fc624b66cc0138b8fabc209247f72d758e1cf3343756d543badbf24212bed8c1501849055600c5491945061150f925090614c11565b821480156115355750600b54600a546115329162010000900461ffff1690614aad565b42105b15611541575050611583565b600c5482141561157b576040517fc4f545db975f34de8f12b4353fa42dd295e802239df19ebbe5fd3c245dad0a5a90600090a15050611583565b5061112e565b505b6001600855565b6007546001600160a01b031633146115b45760405162461bcd60e51b8152600401610f2d90614c5c565b601080546001600160a01b03831673ffffffffffffffffffffffffffffffffffffffff19918216811790925560118054909116821790556040517f2926c01a1380ae82a404a8c554ad486a6842a4a320d80b770e2930d763825e4f90600090a250565b600060095460001415801561162d575060095442115b905090565b6012818154811061164257600080fd5b9060005260206000209060209182820401919006915054906101000a900460ff1681565b600c818154811061167657600080fd5b60009182526020909120015461ffff8116915062010000810468ffffffffffffffffff16906b010000000000000000000000900460ff1683565b336001600160a01b037f000000000000000000000000271682deb8c4e0901d1a1550ad2e64d568e69909161461173657337f000000000000000000000000271682deb8c4e0901d1a1550ad2e64d568e699096040517f1cf993f4000000000000000000000000000000000000000000000000000000008152600401610f2d929190614c6c565b6117408282613699565b5050565b6007546001600160a01b0316331461176e5760405162461bcd60e51b8152600401610f2d90614c5c565b600a546117a7576040517fe5b93aca00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600b54600a546117bb9161ffff1690614aad565b4210156117f4576040517f3e8e963c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040514790600090339083908381818185875af1925050503d8060008114611838576040519150601f19603f3d011682016040523d82523d6000602084013e61183d565b606091505b5050905080611878576040517f27fcd9d100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f4e70a604b23a8edee2b1d0a656e9b9c00b73ad8bb1afc2c59381ee9f69197de7826040516118a79190614093565b60405180910390a15050565b610f0583838361372c565b6007546001600160a01b031633146118e85760405162461bcd60e51b8152600401610f2d90614c5c565b6015546040517fd7ae1d300000000000000000000000000000000000000000000000000000000081526001600160a01b037f000000000000000000000000271682deb8c4e0901d1a1550ad2e64d568e69909169163d7ae1d309161195b9167ffffffffffffffff16903390600401614c87565b600060405180830381600087803b15801561197557600080fd5b505af1158015611989573d6000803e3d6000fd5b50506015805467ffffffffffffffff191690555050565b60006119ab836121c0565b82106119e3576040517f0ddac30e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080546001600160801b03169080805b83811015611ab057600081815260036020908152604091829020825160608101845290546001600160a01b0381168252600160a01b810467ffffffffffffffff1692820192909252600160e01b90910460ff161580159282019290925290611a5c5750611aa8565b80516001600160a01b031615611a7157805192505b876001600160a01b0316836001600160a01b03161415611aa65786841415611a9f57509350610d5592505050565b6001909301925b505b6001016119f4565b50600080fd5b6007546001600160a01b03163314611ae05760405162461bcd60e51b8152600401610f2d90614c5c565b611ae86135f9565b15611b1e576040517fa8ad87cbcccddb5ba11ee5851b9075d95af2c88adb9ad0ae9a4f40b810b74cb590600090a1611b1e611082565b601754479060005b81811015611bc5576016600060178381548110611b4557611b45614a97565b6000918252602080832090910154835282019290925260400190206001015460ff16611bbd576016600060178381548110611b8257611b82614a97565b60009182526020808320909101548352820192909252604001902054611bba9068ffffffffffffffffff620100009091041684614c11565b92505b600101611b26565b508180611bfe576040517f356680b700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006014547f0000000000000000000000002efa2743b863f3bd6f624ac0d58445bc5fb62bf66001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611c61573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c859190614b45565b611c8f9190614c11565b600054600c546017549293506001600160801b03909116915b81811015611ea657600083600c8381548110611cc657611cc6614a97565b600091825260209091200154611ce0919061ffff16614c11565b905080851115611d5957600b54611d279068ffffffffffffffffff720100000000000000000000000000000000000082048116916901000000000000000000900416614cab565b611d3c9068ffffffffffffffffff1682614cce565b611d469089614aad565b9750611d528186614c11565b9450611df5565b600b546901000000000000000000900468ffffffffffffffffff16611d7e8683614c11565b611d889190614cce565b600b54611dc59068ffffffffffffffffff720100000000000000000000000000000000000082048116916901000000000000000000900416614cab565b611dda9068ffffffffffffffffff1687614cce565b611de49190614aad565b611dee9089614aad565b9750600094505b600c8281548110611e0857611e08614a97565b600091825260209091200154611e2f9062010000900468ffffffffffffffffff1689614c11565b97506001881015611e6c576040517f356680b700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b85881015611e78578795505b600c8281548110611e8b57611e8b614a97565b60009182526020909120015461ffff16935050600101611ca8565b50604051600090339086908381818185875af1925050503d8060008114611ee9576040519150601f19603f3d011682016040523d82523d6000602084013e611eee565b606091505b5050905080611f29576040517f27fcd9d100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f4e70a604b23a8edee2b1d0a656e9b9c00b73ad8bb1afc2c59381ee9f69197de785604051611f589190614093565b60405180910390a150505050505050565b610f0583838360405180602001604052806000815250612aaf565b60026008541415611fa75760405162461bcd60e51b8152600401610f2d90614a0d565b60026008556007546001600160a01b03163314611fd65760405162461bcd60e51b8152600401610f2d90614c5c565b6000611fe1846132fe565b9050611fee818484613339565b505060016008555050565b6007546001600160a01b031633146120235760405162461bcd60e51b8152600401610f2d90614c5c565b600b546000548291640100000000900461ffff169061204c9083906001600160801b0316614aad565b1115612084576040517ffd59427a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005460039061209d906001600160801b031684614aad565b11156120d5576040517f74a5d1f500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610f058383613994565b6000610d5582613261565b600080546001600160801b031681805b8281101561217b57600081815260036020908152604091829020825160608101845290546001600160a01b0381168252600160a01b810467ffffffffffffffff1692820192909252600160e01b90910460ff16151591810182905290612172578583141561216b5750949350505050565b6001909201915b506001016120fa565b506040517fa723001c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006121b982613a9b565b5192915050565b60006001600160a01b038216612202576040517f8f4eb60400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b506001600160a01b031660009081526004602052604090205467ffffffffffffffff1690565b6007546001600160a01b031633146122525760405162461bcd60e51b8152600401610f2d90614c5c565b61225c6000613bd8565b565b600260085414156122815760405162461bcd60e51b8152600401610f2d90614a0d565b600260085560175460005b818110156110795760166000601783815481106122ab576122ab614a97565b6000918252602080832090910154835282019290925260400190206001015460ff16158015612344575060166000601783815481106122ec576122ec614a97565b6000918252602080832090910154835282019290925260400190205460ff6b0100000000000000000000009091041615806123445750600b54600954612341916601000000000000900462ffffff1690614aad565b42115b1561262e576015546040517f5d3b1d300000000000000000000000000000000000000000000000000000000081526000916001600160a01b037f000000000000000000000000271682deb8c4e0901d1a1550ad2e64d568e699091691635d3b1d30916123ea917f9fe0eebf5e446e3c998ec9bb19951541aee00bb90ea201ae456421a2ded868059167ffffffffffffffff16906005906207a12090600190600401614aee565b6020604051808303816000875af1158015612409573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061242d9190614b45565b90506040518060600160405280601660006017868154811061245157612451614a97565b600091825260208083209190910154835282810193909352604091820181208251606081018452905461ffff80821683526201000080830468ffffffffffffffffff908116858901526b0100000000000000000000009384900460ff1615158588015293885287870185905285518087018752858152808801869052978601979097528884526016808752858520895180518254828b0151928a01519186166affffffffffffffffffffff199091161791909616909902989098176bff000000000000000000000019169315159092029290921786558685015160018701805460ff1916911515919091179055959092015180516002909501805491909401516001600160a01b0390951675ffffffffffffffffffffffffffffffffffffffffffff1990911617600160a01b9490921693909302179055601780548590811061259c5761259c614a97565b60009182526020808320909101548352820192909252604001902080547fffffffffffffffffffffffffffffffffffffffff00000000000000000000000016815560018101805460ff19169055600201805475ffffffffffffffffffffffffffffffffffffffffffff19169055601780548291908490811061262057612620614a97565b600091825260209091200155505b60010161228c565b60006012828154811061264b5761264b614a97565b6000918252602091829020918104909101546001601f9092166101000a900481161492915050565b6017818154811061268357600080fd5b600091825260209091200154905081565b606060028054610d6a906149b4565b6001600160a01b0382163314156126e6576040517fb06307db00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3360008181526006602090815260408083206001600160a01b038716808552925291829020805460ff191685151517905590519091907f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c319061274990859061407f565b60405180910390a35050565b60175460609060009067ffffffffffffffff811115612776576127766142af565b6040519080825280602002602001820160405280156127e657816020015b6040805160c0810182526000606082018181526080830182905260a083018290528252602080830182905283518085018552828152808201929092529282015282526000199092019101816127945790505b50905060005b6017548110156128e157601660006017838154811061280d5761280d614a97565b600091825260208083209091015483528281019390935260409182019020815160c081018352815461ffff8082166060840190815268ffffffffffffffffff62010000840416608085015260ff6b0100000000000000000000009093048316151560a085015283526001840154909116151582860152835180850185526002909301546001600160a01b0381168452600160a01b900416938201939093529082015282518390839081106128c3576128c3614a97565b602002602001018190525080806128d990614bf6565b9150506127ec565b50919050565b6129126040518060800160405280606081526020016060815260200160608152602001606081525090565b61291b82613261565b612951576040517fa14c4b5000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6010546001600160a01b0316612993576040517f38bdd72700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601154601280546001600160a01b03909216916344ec3631918591829081106129be576129be614a97565b90600052602060002090602091828204019190069054906101000a900460ff166040518363ffffffff1660e01b81526004016129fb929190614ced565b600060405180830381865afa158015612a18573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610d559190810190614f4e565b6007546001600160a01b03163314612a6a5760405162461bcd60e51b8152600401610f2d90614c5c565b612a72611617565b15612aa9576040517fd205ec1b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b42600955565b612aba84848461372c565b612ac684848484613c37565b612ae3576040516368d2bf6b60e11b815260040160405180910390fd5b50505050565b6060612af482613261565b612b2a576040517fa14c4b5000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6010546001600160a01b0316612b4e57505060408051602081019091526000815290565b601154601280546001600160a01b0390921691635cc518ba91859182908110612b7957612b79614a97565b90600052602060002090602091828204019190069054906101000a900460ff166040518363ffffffff1660e01b8152600401612bb6929190614ced565b600060405180830381865afa158015612bd3573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610d559190810190614f89565b60026008541415612c1e5760405162461bcd60e51b8152600401610f2d90614a0d565b600260085560155467ffffffffffffffff16612d72577f000000000000000000000000271682deb8c4e0901d1a1550ad2e64d568e699096001600160a01b031663a21a23e46040518163ffffffff1660e01b81526004016020604051808303816000875af1158015612c94573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612cb89190614fdf565b6015805467ffffffffffffffff191667ffffffffffffffff9290921691821790556040517f7341c10c0000000000000000000000000000000000000000000000000000000081527f000000000000000000000000271682deb8c4e0901d1a1550ad2e64d568e699096001600160a01b031691637341c10c91612d3f91903090600401614c87565b600060405180830381600087803b158015612d5957600080fd5b505af1158015612d6d573d6000803e3d6000fd5b505050505b6015546040516001600160a01b037f000000000000000000000000514910771af9ca656af840dff83e8264ecf986ca1691634000aea0917f000000000000000000000000271682deb8c4e0901d1a1550ad2e64d568e69909918591612de49167ffffffffffffffff1690602001614412565b6040516020818303038152906040526040518463ffffffff1660e01b8152600401612e1193929190615023565b6020604051808303816000875af1158015612e30573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611079919061505b565b60026008541415612e775760405162461bcd60e51b8152600401610f2d90614a0d565b60026008558060005b81811015611fee57612ea9848483818110612e9d57612e9d614a97565b90506020020135613d69565b600101612e80565b612eb9611617565b612eef576040517f63a2de0f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600b546000548391640100000000900461ffff1690612f189083906001600160801b0316614aad565b1115612f50576040517ffd59427a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60026008541415612f735760405162461bcd60e51b8152600401610f2d90614a0d565b6002600855600b54600090612fa19085906901000000000000000000900468ffffffffffffffffff16614cce565b8351909150600090815b8181101561319957336001600160a01b03167f0000000000000000000000002efa2743b863f3bd6f624ac0d58445bc5fb62bf66001600160a01b0316636352211e888481518110612ffe57612ffe614a97565b60200260200101516040518263ffffffff1660e01b81526004016130229190614093565b602060405180830381865afa15801561303f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130639190614a28565b6001600160a01b0316146130a3576040517f5246352300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601360008783815181106130b9576130b9614a97565b60209081029190910181015182528101919091526040016000205460ff161580156130e357508683105b156131915760016013600088848151811061310057613100614a97565b6020026020010151815260200190815260200160002060006101000a81548160ff021916908315150217905550828061313890614bf6565b600b54909450613179915068ffffffffffffffffff720100000000000000000000000000000000000082048116916901000000000000000000900416614cab565b61318e9068ffffffffffffffffff1685614c11565b93505b600101612fab565b5081601460008282546131ac9190614aad565b90915550503483146131ee5782346040517f6871963e000000000000000000000000000000000000000000000000000000008152600401610f2d92919061507c565b6131f83387613994565b5050600160085550505050565b6007546001600160a01b0316331461322f5760405162461bcd60e51b8152600401610f2d90614c5c565b6001600160a01b0381166132555760405162461bcd60e51b8152600401610f2d90615097565b61325e81613bd8565b50565b600080546001600160801b031682108015610d55575050600090815260036020526040902054600160e01b900460ff161590565b600082815260056020526040808220805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0387811691821790925591518593918516917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a4505050565b600061330b60ff836150f8565b60405160200161331b9190615124565b60408051601f19818403018152919052805160209091012092915050565b60008381526016602052604090206001015460ff1615613385576040517f636d49d300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008381526016602052604090205462010000900468ffffffffffffffffff166133db576040517f8e1773d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b816001600160a01b03166133ee826121ae565b6001600160a01b03161461342e576040517f03e21ec200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008381526016602052604090205461344d9060019061ffff16615136565b61ffff1681111561348a576040517f518af55d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008381526016602081815260408084206001818101805460ff19169091179055815180830183526001600160a01b0380891680835261ffff808a168488019081528c8a529790965282516002850180549851909716600160a01b0275ffffffffffffffffffffffffffffffffffffffffffff19909816921691909117959095179093555490519193929168ffffffffffffffffff62010000909204919091169060006040518083038185875af1925050503d8060008114613568576040519150601f19603f3d011682016040523d82523d6000602084013e61356d565b606091505b50509050806135a8576040517f90b8ec1800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008581526016602052604090819020905186917f7d2db4ed55b360e8ea7d70390d6f63a1404136410fa6f3f94a41d1cf99488a7f916135ea91908690615144565b60405180910390a25050505050565b600c54601754600091141561360e5750600090565b600c5461361d90600190614c11565b6017541480156136455750600b54600a546136429162010000900461ffff1690614aad565b42105b156136505750600090565b600054601754600c80546001600160801b0390931692909190811061367757613677614a97565b60009182526020909120015461ffff1611156136935750600090565b50600190565b60008281526016602052604090205461ffff16806136e3576040517f018bd28900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600081836000815181106136f9576136f9614a97565b602002602001015161370b91906150f8565b90506000613718826121ae565b9050613725858284613339565b5050505050565b600061373782613a9b565b80519091506000906001600160a01b0316336001600160a01b03161480613765575081516137659033610bd4565b8061378057503361377584610ded565b6001600160a01b0316145b9050806137b9576040517f59c896be00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b846001600160a01b031682600001516001600160a01b031614613808576040517fa114810000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b038416613848576040517fea553b3400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6138586000848460000151613295565b6001600160a01b038581166000908152600460209081526040808320805467ffffffffffffffff1980821667ffffffffffffffff92831660001901831617909255898616808652838620805493841693831660019081018416949094179055898652600390945282852080546001600160e01b031916909417600160a01b42909216919091021790925590860180835291205490911661394d576000546001600160801b031681101561394d578251600082815260036020908152604090912080549186015167ffffffffffffffff16600160a01b026001600160e01b03199092166001600160a01b03909316929092171790555b5082846001600160a01b0316866001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4613725565b60208111156139cf576040517f359fd04400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600081333442446040516020016139ea959493929190615187565b60405160208183030381529060405280519060200120905060005b82811015613a635760126001838360208110613a2357613a23614a97565b83546001808201865560009586526020958690209582049095018054601f9092166101000a60ff818102199093169490931a90941b160217905501613a05565b50613a6e8383613e29565b600b5460005464010000000090910461ffff166001600160801b039091161415610f055742600a55505050565b60408051606081018252600080825260208201819052918101829052905482906001600160801b0316811015613ba657600081815260036020908152604091829020825160608101845290546001600160a01b0381168252600160a01b810467ffffffffffffffff1692820192909252600160e01b90910460ff16151591810182905290613ba45780516001600160a01b031615613b3a579392505050565b5060001901600081815260036020908152604091829020825160608101845290546001600160a01b038116808352600160a01b820467ffffffffffffffff1693830193909352600160e01b900460ff1615159281019290925215613b9f579392505050565b613b3a565b505b6040517fdf2d9b4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600780546001600160a01b0383811673ffffffffffffffffffffffffffffffffffffffff19831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60006001600160a01b0384163b15613d5d576040517f150b7a020000000000000000000000000000000000000000000000000000000081526001600160a01b0385169063150b7a0290613c949033908990889088906004016151d1565b6020604051808303816000875af1925050508015613ccf575060408051601f3d908101601f19168201909252613ccc91810190615216565b60015b613d2a573d808015613cfd576040519150601f19603f3d011682016040523d82523d6000602084013e613d02565b606091505b508051613d22576040516368d2bf6b60e11b815260040160405180910390fd5b805181602001fd5b6001600160e01b0319167f150b7a0200000000000000000000000000000000000000000000000000000000149050613d61565b5060015b949350505050565b33613d73826121ae565b6001600160a01b031614613db3576040517fff68d35d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60128181548110613dc657613dc6614a97565b90600052602060002090602091828204019190069054906101000a900460ff1660011860128281548110613dfc57613dfc614a97565b90600052602060002090602091828204019190066101000a81548160ff021916908360ff16021790555050565b611740828260405180602001604052806000815250610f0583838360016000546001600160801b03166001600160a01b038516613e92576040517f2e07630000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b83613ec9576040517fb562e8dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b038516600081815260046020908152604080832080547fffffffffffffffffffffffffffffffff00000000000000000000000000000000811667ffffffffffffffff8083168c0181169182176801000000000000000067ffffffffffffffff1990941690921783900481168c018116909202179091558584526003909252822080546001600160e01b031916909317600160a01b42909216919091021790915581905b85811015613ff45760405182906001600160a01b038916906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a4838015613fca5750613fc86000888488613c37565b155b15613fe8576040516368d2bf6b60e11b815260040160405180910390fd5b60019182019101613f73565b50600080547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166001600160801b0392909216919091179055613725565b6001600160e01b031981165b811461325e57600080fd5b8035610d5581614032565b60006020828403121561406957614069600080fd5b6000613d618484614049565b8015155b82525050565b60208101610d558284614075565b80614079565b60208101610d55828461408d565b60005b838110156140bc5781810151838201526020016140a4565b83811115612ae35750506000910152565b60006140d7825190565b8084526020840193506140ee8185602086016140a1565b601f01601f19169290920192915050565b6020808252810161411081846140cd565b9392505050565b8061403e565b8035610d5581614117565b60006020828403121561413d5761413d600080fd5b6000613d61848461411d565b60006001600160a01b038216610d55565b61407981614149565b60208101610d55828461415a565b61403e81614149565b8035610d5581614171565b6000806040838503121561419b5761419b600080fd5b60006141a7858561417a565b92505060206141b88582860161411d565b9150509250929050565b600080604083850312156141d8576141d8600080fd5b60006141a7858561411d565b60ff8116614079565b60208101610d5582846141e4565b60006020828403121561421057614210600080fd5b6000613d61848461417a565b6000610d556001600160a01b038316614233565b90565b6001600160a01b031690565b6000610d558261421c565b6000610d558261423f565b6140798161424a565b60208101610d558284614255565b61ffff8116614079565b68ffffffffffffffffff8116614079565b60608101614295828661426c565b6142a26020830185614276565b613d616040830184614075565b634e487b7160e01b600052604160045260246000fd5b601f19601f830116810181811067ffffffffffffffff821117156142eb576142eb6142af565b6040525050565b60006142fd60405190565b905061430982826142c5565b919050565b600067ffffffffffffffff821115614328576143286142af565b5060209081020190565b60006143456143408461430e565b6142f2565b8381529050602080820190840283018581111561436457614364600080fd5b835b8181101561438657614378878261411d565b835260209283019201614366565b5050509392505050565b600082601f8301126143a4576143a4600080fd5b8135613d61848260208601614332565b600080604083850312156143ca576143ca600080fd5b60006143d6858561411d565b925050602083013567ffffffffffffffff8111156143f6576143f6600080fd5b6141b885828601614390565b67ffffffffffffffff8116614079565b60208101610d558284614402565b60008060006060848603121561443857614438600080fd5b6000614444868661417a565b93505060206144558682870161417a565b92505060406144668682870161411d565b9150509250925092565b60008060006060848603121561448857614488600080fd5b6000614444868661411d565b80516144a0838261426c565b5060208101516144b36020840182614276565b506040810151610f056040840182614075565b80516144d2838261415a565b506020810151610f05602084018261426c565b60c081016144f38286614494565b6145006060830185614075565b613d6160808301846144c6565b80151561403e565b8035610d558161450d565b6000806040838503121561453657614536600080fd5b6000614542858561417a565b92505060206141b885828601614515565b805161455f8382614494565b5060208101516145726060840182614075565b506040810151610f0560808401826144c6565b61458f8282614553565b5060c00190565b60200190565b60006145a6825190565b808452602093840193830160005b828110156145d95781516145c88782614585565b9650506020820191506001016145b4565b5093949350505050565b60208082528101614110818461459c565b62ffffff8116614079565b60c0810161460d828961426c565b61461a602083018861426c565b614627604083018761426c565b61463460608301866145f4565b6146416080830185614276565b61464e60a0830184614276565b979650505050505050565b805160408084526000919084019061467182826140cd565b9150506020830151848203602086015261468b82826140cd565b95945050505050565b60006141108383614659565b60006146aa825190565b808452602084019350836020820285016146c48560200190565b60005b848110156146f857838303885281516146e08482614694565b935050602082016020989098019791506001016146c7565b50909695505050505050565b805160808084526000919084019061471c82826140cd565b9150506020830151848203602086015261473682826140cd565b9150506040830151848203604086015261475082826140cd565b9150506060830151848203606086015261468b82826146a0565b602080825281016141108184614704565b600067ffffffffffffffff821115614795576147956142af565b601f19601f83011660200192915050565b82818337506000910152565b60006147c06143408461477b565b9050828152602081018484840111156147db576147db600080fd5b6147e68482856147a6565b509392505050565b600082601f83011261480257614802600080fd5b8135613d618482602086016147b2565b6000806000806080858703121561482b5761482b600080fd5b6000614837878761417a565b94505060206148488782880161417a565b93505060406148598782880161411d565b925050606085013567ffffffffffffffff81111561487957614879600080fd5b614885878288016147ee565b91505092959194509250565b6bffffffffffffffffffffffff811661403e565b8035610d5581614891565b6000602082840312156148c5576148c5600080fd5b6000613d6184846148a5565b60008083601f8401126148e6576148e6600080fd5b50813567ffffffffffffffff81111561490157614901600080fd5b60208301915083602082028301111561491c5761491c600080fd5b9250929050565b6000806020838503121561493957614939600080fd5b823567ffffffffffffffff81111561495357614953600080fd5b61495f858286016148d1565b92509250509250929050565b6000806040838503121561498157614981600080fd5b600061498d858561417a565b92505060206141b88582860161417a565b634e487b7160e01b600052602260045260246000fd5b6002810460018216806149c857607f821691505b602082108114156128e1576128e161499e565b601f8152602081017f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0081529050614596565b60208082528101610d55816149db565b8051610d5581614171565b600060208284031215614a3d57614a3d600080fd5b6000613d618484614a1d565b634e487b7160e01b600052601160045260246000fd5b6001600160801b03811690506001600160801b03821691506000826001600160801b0303821115614a9257614a92614a49565b500190565b634e487b7160e01b600052603260045260246000fd5b60008219821115614a9257614a92614a49565b6000610d55825b61ffff1690565b61407981614ac0565b600063ffffffff8216610d55565b61407981614ad7565b60a08101614afc828861408d565b614b096020830187614402565b614b166040830186614ace565b614b236060830185614ae5565b614b306080830184614ae5565b9695505050505050565b8051610d5581614117565b600060208284031215614b5a57614b5a600080fd5b6000613d618484614b3a565b6000610d5582614ac7565b6000610d55614b808360101c90565b68ffffffffffffffffff1690565b6000610d55614b9d8360581c90565b60ff1690565b8054614bae81614b66565b614bb8848261426c565b50614bc281614b71565b614bcf6020850182614276565b50614bd981614b8e565b9050610f056040840182614075565b60608101610d558284614ba3565b6000600019821415614c0a57614c0a614a49565b5060010190565b815b9150600082821015614c2757614c27614a49565b500390565b60208082527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65729101908152614596565b60208082528101610d5581614c2c565b60408101614c7a828561415a565b614110602083018461415a565b60408101614c7a8285614402565b634e487b7160e01b600052601260045260246000fd5b68ffffffffffffffffff9182169116600082614cc957614cc9614c95565b500490565b6000816000190483118215151615614ce857614ce8614a49565b500290565b60408101614cfb828561408d565b61411060208301846141e4565b6000614d166143408461477b565b905082815260208101848484011115614d3157614d31600080fd5b6147e68482856140a1565b600082601f830112614d5057614d50600080fd5b8151613d61848260208601614d08565b600060408284031215614d7557614d75600080fd5b614d7f60406142f2565b825190915067ffffffffffffffff811115614d9c57614d9c600080fd5b614da884828501614d3c565b825250602082015167ffffffffffffffff811115614dc857614dc8600080fd5b614dd484828501614d3c565b60208301525092915050565b6000614dee6143408461430e565b83815290506020808201908402830185811115614e0d57614e0d600080fd5b835b8181101561438657805167ffffffffffffffff811115614e3157614e31600080fd5b8501614e3d8882614d60565b84525060209283019201614e0f565b600082601f830112614e6057614e60600080fd5b8151613d61848260208601614de0565b600060808284031215614e8557614e85600080fd5b614e8f60806142f2565b825190915067ffffffffffffffff811115614eac57614eac600080fd5b614eb884828501614d3c565b825250602082015167ffffffffffffffff811115614ed857614ed8600080fd5b614ee484828501614d3c565b602083015250604082015167ffffffffffffffff811115614f0757614f07600080fd5b614f1384828501614d3c565b604083015250606082015167ffffffffffffffff811115614f3657614f36600080fd5b614f4284828501614e4c565b60608301525092915050565b600060208284031215614f6357614f63600080fd5b815167ffffffffffffffff811115614f7d57614f7d600080fd5b613d6184828501614e70565b600060208284031215614f9e57614f9e600080fd5b815167ffffffffffffffff811115614fb857614fb8600080fd5b613d6184828501614d3c565b67ffffffffffffffff811661403e565b8051610d5581614fc4565b600060208284031215614ff457614ff4600080fd5b6000613d618484614fd4565b6000610d556142306bffffffffffffffffffffffff841681565b61407981615000565b60608101615031828661415a565b61503e602083018561501a565b818103604083015261468b81846140cd565b8051610d558161450d565b60006020828403121561507057615070600080fd5b6000613d618484615050565b6040810161508a828561408d565b614110602083018461408d565b60208082528101610d5581602681527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160208201527f6464726573730000000000000000000000000000000000000000000000000000604082015260600190565b60008261510757615107614c95565b500690565b6000610d558260f81b90565b61407960ff821661510c565b61512e8183615118565b600101919050565b61ffff908116908216614c13565b60a081016151528285614ba3565b61411060608301846144c6565b6000610d558260601b90565b6000610d558261515f565b61407961518282614149565b61516b565b615191818761408d565b60200161519e8186615176565b6014016151ab818561408d565b6020016151b8818461408d565b6020016151c5818361408d565b60200195945050505050565b608081016151df828761415a565b6151ec602083018661415a565b6151f9604083018561408d565b8181036060830152614b3081846140cd565b8051610d5581614032565b60006020828403121561522b5761522b600080fd5b6000613d61848461520b56fea26469706673582212207dd66c8d317298ce56e6a7158ceeab1e7aba2a50e9aee48f85e7c4089ad87e4864736f6c634300080c0033

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

0000000000000000000000000000000000000000000000000000000000000240000000000000000000000000000000000000000000000000000000000000028000000000000000000000000004af8975918169ae48b25da78d5145bd673b2b6e000000000000000000000000271682deb8c4e0901d1a1550ad2e64d568e69909000000000000000000000000514910771af9ca656af840dff83e8264ecf986ca9fe0eebf5e446e3c998ec9bb19951541aee00bb90ea201ae456421a2ded868050000000000000000000000000000000000000000000000000000000000001c200000000000000000000000000000000000000000000000000000000000000e100000000000000000000000000000000000000000000000000000000000002710000000000000000000000000000000000000000000000000000000000024ea0000000000000000000000000000000000000000000000000000b1a2bc2ec50000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000002c000000000000000000000000057f1887a8bf19b14fc0df6fd9b2acc9af147ea850000000000000000000000002efa2743b863f3bd6f624ac0d58445bc5fb62bf66f4b4baf771f79ee3db2afdf13c35c213ea9f36f199efb86410649ffdf1adb0e000000000000000000000000000000000000000000000000000000000000002a0000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000b436f2d426f747320322e3000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044342544500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001f00000000000000000000000000000000000000000000000000000000000000640000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c80000000000000000000000000000000000000000000000001bc16d674ec800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012c00000000000000000000000000000000000000000000000029a2241af62c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001900000000000000000000000000000000000000000000000003782dace9d900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001f40000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000001f40000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000001f40000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000001f40000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000001f40000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000002ee00000000000000000000000000000000000000000000000053444835ec580000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003e80000000000000000000000000000000000000000000000006124fee993bc0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005dc0000000000000000000000000000000000000000000000006f05b59d3b200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007d00000000000000000000000000000000000000000000000007ce66c50e284000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000bb80000000000000000000000000000000000000000000000001bc16d674ec8000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000bb80000000000000000000000000000000000000000000000001bc16d674ec8000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000bb80000000000000000000000000000000000000000000000001bc16d674ec8000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000bb80000000000000000000000000000000000000000000000001bc16d674ec8000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000bb80000000000000000000000000000000000000000000000001bc16d674ec8000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000fa0000000000000000000000000000000000000000000000000a688906bd8b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001388000000000000000000000000000000000000000000000000c249fdd32778000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001388000000000000000000000000000000000000000000000002b5e3af16b188000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000001770000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001b58000000000000000000000000000000000000000000000000f9ccd8a1c508000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001f400000000000000000000000000000000000000000000000003782dace9d90000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000001f400000000000000000000000000000000000000000000000003782dace9d90000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000001f400000000000000000000000000000000000000000000000003782dace9d90000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000001f400000000000000000000000000000000000000000000000003782dace9d90000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000001f400000000000000000000000000000000000000000000000003782dace9d90000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000002328000000000000000000000000000000000000000000000001314fb37062980000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000027100000000000000000000000000000000000000000000000014d1120d7b160000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002710000000000000000000000000000000000000000000000003bd913e6c1df400000000000000000000000000000000000000000000000000000000000000000000

-----Decoded View---------------
Arg [0] : name_ (string): Co-Bots 2.0
Arg [1] : symbol_ (string): CBTE
Arg [2] : _rendererAddress (address): 0x04af8975918169Ae48B25DA78D5145BD673B2b6E
Arg [3] : vrfCoordinator (address): 0x271682DEB8C4E0901D1a1550aD2e64D568E69909
Arg [4] : link (address): 0x514910771AF9Ca656af840dff83E8264EcF986CA
Arg [5] : keyHash (bytes32): 0x9fe0eebf5e446e3c998ec9bb19951541aee00bb90ea201ae456421a2ded86805
Arg [6] : _parameters (tuple): System.Collections.Generic.List`1[Nethereum.ABI.FunctionEncoding.ParameterOutput]
Arg [7] : _prizes (tuple[]): System.Collections.Generic.List`1[Nethereum.ABI.FunctionEncoding.ParameterOutput],System.Collections.Generic.List`1[Nethereum.ABI.FunctionEncoding.ParameterOutput],System.Collections.Generic.List`1[Nethereum.ABI.FunctionEncoding.ParameterOutput],System.Collections.Generic.List`1[Nethereum.ABI.FunctionEncoding.ParameterOutput],System.Collections.Generic.List`1[Nethereum.ABI.FunctionEncoding.ParameterOutput],System.Collections.Generic.List`1[Nethereum.ABI.FunctionEncoding.ParameterOutput],System.Collections.Generic.List`1[Nethereum.ABI.FunctionEncoding.ParameterOutput],System.Collections.Generic.List`1[Nethereum.ABI.FunctionEncoding.ParameterOutput],System.Collections.Generic.List`1[Nethereum.ABI.FunctionEncoding.ParameterOutput],System.Collections.Generic.List`1[Nethereum.ABI.FunctionEncoding.ParameterOutput],System.Collections.Generic.List`1[Nethereum.ABI.FunctionEncoding.ParameterOutput],System.Collections.Generic.List`1[Nethereum.ABI.FunctionEncoding.ParameterOutput],System.Collections.Generic.List`1[Nethereum.ABI.FunctionEncoding.ParameterOutput],System.Collections.Generic.List`1[Nethereum.ABI.FunctionEncoding.ParameterOutput],System.Collections.Generic.List`1[Nethereum.ABI.FunctionEncoding.ParameterOutput],System.Collections.Generic.List`1[Nethereum.ABI.FunctionEncoding.ParameterOutput],System.Collections.Generic.List`1[Nethereum.ABI.FunctionEncoding.ParameterOutput],System.Collections.Generic.List`1[Nethereum.ABI.FunctionEncoding.ParameterOutput],System.Collections.Generic.List`1[Nethereum.ABI.FunctionEncoding.ParameterOutput],System.Collections.Generic.List`1[Nethereum.ABI.FunctionEncoding.ParameterOutput],System.Collections.Generic.List`1[Nethereum.ABI.FunctionEncoding.ParameterOutput],System.Collections.Generic.List`1[Nethereum.ABI.FunctionEncoding.ParameterOutput],System.Collections.Generic.List`1[Nethereum.ABI.FunctionEncoding.ParameterOutput],System.Collections.Generic.List`1[Nethereum.ABI.FunctionEncoding.ParameterOutput],System.Collections.Generic.List`1[Nethereum.ABI.FunctionEncoding.ParameterOutput],System.Collections.Generic.List`1[Nethereum.ABI.FunctionEncoding.ParameterOutput],System.Collections.Generic.List`1[Nethereum.ABI.FunctionEncoding.ParameterOutput],System.Collections.Generic.List`1[Nethereum.ABI.FunctionEncoding.ParameterOutput],System.Collections.Generic.List`1[Nethereum.ABI.FunctionEncoding.ParameterOutput],System.Collections.Generic.List`1[Nethereum.ABI.FunctionEncoding.ParameterOutput],System.Collections.Generic.List`1[Nethereum.ABI.FunctionEncoding.ParameterOutput]
Arg [8] : ens (address): 0x57f1887a8BF19b14fC0dF6Fd9B2acc9Af147eA85
Arg [9] : cobotsV1 (address): 0x2eFa2743B863F3Bd6f624Ac0d58445bC5fB62bf6
Arg [10] : _mysteryChallenge (tuple): System.Collections.Generic.List`1[Nethereum.ABI.FunctionEncoding.ParameterOutput]

-----Encoded View---------------
116 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000240
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000280
Arg [2] : 00000000000000000000000004af8975918169ae48b25da78d5145bd673b2b6e
Arg [3] : 000000000000000000000000271682deb8c4e0901d1a1550ad2e64d568e69909
Arg [4] : 000000000000000000000000514910771af9ca656af840dff83e8264ecf986ca
Arg [5] : 9fe0eebf5e446e3c998ec9bb19951541aee00bb90ea201ae456421a2ded86805
Arg [6] : 0000000000000000000000000000000000000000000000000000000000001c20
Arg [7] : 0000000000000000000000000000000000000000000000000000000000000e10
Arg [8] : 0000000000000000000000000000000000000000000000000000000000002710
Arg [9] : 000000000000000000000000000000000000000000000000000000000024ea00
Arg [10] : 00000000000000000000000000000000000000000000000000b1a2bc2ec50000
Arg [11] : 0000000000000000000000000000000000000000000000000000000000000002
Arg [12] : 00000000000000000000000000000000000000000000000000000000000002c0
Arg [13] : 00000000000000000000000057f1887a8bf19b14fc0df6fd9b2acc9af147ea85
Arg [14] : 0000000000000000000000002efa2743b863f3bd6f624ac0d58445bc5fb62bf6
Arg [15] : 6f4b4baf771f79ee3db2afdf13c35c213ea9f36f199efb86410649ffdf1adb0e
Arg [16] : 000000000000000000000000000000000000000000000000000000000000002a
Arg [17] : 0000000000000000000000000000000000000000000000000000000000000014
Arg [18] : 000000000000000000000000000000000000000000000000000000000000000b
Arg [19] : 436f2d426f747320322e30000000000000000000000000000000000000000000
Arg [20] : 0000000000000000000000000000000000000000000000000000000000000004
Arg [21] : 4342544500000000000000000000000000000000000000000000000000000000
Arg [22] : 000000000000000000000000000000000000000000000000000000000000001f
Arg [23] : 0000000000000000000000000000000000000000000000000000000000000064
Arg [24] : 0000000000000000000000000000000000000000000000000de0b6b3a7640000
Arg [25] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [26] : 00000000000000000000000000000000000000000000000000000000000000c8
Arg [27] : 0000000000000000000000000000000000000000000000001bc16d674ec80000
Arg [28] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [29] : 000000000000000000000000000000000000000000000000000000000000012c
Arg [30] : 00000000000000000000000000000000000000000000000029a2241af62c0000
Arg [31] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [32] : 0000000000000000000000000000000000000000000000000000000000000190
Arg [33] : 0000000000000000000000000000000000000000000000003782dace9d900000
Arg [34] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [35] : 00000000000000000000000000000000000000000000000000000000000001f4
Arg [36] : 0000000000000000000000000000000000000000000000000de0b6b3a7640000
Arg [37] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [38] : 00000000000000000000000000000000000000000000000000000000000001f4
Arg [39] : 0000000000000000000000000000000000000000000000000de0b6b3a7640000
Arg [40] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [41] : 00000000000000000000000000000000000000000000000000000000000001f4
Arg [42] : 0000000000000000000000000000000000000000000000000de0b6b3a7640000
Arg [43] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [44] : 00000000000000000000000000000000000000000000000000000000000001f4
Arg [45] : 0000000000000000000000000000000000000000000000000de0b6b3a7640000
Arg [46] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [47] : 00000000000000000000000000000000000000000000000000000000000001f4
Arg [48] : 0000000000000000000000000000000000000000000000000de0b6b3a7640000
Arg [49] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [50] : 00000000000000000000000000000000000000000000000000000000000002ee
Arg [51] : 00000000000000000000000000000000000000000000000053444835ec580000
Arg [52] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [53] : 00000000000000000000000000000000000000000000000000000000000003e8
Arg [54] : 0000000000000000000000000000000000000000000000006124fee993bc0000
Arg [55] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [56] : 00000000000000000000000000000000000000000000000000000000000005dc
Arg [57] : 0000000000000000000000000000000000000000000000006f05b59d3b200000
Arg [58] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [59] : 00000000000000000000000000000000000000000000000000000000000007d0
Arg [60] : 0000000000000000000000000000000000000000000000007ce66c50e2840000
Arg [61] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [62] : 0000000000000000000000000000000000000000000000000000000000000bb8
Arg [63] : 0000000000000000000000000000000000000000000000001bc16d674ec80000
Arg [64] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [65] : 0000000000000000000000000000000000000000000000000000000000000bb8
Arg [66] : 0000000000000000000000000000000000000000000000001bc16d674ec80000
Arg [67] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [68] : 0000000000000000000000000000000000000000000000000000000000000bb8
Arg [69] : 0000000000000000000000000000000000000000000000001bc16d674ec80000
Arg [70] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [71] : 0000000000000000000000000000000000000000000000000000000000000bb8
Arg [72] : 0000000000000000000000000000000000000000000000001bc16d674ec80000
Arg [73] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [74] : 0000000000000000000000000000000000000000000000000000000000000bb8
Arg [75] : 0000000000000000000000000000000000000000000000001bc16d674ec80000
Arg [76] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [77] : 0000000000000000000000000000000000000000000000000000000000000fa0
Arg [78] : 000000000000000000000000000000000000000000000000a688906bd8b00000
Arg [79] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [80] : 0000000000000000000000000000000000000000000000000000000000001388
Arg [81] : 000000000000000000000000000000000000000000000000c249fdd327780000
Arg [82] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [83] : 0000000000000000000000000000000000000000000000000000000000001388
Arg [84] : 000000000000000000000000000000000000000000000002b5e3af16b1880000
Arg [85] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [86] : 0000000000000000000000000000000000000000000000000000000000001770
Arg [87] : 000000000000000000000000000000000000000000000000de0b6b3a76400000
Arg [88] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [89] : 0000000000000000000000000000000000000000000000000000000000001b58
Arg [90] : 000000000000000000000000000000000000000000000000f9ccd8a1c5080000
Arg [91] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [92] : 0000000000000000000000000000000000000000000000000000000000001f40
Arg [93] : 0000000000000000000000000000000000000000000000003782dace9d900000
Arg [94] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [95] : 0000000000000000000000000000000000000000000000000000000000001f40
Arg [96] : 0000000000000000000000000000000000000000000000003782dace9d900000
Arg [97] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [98] : 0000000000000000000000000000000000000000000000000000000000001f40
Arg [99] : 0000000000000000000000000000000000000000000000003782dace9d900000
Arg [100] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [101] : 0000000000000000000000000000000000000000000000000000000000001f40
Arg [102] : 0000000000000000000000000000000000000000000000003782dace9d900000
Arg [103] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [104] : 0000000000000000000000000000000000000000000000000000000000001f40
Arg [105] : 0000000000000000000000000000000000000000000000003782dace9d900000
Arg [106] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [107] : 0000000000000000000000000000000000000000000000000000000000002328
Arg [108] : 000000000000000000000000000000000000000000000001314fb37062980000
Arg [109] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [110] : 0000000000000000000000000000000000000000000000000000000000002710
Arg [111] : 0000000000000000000000000000000000000000000000014d1120d7b1600000
Arg [112] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [113] : 0000000000000000000000000000000000000000000000000000000000002710
Arg [114] : 000000000000000000000000000000000000000000000003bd913e6c1df40000
Arg [115] : 0000000000000000000000000000000000000000000000000000000000000000


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.