ETH Price: $2,950.21 (-0.19%)
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Token Holdings

More Info

Private Name Tags

TokenTracker

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Set Approval For...210157642024-10-21 18:31:11460 days ago1729535471IN
0x89E37352...756ae0941
0 ETH0.000442829.59570154
Set Approval For...164442942023-01-20 0:00:591101 days ago1674172859IN
0x89E37352...756ae0941
0 ETH0.0004275217.57928759
Set Approval For...147144582022-05-05 1:50:301361 days ago1651715430IN
0x89E37352...756ae0941
0 ETH0.0016333735.32991055
Transfer From144774902022-03-28 22:56:331398 days ago1648508193IN
0x89E37352...756ae0941
0 ETH0.0025215954.09514107
Transfer From144774902022-03-28 22:56:331398 days ago1648508193IN
0x89E37352...756ae0941
0 ETH0.0048909554.09514107
Refund Full143959032022-03-16 6:07:401410 days ago1647410860IN
0x89E37352...756ae0941
0 ETH0.0047654551.87392864
Refund Full143958972022-03-16 6:05:511410 days ago1647410751IN
0x89E37352...756ae0941
0 ETH0.0049412140.04227715
Refund Full143958622022-03-16 5:58:291410 days ago1647410309IN
0x89E37352...756ae0941
0 ETH0.0027484925.86430497
Refund Full143958602022-03-16 5:57:441410 days ago1647410264IN
0x89E37352...756ae0941
0 ETH0.0031523524.46604651
Refund Full143932722022-03-15 20:19:361411 days ago1647375576IN
0x89E37352...756ae0941
0 ETH0.0044466346
Refund Full143909482022-03-15 11:41:361411 days ago1647344496IN
0x89E37352...756ae0941
0 ETH0.0013814513
Refund Keep Art143906442022-03-15 10:34:341411 days ago1647340474IN
0x89E37352...756ae0941
0 ETH0.0012830525.13435896
Refund Keep Art143897102022-03-15 7:04:071411 days ago1647327847IN
0x89E37352...756ae0941
0 ETH0.0009593616.07565633
Refund Keep Art143897022022-03-15 7:02:411411 days ago1647327761IN
0x89E37352...756ae0941
0 ETH0.0018157220.26860314
Refund Full143764492022-03-13 5:22:101413 days ago1647148930IN
0x89E37352...756ae0941
0 ETH0.0014540717.63454379
Refund Full143738422022-03-12 19:33:431414 days ago1647113623IN
0x89E37352...756ae0941
0 ETH0.0021427423.32472115
Refund Full143738322022-03-12 19:31:351414 days ago1647113495IN
0x89E37352...756ae0941
0 ETH0.0013987325.10023108
Refund Full143738312022-03-12 19:31:121414 days ago1647113472IN
0x89E37352...756ae0941
0 ETH0.002924522.69767999
Refund Full143558322022-03-10 0:18:051417 days ago1646871485IN
0x89E37352...756ae0941
0 ETH0.0020786622.62716362
Refund Full143558262022-03-10 0:16:571417 days ago1646871417IN
0x89E37352...756ae0941
0 ETH0.0035819327.80012562
Refund Keep Art143484422022-03-08 21:01:091418 days ago1646773269IN
0x89E37352...756ae0941
0 ETH0.0032262963.20127834
Refund Keep Art143468392022-03-08 15:01:071418 days ago1646751667IN
0x89E37352...756ae0941
0 ETH0.0032813439
Refund Full143464992022-03-08 13:37:201418 days ago1646746640IN
0x89E37352...756ae0941
0 ETH0.0028288734.30391526
Refund Full143447452022-03-08 7:00:281418 days ago1646722828IN
0x89E37352...756ae0941
0 ETH0.0021427820.16433687
Refund Full143447302022-03-08 6:57:181418 days ago1646722638IN
0x89E37352...756ae0941
0 ETH0.0009505517.05769499
View all transactions

Latest 25 internal transactions (View All)

Advanced mode:
Parent Transaction Hash Method Block
From
To
-145169512022-04-04 2:51:381391 days ago1649040698
0x89E37352...756ae0941
16.15 ETH
-143959032022-03-16 6:07:401410 days ago1647410860
0x89E37352...756ae0941
0.15 ETH
-143958972022-03-16 6:05:511410 days ago1647410751
0x89E37352...756ae0941
0.15 ETH
-143958972022-03-16 6:05:511410 days ago1647410751
0x89E37352...756ae0941
0.3 ETH
-143958622022-03-16 5:58:291410 days ago1647410309
0x89E37352...756ae0941
0.15 ETH
-143958602022-03-16 5:57:441410 days ago1647410264
0x89E37352...756ae0941
0.15 ETH
-143958602022-03-16 5:57:441410 days ago1647410264
0x89E37352...756ae0941
0.3 ETH
-143932722022-03-15 20:19:361411 days ago1647375576
0x89E37352...756ae0941
0.15 ETH
-143909482022-03-15 11:41:361411 days ago1647344496
0x89E37352...756ae0941
0.15 ETH
-143906442022-03-15 10:34:341411 days ago1647340474
0x89E37352...756ae0941
0.05 ETH
-143897102022-03-15 7:04:071411 days ago1647327847
0x89E37352...756ae0941
0.05 ETH
-143897022022-03-15 7:02:411411 days ago1647327761
0x89E37352...756ae0941
0.05 ETH
-143897022022-03-15 7:02:411411 days ago1647327761
0x89E37352...756ae0941
0.3 ETH
-143764492022-03-13 5:22:101413 days ago1647148930
0x89E37352...756ae0941
0.15 ETH
-143738422022-03-12 19:33:431414 days ago1647113623
0x89E37352...756ae0941
0.15 ETH
-143738312022-03-12 19:31:121414 days ago1647113472
0x89E37352...756ae0941
0.15 ETH
-143738312022-03-12 19:31:121414 days ago1647113472
0x89E37352...756ae0941
0.3 ETH
-143558322022-03-10 0:18:051417 days ago1646871485
0x89E37352...756ae0941
0.15 ETH
-143558262022-03-10 0:16:571417 days ago1646871417
0x89E37352...756ae0941
0.15 ETH
-143558262022-03-10 0:16:571417 days ago1646871417
0x89E37352...756ae0941
0.3 ETH
-143484422022-03-08 21:01:091418 days ago1646773269
0x89E37352...756ae0941
0.05 ETH
-143468392022-03-08 15:01:071418 days ago1646751667
0x89E37352...756ae0941
0.05 ETH
-143468392022-03-08 15:01:071418 days ago1646751667
0x89E37352...756ae0941
0.3 ETH
-143464992022-03-08 13:37:201418 days ago1646746640
0x89E37352...756ae0941
0.15 ETH
-143447452022-03-08 7:00:281418 days ago1646722828
0x89E37352...756ae0941
0.15 ETH
View All Internal Transactions
Loading...
Loading
Cross-Chain Transactions

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
SocietyMember

Compiler Version
v0.8.9+commit.e5eed63a

Optimization Enabled:
Yes with 10000 runs

Other Settings:
default evmVersion
File 1 of 17 : SocietyMember.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.9;

//   ____  _  _  ____    ____   __    ___  __  ____  ____  _  _
//  (_  _)/ )( \(  __)  / ___) /  \  / __)(  )(  __)(_  _)( \/ )
//    )(  ) __ ( ) _)   \___ \(  O )( (__  )(  ) _)   )(   )  /
//   (__) \_)(_/(____)  (____/ \__/  \___)(__)(____) (__) (__/
//

import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/interfaces/IERC721Receiver.sol";
import "@openzeppelin/contracts/interfaces/IERC2981.sol";
import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";

// Society membership is captured in this contract.
//
// It is an NFT (ERC721) with a few custom enhancements:
//
//  1. Captcha Scheme
//      We use a captcha scheme to prevent bots from minting.
//        #isProbablyHuman() - matches a captcha signature signed elsewhere
//
//  2. Money-back Warranty
//      We promise your money back if we don't get enough members:
//               #withdraw()  - locks the money unless there are >=2000 members
//             #refundFull(), - these return your money during refunding
//          #refundKeepArt()    and they're enabled automatically after time has elapsed
//
//      (see "Refund Warranty Process" below for more details)
//
//  3. Minting Limits
//      A single wallet may only mint 2 memberships.
//
//  4. Founding Team
//      During contract construction, we mint 7 memberships,
//      one for each member of the founding team and the first artist.
//
//  5. Member Migration
//      This contract is an improved edition of an earlier membership contract.
//      Early token holders can migrate into this and receive an additional token
//      for their continued loyalty.
//
//  6. Gold/Standard Tokens
//      The first 2,000 memberships will get a Gold token, these are
//      identified by having an ID number 1-2000.
//
//  7. Limited Sales Window
//      After the Feb. 18 sales deadline one of two things will happen:
//        - if there are <2,000 members, then refunds are enabled and the society winds down.
//        - if there are 2,000+ members, then membership is capped to the number already sold.
//
//  Refund Warranty Process
//
//  If 2,000+ memberships are sold by Feb 18 there are no refunds.
//  But if less than 2,000 are sold by Feb 18, then the refund
//  implementation operates within three phases:
//
//   Phase 1: Jan 18 - Feb 18
//     After contract creation, until the sales deadline or >2,000 sold,
//     all minting fees remain locked in the contract.
//       - The Society's #withdraw() is disabled
//       - Member's #refund...() are also disabled
//
//   Phase 2: Feb 18 - Mar 18
//     After the sales deadline (if <2,000 sold), until the refund deadline,
//     Members may claim a #refund...() for the sale price.
//       - The Society's #withdraw() is still disabled
//       - Member's #refund...() are now enabled
//
//   Phase 3: after Mar 18
//     After the refund deadline, Members can no longer claim a #refund...()
//     and The Society can #withdraw() any unrefunded fees.
//       - The Society's #withdraw() is enabled
//       - Member's #refund...() are disabled

contract SocietyMember is
    ERC721,
    IERC2981,
    IERC721Receiver,
    Ownable,
    ReentrancyGuard
{
    using ECDSA for bytes32;

    // This indicates what mode this contract is operating in.
    // See #updateMode() for implementation
    enum Mode {
        // Happy path:
        SellingPreThreshold, // before sales deadline < 2,000 sold
        SellingPostThreshold, // > 2,000 sold, < 5,000 sold
        SoldOut, // 5,000 sold (or 2,000+ sold after sales deadline)
        // Sad path:
        Refunding, // < 2,000 sold, after sales deadline before refund deadline
        ClosingAfterRefundPeriod // < 2,000 sold, after refund deadline
    }

    // This is the sale price of each membership.
    uint256 public constant SALE_PRICE = 0.15 ether;
    // This is the price of individual pieces of art.
    // NOTE: we only use this if people opt for partial refund.
    uint256 public constant ART_PRICE = 0.1 ether;

    // A single wallet may only mint 2 memberships.
    uint256 public constant MINTS_PER_WALLET = 2;

    // There can be only 5,000 members (2,000 gold).
    // However many memberships have been sold at the sales deadline,
    // that number becomes the new maximum total member count.
    uint256 public MAXIMUM_TOTAL_MEMBER_COUNT;
    uint256 public immutable MAXIMUM_GOLD_MEMBER_COUNT;

    // When members rollover a token from the original membership contract
    // they will receive 3 memberships. They receive 2 memberships immediately
    // and then receive a 3rd when the sales threshold is reached.
    // For each membership token, members also receives a piece of artwork.
    // This records where to send the token post-threshold.
    mapping(uint16 => address) private pendingTransfers;
    // Emitted when `tokenId` token is minted and pending transfer to `to`.
    event PendingTransfer(address indexed to, uint256 indexed tokenId);
    // This records the migrated token so the old refund can be claimed.
    mapping(uint16 => uint16) private pendingRefundTokens;
    // The old member contract is used to verify migration.
    IOldMember private oldMemberK;

    // There need to be 2,000 members to proceed.
    // NOTE: permanently fixed upon contract creation
    uint256 public immutable ENOUGH_MEMBERS_TO_PROCEED;

    // Sales must exceed 2,000 members for the Society to proceed.
    // If we fail to get 2,000 members then the first #refund() request
    // after this time will start refunding.
    //   See note re "Refund Warrant Process" for more details.
    // NOTE: permanently fixed upon contract creation
    uint256 public immutable SALES_DEADLINE; // timestamp in seconds

    // If we fail to get 2,000 members then Members have until
    // this time to claim their #refund()
    //   See note re "Refund Warrant Process" for more details.
    // NOTE: permanently fixed upon contract creation
    uint256 public immutable REFUND_DEADLINE; // timestamp in seconds

    // During contract construction, we mint 7 tokens,
    // one for each member of the founding team and the first artist.
    // NOTE: permanently fixed upon contract creation
    uint256 private immutable FOUNDING_TEAM_COUNT;

    // This indicates the current mode (selling, refunding etc)
    Mode public mode;

    // We generate the next token ID by incrementing these counters.
    // Gold tokens have an ID <= 2,000.
    uint16 private goldIds; // 1 - 2000
    uint16 private standardIds; // 2001 - 5000

    // This tracks mint counts to help limit mints per wallet.
    mapping(address => uint8) private mintCountsByAddress;

    // This tracks gold token count per owner.
    mapping(address => uint16) private goldBalances;

    // Minting membership includes an item from the initial art collection.
    IInitialArtSale private artSale;

    // This contains the base URI (e.g. "https://example.com/tokens/")
    // that is used to produce a URI for the metadata about
    // each token (e.g. "https://example.com/tokens/1234")
    string private baseURI;

    // For exchanges that support ERC2981, this sets our royalty rate.
    // NOTE: whereas "percent" is /100, this uses "per mille" which is /1000
    uint256 private royaltyPerMille;

    // To combat bots, minting requests include a captcha signed elsewhere.
    // To verify the captcha, we compare its signature with this signer.
    address private captchaSigner;

    // To enable gas-free listings on OpenSea we integrate with the proxy registry.
    address private openSeaProxyRegistry;
    // The Society can disable gas-free listings in case OpenSea is compromised.
    bool private isOpenSeaProxyEnabled = true;

    struct Config {
        address[] foundingTeam;
        uint256 maximumTotalMemberCount;
        uint256 maximumGoldMemberCount;
        uint256 enoughMembersToProceed;
        uint256 salesDeadline;
        uint256 refundDeadline;
        uint256 royaltyPerMille;
        address captchaSigner;
        address openSeaProxyRegistry;
        IOldMember oldMemberK;
    }

    constructor(Config memory config) ERC721("Collector", "COLLECTOR") {
        require(
            config.enoughMembersToProceed <= config.maximumTotalMemberCount
        );
        require(
            config.maximumGoldMemberCount <= config.maximumTotalMemberCount
        );
        require(config.salesDeadline <= config.refundDeadline);

        MAXIMUM_TOTAL_MEMBER_COUNT = config.maximumTotalMemberCount;
        MAXIMUM_GOLD_MEMBER_COUNT = config.maximumGoldMemberCount;
        ENOUGH_MEMBERS_TO_PROCEED = config.enoughMembersToProceed;
        SALES_DEADLINE = config.salesDeadline;
        REFUND_DEADLINE = config.refundDeadline;
        royaltyPerMille = config.royaltyPerMille;
        captchaSigner = config.captchaSigner;
        openSeaProxyRegistry = config.openSeaProxyRegistry;
        oldMemberK = config.oldMemberK;
        mode = Mode.SellingPreThreshold;

        // Grant the founding team the first 7 tokens.
        FOUNDING_TEAM_COUNT = config.foundingTeam.length;
        for (uint256 i = 0; i < config.foundingTeam.length; i++) {
            _mint(config.foundingTeam[i], generateTokenId());
            // NOTE: the accompanying art is minted later when we #setInitialArtSale().
        }
    }

    //
    // Public Read Methods
    //

    // See how many memberships have been minted by the specified wallet.
    // NOTE: this is not the same as ownership
    function getMintCountByAddress(address minter_)
        external
        view
        returns (uint8)
    {
        return mintCountsByAddress[minter_];
    }

    // How many gold tokens have been issued.
    function goldSupply() external view returns (uint256) {
        return goldIds;
    }

    // Returns the number of gold tokens held by `owner`.
    function goldBalanceOf(address owner) external view returns (uint256) {
        return goldBalances[owner];
    }

    //
    // Public Write Methods
    //

    // This mints membership tokens to the sender.
    // Each token also includes a mint of artwork from the current collection.
    // It requires a `captcha` which is used to verify that
    // the sender is probably human and came here via our web flow.
    function mint(bytes memory captcha, uint8 numberOfTokens)
        external
        payable
        nonReentrant
    {
        require(numberOfTokens > 0, "missing number of tokens to mint");
        updateMode();
        require(
            mode == Mode.SellingPreThreshold ||
                mode == Mode.SellingPostThreshold,
            "minting is not available"
        );
        require(
            memberCount() + numberOfTokens <= MAXIMUM_TOTAL_MEMBER_COUNT,
            "not enough memberships remaining"
        );
        require(
            msg.value == SALE_PRICE * numberOfTokens,
            "incorrect ETH payment amount"
        );
        require(isProbablyHuman(captcha, msg.sender), "you seem like a robot");
        uint8 mintCount = mintCountsByAddress[msg.sender];
        require(
            mintCount + numberOfTokens <= MINTS_PER_WALLET,
            "you can only mint two memberships per wallet"
        );

        mintCountsByAddress[msg.sender] = mintCount + numberOfTokens;

        for (uint256 i = 0; i < numberOfTokens; i++) {
            mintWithArt(msg.sender, generateTokenId());
        }
    }

    // This mints 3 memberships for the user when they migrate the old token.
    // The first 2 memberships are transferred immediately along with 2 art pieces.
    // The 3rd token is marked as pending until reaching the sales threshold.
    function migrateMint(uint256[] memory oldTokenIds) external nonReentrant {
        updateMode();
        require(
            mode == Mode.SellingPreThreshold ||
                mode == Mode.SellingPostThreshold,
            "minting is not available"
        );
        require(
            memberCount() + 3 * oldTokenIds.length <=
                MAXIMUM_TOTAL_MEMBER_COUNT,
            "not enough memberships remaining"
        );
        require(oldTokenIds.length < 4, "migrating too many in a single call");
        for (uint256 i = 0; i < oldTokenIds.length; i++) {
            uint256 oldTokenId = oldTokenIds[i];
            require(
                oldTokenId > FOUNDING_TEAM_COUNT,
                "founding team tokens cannot migrate"
            );

            // The first 2 tokens transfer immediately.
            oldMemberK.transferFrom(msg.sender, address(this), oldTokenId);
            mintFromOldWithArt(oldTokenId, msg.sender, generateTokenId());
            mintFromOldWithArt(oldTokenId, msg.sender, generateTokenId());

            // And we mint the 3rd token and record where it should eventually go.
            // It is transferred upon reaching the sales threshold. See #claimPending()
            uint256 pendingTokenId = generateTokenId();
            _mint(address(this), pendingTokenId);
            pendingTransfers[uint16(pendingTokenId)] = msg.sender;
            emit PendingTransfer(msg.sender, pendingTokenId);
        }
    }

    // After reaching the sales threshold, this transfers the
    // pending 3rd token for migrated members.
    function claimPending(uint256[] memory tokenIds) external nonReentrant {
        updateMode();
        require(
            mode == Mode.SellingPostThreshold || mode == Mode.SoldOut,
            "token remains pending until post-threshold"
        );
        require(tokenIds.length < 8, "claiming too many in a single call");
        for (uint256 i = 0; i < tokenIds.length; i++) {
            uint256 tokenId = tokenIds[i];
            address to = pendingTransfers[uint16(tokenId)];
            require(to != address(0), "token is not pending transfer");
            pendingTransfers[uint16(tokenId)] = address(0);
            _transfer(address(this), to, tokenId);
            artSale.mintTo(to);
        }
    }

    //
    // Refund Options
    // If we fail to get >2,000 members members can call these to receive their ETH back.
    // During a refund, the member can decide what to do with the artwork they received during mint:
    //
    //     refundFull:  a member returns both their membership and the artwork they received.
    //                  The member receives a full refund (.15E).
    //
    //  refundKeepArt:  a member returns their membership but keeps the artwork.
    //                  The member receives the full price minus the art price (.15E - .1E = .05E)
    //

    // This lets a member return both their membership and the artwork they received.
    // The member receives a full refund (.15E).
    // NOTE: to receive the full refund, the member does NOT retain the artwork.
    // NOTE: after the sales deadline this is enabled automatically.
    function refundFull(uint256 memberTokenId, uint256 artTokenId)
        external
        nonReentrant
    {
        require(
            ownerOf(memberTokenId) == msg.sender,
            "only the owner may claim a refund"
        );
        require(
            memberTokenId > FOUNDING_TEAM_COUNT,
            "founding team tokens do not get a refund"
        );
        updateMode();
        require(mode == Mode.Refunding, "refunding is not available");

        claimAnyOldRefunds(memberTokenId);
        artSale.transferFrom(msg.sender, address(this), artTokenId);
        _burn(memberTokenId);
        payable(msg.sender).transfer(SALE_PRICE);
    }

    // This lets a member returns their membership but keeps the artwork.
    // The member receives the full price minus the art price (.15E - .1E = .05E)
    // NOTE: the amount refunded is reduced by the price of the artwork.
    // NOTE: after the sales deadline this is enabled automatically.
    function refundKeepArt(uint256 memberTokenId) external nonReentrant {
        require(
            ownerOf(memberTokenId) == msg.sender,
            "only the owner may claim a refund"
        );
        require(
            memberTokenId > FOUNDING_TEAM_COUNT,
            "founding team tokens do not get a refund"
        );
        updateMode();
        require(mode == Mode.Refunding, "refunding is not available");

        claimAnyOldRefunds(memberTokenId);
        _burn(memberTokenId);
        payable(msg.sender).transfer(SALE_PRICE - ART_PRICE);
    }

    //
    // Admin Methods
    //

    // This allows the Society to withdraw funds from the treasury.
    // NOTE: this is locked until there are at least 2,000 members.
    function withdraw() external onlyOwner {
        updateMode();
        require(
            mode == Mode.SellingPostThreshold ||
                mode == Mode.SoldOut ||
                mode == Mode.ClosingAfterRefundPeriod,
            "locked until there are enough members (or after refund period)"
        );
        uint256 balance = address(this).balance;
        payable(msg.sender).transfer(balance);
    }

    // This allows the Society to withdraw any received ERC20 tokens.
    // NOTE: This method exists to avoid the sad scenario where someone
    //       accidentally sends tokens to this address and the tokens get stuck.
    function withdrawERC20Tokens(IERC20 token) external onlyOwner {
        uint256 balance = token.balanceOf(address(this));
        token.transfer(msg.sender, balance);
    }

    // This allows the Society to withdraw any received ERC721 tokens.
    // NOTE: This method locks to secure old memberships used for refunds.
    // NOTE: This method also exists to avoid the sad scenario where someone
    //       accidentally sends tokens to this address and the tokens get stuck.
    function withdrawERC721Token(IERC721 token, uint256 tokenId)
        external
        onlyOwner
    {
        updateMode();
        require(
            mode == Mode.SellingPostThreshold ||
                mode == Mode.SoldOut ||
                mode == Mode.ClosingAfterRefundPeriod,
            "locked until there are enough members (or after refund period)"
        );
        token.transferFrom(address(this), msg.sender, tokenId);
    }

    // The society can update the baseURI for metadata.
    //  e.g. if there is a hosting change
    function setBaseURI(string memory uri) external onlyOwner {
        baseURI = uri;
    }

    // The society can update the ERC2981 royalty rate.
    // NOTE: whereas "percent" is /100, this uses "per mille" which is /1000
    function setRoyalty(uint256 _royaltyPerMille) external onlyOwner {
        royaltyPerMille = _royaltyPerMille;
    }

    // The society can set the initial art sale.
    function setInitialArtSale(IInitialArtSale _artSale) external onlyOwner {
        require(
            address(artSale) == address(0),
            "initial art sale already specified"
        );
        artSale = _artSale;
        // The art to accompany the founding team's memberships (#1..#7) can now be minted.
        for (uint256 i = 0; i < FOUNDING_TEAM_COUNT; i++) {
            artSale.mintTo(ownerOf(i + 1));
        }
    }

    // The society can update the signer of the captcha used to secure #mint().
    function setCaptchaSigner(address _captchaSigner) external onlyOwner {
        captchaSigner = _captchaSigner;
    }

    // The society can disable gas-less listings for security in case OpenSea is compromised.
    function setOpenSeaProxyEnabled(bool isEnabled) external onlyOwner {
        isOpenSeaProxyEnabled = isEnabled;
    }

    //
    // Interface Override Methods
    //

    // The membership contract can receive ETH deposits.
    receive() external payable {}

    // The membership contract can receive ERC721 tokens.
    // See IERC721Receiver
    function onERC721Received(
        address,
        address,
        uint256,
        bytes calldata
    ) public virtual override returns (bytes4) {
        return this.onERC721Received.selector;
    }

    // This hooks into the ERC721 implementation
    // it is used by `tokenURI(..)` to produce the full thing.
    function _baseURI() internal view override returns (string memory) {
        return baseURI;
    }

    ///
    /// IERC2981 Implementation
    ///

    /**
     * @dev See {IERC2981-royaltyInfo}.
     * This exposes the ERC2981 royalty rate.
     */
    function royaltyInfo(uint256 tokenId, uint256 salePrice)
        external
        view
        returns (address receiver, uint256 royaltyAmount)
    {
        require(_exists(tokenId), "not a valid token");
        return (owner(), (salePrice * royaltyPerMille) / 1000);
    }

    ///
    /// IERC721Enumerable Implementation (partial)
    ///   NOTE: to reduce gas costs, we don't implement tokenOfOwnerByIndex()
    ///

    /**
     * @dev See {IERC721Enumerable-totalSupply}.
     * Returns the total amount of tokens stored by the contract.
     */
    function totalSupply() external view returns (uint256) {
        return memberCount();
    }

    /**
     * @dev See {IERC721Enumerable-tokenByIndex}.
     * 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) {
        if (_index >= goldIds) {
            _index = MAXIMUM_GOLD_MEMBER_COUNT + (goldIds - _index);
        }
        require(_exists(_index + 1), "bad token index");
        return _index + 1;
    }

    // This hooks into transfers to track gold balances.
    function _beforeTokenTransfer(
        address from,
        address to,
        uint256 tokenId
    ) internal virtual override {
        if (tokenId > MAXIMUM_GOLD_MEMBER_COUNT) {
            // We only do the extra bookkeeping
            // when a gold token is being transferred.
            return;
        }
        if (from != address(0)) {
            goldBalances[from] -= 1;
        }
        if (to != address(0)) {
            goldBalances[to] += 1;
        }
    }

    // This hooks into approvals to allow gas-free listings on OpenSea.
    function isApprovedForAll(address owner, address operator)
        public
        view
        override
        returns (bool)
    {
        if (isOpenSeaProxyEnabled) {
            ProxyRegistry registry = ProxyRegistry(openSeaProxyRegistry);
            if (address(registry.proxies(owner)) == operator) {
                return true;
            }
        }

        return super.isApprovedForAll(owner, operator);
    }

    ///
    /// IERC165 Implementation
    ///

    /**
     * @dev See {IERC165-supportsInterface}.
     * This implements ERC165 which announces our other supported interfaces:
     *   - ERC2981 (royalty info)
     */
    function supportsInterface(bytes4 interfaceId)
        public
        view
        virtual
        override(IERC165, ERC721)
        returns (bool)
    {
        if (interfaceId == type(IERC2981).interfaceId) {
            return true;
        }
        // NOTE: we don't include IERC721Enumerable
        //       because ours is only a partial implementation.
        return super.supportsInterface(interfaceId);
    }

    //
    // Private Helper Methods
    //

    // This tries to prevent robots from minting a membership.
    // The `captcha` contains a signature (generated via web captcha flow)
    // that was made using the Society's private key.
    //
    // This method checks the signature to see:
    //  - if it was signed by the Society's key and
    //  - if it was for the current msg.sender
    function isProbablyHuman(bytes memory captcha, address sender)
        private
        view
        returns (bool)
    {
        // First we recreate the same message that was originally signed.
        // This is equivalent to how we created it elsewhere:
        //      message = ethers.utils.solidityKeccak256(
        //                  ["string", "address"],
        //                  ["member", sender]);
        bytes32 message = keccak256(abi.encodePacked("member", sender));

        // Now we can see who actually signed it
        address signer = message.toEthSignedMessageHash().recover(captcha);

        // And finally check if the signer was us!
        return signer == captchaSigner;
    }

    // This updates the current mode based on the member count and the time.
    // The contract calls this before any use of the current mode.
    // See "Refund Warranty Process" above for more details.
    function updateMode() private {
        if (mode == Mode.SoldOut) {
            // After selling out, the mode cannot change.
            return;
        }
        uint256 count = memberCount();

        // After the sales deadline, the total supply is fixed to the number sold.
        if (
            block.timestamp >= SALES_DEADLINE &&
            count >= ENOUGH_MEMBERS_TO_PROCEED
        ) {
            MAXIMUM_TOTAL_MEMBER_COUNT = count;
        }

        // Update the mode based on the sales count and time.
        if (count >= MAXIMUM_TOTAL_MEMBER_COUNT) {
            mode = Mode.SoldOut;
        } else if (count >= ENOUGH_MEMBERS_TO_PROCEED) {
            mode = Mode.SellingPostThreshold;
        } else {
            // count < enoughMembersToProceed
            // When there are not enough members to proceed
            // then the mode depends on the time.
            if (block.timestamp < SALES_DEADLINE) {
                // Before sales deadline
                mode = Mode.SellingPreThreshold;
            } else if (block.timestamp < REFUND_DEADLINE) {
                // After sales deadline, before refund deadline
                mode = Mode.Refunding;
            } else {
                // block.timestamp >= refundDeadline
                // After the refund deadline
                mode = Mode.ClosingAfterRefundPeriod;
            }
        }
    }

    // Create the next token ID to be used.
    // This is complicated because we shuffle between two ID ranges:
    //       1-2000 -> gold
    //    2001-5000 -> standard
    // So if there are gold remaining then we use the gold IDs.
    // Otherwise we use the standard IDs.
    function generateTokenId() private returns (uint256) {
        if (goldIds < MAXIMUM_GOLD_MEMBER_COUNT) {
            goldIds += 1;
            return goldIds;
        }
        standardIds += 1;
        return standardIds + MAXIMUM_GOLD_MEMBER_COUNT;
    }

    // Compute the total member count.
    function memberCount() private view returns (uint256) {
        return goldIds + standardIds;
    }

    // This claims any old pending refund to cover the refund of this `memberTokenId`.
    function claimAnyOldRefunds(uint256 memberTokenId) private {
        uint16 oldMemberTokenId = pendingRefundTokens[uint16(memberTokenId)];
        if (oldMemberTokenId != 0) {
            try oldMemberK.refund(oldMemberTokenId) {} catch (bytes memory) {}
        }
    }

    // This actually mints `memberTokenId` to `to` along with a piece of artwork.
    function mintWithArt(address to, uint256 memberTokenId) private {
        _safeMint(to, memberTokenId);
        artSale.mintTo(to);
    }

    // This actually mints `memberTokenId` to `to` along with a piece of artwork.
    // It also associates the minted `memberTokenId` with a pending refund for `oldMemberTokenId`
    function mintFromOldWithArt(
        uint256 oldMemberTokenId,
        address to,
        uint256 memberTokenId
    ) private {
        pendingRefundTokens[uint16(memberTokenId)] = uint16(oldMemberTokenId);
        mintWithArt(to, memberTokenId);
    }
}

// This is the interface to the old membership contract.
interface IOldMember is IERC721 {
    // This allows the membership contract to claim the refund for migrated tokens.
    function refund(uint256 tokenId) external;
}

// This is the interface to the ongoing art sale.
interface IInitialArtSale is IERC721 {
    // This allows the membership contract to mint artwork to a new member.
    function mintTo(address to) external payable;
}

// These types define our interface to the OpenSea proxy registry.
// We use these to support gas-free listings.
contract OwnableDelegateProxy {

}

contract ProxyRegistry {
    mapping(address => OwnableDelegateProxy) public proxies;
}

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "./IERC721.sol";
import "./IERC721Receiver.sol";
import "./extensions/IERC721Metadata.sol";
import "../../utils/Address.sol";
import "../../utils/Context.sol";
import "../../utils/Strings.sol";
import "../../utils/introspection/ERC165.sol";

/**
 * @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including
 * the Metadata extension, but not including the Enumerable extension, which is available separately as
 * {ERC721Enumerable}.
 */
contract ERC721 is Context, ERC165, IERC721, IERC721Metadata {
    using Address for address;
    using Strings for uint256;

    // Token name
    string private _name;

    // Token symbol
    string private _symbol;

    // Mapping from token ID to owner address
    mapping(uint256 => address) private _owners;

    // Mapping owner address to token count
    mapping(address => uint256) private _balances;

    // 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;

    /**
     * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.
     */
    constructor(string memory name_, string memory symbol_) {
        _name = name_;
        _symbol = symbol_;
    }

    /**
     * @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 ||
            super.supportsInterface(interfaceId);
    }

    /**
     * @dev See {IERC721-balanceOf}.
     */
    function balanceOf(address owner) public view virtual override returns (uint256) {
        require(owner != address(0), "ERC721: balance query for the zero address");
        return _balances[owner];
    }

    /**
     * @dev See {IERC721-ownerOf}.
     */
    function ownerOf(uint256 tokenId) public view virtual override returns (address) {
        address owner = _owners[tokenId];
        require(owner != address(0), "ERC721: owner query for nonexistent token");
        return owner;
    }

    /**
     * @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) {
        require(_exists(tokenId), "ERC721Metadata: URI query for nonexistent token");

        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 virtual override {
        address owner = ERC721.ownerOf(tokenId);
        require(to != owner, "ERC721: approval to current owner");

        require(
            _msgSender() == owner || isApprovedForAll(owner, _msgSender()),
            "ERC721: approve caller is not owner nor approved for all"
        );

        _approve(to, tokenId);
    }

    /**
     * @dev See {IERC721-getApproved}.
     */
    function getApproved(uint256 tokenId) public view virtual override returns (address) {
        require(_exists(tokenId), "ERC721: approved query for nonexistent token");

        return _tokenApprovals[tokenId];
    }

    /**
     * @dev See {IERC721-setApprovalForAll}.
     */
    function setApprovalForAll(address operator, bool approved) public virtual override {
        require(operator != _msgSender(), "ERC721: approve to caller");

        _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 {
        //solhint-disable-next-line max-line-length
        require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved");

        _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 {
        require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved");
        _safeTransfer(from, to, tokenId, _data);
    }

    /**
     * @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.
     *
     * `_data` is additional data, it has no specified format and it is sent in call to `to`.
     *
     * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.
     * implement alternative mechanisms to perform token transfer, such as signature-based.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function _safeTransfer(
        address from,
        address to,
        uint256 tokenId,
        bytes memory _data
    ) internal virtual {
        _transfer(from, to, tokenId);
        require(_checkOnERC721Received(from, to, tokenId, _data), "ERC721: transfer to non ERC721Receiver implementer");
    }

    /**
     * @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`),
     * and stop existing when they are burned (`_burn`).
     */
    function _exists(uint256 tokenId) internal view virtual returns (bool) {
        return _owners[tokenId] != address(0);
    }

    /**
     * @dev Returns whether `spender` is allowed to manage `tokenId`.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {
        require(_exists(tokenId), "ERC721: operator query for nonexistent token");
        address owner = ERC721.ownerOf(tokenId);
        return (spender == owner || getApproved(tokenId) == spender || isApprovedForAll(owner, spender));
    }

    /**
     * @dev Safely mints `tokenId` and transfers it to `to`.
     *
     * Requirements:
     *
     * - `tokenId` must not exist.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function _safeMint(address to, uint256 tokenId) internal virtual {
        _safeMint(to, tokenId, "");
    }

    /**
     * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is
     * forwarded in {IERC721Receiver-onERC721Received} to contract recipients.
     */
    function _safeMint(
        address to,
        uint256 tokenId,
        bytes memory _data
    ) internal virtual {
        _mint(to, tokenId);
        require(
            _checkOnERC721Received(address(0), to, tokenId, _data),
            "ERC721: transfer to non ERC721Receiver implementer"
        );
    }

    /**
     * @dev Mints `tokenId` and transfers it to `to`.
     *
     * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible
     *
     * Requirements:
     *
     * - `tokenId` must not exist.
     * - `to` cannot be the zero address.
     *
     * Emits a {Transfer} event.
     */
    function _mint(address to, uint256 tokenId) internal virtual {
        require(to != address(0), "ERC721: mint to the zero address");
        require(!_exists(tokenId), "ERC721: token already minted");

        _beforeTokenTransfer(address(0), to, tokenId);

        _balances[to] += 1;
        _owners[tokenId] = to;

        emit Transfer(address(0), to, tokenId);
    }

    /**
     * @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 {
        address owner = ERC721.ownerOf(tokenId);

        _beforeTokenTransfer(owner, address(0), tokenId);

        // Clear approvals
        _approve(address(0), tokenId);

        _balances[owner] -= 1;
        delete _owners[tokenId];

        emit Transfer(owner, address(0), tokenId);
    }

    /**
     * @dev Transfers `tokenId` from `from` to `to`.
     *  As opposed to {transferFrom}, this imposes no restrictions on msg.sender.
     *
     * 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
    ) internal virtual {
        require(ERC721.ownerOf(tokenId) == from, "ERC721: transfer of token that is not own");
        require(to != address(0), "ERC721: transfer to the zero address");

        _beforeTokenTransfer(from, to, tokenId);

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

        _balances[from] -= 1;
        _balances[to] += 1;
        _owners[tokenId] = to;

        emit Transfer(from, to, tokenId);
    }

    /**
     * @dev Approve `to` to operate on `tokenId`
     *
     * Emits a {Approval} event.
     */
    function _approve(address to, uint256 tokenId) internal virtual {
        _tokenApprovals[tokenId] = to;
        emit Approval(ERC721.ownerOf(tokenId), 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.onERC721Received.selector;
            } catch (bytes memory reason) {
                if (reason.length == 0) {
                    revert("ERC721: transfer to non ERC721Receiver implementer");
                } else {
                    assembly {
                        revert(add(32, reason), mload(reason))
                    }
                }
            }
        } else {
            return true;
        }
    }

    /**
     * @dev Hook that is called before any token transfer. This includes minting
     * and burning.
     *
     * 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, ``from``'s `tokenId` will be burned.
     * - `from` and `to` are never both zero.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _beforeTokenTransfer(
        address from,
        address to,
        uint256 tokenId
    ) internal virtual {}
}

File 3 of 17 : IERC721Receiver.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "../token/ERC721/IERC721Receiver.sol";

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "./IERC165.sol";

/**
 * @dev Interface for the NFT Royalty Standard
 */
interface IERC2981 is IERC165 {
    /**
     * @dev Called with the sale price to determine how much royalty is owed and to whom.
     * @param tokenId - the NFT asset queried for royalty information
     * @param salePrice - the sale price of the NFT asset specified by `tokenId`
     * @return receiver - address of who should be sent the royalty payment
     * @return royaltyAmount - the royalty payment amount for `salePrice`
     */
    function royaltyInfo(uint256 tokenId, uint256 salePrice)
        external
        view
        returns (address receiver, uint256 royaltyAmount);
}

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.
 *
 * These functions can be used to verify that a message was signed by the holder
 * of the private keys of a given address.
 */
library ECDSA {
    enum RecoverError {
        NoError,
        InvalidSignature,
        InvalidSignatureLength,
        InvalidSignatureS,
        InvalidSignatureV
    }

    function _throwError(RecoverError error) private pure {
        if (error == RecoverError.NoError) {
            return; // no error: do nothing
        } else if (error == RecoverError.InvalidSignature) {
            revert("ECDSA: invalid signature");
        } else if (error == RecoverError.InvalidSignatureLength) {
            revert("ECDSA: invalid signature length");
        } else if (error == RecoverError.InvalidSignatureS) {
            revert("ECDSA: invalid signature 's' value");
        } else if (error == RecoverError.InvalidSignatureV) {
            revert("ECDSA: invalid signature 'v' value");
        }
    }

    /**
     * @dev Returns the address that signed a hashed message (`hash`) with
     * `signature` or error string. This address can then be used for verification purposes.
     *
     * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
     * this function rejects them by requiring the `s` value to be in the lower
     * half order, and the `v` value to be either 27 or 28.
     *
     * IMPORTANT: `hash` _must_ be the result of a hash operation for the
     * verification to be secure: it is possible to craft signatures that
     * recover to arbitrary addresses for non-hashed data. A safe way to ensure
     * this is by receiving a hash of the original message (which may otherwise
     * be too long), and then calling {toEthSignedMessageHash} on it.
     *
     * Documentation for signature generation:
     * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]
     * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]
     *
     * _Available since v4.3._
     */
    function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {
        // Check the signature length
        // - case 65: r,s,v signature (standard)
        // - case 64: r,vs signature (cf https://eips.ethereum.org/EIPS/eip-2098) _Available since v4.1._
        if (signature.length == 65) {
            bytes32 r;
            bytes32 s;
            uint8 v;
            // ecrecover takes the signature parameters, and the only way to get them
            // currently is to use assembly.
            assembly {
                r := mload(add(signature, 0x20))
                s := mload(add(signature, 0x40))
                v := byte(0, mload(add(signature, 0x60)))
            }
            return tryRecover(hash, v, r, s);
        } else if (signature.length == 64) {
            bytes32 r;
            bytes32 vs;
            // ecrecover takes the signature parameters, and the only way to get them
            // currently is to use assembly.
            assembly {
                r := mload(add(signature, 0x20))
                vs := mload(add(signature, 0x40))
            }
            return tryRecover(hash, r, vs);
        } else {
            return (address(0), RecoverError.InvalidSignatureLength);
        }
    }

    /**
     * @dev Returns the address that signed a hashed message (`hash`) with
     * `signature`. This address can then be used for verification purposes.
     *
     * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
     * this function rejects them by requiring the `s` value to be in the lower
     * half order, and the `v` value to be either 27 or 28.
     *
     * IMPORTANT: `hash` _must_ be the result of a hash operation for the
     * verification to be secure: it is possible to craft signatures that
     * recover to arbitrary addresses for non-hashed data. A safe way to ensure
     * this is by receiving a hash of the original message (which may otherwise
     * be too long), and then calling {toEthSignedMessageHash} on it.
     */
    function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {
        (address recovered, RecoverError error) = tryRecover(hash, signature);
        _throwError(error);
        return recovered;
    }

    /**
     * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.
     *
     * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]
     *
     * _Available since v4.3._
     */
    function tryRecover(
        bytes32 hash,
        bytes32 r,
        bytes32 vs
    ) internal pure returns (address, RecoverError) {
        bytes32 s;
        uint8 v;
        assembly {
            s := and(vs, 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff)
            v := add(shr(255, vs), 27)
        }
        return tryRecover(hash, v, r, s);
    }

    /**
     * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.
     *
     * _Available since v4.2._
     */
    function recover(
        bytes32 hash,
        bytes32 r,
        bytes32 vs
    ) internal pure returns (address) {
        (address recovered, RecoverError error) = tryRecover(hash, r, vs);
        _throwError(error);
        return recovered;
    }

    /**
     * @dev Overload of {ECDSA-tryRecover} that receives the `v`,
     * `r` and `s` signature fields separately.
     *
     * _Available since v4.3._
     */
    function tryRecover(
        bytes32 hash,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) internal pure returns (address, RecoverError) {
        // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature
        // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines
        // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most
        // signatures from current libraries generate a unique signature with an s-value in the lower half order.
        //
        // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value
        // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or
        // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept
        // these malleable signatures as well.
        if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {
            return (address(0), RecoverError.InvalidSignatureS);
        }
        if (v != 27 && v != 28) {
            return (address(0), RecoverError.InvalidSignatureV);
        }

        // If the signature is valid (and not malleable), return the signer address
        address signer = ecrecover(hash, v, r, s);
        if (signer == address(0)) {
            return (address(0), RecoverError.InvalidSignature);
        }

        return (signer, RecoverError.NoError);
    }

    /**
     * @dev Overload of {ECDSA-recover} that receives the `v`,
     * `r` and `s` signature fields separately.
     */
    function recover(
        bytes32 hash,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) internal pure returns (address) {
        (address recovered, RecoverError error) = tryRecover(hash, v, r, s);
        _throwError(error);
        return recovered;
    }

    /**
     * @dev Returns an Ethereum Signed Message, created from a `hash`. This
     * produces hash corresponding to the one signed with the
     * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]
     * JSON-RPC method as part of EIP-191.
     *
     * See {recover}.
     */
    function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {
        // 32 is the length in bytes of hash,
        // enforced by the type signature above
        return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash));
    }

    /**
     * @dev Returns an Ethereum Signed Typed Data, created from a
     * `domainSeparator` and a `structHash`. This produces hash corresponding
     * to the one signed with the
     * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]
     * JSON-RPC method as part of EIP-712.
     *
     * See {recover}.
     */
    function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {
        return keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash));
    }
}

// SPDX-License-Identifier: MIT

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() {
        _setOwner(_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 {
        _setOwner(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");
        _setOwner(newOwner);
    }

    function _setOwner(address newOwner) private {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}

File 7 of 17 : ReentrancyGuard.sol
// SPDX-License-Identifier: MIT

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 make 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;
    }
}

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the amount of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves `amount` tokens from the caller's account to `recipient`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address recipient, uint256 amount) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 amount) external returns (bool);

    /**
     * @dev Moves `amount` tokens from `sender` to `recipient` using the
     * allowance mechanism. `amount` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(
        address sender,
        address recipient,
        uint256 amount
    ) external returns (bool);

    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);
}

// SPDX-License-Identifier: MIT

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 10 of 17 : IERC721Receiver.sol
// SPDX-License-Identifier: MIT

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);
}

// SPDX-License-Identifier: MIT

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);
}

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @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
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // This method relies on extcodesize, which returns 0 for contracts in
        // construction, since the code is only stored at the end of the
        // constructor execution.

        uint256 size;
        assembly {
            size := extcodesize(account)
        }
        return size > 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);
            }
        }
    }
}

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

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

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

// SPDX-License-Identifier: MIT

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);
    }
}

// SPDX-License-Identifier: MIT

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;
    }
}

// SPDX-License-Identifier: MIT

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);
}

File 17 of 17 : IERC165.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

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

Settings
{
  "optimizer": {
    "enabled": true,
    "runs": 10000
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "libraries": {}
}

Contract Security Audit

Contract ABI

API
[{"inputs":[{"components":[{"internalType":"address[]","name":"foundingTeam","type":"address[]"},{"internalType":"uint256","name":"maximumTotalMemberCount","type":"uint256"},{"internalType":"uint256","name":"maximumGoldMemberCount","type":"uint256"},{"internalType":"uint256","name":"enoughMembersToProceed","type":"uint256"},{"internalType":"uint256","name":"salesDeadline","type":"uint256"},{"internalType":"uint256","name":"refundDeadline","type":"uint256"},{"internalType":"uint256","name":"royaltyPerMille","type":"uint256"},{"internalType":"address","name":"captchaSigner","type":"address"},{"internalType":"address","name":"openSeaProxyRegistry","type":"address"},{"internalType":"contract IOldMember","name":"oldMemberK","type":"address"}],"internalType":"struct SocietyMember.Config","name":"config","type":"tuple"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"PendingTransfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"ART_PRICE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ENOUGH_MEMBERS_TO_PROCEED","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAXIMUM_GOLD_MEMBER_COUNT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAXIMUM_TOTAL_MEMBER_COUNT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MINTS_PER_WALLET","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"REFUND_DEADLINE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SALES_DEADLINE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SALE_PRICE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","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":[{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"name":"claimPending","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"minter_","type":"address"}],"name":"getMintCountByAddress","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"goldBalanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"goldSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"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":"oldTokenIds","type":"uint256[]"}],"name":"migrateMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"captcha","type":"bytes"},{"internalType":"uint8","name":"numberOfTokens","type":"uint8"}],"name":"mint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"mode","outputs":[{"internalType":"enum SocietyMember.Mode","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC721Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"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":[{"internalType":"uint256","name":"memberTokenId","type":"uint256"},{"internalType":"uint256","name":"artTokenId","type":"uint256"}],"name":"refundFull","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"memberTokenId","type":"uint256"}],"name":"refundKeepArt","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"salePrice","type":"uint256"}],"name":"royaltyInfo","outputs":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"royaltyAmount","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":"string","name":"uri","type":"string"}],"name":"setBaseURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_captchaSigner","type":"address"}],"name":"setCaptchaSigner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IInitialArtSale","name":"_artSale","type":"address"}],"name":"setInitialArtSale","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"isEnabled","type":"bool"}],"name":"setOpenSeaProxyEnabled","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_royaltyPerMille","type":"uint256"}],"name":"setRoyalty","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":"_index","type":"uint256"}],"name":"tokenByIndex","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"},{"inputs":[{"internalType":"contract IERC20","name":"token","type":"address"}],"name":"withdrawERC20Tokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC721","name":"token","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"withdrawERC721Token","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]

6101206040526012805460ff60a01b1916600160a01b1790553480156200002557600080fd5b506040516200557838038062005578833981016040819052620000489162000724565b6040518060400160405280600981526020016821b7b63632b1ba37b960b91b8152506040518060400160405280600981526020016821a7a62622a1aa27a960b91b8152508160009080519060200190620000a492919062000562565b508051620000ba90600190602084019062000562565b505050620000d7620000d16200021260201b60201c565b62000216565b6001600755602081015160608201511115620000f257600080fd5b8060200151816040015111156200010857600080fd5b8060a00151816080015111156200011e57600080fd5b602081015160085560408101516080908152606082015160a09081529082015160c09081529082015160e090815290820151601055810151601180546001600160a01b039283166001600160a01b03199182161790915561010080840151601280549185169190931617909155610120830151600b80546001600160a81b0319169190931617909155815151905260005b8151518110156200020a57620001f582600001518281518110620001d757620001d762000816565b6020026020010151620001ef6200026860201b60201c565b6200033f565b80620002018162000842565b915050620001af565b505062000907565b3390565b600680546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b608051600b54600091600160a81b90910461ffff161015620002da576001600b60158282829054906101000a900461ffff16620002a6919062000860565b92506101000a81548161ffff021916908361ffff160217905550600b60159054906101000a900461ffff1661ffff16905090565b6001600b60178282829054906101000a900461ffff16620002fc919062000860565b92506101000a81548161ffff021916908361ffff160217905550608051600b60179054906101000a900461ffff1661ffff166200033a919062000889565b905090565b6001600160a01b0382166200039b5760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f206164647265737360448201526064015b60405180910390fd5b6000818152600260205260409020546001600160a01b031615620004025760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e74656400000000604482015260640162000392565b620004106000838362000499565b6001600160a01b03821660009081526003602052604081208054600192906200043b90849062000889565b909155505060008181526002602052604080822080546001600160a01b0319166001600160a01b03861690811790915590518392907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b608051811115620004a957505050565b6001600160a01b0383161562000503576001600160a01b0383166000908152600d60205260408120805460019290620004e890849061ffff16620008a4565b92506101000a81548161ffff021916908361ffff1602179055505b6001600160a01b038216156200055d576001600160a01b0382166000908152600d602052604081208054600192906200054290849061ffff1662000860565b92506101000a81548161ffff021916908361ffff1602179055505b505050565b8280546200057090620008ca565b90600052602060002090601f016020900481019282620005945760008555620005df565b82601f10620005af57805160ff1916838001178555620005df565b82800160010185558215620005df579182015b82811115620005df578251825591602001919060010190620005c2565b50620005ed929150620005f1565b5090565b5b80821115620005ed5760008155600101620005f2565b634e487b7160e01b600052604160045260246000fd5b60405161014081016001600160401b038111828210171562000644576200064462000608565b60405290565b6001600160a01b03811681146200066057600080fd5b50565b805162000670816200064a565b919050565b600082601f8301126200068757600080fd5b815160206001600160401b0380831115620006a657620006a662000608565b8260051b604051601f19603f83011681018181108482111715620006ce57620006ce62000608565b604052938452858101830193838101925087851115620006ed57600080fd5b83870191505b848210156200071957815162000709816200064a565b83529183019190830190620006f3565b979650505050505050565b6000602082840312156200073757600080fd5b81516001600160401b03808211156200074f57600080fd5b9083019061014082860312156200076557600080fd5b6200076f6200061e565b8251828111156200077f57600080fd5b6200078d8782860162000675565b8252506020830151602082015260408301516040820152606083015160608201526080830151608082015260a083015160a082015260c083015160c0820152620007da60e0840162000663565b60e08201526101009150620007f182840162000663565b8282015261012091506200080782840162000663565b91810191909152949350505050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b60006000198214156200085957620008596200082c565b5060010190565b600061ffff8083168185168083038211156200088057620008806200082c565b01949350505050565b600082198211156200089f576200089f6200082c565b500190565b600061ffff83811690831681811015620008c257620008c26200082c565b039392505050565b600181811c90821680620008df57607f821691505b602082108114156200090157634e487b7160e01b600052602260045260246000fd5b50919050565b60805160a05160c05160e05161010051614bd8620009a060003960008181611ca101528181611f500152818161219f0152612bba01526000818161086a01526132a30152600081816103c50152818161314d01526132460152600081816107560152818161317801526131ea0152600081816107060152818161125c01528181613491015281816135640152613af00152614bd86000f3fe6080604052600436106102f65760003560e01c8063715018a61161018f578063a17dbd01116100e1578063c5d928c21161008a578063f2fde38b11610064578063f2fde38b14610957578063f7b6823b14610977578063fd91f0d81461099757600080fd5b8063c5d928c214610901578063c87b56dd14610917578063e985e9c51461093757600080fd5b8063aa0dfe77116100bb578063aa0dfe77146108ac578063b1a953e5146108c1578063b88d4fde146108e157600080fd5b8063a17dbd0114610838578063a1e6802514610858578063a22cb4651461088c57600080fd5b806385d24080116101435780638aaa4c0c1161011d5780638aaa4c0c146107e55780638da5cb5b1461080557806395d89b411461082357600080fd5b806385d2408014610778578063864ca3001461078b5780638a09bbb8146107c557600080fd5b80637a2a6d58116101745780637a2a6d58146106f45780637f205a741461072857806380dd1d3d1461074457600080fd5b8063715018a6146106bf578063765b080e146106d457600080fd5b80632a55205a116102485780634f6ccce7116101fc5780636352211e116101d65780636352211e1461064d5780636edf15491461066d57806370a082311461069f57600080fd5b80634f6ccce7146105ed5780634ff7ff321461060d57806355f804b31461062d57600080fd5b80633ccfd60b1161022d5780633ccfd60b146105985780634209a2e1146105ad57806342842e0e146105cd57600080fd5b80632a55205a146105395780633aaed7b91461057857600080fd5b80630df1da8d116102aa57806321b02b641161028457806321b02b64146104cb57806323b872dd146104eb578063295a52121461050b57600080fd5b80630df1da8d146103f5578063150b7a021461044057806318160ddd146104b657600080fd5b8063081812fc116102db578063081812fc14610359578063095ea7b3146103915780630db6a786146103b357600080fd5b806301ffc9a71461030257806306fdde031461033757600080fd5b366102fd57005b600080fd5b34801561030e57600080fd5b5061032261031d3660046142d7565b6109b3565b60405190151581526020015b60405180910390f35b34801561034357600080fd5b5061034c610a16565b60405161032e919061436a565b34801561036557600080fd5b5061037961037436600461437d565b610aa8565b6040516001600160a01b03909116815260200161032e565b34801561039d57600080fd5b506103b16103ac3660046143ab565b610b53565b005b3480156103bf57600080fd5b506103e77f000000000000000000000000000000000000000000000000000000000000000081565b60405190815260200161032e565b34801561040157600080fd5b5061042e6104103660046143d7565b6001600160a01b03166000908152600c602052604090205460ff1690565b60405160ff909116815260200161032e565b34801561044c57600080fd5b5061048561045b3660046143f4565b7f150b7a020000000000000000000000000000000000000000000000000000000095945050505050565b6040517fffffffff00000000000000000000000000000000000000000000000000000000909116815260200161032e565b3480156104c257600080fd5b506103e7610c85565b3480156104d757600080fd5b506103b16104e63660046144a1565b610c94565b3480156104f757600080fd5b506103b16105063660046144be565b610d27565b34801561051757600080fd5b50600b5461052c90600160a01b900460ff1681565b60405161032e919061452e565b34801561054557600080fd5b5061055961055436600461456f565b610dae565b604080516001600160a01b03909316835260208301919091520161032e565b34801561058457600080fd5b506103b16105933660046143ab565b610e47565b3480156105a457600080fd5b506103b1611010565b3480156105b957600080fd5b506103b16105c836600461437d565b611188565b3480156105d957600080fd5b506103b16105e83660046144be565b6111e7565b3480156105f957600080fd5b506103e761060836600461437d565b611202565b34801561061957600080fd5b506103b16106283660046143d7565b611305565b34801561063957600080fd5b506103b1610648366004614685565b61148e565b34801561065957600080fd5b5061037961066836600461437d565b6114fb565b34801561067957600080fd5b50600b547501000000000000000000000000000000000000000000900461ffff166103e7565b3480156106ab57600080fd5b506103e76106ba3660046143d7565b611586565b3480156106cb57600080fd5b506103b1611620565b3480156106e057600080fd5b506103b16106ef3660046143d7565b611686565b34801561070057600080fd5b506103e77f000000000000000000000000000000000000000000000000000000000000000081565b34801561073457600080fd5b506103e7670214e8348c4f000081565b34801561075057600080fd5b506103e77f000000000000000000000000000000000000000000000000000000000000000081565b6103b16107863660046146ee565b61171a565b34801561079757600080fd5b506103e76107a63660046143d7565b6001600160a01b03166000908152600d602052604090205461ffff1690565b3480156107d157600080fd5b506103b16107e0366004614746565b611a99565b3480156107f157600080fd5b506103b161080036600461437d565b611e70565b34801561081157600080fd5b506006546001600160a01b0316610379565b34801561082f57600080fd5b5061034c6120b0565b34801561084457600080fd5b506103b161085336600461456f565b6120bf565b34801561086457600080fd5b506103e77f000000000000000000000000000000000000000000000000000000000000000081565b34801561089857600080fd5b506103b16108a73660046147ec565b612376565b3480156108b857600080fd5b506103e7600281565b3480156108cd57600080fd5b506103b16108dc366004614746565b612459565b3480156108ed57600080fd5b506103b16108fc36600461481a565b612756565b34801561090d57600080fd5b506103e760085481565b34801561092357600080fd5b5061034c61093236600461437d565b6127e4565b34801561094357600080fd5b50610322610952366004614886565b6128cd565b34801561096357600080fd5b506103b16109723660046143d7565b6129c7565b34801561098357600080fd5b506103b16109923660046143d7565b612aa9565b3480156109a357600080fd5b506103e767016345785d8a000081565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f2a55205a000000000000000000000000000000000000000000000000000000001415610a0757506001919050565b610a1082612c83565b92915050565b606060008054610a25906148b4565b80601f0160208091040260200160405190810160405280929190818152602001828054610a51906148b4565b8015610a9e5780601f10610a7357610100808354040283529160200191610a9e565b820191906000526020600020905b815481529060010190602001808311610a8157829003601f168201915b5050505050905090565b6000818152600260205260408120546001600160a01b0316610b375760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a20617070726f76656420717565727920666f72206e6f6e657860448201527f697374656e7420746f6b656e000000000000000000000000000000000000000060648201526084015b60405180910390fd5b506000908152600460205260409020546001600160a01b031690565b6000610b5e826114fb565b9050806001600160a01b0316836001600160a01b03161415610be85760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e6560448201527f72000000000000000000000000000000000000000000000000000000000000006064820152608401610b2e565b336001600160a01b0382161480610c045750610c0481336128cd565b610c765760405162461bcd60e51b815260206004820152603860248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f74206f7760448201527f6e6572206e6f7220617070726f76656420666f7220616c6c00000000000000006064820152608401610b2e565b610c808383612d66565b505050565b6000610c8f612dec565b905090565b6006546001600160a01b03163314610cee5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610b2e565b60128054911515600160a01b027fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff909216919091179055565b610d313382612e3f565b610da35760405162461bcd60e51b815260206004820152603160248201527f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f60448201527f776e6572206e6f7220617070726f7665640000000000000000000000000000006064820152608401610b2e565b610c80838383612f27565b60008281526002602052604081205481906001600160a01b0316610e145760405162461bcd60e51b815260206004820152601160248201527f6e6f7420612076616c696420746f6b656e0000000000000000000000000000006044820152606401610b2e565b6006546001600160a01b03166103e860105485610e319190614937565b610e3b91906149a3565b915091505b9250929050565b6006546001600160a01b03163314610ea15760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610b2e565b610ea9613117565b6001600b54600160a01b900460ff166004811115610ec957610ec96144ff565b1480610ef257506002600b54600160a01b900460ff166004811115610ef057610ef06144ff565b145b80610f1a57506004600b54600160a01b900460ff166004811115610f1857610f186144ff565b145b610f8c5760405162461bcd60e51b815260206004820152603e60248201527f6c6f636b656420756e74696c2074686572652061726520656e6f756768206d6560448201527f6d6265727320286f7220616674657220726566756e6420706572696f642900006064820152608401610b2e565b6040517f23b872dd000000000000000000000000000000000000000000000000000000008152306004820152336024820152604481018290526001600160a01b038316906323b872dd906064015b600060405180830381600087803b158015610ff457600080fd5b505af1158015611008573d6000803e3d6000fd5b505050505050565b6006546001600160a01b0316331461106a5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610b2e565b611072613117565b6001600b54600160a01b900460ff166004811115611092576110926144ff565b14806110bb57506002600b54600160a01b900460ff1660048111156110b9576110b96144ff565b145b806110e357506004600b54600160a01b900460ff1660048111156110e1576110e16144ff565b145b6111555760405162461bcd60e51b815260206004820152603e60248201527f6c6f636b656420756e74696c2074686572652061726520656e6f756768206d6560448201527f6d6265727320286f7220616674657220726566756e6420706572696f642900006064820152608401610b2e565b6040514790339082156108fc029083906000818181858888f19350505050158015611184573d6000803e3d6000fd5b5050565b6006546001600160a01b031633146111e25760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610b2e565b601055565b610c8083838360405180602001604052806000815250612756565b600b546000907501000000000000000000000000000000000000000000900461ffff16821061128357600b546112569083907501000000000000000000000000000000000000000000900461ffff166149b7565b611280907f00000000000000000000000000000000000000000000000000000000000000006149ce565b91505b6112ae6112918360016149ce565b6000908152600260205260409020546001600160a01b0316151590565b6112fa5760405162461bcd60e51b815260206004820152600f60248201527f62616420746f6b656e20696e64657800000000000000000000000000000000006044820152606401610b2e565b610a108260016149ce565b6006546001600160a01b0316331461135f5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610b2e565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526000906001600160a01b038316906370a082319060240160206040518083038186803b1580156113ba57600080fd5b505afa1580156113ce573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113f291906149e6565b6040517fa9059cbb000000000000000000000000000000000000000000000000000000008152336004820152602481018290529091506001600160a01b0383169063a9059cbb90604401602060405180830381600087803b15801561145657600080fd5b505af115801561146a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c8091906149ff565b6006546001600160a01b031633146114e85760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610b2e565b805161118490600f906020840190614210565b6000818152600260205260408120546001600160a01b031680610a105760405162461bcd60e51b815260206004820152602960248201527f4552433732313a206f776e657220717565727920666f72206e6f6e657869737460448201527f656e7420746f6b656e00000000000000000000000000000000000000000000006064820152608401610b2e565b60006001600160a01b0382166116045760405162461bcd60e51b815260206004820152602a60248201527f4552433732313a2062616c616e636520717565727920666f7220746865207a6560448201527f726f2061646472657373000000000000000000000000000000000000000000006064820152608401610b2e565b506001600160a01b031660009081526003602052604090205490565b6006546001600160a01b0316331461167a5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610b2e565b6116846000613340565b565b6006546001600160a01b031633146116e05760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610b2e565b601180547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b6002600754141561176d5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610b2e565b600260075560ff81166117c25760405162461bcd60e51b815260206004820181905260248201527f6d697373696e67206e756d626572206f6620746f6b656e7320746f206d696e746044820152606401610b2e565b6117ca613117565b6000600b54600160a01b900460ff1660048111156117ea576117ea6144ff565b148061181357506001600b54600160a01b900460ff166004811115611811576118116144ff565b145b61185f5760405162461bcd60e51b815260206004820152601860248201527f6d696e74696e67206973206e6f7420617661696c61626c6500000000000000006044820152606401610b2e565b6008548160ff1661186e612dec565b61187891906149ce565b11156118c65760405162461bcd60e51b815260206004820181905260248201527f6e6f7420656e6f756768206d656d62657273686970732072656d61696e696e676044820152606401610b2e565b6118db60ff8216670214e8348c4f0000614937565b34146119295760405162461bcd60e51b815260206004820152601c60248201527f696e636f727265637420455448207061796d656e7420616d6f756e74000000006044820152606401610b2e565b61193382336133aa565b61197f5760405162461bcd60e51b815260206004820152601560248201527f796f75207365656d206c696b65206120726f626f7400000000000000000000006044820152606401610b2e565b336000908152600c602052604090205460ff16600261199e8383614a1c565b60ff161115611a155760405162461bcd60e51b815260206004820152602c60248201527f796f752063616e206f6e6c79206d696e742074776f206d656d6265727368697060448201527f73207065722077616c6c657400000000000000000000000000000000000000006064820152608401610b2e565b611a1f8282614a1c565b336000908152600c6020526040812080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff93909316929092179091555b8260ff16811015611a8e57611a7c33611a77613489565b6135a2565b80611a8681614a41565b915050611a60565b505060016007555050565b60026007541415611aec5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610b2e565b6002600755611af9613117565b6000600b54600160a01b900460ff166004811115611b1957611b196144ff565b1480611b4257506001600b54600160a01b900460ff166004811115611b4057611b406144ff565b145b611b8e5760405162461bcd60e51b815260206004820152601860248201527f6d696e74696e67206973206e6f7420617661696c61626c6500000000000000006044820152606401610b2e565b6008548151611b9e906003614937565b611ba6612dec565b611bb091906149ce565b1115611bfe5760405162461bcd60e51b815260206004820181905260248201527f6e6f7420656e6f756768206d656d62657273686970732072656d61696e696e676044820152606401610b2e565b6004815110611c755760405162461bcd60e51b815260206004820152602360248201527f6d6967726174696e6720746f6f206d616e7920696e20612073696e676c65206360448201527f616c6c00000000000000000000000000000000000000000000000000000000006064820152608401610b2e565b60005b8151811015611e67576000828281518110611c9557611c95614a7a565b602002602001015190507f00000000000000000000000000000000000000000000000000000000000000008111611d345760405162461bcd60e51b815260206004820152602360248201527f666f756e64696e67207465616d20746f6b656e732063616e6e6f74206d69677260448201527f61746500000000000000000000000000000000000000000000000000000000006064820152608401610b2e565b600b546040517f23b872dd000000000000000000000000000000000000000000000000000000008152336004820152306024820152604481018390526001600160a01b03909116906323b872dd90606401600060405180830381600087803b158015611d9f57600080fd5b505af1158015611db3573d6000803e3d6000fd5b50505050611dc98133611dc4613489565b6135f7565b611dd68133611dc4613489565b6000611de0613489565b9050611dec3082613642565b61ffff811660009081526009602052604080822080547fffffffffffffffffffffffff00000000000000000000000000000000000000001633908117909155905183927f9f45a4ef7adb5b3e01ef919bb93ad80a8b568e89d896412723d27db107ed1c2b91a350508080611e5f90614a41565b915050611c78565b50506001600755565b60026007541415611ec35760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610b2e565b600260075533611ed2826114fb565b6001600160a01b031614611f4e5760405162461bcd60e51b815260206004820152602160248201527f6f6e6c7920746865206f776e6572206d617920636c61696d206120726566756e60448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610b2e565b7f00000000000000000000000000000000000000000000000000000000000000008111611fe35760405162461bcd60e51b815260206004820152602860248201527f666f756e64696e67207465616d20746f6b656e7320646f206e6f74206765742060448201527f6120726566756e640000000000000000000000000000000000000000000000006064820152608401610b2e565b611feb613117565b6003600b54600160a01b900460ff16600481111561200b5761200b6144ff565b146120585760405162461bcd60e51b815260206004820152601a60248201527f726566756e64696e67206973206e6f7420617661696c61626c650000000000006044820152606401610b2e565b612061816137a8565b61206a81613865565b336108fc61208867016345785d8a0000670214e8348c4f00006149b7565b6040518115909202916000818181858888f19350505050158015611e67573d6000803e3d6000fd5b606060018054610a25906148b4565b600260075414156121125760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610b2e565b600260075533612121836114fb565b6001600160a01b03161461219d5760405162461bcd60e51b815260206004820152602160248201527f6f6e6c7920746865206f776e6572206d617920636c61696d206120726566756e60448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610b2e565b7f000000000000000000000000000000000000000000000000000000000000000082116122325760405162461bcd60e51b815260206004820152602860248201527f666f756e64696e67207465616d20746f6b656e7320646f206e6f74206765742060448201527f6120726566756e640000000000000000000000000000000000000000000000006064820152608401610b2e565b61223a613117565b6003600b54600160a01b900460ff16600481111561225a5761225a6144ff565b146122a75760405162461bcd60e51b815260206004820152601a60248201527f726566756e64696e67206973206e6f7420617661696c61626c650000000000006044820152606401610b2e565b6122b0826137a8565b600e546040517f23b872dd000000000000000000000000000000000000000000000000000000008152336004820152306024820152604481018390526001600160a01b03909116906323b872dd90606401600060405180830381600087803b15801561231b57600080fd5b505af115801561232f573d6000803e3d6000fd5b5050505061233c82613865565b6040513390600090670214e8348c4f00009082818181858883f1935050505015801561236c573d6000803e3d6000fd5b5050600160075550565b6001600160a01b0382163314156123cf5760405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c6572000000000000006044820152606401610b2e565b3360008181526005602090815260408083206001600160a01b0387168085529083529281902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b600260075414156124ac5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610b2e565b60026007556124b9613117565b6001600b54600160a01b900460ff1660048111156124d9576124d96144ff565b148061250257506002600b54600160a01b900460ff166004811115612500576125006144ff565b145b6125745760405162461bcd60e51b815260206004820152602a60248201527f746f6b656e2072656d61696e732070656e64696e6720756e74696c20706f737460448201527f2d7468726573686f6c64000000000000000000000000000000000000000000006064820152608401610b2e565b60088151106125eb5760405162461bcd60e51b815260206004820152602260248201527f636c61696d696e6720746f6f206d616e7920696e20612073696e676c6520636160448201527f6c6c0000000000000000000000000000000000000000000000000000000000006064820152608401610b2e565b60005b8151811015611e6757600082828151811061260b5761260b614a7a565b60209081029190910181015161ffff8116600090815260099092526040909120549091506001600160a01b0316806126855760405162461bcd60e51b815260206004820152601d60248201527f746f6b656e206973206e6f742070656e64696e67207472616e736665720000006044820152606401610b2e565b61ffff8216600090815260096020526040902080547fffffffffffffffffffffffff00000000000000000000000000000000000000001690556126c9308284612f27565b600e546040517f755edd170000000000000000000000000000000000000000000000000000000081526001600160a01b0383811660048301529091169063755edd1790602401600060405180830381600087803b15801561272957600080fd5b505af115801561273d573d6000803e3d6000fd5b505050505050808061274e90614a41565b9150506125ee565b6127603383612e3f565b6127d25760405162461bcd60e51b815260206004820152603160248201527f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f60448201527f776e6572206e6f7220617070726f7665640000000000000000000000000000006064820152608401610b2e565b6127de84848484613924565b50505050565b6000818152600260205260409020546060906001600160a01b03166128715760405162461bcd60e51b815260206004820152602f60248201527f4552433732314d657461646174613a2055524920717565727920666f72206e6f60448201527f6e6578697374656e7420746f6b656e00000000000000000000000000000000006064820152608401610b2e565b600061287b6139ad565b9050600081511161289b57604051806020016040528060008152506128c6565b806128a5846139bc565b6040516020016128b6929190614aa9565b6040516020818303038152906040525b9392505050565b601254600090600160a01b900460ff1615612998576012546040517fc45527910000000000000000000000000000000000000000000000000000000081526001600160a01b03858116600483015291821691841690829063c45527919060240160206040518083038186803b15801561294557600080fd5b505afa158015612959573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061297d9190614ad8565b6001600160a01b03161415612996576001915050610a10565b505b506001600160a01b03918216600090815260056020908152604080832093909416825291909152205460ff1690565b6006546001600160a01b03163314612a215760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610b2e565b6001600160a01b038116612a9d5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610b2e565b612aa681613340565b50565b6006546001600160a01b03163314612b035760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610b2e565b600e546001600160a01b031615612b825760405162461bcd60e51b815260206004820152602260248201527f696e697469616c206172742073616c6520616c7265616479207370656369666960448201527f65640000000000000000000000000000000000000000000000000000000000006064820152608401610b2e565b600e80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b03831617905560005b7f000000000000000000000000000000000000000000000000000000000000000081101561118457600e546001600160a01b031663755edd17612bff6106688460016149ce565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b1681526001600160a01b039091166004820152602401600060405180830381600087803b158015612c5857600080fd5b505af1158015612c6c573d6000803e3d6000fd5b505050508080612c7b90614a41565b915050612bb8565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f80ac58cd000000000000000000000000000000000000000000000000000000001480612d1657507fffffffff0000000000000000000000000000000000000000000000000000000082167f5b5e139f00000000000000000000000000000000000000000000000000000000145b80610a1057507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000831614610a10565b600081815260046020526040902080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0384169081179091558190612db3826114fb565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b600b54600090612e369061ffff7701000000000000000000000000000000000000000000000082048116917501000000000000000000000000000000000000000000900416614af5565b61ffff16905090565b6000818152600260205260408120546001600160a01b0316612ec95760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a206f70657261746f7220717565727920666f72206e6f6e657860448201527f697374656e7420746f6b656e00000000000000000000000000000000000000006064820152608401610b2e565b6000612ed4836114fb565b9050806001600160a01b0316846001600160a01b03161480612f0f5750836001600160a01b0316612f0484610aa8565b6001600160a01b0316145b80612f1f5750612f1f81856128cd565b949350505050565b826001600160a01b0316612f3a826114fb565b6001600160a01b031614612fb65760405162461bcd60e51b815260206004820152602960248201527f4552433732313a207472616e73666572206f6620746f6b656e2074686174206960448201527f73206e6f74206f776e00000000000000000000000000000000000000000000006064820152608401610b2e565b6001600160a01b0382166130315760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f2061646460448201527f72657373000000000000000000000000000000000000000000000000000000006064820152608401610b2e565b61303c838383613aee565b613047600082612d66565b6001600160a01b03831660009081526003602052604081208054600192906130709084906149b7565b90915550506001600160a01b038216600090815260036020526040812080546001929061309e9084906149ce565b909155505060008181526002602052604080822080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0386811691821790925591518493918716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b6002600b54600160a01b900460ff166004811115613137576131376144ff565b141561313f57565b6000613149612dec565b90507f0000000000000000000000000000000000000000000000000000000000000000421015801561319b57507f00000000000000000000000000000000000000000000000000000000000000008110155b156131a65760088190555b60085481106131e857600b8054600291907fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16600160a01b835b021790555050565b7f0000000000000000000000000000000000000000000000000000000000000000811061324457600b8054600191907fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16600160a01b836131e0565b7f00000000000000000000000000000000000000000000000000000000000000004210156132a157600b8054600091907fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16600160a01b836131e0565b7f00000000000000000000000000000000000000000000000000000000000000004210156132fe57600b8054600391907fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16600160a01b836131e0565b50600b80547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674040000000000000000000000000000000000000000179055565b600680546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b604080517f6d656d6265720000000000000000000000000000000000000000000000000000602080830191909152606084901b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001660268301528251601a818403018152603a830184528051908201207f19457468657265756d205369676e6564204d6573736167653a0a333200000000605a8401526076808401829052845180850390910181526096909301909352815191012060009190829061346f9086613bcd565b6011546001600160a01b0390811691161495945050505050565b600b546000907f0000000000000000000000000000000000000000000000000000000000000000750100000000000000000000000000000000000000000090910461ffff161015613528576001600b60158282829054906101000a900461ffff166134f49190614af5565b92506101000a81548161ffff021916908361ffff160217905550600b60159054906101000a900461ffff1661ffff16905090565b6001600b60178282829054906101000a900461ffff166135489190614af5565b92506101000a81548161ffff021916908361ffff1602179055507f0000000000000000000000000000000000000000000000000000000000000000600b60179054906101000a900461ffff1661ffff16610c8f91906149ce565b6135ac8282613bf1565b600e546040517f755edd170000000000000000000000000000000000000000000000000000000081526001600160a01b0384811660048301529091169063755edd1790602401610fda565b61ffff8181166000908152600a6020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000016918516919091179055610c8082826135a2565b6001600160a01b0382166136985760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f20616464726573736044820152606401610b2e565b6000818152600260205260409020546001600160a01b0316156136fd5760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e746564000000006044820152606401610b2e565b61370960008383613aee565b6001600160a01b03821660009081526003602052604081208054600192906137329084906149ce565b909155505060008181526002602052604080822080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b03861690811790915590518392907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b61ffff8082166000908152600a602052604090205416801561118457600b546040517f278ecde100000000000000000000000000000000000000000000000000000000815261ffff831660048201526001600160a01b039091169063278ecde190602401600060405180830381600087803b15801561382657600080fd5b505af1925050508015613837575060015b611184573d8080156127de576040519150601f19603f3d011682016040523d82523d6000602084013e6127de565b6000613870826114fb565b905061387e81600084613aee565b613889600083612d66565b6001600160a01b03811660009081526003602052604081208054600192906138b29084906149b7565b909155505060008281526002602052604080822080547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055518391906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45050565b61392f848484612f27565b61393b84848484613c0b565b6127de5760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527f63656976657220696d706c656d656e74657200000000000000000000000000006064820152608401610b2e565b6060600f8054610a25906148b4565b6060816139fc57505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b8115613a265780613a1081614a41565b9150613a1f9050600a836149a3565b9150613a00565b60008167ffffffffffffffff811115613a4157613a41614591565b6040519080825280601f01601f191660200182016040528015613a6b576020820181803683370190505b5090505b8415612f1f57613a806001836149b7565b9150613a8d600a86614b12565b613a989060306149ce565b60f81b818381518110613aad57613aad614a7a565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350613ae7600a866149a3565b9450613a6f565b7f0000000000000000000000000000000000000000000000000000000000000000811115613b1b57505050565b6001600160a01b03831615613b72576001600160a01b0383166000908152600d60205260408120805460019290613b5790849061ffff16614b26565b92506101000a81548161ffff021916908361ffff1602179055505b6001600160a01b03821615610c80576001600160a01b0382166000908152600d60205260408120805460019290613bae90849061ffff16614af5565b92506101000a81548161ffff021916908361ffff160217905550505050565b6000806000613bdc8585613dd6565b91509150613be981613e43565b509392505050565b611184828260405180602001604052806000815250614034565b60006001600160a01b0384163b15613dcb576040517f150b7a020000000000000000000000000000000000000000000000000000000081526001600160a01b0385169063150b7a0290613c68903390899088908890600401614b49565b602060405180830381600087803b158015613c8257600080fd5b505af1925050508015613cd0575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201909252613ccd91810190614b85565b60015b613d80573d808015613cfe576040519150601f19603f3d011682016040523d82523d6000602084013e613d03565b606091505b508051613d785760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527f63656976657220696d706c656d656e74657200000000000000000000000000006064820152608401610b2e565b805181602001fd5b7fffffffff00000000000000000000000000000000000000000000000000000000167f150b7a0200000000000000000000000000000000000000000000000000000000149050612f1f565b506001949350505050565b600080825160411415613e0d5760208301516040840151606085015160001a613e01878285856140bd565b94509450505050610e40565b825160401415613e375760208301516040840151613e2c8683836141c8565b935093505050610e40565b50600090506002610e40565b6000816004811115613e5757613e576144ff565b1415613e605750565b6001816004811115613e7457613e746144ff565b1415613ec25760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e617475726500000000000000006044820152606401610b2e565b6002816004811115613ed657613ed66144ff565b1415613f245760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606401610b2e565b6003816004811115613f3857613f386144ff565b1415613fac5760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c60448201527f75650000000000000000000000000000000000000000000000000000000000006064820152608401610b2e565b6004816004811115613fc057613fc06144ff565b1415612aa65760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202776272076616c60448201527f75650000000000000000000000000000000000000000000000000000000000006064820152608401610b2e565b61403e8383613642565b61404b6000848484613c0b565b610c805760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527f63656976657220696d706c656d656e74657200000000000000000000000000006064820152608401610b2e565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08311156140f457506000905060036141bf565b8460ff16601b1415801561410c57508460ff16601c14155b1561411d57506000905060046141bf565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015614171573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001519150506001600160a01b0381166141b8576000600192509250506141bf565b9150600090505b94509492505050565b6000807f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff831660ff84901c601b01614202878288856140bd565b935093505050935093915050565b82805461421c906148b4565b90600052602060002090601f01602090048101928261423e5760008555614284565b82601f1061425757805160ff1916838001178555614284565b82800160010185558215614284579182015b82811115614284578251825591602001919060010190614269565b50614290929150614294565b5090565b5b808211156142905760008155600101614295565b7fffffffff0000000000000000000000000000000000000000000000000000000081168114612aa657600080fd5b6000602082840312156142e957600080fd5b81356128c6816142a9565b60005b8381101561430f5781810151838201526020016142f7565b838111156127de5750506000910152565b600081518084526143388160208601602086016142f4565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006128c66020830184614320565b60006020828403121561438f57600080fd5b5035919050565b6001600160a01b0381168114612aa657600080fd5b600080604083850312156143be57600080fd5b82356143c981614396565b946020939093013593505050565b6000602082840312156143e957600080fd5b81356128c681614396565b60008060008060006080868803121561440c57600080fd5b853561441781614396565b9450602086013561442781614396565b935060408601359250606086013567ffffffffffffffff8082111561444b57600080fd5b818801915088601f83011261445f57600080fd5b81358181111561446e57600080fd5b89602082850101111561448057600080fd5b9699959850939650602001949392505050565b8015158114612aa657600080fd5b6000602082840312156144b357600080fd5b81356128c681614493565b6000806000606084860312156144d357600080fd5b83356144de81614396565b925060208401356144ee81614396565b929592945050506040919091013590565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b6020810160058310614569577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b91905290565b6000806040838503121561458257600080fd5b50508035926020909101359150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561460757614607614591565b604052919050565b600067ffffffffffffffff83111561462957614629614591565b61465a60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f860116016145c0565b905082815283838301111561466e57600080fd5b828260208301376000602084830101529392505050565b60006020828403121561469757600080fd5b813567ffffffffffffffff8111156146ae57600080fd5b8201601f810184136146bf57600080fd5b612f1f8482356020840161460f565b600082601f8301126146df57600080fd5b6128c68383356020850161460f565b6000806040838503121561470157600080fd5b823567ffffffffffffffff81111561471857600080fd5b614724858286016146ce565b925050602083013560ff8116811461473b57600080fd5b809150509250929050565b6000602080838503121561475957600080fd5b823567ffffffffffffffff8082111561477157600080fd5b818501915085601f83011261478557600080fd5b81358181111561479757614797614591565b8060051b91506147a88483016145c0565b81815291830184019184810190888411156147c257600080fd5b938501935b838510156147e0578435825293850193908501906147c7565b98975050505050505050565b600080604083850312156147ff57600080fd5b823561480a81614396565b9150602083013561473b81614493565b6000806000806080858703121561483057600080fd5b843561483b81614396565b9350602085013561484b81614396565b925060408501359150606085013567ffffffffffffffff81111561486e57600080fd5b61487a878288016146ce565b91505092959194509250565b6000806040838503121561489957600080fd5b82356148a481614396565b9150602083013561473b81614396565b600181811c908216806148c857607f821691505b60208210811415614902577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561496f5761496f614908565b500290565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000826149b2576149b2614974565b500490565b6000828210156149c9576149c9614908565b500390565b600082198211156149e1576149e1614908565b500190565b6000602082840312156149f857600080fd5b5051919050565b600060208284031215614a1157600080fd5b81516128c681614493565b600060ff821660ff84168060ff03821115614a3957614a39614908565b019392505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821415614a7357614a73614908565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008351614abb8184602088016142f4565b835190830190614acf8183602088016142f4565b01949350505050565b600060208284031215614aea57600080fd5b81516128c681614396565b600061ffff808316818516808303821115614acf57614acf614908565b600082614b2157614b21614974565b500690565b600061ffff83811690831681811015614b4157614b41614908565b039392505050565b60006001600160a01b03808716835280861660208401525083604083015260806060830152614b7b6080830184614320565b9695505050505050565b600060208284031215614b9757600080fd5b81516128c6816142a956fea2646970667358221220c8955f5b951296a65b4c7e1ae2528e0239b369de5887de470d91fd51c3d54c1664736f6c6343000809003300000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000138800000000000000000000000000000000000000000000000000000000000007d000000000000000000000000000000000000000000000000000000000000007d000000000000000000000000000000000000000000000000000000000620ffac0000000000000000000000000000000000000000000000000000000006234d6b0000000000000000000000000000000000000000000000000000000000000004b000000000000000000000000acce5556a5db4a0fc4769ad87fd673ef61b9c4a1000000000000000000000000a5409ec958c83c3f309868babaca7c86dcb077c1000000000000000000000000d3426b1e7f7cde3948368318df9c0fd1ae21e8270000000000000000000000000000000000000000000000000000000000000007000000000000000000000000155814ac8095111566f614819acfc2b59fce3a7100000000000000000000000097f47b2dea15c5eb4ce06c7b90857593545d110800000000000000000000000041e2e49f809963636c6cda9789a5e163991b04e000000000000000000000000024598829930ba2d947fe6ebeea30c662739ce81b00000000000000000000000062ad3bd57596c5836420c53275d4e78a5e95bcee0000000000000000000000006ae5b9b1ae8df7b0b90edae05d4788950b0a6cfd00000000000000000000000002a166016d28b9de68143b368568d642a8d226d9

Deployed Bytecode

0x6080604052600436106102f65760003560e01c8063715018a61161018f578063a17dbd01116100e1578063c5d928c21161008a578063f2fde38b11610064578063f2fde38b14610957578063f7b6823b14610977578063fd91f0d81461099757600080fd5b8063c5d928c214610901578063c87b56dd14610917578063e985e9c51461093757600080fd5b8063aa0dfe77116100bb578063aa0dfe77146108ac578063b1a953e5146108c1578063b88d4fde146108e157600080fd5b8063a17dbd0114610838578063a1e6802514610858578063a22cb4651461088c57600080fd5b806385d24080116101435780638aaa4c0c1161011d5780638aaa4c0c146107e55780638da5cb5b1461080557806395d89b411461082357600080fd5b806385d2408014610778578063864ca3001461078b5780638a09bbb8146107c557600080fd5b80637a2a6d58116101745780637a2a6d58146106f45780637f205a741461072857806380dd1d3d1461074457600080fd5b8063715018a6146106bf578063765b080e146106d457600080fd5b80632a55205a116102485780634f6ccce7116101fc5780636352211e116101d65780636352211e1461064d5780636edf15491461066d57806370a082311461069f57600080fd5b80634f6ccce7146105ed5780634ff7ff321461060d57806355f804b31461062d57600080fd5b80633ccfd60b1161022d5780633ccfd60b146105985780634209a2e1146105ad57806342842e0e146105cd57600080fd5b80632a55205a146105395780633aaed7b91461057857600080fd5b80630df1da8d116102aa57806321b02b641161028457806321b02b64146104cb57806323b872dd146104eb578063295a52121461050b57600080fd5b80630df1da8d146103f5578063150b7a021461044057806318160ddd146104b657600080fd5b8063081812fc116102db578063081812fc14610359578063095ea7b3146103915780630db6a786146103b357600080fd5b806301ffc9a71461030257806306fdde031461033757600080fd5b366102fd57005b600080fd5b34801561030e57600080fd5b5061032261031d3660046142d7565b6109b3565b60405190151581526020015b60405180910390f35b34801561034357600080fd5b5061034c610a16565b60405161032e919061436a565b34801561036557600080fd5b5061037961037436600461437d565b610aa8565b6040516001600160a01b03909116815260200161032e565b34801561039d57600080fd5b506103b16103ac3660046143ab565b610b53565b005b3480156103bf57600080fd5b506103e77f00000000000000000000000000000000000000000000000000000000620ffac081565b60405190815260200161032e565b34801561040157600080fd5b5061042e6104103660046143d7565b6001600160a01b03166000908152600c602052604090205460ff1690565b60405160ff909116815260200161032e565b34801561044c57600080fd5b5061048561045b3660046143f4565b7f150b7a020000000000000000000000000000000000000000000000000000000095945050505050565b6040517fffffffff00000000000000000000000000000000000000000000000000000000909116815260200161032e565b3480156104c257600080fd5b506103e7610c85565b3480156104d757600080fd5b506103b16104e63660046144a1565b610c94565b3480156104f757600080fd5b506103b16105063660046144be565b610d27565b34801561051757600080fd5b50600b5461052c90600160a01b900460ff1681565b60405161032e919061452e565b34801561054557600080fd5b5061055961055436600461456f565b610dae565b604080516001600160a01b03909316835260208301919091520161032e565b34801561058457600080fd5b506103b16105933660046143ab565b610e47565b3480156105a457600080fd5b506103b1611010565b3480156105b957600080fd5b506103b16105c836600461437d565b611188565b3480156105d957600080fd5b506103b16105e83660046144be565b6111e7565b3480156105f957600080fd5b506103e761060836600461437d565b611202565b34801561061957600080fd5b506103b16106283660046143d7565b611305565b34801561063957600080fd5b506103b1610648366004614685565b61148e565b34801561065957600080fd5b5061037961066836600461437d565b6114fb565b34801561067957600080fd5b50600b547501000000000000000000000000000000000000000000900461ffff166103e7565b3480156106ab57600080fd5b506103e76106ba3660046143d7565b611586565b3480156106cb57600080fd5b506103b1611620565b3480156106e057600080fd5b506103b16106ef3660046143d7565b611686565b34801561070057600080fd5b506103e77f00000000000000000000000000000000000000000000000000000000000007d081565b34801561073457600080fd5b506103e7670214e8348c4f000081565b34801561075057600080fd5b506103e77f00000000000000000000000000000000000000000000000000000000000007d081565b6103b16107863660046146ee565b61171a565b34801561079757600080fd5b506103e76107a63660046143d7565b6001600160a01b03166000908152600d602052604090205461ffff1690565b3480156107d157600080fd5b506103b16107e0366004614746565b611a99565b3480156107f157600080fd5b506103b161080036600461437d565b611e70565b34801561081157600080fd5b506006546001600160a01b0316610379565b34801561082f57600080fd5b5061034c6120b0565b34801561084457600080fd5b506103b161085336600461456f565b6120bf565b34801561086457600080fd5b506103e77f000000000000000000000000000000000000000000000000000000006234d6b081565b34801561089857600080fd5b506103b16108a73660046147ec565b612376565b3480156108b857600080fd5b506103e7600281565b3480156108cd57600080fd5b506103b16108dc366004614746565b612459565b3480156108ed57600080fd5b506103b16108fc36600461481a565b612756565b34801561090d57600080fd5b506103e760085481565b34801561092357600080fd5b5061034c61093236600461437d565b6127e4565b34801561094357600080fd5b50610322610952366004614886565b6128cd565b34801561096357600080fd5b506103b16109723660046143d7565b6129c7565b34801561098357600080fd5b506103b16109923660046143d7565b612aa9565b3480156109a357600080fd5b506103e767016345785d8a000081565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f2a55205a000000000000000000000000000000000000000000000000000000001415610a0757506001919050565b610a1082612c83565b92915050565b606060008054610a25906148b4565b80601f0160208091040260200160405190810160405280929190818152602001828054610a51906148b4565b8015610a9e5780601f10610a7357610100808354040283529160200191610a9e565b820191906000526020600020905b815481529060010190602001808311610a8157829003601f168201915b5050505050905090565b6000818152600260205260408120546001600160a01b0316610b375760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a20617070726f76656420717565727920666f72206e6f6e657860448201527f697374656e7420746f6b656e000000000000000000000000000000000000000060648201526084015b60405180910390fd5b506000908152600460205260409020546001600160a01b031690565b6000610b5e826114fb565b9050806001600160a01b0316836001600160a01b03161415610be85760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e6560448201527f72000000000000000000000000000000000000000000000000000000000000006064820152608401610b2e565b336001600160a01b0382161480610c045750610c0481336128cd565b610c765760405162461bcd60e51b815260206004820152603860248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f74206f7760448201527f6e6572206e6f7220617070726f76656420666f7220616c6c00000000000000006064820152608401610b2e565b610c808383612d66565b505050565b6000610c8f612dec565b905090565b6006546001600160a01b03163314610cee5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610b2e565b60128054911515600160a01b027fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff909216919091179055565b610d313382612e3f565b610da35760405162461bcd60e51b815260206004820152603160248201527f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f60448201527f776e6572206e6f7220617070726f7665640000000000000000000000000000006064820152608401610b2e565b610c80838383612f27565b60008281526002602052604081205481906001600160a01b0316610e145760405162461bcd60e51b815260206004820152601160248201527f6e6f7420612076616c696420746f6b656e0000000000000000000000000000006044820152606401610b2e565b6006546001600160a01b03166103e860105485610e319190614937565b610e3b91906149a3565b915091505b9250929050565b6006546001600160a01b03163314610ea15760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610b2e565b610ea9613117565b6001600b54600160a01b900460ff166004811115610ec957610ec96144ff565b1480610ef257506002600b54600160a01b900460ff166004811115610ef057610ef06144ff565b145b80610f1a57506004600b54600160a01b900460ff166004811115610f1857610f186144ff565b145b610f8c5760405162461bcd60e51b815260206004820152603e60248201527f6c6f636b656420756e74696c2074686572652061726520656e6f756768206d6560448201527f6d6265727320286f7220616674657220726566756e6420706572696f642900006064820152608401610b2e565b6040517f23b872dd000000000000000000000000000000000000000000000000000000008152306004820152336024820152604481018290526001600160a01b038316906323b872dd906064015b600060405180830381600087803b158015610ff457600080fd5b505af1158015611008573d6000803e3d6000fd5b505050505050565b6006546001600160a01b0316331461106a5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610b2e565b611072613117565b6001600b54600160a01b900460ff166004811115611092576110926144ff565b14806110bb57506002600b54600160a01b900460ff1660048111156110b9576110b96144ff565b145b806110e357506004600b54600160a01b900460ff1660048111156110e1576110e16144ff565b145b6111555760405162461bcd60e51b815260206004820152603e60248201527f6c6f636b656420756e74696c2074686572652061726520656e6f756768206d6560448201527f6d6265727320286f7220616674657220726566756e6420706572696f642900006064820152608401610b2e565b6040514790339082156108fc029083906000818181858888f19350505050158015611184573d6000803e3d6000fd5b5050565b6006546001600160a01b031633146111e25760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610b2e565b601055565b610c8083838360405180602001604052806000815250612756565b600b546000907501000000000000000000000000000000000000000000900461ffff16821061128357600b546112569083907501000000000000000000000000000000000000000000900461ffff166149b7565b611280907f00000000000000000000000000000000000000000000000000000000000007d06149ce565b91505b6112ae6112918360016149ce565b6000908152600260205260409020546001600160a01b0316151590565b6112fa5760405162461bcd60e51b815260206004820152600f60248201527f62616420746f6b656e20696e64657800000000000000000000000000000000006044820152606401610b2e565b610a108260016149ce565b6006546001600160a01b0316331461135f5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610b2e565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526000906001600160a01b038316906370a082319060240160206040518083038186803b1580156113ba57600080fd5b505afa1580156113ce573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113f291906149e6565b6040517fa9059cbb000000000000000000000000000000000000000000000000000000008152336004820152602481018290529091506001600160a01b0383169063a9059cbb90604401602060405180830381600087803b15801561145657600080fd5b505af115801561146a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c8091906149ff565b6006546001600160a01b031633146114e85760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610b2e565b805161118490600f906020840190614210565b6000818152600260205260408120546001600160a01b031680610a105760405162461bcd60e51b815260206004820152602960248201527f4552433732313a206f776e657220717565727920666f72206e6f6e657869737460448201527f656e7420746f6b656e00000000000000000000000000000000000000000000006064820152608401610b2e565b60006001600160a01b0382166116045760405162461bcd60e51b815260206004820152602a60248201527f4552433732313a2062616c616e636520717565727920666f7220746865207a6560448201527f726f2061646472657373000000000000000000000000000000000000000000006064820152608401610b2e565b506001600160a01b031660009081526003602052604090205490565b6006546001600160a01b0316331461167a5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610b2e565b6116846000613340565b565b6006546001600160a01b031633146116e05760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610b2e565b601180547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b6002600754141561176d5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610b2e565b600260075560ff81166117c25760405162461bcd60e51b815260206004820181905260248201527f6d697373696e67206e756d626572206f6620746f6b656e7320746f206d696e746044820152606401610b2e565b6117ca613117565b6000600b54600160a01b900460ff1660048111156117ea576117ea6144ff565b148061181357506001600b54600160a01b900460ff166004811115611811576118116144ff565b145b61185f5760405162461bcd60e51b815260206004820152601860248201527f6d696e74696e67206973206e6f7420617661696c61626c6500000000000000006044820152606401610b2e565b6008548160ff1661186e612dec565b61187891906149ce565b11156118c65760405162461bcd60e51b815260206004820181905260248201527f6e6f7420656e6f756768206d656d62657273686970732072656d61696e696e676044820152606401610b2e565b6118db60ff8216670214e8348c4f0000614937565b34146119295760405162461bcd60e51b815260206004820152601c60248201527f696e636f727265637420455448207061796d656e7420616d6f756e74000000006044820152606401610b2e565b61193382336133aa565b61197f5760405162461bcd60e51b815260206004820152601560248201527f796f75207365656d206c696b65206120726f626f7400000000000000000000006044820152606401610b2e565b336000908152600c602052604090205460ff16600261199e8383614a1c565b60ff161115611a155760405162461bcd60e51b815260206004820152602c60248201527f796f752063616e206f6e6c79206d696e742074776f206d656d6265727368697060448201527f73207065722077616c6c657400000000000000000000000000000000000000006064820152608401610b2e565b611a1f8282614a1c565b336000908152600c6020526040812080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff93909316929092179091555b8260ff16811015611a8e57611a7c33611a77613489565b6135a2565b80611a8681614a41565b915050611a60565b505060016007555050565b60026007541415611aec5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610b2e565b6002600755611af9613117565b6000600b54600160a01b900460ff166004811115611b1957611b196144ff565b1480611b4257506001600b54600160a01b900460ff166004811115611b4057611b406144ff565b145b611b8e5760405162461bcd60e51b815260206004820152601860248201527f6d696e74696e67206973206e6f7420617661696c61626c6500000000000000006044820152606401610b2e565b6008548151611b9e906003614937565b611ba6612dec565b611bb091906149ce565b1115611bfe5760405162461bcd60e51b815260206004820181905260248201527f6e6f7420656e6f756768206d656d62657273686970732072656d61696e696e676044820152606401610b2e565b6004815110611c755760405162461bcd60e51b815260206004820152602360248201527f6d6967726174696e6720746f6f206d616e7920696e20612073696e676c65206360448201527f616c6c00000000000000000000000000000000000000000000000000000000006064820152608401610b2e565b60005b8151811015611e67576000828281518110611c9557611c95614a7a565b602002602001015190507f00000000000000000000000000000000000000000000000000000000000000078111611d345760405162461bcd60e51b815260206004820152602360248201527f666f756e64696e67207465616d20746f6b656e732063616e6e6f74206d69677260448201527f61746500000000000000000000000000000000000000000000000000000000006064820152608401610b2e565b600b546040517f23b872dd000000000000000000000000000000000000000000000000000000008152336004820152306024820152604481018390526001600160a01b03909116906323b872dd90606401600060405180830381600087803b158015611d9f57600080fd5b505af1158015611db3573d6000803e3d6000fd5b50505050611dc98133611dc4613489565b6135f7565b611dd68133611dc4613489565b6000611de0613489565b9050611dec3082613642565b61ffff811660009081526009602052604080822080547fffffffffffffffffffffffff00000000000000000000000000000000000000001633908117909155905183927f9f45a4ef7adb5b3e01ef919bb93ad80a8b568e89d896412723d27db107ed1c2b91a350508080611e5f90614a41565b915050611c78565b50506001600755565b60026007541415611ec35760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610b2e565b600260075533611ed2826114fb565b6001600160a01b031614611f4e5760405162461bcd60e51b815260206004820152602160248201527f6f6e6c7920746865206f776e6572206d617920636c61696d206120726566756e60448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610b2e565b7f00000000000000000000000000000000000000000000000000000000000000078111611fe35760405162461bcd60e51b815260206004820152602860248201527f666f756e64696e67207465616d20746f6b656e7320646f206e6f74206765742060448201527f6120726566756e640000000000000000000000000000000000000000000000006064820152608401610b2e565b611feb613117565b6003600b54600160a01b900460ff16600481111561200b5761200b6144ff565b146120585760405162461bcd60e51b815260206004820152601a60248201527f726566756e64696e67206973206e6f7420617661696c61626c650000000000006044820152606401610b2e565b612061816137a8565b61206a81613865565b336108fc61208867016345785d8a0000670214e8348c4f00006149b7565b6040518115909202916000818181858888f19350505050158015611e67573d6000803e3d6000fd5b606060018054610a25906148b4565b600260075414156121125760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610b2e565b600260075533612121836114fb565b6001600160a01b03161461219d5760405162461bcd60e51b815260206004820152602160248201527f6f6e6c7920746865206f776e6572206d617920636c61696d206120726566756e60448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610b2e565b7f000000000000000000000000000000000000000000000000000000000000000782116122325760405162461bcd60e51b815260206004820152602860248201527f666f756e64696e67207465616d20746f6b656e7320646f206e6f74206765742060448201527f6120726566756e640000000000000000000000000000000000000000000000006064820152608401610b2e565b61223a613117565b6003600b54600160a01b900460ff16600481111561225a5761225a6144ff565b146122a75760405162461bcd60e51b815260206004820152601a60248201527f726566756e64696e67206973206e6f7420617661696c61626c650000000000006044820152606401610b2e565b6122b0826137a8565b600e546040517f23b872dd000000000000000000000000000000000000000000000000000000008152336004820152306024820152604481018390526001600160a01b03909116906323b872dd90606401600060405180830381600087803b15801561231b57600080fd5b505af115801561232f573d6000803e3d6000fd5b5050505061233c82613865565b6040513390600090670214e8348c4f00009082818181858883f1935050505015801561236c573d6000803e3d6000fd5b5050600160075550565b6001600160a01b0382163314156123cf5760405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c6572000000000000006044820152606401610b2e565b3360008181526005602090815260408083206001600160a01b0387168085529083529281902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b600260075414156124ac5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610b2e565b60026007556124b9613117565b6001600b54600160a01b900460ff1660048111156124d9576124d96144ff565b148061250257506002600b54600160a01b900460ff166004811115612500576125006144ff565b145b6125745760405162461bcd60e51b815260206004820152602a60248201527f746f6b656e2072656d61696e732070656e64696e6720756e74696c20706f737460448201527f2d7468726573686f6c64000000000000000000000000000000000000000000006064820152608401610b2e565b60088151106125eb5760405162461bcd60e51b815260206004820152602260248201527f636c61696d696e6720746f6f206d616e7920696e20612073696e676c6520636160448201527f6c6c0000000000000000000000000000000000000000000000000000000000006064820152608401610b2e565b60005b8151811015611e6757600082828151811061260b5761260b614a7a565b60209081029190910181015161ffff8116600090815260099092526040909120549091506001600160a01b0316806126855760405162461bcd60e51b815260206004820152601d60248201527f746f6b656e206973206e6f742070656e64696e67207472616e736665720000006044820152606401610b2e565b61ffff8216600090815260096020526040902080547fffffffffffffffffffffffff00000000000000000000000000000000000000001690556126c9308284612f27565b600e546040517f755edd170000000000000000000000000000000000000000000000000000000081526001600160a01b0383811660048301529091169063755edd1790602401600060405180830381600087803b15801561272957600080fd5b505af115801561273d573d6000803e3d6000fd5b505050505050808061274e90614a41565b9150506125ee565b6127603383612e3f565b6127d25760405162461bcd60e51b815260206004820152603160248201527f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f60448201527f776e6572206e6f7220617070726f7665640000000000000000000000000000006064820152608401610b2e565b6127de84848484613924565b50505050565b6000818152600260205260409020546060906001600160a01b03166128715760405162461bcd60e51b815260206004820152602f60248201527f4552433732314d657461646174613a2055524920717565727920666f72206e6f60448201527f6e6578697374656e7420746f6b656e00000000000000000000000000000000006064820152608401610b2e565b600061287b6139ad565b9050600081511161289b57604051806020016040528060008152506128c6565b806128a5846139bc565b6040516020016128b6929190614aa9565b6040516020818303038152906040525b9392505050565b601254600090600160a01b900460ff1615612998576012546040517fc45527910000000000000000000000000000000000000000000000000000000081526001600160a01b03858116600483015291821691841690829063c45527919060240160206040518083038186803b15801561294557600080fd5b505afa158015612959573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061297d9190614ad8565b6001600160a01b03161415612996576001915050610a10565b505b506001600160a01b03918216600090815260056020908152604080832093909416825291909152205460ff1690565b6006546001600160a01b03163314612a215760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610b2e565b6001600160a01b038116612a9d5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610b2e565b612aa681613340565b50565b6006546001600160a01b03163314612b035760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610b2e565b600e546001600160a01b031615612b825760405162461bcd60e51b815260206004820152602260248201527f696e697469616c206172742073616c6520616c7265616479207370656369666960448201527f65640000000000000000000000000000000000000000000000000000000000006064820152608401610b2e565b600e80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b03831617905560005b7f000000000000000000000000000000000000000000000000000000000000000781101561118457600e546001600160a01b031663755edd17612bff6106688460016149ce565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b1681526001600160a01b039091166004820152602401600060405180830381600087803b158015612c5857600080fd5b505af1158015612c6c573d6000803e3d6000fd5b505050508080612c7b90614a41565b915050612bb8565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f80ac58cd000000000000000000000000000000000000000000000000000000001480612d1657507fffffffff0000000000000000000000000000000000000000000000000000000082167f5b5e139f00000000000000000000000000000000000000000000000000000000145b80610a1057507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000831614610a10565b600081815260046020526040902080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0384169081179091558190612db3826114fb565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b600b54600090612e369061ffff7701000000000000000000000000000000000000000000000082048116917501000000000000000000000000000000000000000000900416614af5565b61ffff16905090565b6000818152600260205260408120546001600160a01b0316612ec95760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a206f70657261746f7220717565727920666f72206e6f6e657860448201527f697374656e7420746f6b656e00000000000000000000000000000000000000006064820152608401610b2e565b6000612ed4836114fb565b9050806001600160a01b0316846001600160a01b03161480612f0f5750836001600160a01b0316612f0484610aa8565b6001600160a01b0316145b80612f1f5750612f1f81856128cd565b949350505050565b826001600160a01b0316612f3a826114fb565b6001600160a01b031614612fb65760405162461bcd60e51b815260206004820152602960248201527f4552433732313a207472616e73666572206f6620746f6b656e2074686174206960448201527f73206e6f74206f776e00000000000000000000000000000000000000000000006064820152608401610b2e565b6001600160a01b0382166130315760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f2061646460448201527f72657373000000000000000000000000000000000000000000000000000000006064820152608401610b2e565b61303c838383613aee565b613047600082612d66565b6001600160a01b03831660009081526003602052604081208054600192906130709084906149b7565b90915550506001600160a01b038216600090815260036020526040812080546001929061309e9084906149ce565b909155505060008181526002602052604080822080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0386811691821790925591518493918716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b6002600b54600160a01b900460ff166004811115613137576131376144ff565b141561313f57565b6000613149612dec565b90507f00000000000000000000000000000000000000000000000000000000620ffac0421015801561319b57507f00000000000000000000000000000000000000000000000000000000000007d08110155b156131a65760088190555b60085481106131e857600b8054600291907fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16600160a01b835b021790555050565b7f00000000000000000000000000000000000000000000000000000000000007d0811061324457600b8054600191907fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16600160a01b836131e0565b7f00000000000000000000000000000000000000000000000000000000620ffac04210156132a157600b8054600091907fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16600160a01b836131e0565b7f000000000000000000000000000000000000000000000000000000006234d6b04210156132fe57600b8054600391907fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16600160a01b836131e0565b50600b80547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674040000000000000000000000000000000000000000179055565b600680546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b604080517f6d656d6265720000000000000000000000000000000000000000000000000000602080830191909152606084901b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001660268301528251601a818403018152603a830184528051908201207f19457468657265756d205369676e6564204d6573736167653a0a333200000000605a8401526076808401829052845180850390910181526096909301909352815191012060009190829061346f9086613bcd565b6011546001600160a01b0390811691161495945050505050565b600b546000907f00000000000000000000000000000000000000000000000000000000000007d0750100000000000000000000000000000000000000000090910461ffff161015613528576001600b60158282829054906101000a900461ffff166134f49190614af5565b92506101000a81548161ffff021916908361ffff160217905550600b60159054906101000a900461ffff1661ffff16905090565b6001600b60178282829054906101000a900461ffff166135489190614af5565b92506101000a81548161ffff021916908361ffff1602179055507f00000000000000000000000000000000000000000000000000000000000007d0600b60179054906101000a900461ffff1661ffff16610c8f91906149ce565b6135ac8282613bf1565b600e546040517f755edd170000000000000000000000000000000000000000000000000000000081526001600160a01b0384811660048301529091169063755edd1790602401610fda565b61ffff8181166000908152600a6020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000016918516919091179055610c8082826135a2565b6001600160a01b0382166136985760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f20616464726573736044820152606401610b2e565b6000818152600260205260409020546001600160a01b0316156136fd5760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e746564000000006044820152606401610b2e565b61370960008383613aee565b6001600160a01b03821660009081526003602052604081208054600192906137329084906149ce565b909155505060008181526002602052604080822080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b03861690811790915590518392907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b61ffff8082166000908152600a602052604090205416801561118457600b546040517f278ecde100000000000000000000000000000000000000000000000000000000815261ffff831660048201526001600160a01b039091169063278ecde190602401600060405180830381600087803b15801561382657600080fd5b505af1925050508015613837575060015b611184573d8080156127de576040519150601f19603f3d011682016040523d82523d6000602084013e6127de565b6000613870826114fb565b905061387e81600084613aee565b613889600083612d66565b6001600160a01b03811660009081526003602052604081208054600192906138b29084906149b7565b909155505060008281526002602052604080822080547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055518391906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45050565b61392f848484612f27565b61393b84848484613c0b565b6127de5760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527f63656976657220696d706c656d656e74657200000000000000000000000000006064820152608401610b2e565b6060600f8054610a25906148b4565b6060816139fc57505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b8115613a265780613a1081614a41565b9150613a1f9050600a836149a3565b9150613a00565b60008167ffffffffffffffff811115613a4157613a41614591565b6040519080825280601f01601f191660200182016040528015613a6b576020820181803683370190505b5090505b8415612f1f57613a806001836149b7565b9150613a8d600a86614b12565b613a989060306149ce565b60f81b818381518110613aad57613aad614a7a565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350613ae7600a866149a3565b9450613a6f565b7f00000000000000000000000000000000000000000000000000000000000007d0811115613b1b57505050565b6001600160a01b03831615613b72576001600160a01b0383166000908152600d60205260408120805460019290613b5790849061ffff16614b26565b92506101000a81548161ffff021916908361ffff1602179055505b6001600160a01b03821615610c80576001600160a01b0382166000908152600d60205260408120805460019290613bae90849061ffff16614af5565b92506101000a81548161ffff021916908361ffff160217905550505050565b6000806000613bdc8585613dd6565b91509150613be981613e43565b509392505050565b611184828260405180602001604052806000815250614034565b60006001600160a01b0384163b15613dcb576040517f150b7a020000000000000000000000000000000000000000000000000000000081526001600160a01b0385169063150b7a0290613c68903390899088908890600401614b49565b602060405180830381600087803b158015613c8257600080fd5b505af1925050508015613cd0575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201909252613ccd91810190614b85565b60015b613d80573d808015613cfe576040519150601f19603f3d011682016040523d82523d6000602084013e613d03565b606091505b508051613d785760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527f63656976657220696d706c656d656e74657200000000000000000000000000006064820152608401610b2e565b805181602001fd5b7fffffffff00000000000000000000000000000000000000000000000000000000167f150b7a0200000000000000000000000000000000000000000000000000000000149050612f1f565b506001949350505050565b600080825160411415613e0d5760208301516040840151606085015160001a613e01878285856140bd565b94509450505050610e40565b825160401415613e375760208301516040840151613e2c8683836141c8565b935093505050610e40565b50600090506002610e40565b6000816004811115613e5757613e576144ff565b1415613e605750565b6001816004811115613e7457613e746144ff565b1415613ec25760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e617475726500000000000000006044820152606401610b2e565b6002816004811115613ed657613ed66144ff565b1415613f245760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606401610b2e565b6003816004811115613f3857613f386144ff565b1415613fac5760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c60448201527f75650000000000000000000000000000000000000000000000000000000000006064820152608401610b2e565b6004816004811115613fc057613fc06144ff565b1415612aa65760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202776272076616c60448201527f75650000000000000000000000000000000000000000000000000000000000006064820152608401610b2e565b61403e8383613642565b61404b6000848484613c0b565b610c805760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527f63656976657220696d706c656d656e74657200000000000000000000000000006064820152608401610b2e565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08311156140f457506000905060036141bf565b8460ff16601b1415801561410c57508460ff16601c14155b1561411d57506000905060046141bf565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015614171573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001519150506001600160a01b0381166141b8576000600192509250506141bf565b9150600090505b94509492505050565b6000807f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff831660ff84901c601b01614202878288856140bd565b935093505050935093915050565b82805461421c906148b4565b90600052602060002090601f01602090048101928261423e5760008555614284565b82601f1061425757805160ff1916838001178555614284565b82800160010185558215614284579182015b82811115614284578251825591602001919060010190614269565b50614290929150614294565b5090565b5b808211156142905760008155600101614295565b7fffffffff0000000000000000000000000000000000000000000000000000000081168114612aa657600080fd5b6000602082840312156142e957600080fd5b81356128c6816142a9565b60005b8381101561430f5781810151838201526020016142f7565b838111156127de5750506000910152565b600081518084526143388160208601602086016142f4565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006128c66020830184614320565b60006020828403121561438f57600080fd5b5035919050565b6001600160a01b0381168114612aa657600080fd5b600080604083850312156143be57600080fd5b82356143c981614396565b946020939093013593505050565b6000602082840312156143e957600080fd5b81356128c681614396565b60008060008060006080868803121561440c57600080fd5b853561441781614396565b9450602086013561442781614396565b935060408601359250606086013567ffffffffffffffff8082111561444b57600080fd5b818801915088601f83011261445f57600080fd5b81358181111561446e57600080fd5b89602082850101111561448057600080fd5b9699959850939650602001949392505050565b8015158114612aa657600080fd5b6000602082840312156144b357600080fd5b81356128c681614493565b6000806000606084860312156144d357600080fd5b83356144de81614396565b925060208401356144ee81614396565b929592945050506040919091013590565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b6020810160058310614569577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b91905290565b6000806040838503121561458257600080fd5b50508035926020909101359150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561460757614607614591565b604052919050565b600067ffffffffffffffff83111561462957614629614591565b61465a60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f860116016145c0565b905082815283838301111561466e57600080fd5b828260208301376000602084830101529392505050565b60006020828403121561469757600080fd5b813567ffffffffffffffff8111156146ae57600080fd5b8201601f810184136146bf57600080fd5b612f1f8482356020840161460f565b600082601f8301126146df57600080fd5b6128c68383356020850161460f565b6000806040838503121561470157600080fd5b823567ffffffffffffffff81111561471857600080fd5b614724858286016146ce565b925050602083013560ff8116811461473b57600080fd5b809150509250929050565b6000602080838503121561475957600080fd5b823567ffffffffffffffff8082111561477157600080fd5b818501915085601f83011261478557600080fd5b81358181111561479757614797614591565b8060051b91506147a88483016145c0565b81815291830184019184810190888411156147c257600080fd5b938501935b838510156147e0578435825293850193908501906147c7565b98975050505050505050565b600080604083850312156147ff57600080fd5b823561480a81614396565b9150602083013561473b81614493565b6000806000806080858703121561483057600080fd5b843561483b81614396565b9350602085013561484b81614396565b925060408501359150606085013567ffffffffffffffff81111561486e57600080fd5b61487a878288016146ce565b91505092959194509250565b6000806040838503121561489957600080fd5b82356148a481614396565b9150602083013561473b81614396565b600181811c908216806148c857607f821691505b60208210811415614902577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561496f5761496f614908565b500290565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000826149b2576149b2614974565b500490565b6000828210156149c9576149c9614908565b500390565b600082198211156149e1576149e1614908565b500190565b6000602082840312156149f857600080fd5b5051919050565b600060208284031215614a1157600080fd5b81516128c681614493565b600060ff821660ff84168060ff03821115614a3957614a39614908565b019392505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821415614a7357614a73614908565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008351614abb8184602088016142f4565b835190830190614acf8183602088016142f4565b01949350505050565b600060208284031215614aea57600080fd5b81516128c681614396565b600061ffff808316818516808303821115614acf57614acf614908565b600082614b2157614b21614974565b500690565b600061ffff83811690831681811015614b4157614b41614908565b039392505050565b60006001600160a01b03808716835280861660208401525083604083015260806060830152614b7b6080830184614320565b9695505050505050565b600060208284031215614b9757600080fd5b81516128c6816142a956fea2646970667358221220c8955f5b951296a65b4c7e1ae2528e0239b369de5887de470d91fd51c3d54c1664736f6c63430008090033

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

00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000138800000000000000000000000000000000000000000000000000000000000007d000000000000000000000000000000000000000000000000000000000000007d000000000000000000000000000000000000000000000000000000000620ffac0000000000000000000000000000000000000000000000000000000006234d6b0000000000000000000000000000000000000000000000000000000000000004b000000000000000000000000acce5556a5db4a0fc4769ad87fd673ef61b9c4a1000000000000000000000000a5409ec958c83c3f309868babaca7c86dcb077c1000000000000000000000000d3426b1e7f7cde3948368318df9c0fd1ae21e8270000000000000000000000000000000000000000000000000000000000000007000000000000000000000000155814ac8095111566f614819acfc2b59fce3a7100000000000000000000000097f47b2dea15c5eb4ce06c7b90857593545d110800000000000000000000000041e2e49f809963636c6cda9789a5e163991b04e000000000000000000000000024598829930ba2d947fe6ebeea30c662739ce81b00000000000000000000000062ad3bd57596c5836420c53275d4e78a5e95bcee0000000000000000000000006ae5b9b1ae8df7b0b90edae05d4788950b0a6cfd00000000000000000000000002a166016d28b9de68143b368568d642a8d226d9

-----Decoded View---------------
Arg [0] : config (tuple):
Arg [1] : foundingTeam (address[]): 0x155814ac8095111566f614819ACFC2B59FCe3a71,0x97f47b2deA15c5Eb4Ce06C7B90857593545d1108,0x41e2e49f809963636c6CdA9789A5E163991B04E0,0x24598829930bA2D947Fe6ebeea30C662739Ce81B,0x62Ad3bd57596C5836420c53275D4E78a5e95bCEE,0x6aE5B9b1aE8dF7b0b90edae05d4788950B0a6cFd,0x02A166016D28B9De68143b368568d642A8D226d9
Arg [2] : maximumTotalMemberCount (uint256): 5000
Arg [3] : maximumGoldMemberCount (uint256): 2000
Arg [4] : enoughMembersToProceed (uint256): 2000
Arg [5] : salesDeadline (uint256): 1645214400
Arg [6] : refundDeadline (uint256): 1647630000
Arg [7] : royaltyPerMille (uint256): 75
Arg [8] : captchaSigner (address): 0xACCE5556A5Db4a0Fc4769AD87Fd673ef61b9c4a1
Arg [9] : openSeaProxyRegistry (address): 0xa5409ec958C83C3f309868babACA7c86DCB077c1
Arg [10] : oldMemberK (address): 0xd3426B1E7f7CdE3948368318df9C0fd1Ae21E827


-----Encoded View---------------
19 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000020
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000140
Arg [2] : 0000000000000000000000000000000000000000000000000000000000001388
Arg [3] : 00000000000000000000000000000000000000000000000000000000000007d0
Arg [4] : 00000000000000000000000000000000000000000000000000000000000007d0
Arg [5] : 00000000000000000000000000000000000000000000000000000000620ffac0
Arg [6] : 000000000000000000000000000000000000000000000000000000006234d6b0
Arg [7] : 000000000000000000000000000000000000000000000000000000000000004b
Arg [8] : 000000000000000000000000acce5556a5db4a0fc4769ad87fd673ef61b9c4a1
Arg [9] : 000000000000000000000000a5409ec958c83c3f309868babaca7c86dcb077c1
Arg [10] : 000000000000000000000000d3426b1e7f7cde3948368318df9c0fd1ae21e827
Arg [11] : 0000000000000000000000000000000000000000000000000000000000000007
Arg [12] : 000000000000000000000000155814ac8095111566f614819acfc2b59fce3a71
Arg [13] : 00000000000000000000000097f47b2dea15c5eb4ce06c7b90857593545d1108
Arg [14] : 00000000000000000000000041e2e49f809963636c6cda9789a5e163991b04e0
Arg [15] : 00000000000000000000000024598829930ba2d947fe6ebeea30c662739ce81b
Arg [16] : 00000000000000000000000062ad3bd57596c5836420c53275d4e78a5e95bcee
Arg [17] : 0000000000000000000000006ae5b9b1ae8df7b0b90edae05d4788950b0a6cfd
Arg [18] : 00000000000000000000000002a166016d28b9de68143b368568d642a8d226d9


Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export  ]
[ Download: CSV Export  ]

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.