ETH Price: $2,388.76 (-0.41%)

Token

Black Square (BLACKSQUARE)
 

Overview

Max Total Supply

72 BLACKSQUARE

Holders

36

Market

Volume (24H)

N/A

Min Price (24H)

N/A

Max Price (24H)

N/A
Filtered by Token Holder
theblacktoad.eth
Balance
1 BLACKSQUARE
0x19fee090c8d88b07e1d18e55b4393b8b6c532fe9
Loading...
Loading
Loading...
Loading
Loading...
Loading

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

Contract Source Code Verified (Exact Match)

Contract Name:
BlackSquare

Compiler Version
v0.8.9+commit.e5eed63a

Optimization Enabled:
No with 200 runs

Other Settings:
default evmVersion
File 1 of 25 : BlackSquare.sol
// SPDX-License-Identifier: UNLICENSED
// Copyright 2021; All rights reserved
// Author: 0x99c520ed5a5e57b2128737531f5626d026ea39f20960b0e750077b9768543949
pragma solidity >=0.8.0 <0.9.0;

import "./ERC721Common.sol";
import "./BlackSquareRandomAttributes.sol";
import "base64-sol/base64.sol";
import "@openzeppelin/contracts/finance/PaymentSplitter.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "@openzeppelin/contracts/utils/Strings.sol";

contract BlackSquare is ERC721Common, ReentrancyGuard {
    using Base64 for string;
    
    /// @notice Constants defining numbers and prices of tokens.
    uint256 immutable public MAX_TOKENS;
    uint256 constant public MINT_PRICE = 0.1 ether;
    uint256 constant public MAX_PER_ADDRESS = 10;

    /// @notice An instance of RandomAttributes.sol responsible for allocating
    /// metadata attributes after the call to setEntropy().
    BlackSquareRandomAttributes immutable public attrs;

    /// @notice An escrow contract to split revenues.
    PaymentSplitter public paymentSplitter;

    constructor(
        string memory name,
        string memory symbol,
        address openSeaProxyRegistry,
        uint256 maxTokens,
        address payable _paymentSplitter
    )
        ERC721Common(name, symbol, openSeaProxyRegistry)
    {
        attrs = new BlackSquareRandomAttributes(maxTokens);
        paymentSplitter = PaymentSplitter(_paymentSplitter);
        MAX_TOKENS = maxTokens;
    }

    /// @notice Tracks the number of tokens already minted by an address,
    /// regardless of transferring out.
    mapping(address => uint) public minted;

    /// @notice Mint the specified number of tokens to the sender.
    /// @dev Reduces n if the origin or sender has already minted tokens or if
    // the total supply is insufficient. The cost is then calculated and the
    /// excess is reimbursed. Although it's possible for someone to set up
    /// multiple wallets, this was a minimal requirement included in the spec.
    function safeMint(uint256 n) nonReentrant payable public {
        /**
         * ##### CHECKS
         */
        n = _capExtra(n, msg.sender, "Sender limit");
        // Enforce the limit even if proxying through a contract.
        if (msg.sender != tx.origin) {
            n = _capExtra(n, tx.origin, "Origin limit");
        }
        
        uint256 nextTokenId = totalSupply();
        uint256 left = MAX_TOKENS - nextTokenId;
        require (left > 0, "Sold out");
        if (n > left) {
            n = left;
        }

        uint256 cost = n * MINT_PRICE;
        require(msg.value >= cost, "Insufficient payment");

        /**
         * ##### EFFECTS
         */
        minted[msg.sender] += n;
        if (msg.sender != tx.origin) {
            minted[tx.origin] += n;
        }

        for (uint end = nextTokenId + n; nextTokenId < end; nextTokenId++) {
            _safeMint(msg.sender, nextTokenId);
        }

        /**
         * ##### INTERACTIONS (also nonReentrant)
         */
        payable(paymentSplitter).transfer(cost);
        
        if (msg.value > cost) {
            address payable reimburse = payable(msg.sender);
            reimburse.transfer(msg.value - cost);
        }
    }

    /// @notice Changes the address of the PaymentSplitter contract.
    function setPaymentSplitter(address payable _paymentSplitter) onlyOwner external {
        paymentSplitter = PaymentSplitter(_paymentSplitter);
    }

    /// @notice Returns min(n, max(extra tokens addr can mint)).
    function _capExtra(uint256 n, address addr, string memory zeroMsg) internal view returns (uint256) {
        uint256 extra = MAX_PER_ADDRESS - minted[addr];
        require (extra > 0, zeroMsg);
        if (n > extra) {
            return extra;
        }
        return n;
    }

    /// @notice Sets the entropy source for deciding on random attributes.
    /// @dev This MUST be set after all tokens are minted so minters can't cheat
    /// the system, and MUST also be a value out of our control; in the absence
    /// of a VRF, a good choice is the block hash of the first block after final
    /// token mint.
    function setEntropy(bytes32 entropy) onlyOwner external {
        attrs.setEntropy(entropy);
    }

    /// @notice Returns the value passed to setEntropy() or 0 if not already
    /// called.
    function getEntropy() external view returns (bytes32) {
        return attrs.getEntropy();
    }

    /// @notice Exposes RandomAttributes._newTieredTrait().
    function newTieredTrait(uint index, RandomAttributes.TieredTrait memory trait) onlyOwner public {
        attrs._newTieredTrait(index, trait);
    }

    /// @notice Exposes RandomAttributes._newAllocatedTrait(), allowing for
    /// multiple allocations to be passed in a single call.
    function newAllocatedTraits(uint firstIndex, RandomAttributes.Allocated[] memory alloc) onlyOwner public {
        for (uint i = 0; i < alloc.length; i++) {
            attrs._newAllocatedTrait(firstIndex+i, alloc[i]);
        }
    }

    /// @notice Returns the number equivalent to a basis point (0.01%) as used
    /// by RandomAttributes.
    function basisPoint() external view returns (uint256) {
        return attrs.BASIS_POINT();
    }

    /// @notice Returns the token's metadata. This will change after the call to
    /// setEntropy(), after which it will be immutable.
    function tokenURI(uint256 tokenId) override public view returns (string memory) {
        require (ERC721._exists(tokenId), "Token doesn't exist");

        bytes memory json = abi.encodePacked(
            '{',
                '"name": "', name(), ' #', Strings.toString(tokenId), '",',
                '"image": "data:image/svg+xml;base64,',
                    'PHN2ZyB3aWR0aD0iMTQwMCIgaGVpZ2h0PSIxNDAwIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcv',
                    'MjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIj48cmVj',
                    'dCB3aWR0aD0iMTQwMCIgaGVpZ2h0PSIxNDAwIiBzdHlsZT0iZmlsbDpyZ2IoMCwwLDApO3N0cm9r',
                    'ZS13aWlkdGg6MCIgLz48L3N2Zz4=",',
                '"attributes": ['
        );

        if (attrs.entropySet()) {
            json = abi.encodePacked(
                json,
                '{"value": "The world is better with you in it"}',
                attrs._attributesOf(tokenId)
            );
        } else {
            json = abi.encodePacked(json, '{"value": "AWGMI?"}');
        }

        json = abi.encodePacked(
            json,
                ']',
            '}'
        );

        return string(abi.encodePacked(
            "data:application/json;base64,", Base64.encode(json)
        ));
    }
}

File 2 of 25 : base64.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0;

/// @title Base64
/// @author Brecht Devos - <[email protected]>
/// @notice Provides functions for encoding/decoding base64
library Base64 {
    string internal constant TABLE_ENCODE = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
    bytes  internal constant TABLE_DECODE = hex"0000000000000000000000000000000000000000000000000000000000000000"
                                            hex"00000000000000000000003e0000003f3435363738393a3b3c3d000000000000"
                                            hex"00000102030405060708090a0b0c0d0e0f101112131415161718190000000000"
                                            hex"001a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132330000000000";

    function encode(bytes memory data) internal pure returns (string memory) {
        if (data.length == 0) return '';

        // load the table into memory
        string memory table = TABLE_ENCODE;

        // multiply by 4/3 rounded up
        uint256 encodedLen = 4 * ((data.length + 2) / 3);

        // add some extra buffer at the end required for the writing
        string memory result = new string(encodedLen + 32);

        assembly {
            // set the actual output length
            mstore(result, encodedLen)

            // prepare the lookup table
            let tablePtr := add(table, 1)

            // input ptr
            let dataPtr := data
            let endPtr := add(dataPtr, mload(data))

            // result ptr, jump over length
            let resultPtr := add(result, 32)

            // run over the input, 3 bytes at a time
            for {} lt(dataPtr, endPtr) {}
            {
                // read 3 bytes
                dataPtr := add(dataPtr, 3)
                let input := mload(dataPtr)

                // write 4 characters
                mstore8(resultPtr, mload(add(tablePtr, and(shr(18, input), 0x3F))))
                resultPtr := add(resultPtr, 1)
                mstore8(resultPtr, mload(add(tablePtr, and(shr(12, input), 0x3F))))
                resultPtr := add(resultPtr, 1)
                mstore8(resultPtr, mload(add(tablePtr, and(shr( 6, input), 0x3F))))
                resultPtr := add(resultPtr, 1)
                mstore8(resultPtr, mload(add(tablePtr, and(        input,  0x3F))))
                resultPtr := add(resultPtr, 1)
            }

            // padding with '='
            switch mod(mload(data), 3)
            case 1 { mstore(sub(resultPtr, 2), shl(240, 0x3d3d)) }
            case 2 { mstore(sub(resultPtr, 1), shl(248, 0x3d)) }
        }

        return result;
    }

    function decode(string memory _data) internal pure returns (bytes memory) {
        bytes memory data = bytes(_data);

        if (data.length == 0) return new bytes(0);
        require(data.length % 4 == 0, "invalid base64 decoder input");

        // load the table into memory
        bytes memory table = TABLE_DECODE;

        // every 4 characters represent 3 bytes
        uint256 decodedLen = (data.length / 4) * 3;

        // add some extra buffer at the end required for the writing
        bytes memory result = new bytes(decodedLen + 32);

        assembly {
            // padding with '='
            let lastBytes := mload(add(data, mload(data)))
            if eq(and(lastBytes, 0xFF), 0x3d) {
                decodedLen := sub(decodedLen, 1)
                if eq(and(lastBytes, 0xFFFF), 0x3d3d) {
                    decodedLen := sub(decodedLen, 1)
                }
            }

            // set the actual output length
            mstore(result, decodedLen)

            // prepare the lookup table
            let tablePtr := add(table, 1)

            // input ptr
            let dataPtr := data
            let endPtr := add(dataPtr, mload(data))

            // result ptr, jump over length
            let resultPtr := add(result, 32)

            // run over the input, 4 characters at a time
            for {} lt(dataPtr, endPtr) {}
            {
               // read 4 characters
               dataPtr := add(dataPtr, 4)
               let input := mload(dataPtr)

               // write 3 bytes
               let output := add(
                   add(
                       shl(18, and(mload(add(tablePtr, and(shr(24, input), 0xFF))), 0xFF)),
                       shl(12, and(mload(add(tablePtr, and(shr(16, input), 0xFF))), 0xFF))),
                   add(
                       shl( 6, and(mload(add(tablePtr, and(shr( 8, input), 0xFF))), 0xFF)),
                               and(mload(add(tablePtr, and(        input , 0xFF))), 0xFF)
                    )
                )
                mstore(resultPtr, shl(232, output))
                resultPtr := add(resultPtr, 3)
            }
        }

        return result;
    }
}

File 3 of 25 : SafeMath.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

// CAUTION
// This version of SafeMath should only be used with Solidity 0.8 or later,
// because it relies on the compiler's built in overflow checks.

/**
 * @dev Wrappers over Solidity's arithmetic operations.
 *
 * NOTE: `SafeMath` is no longer needed starting with Solidity 0.8. The compiler
 * now has built in overflow checking.
 */
library SafeMath {
    /**
     * @dev Returns the addition of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            uint256 c = a + b;
            if (c < a) return (false, 0);
            return (true, c);
        }
    }

    /**
     * @dev Returns the substraction of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (b > a) return (false, 0);
            return (true, a - b);
        }
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
            // benefit is lost if 'b' is also tested.
            // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
            if (a == 0) return (true, 0);
            uint256 c = a * b;
            if (c / a != b) return (false, 0);
            return (true, c);
        }
    }

    /**
     * @dev Returns the division of two unsigned integers, with a division by zero flag.
     *
     * _Available since v3.4._
     */
    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (b == 0) return (false, 0);
            return (true, a / b);
        }
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
     *
     * _Available since v3.4._
     */
    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (b == 0) return (false, 0);
            return (true, a % b);
        }
    }

    /**
     * @dev Returns the addition of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `+` operator.
     *
     * Requirements:
     *
     * - Addition cannot overflow.
     */
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        return a + b;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting on
     * overflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        return a - b;
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `*` operator.
     *
     * Requirements:
     *
     * - Multiplication cannot overflow.
     */
    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        return a * b;
    }

    /**
     * @dev Returns the integer division of two unsigned integers, reverting on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator.
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        return a / b;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * reverting when dividing by zero.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function mod(uint256 a, uint256 b) internal pure returns (uint256) {
        return a % b;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
     * overflow (when the result is negative).
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {trySub}.
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(
        uint256 a,
        uint256 b,
        string memory errorMessage
    ) internal pure returns (uint256) {
        unchecked {
            require(b <= a, errorMessage);
            return a - b;
        }
    }

    /**
     * @dev Returns the integer division of two unsigned integers, reverting with custom message on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(
        uint256 a,
        uint256 b,
        string memory errorMessage
    ) internal pure returns (uint256) {
        unchecked {
            require(b > 0, errorMessage);
            return a / b;
        }
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * reverting with custom message when dividing by zero.
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {tryMod}.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function mod(
        uint256 a,
        uint256 b,
        string memory errorMessage
    ) internal pure returns (uint256) {
        unchecked {
            require(b > 0, errorMessage);
            return a % b;
        }
    }
}

File 4 of 25 : IERC165.sol
// 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 5 of 25 : ERC165.sol
// 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;
    }
}

File 6 of 25 : Strings.sol
// 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);
    }
}

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

File 8 of 25 : Address.sol
// 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);
            }
        }
    }
}

File 9 of 25 : IERC721Metadata.sol
// 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);
}

File 10 of 25 : IERC721Enumerable.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "../IERC721.sol";

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

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

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

File 11 of 25 : ERC721Pausable.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "../ERC721.sol";
import "../../../security/Pausable.sol";

/**
 * @dev ERC721 token with pausable token transfers, minting and burning.
 *
 * Useful for scenarios such as preventing trades until the end of an evaluation
 * period, or having an emergency switch for freezing all token transfers in the
 * event of a large bug.
 */
abstract contract ERC721Pausable is ERC721, Pausable {
    /**
     * @dev See {ERC721-_beforeTokenTransfer}.
     *
     * Requirements:
     *
     * - the contract must not be paused.
     */
    function _beforeTokenTransfer(
        address from,
        address to,
        uint256 tokenId
    ) internal virtual override {
        super._beforeTokenTransfer(from, to, tokenId);

        require(!paused(), "ERC721Pausable: token transfer while paused");
    }
}

File 12 of 25 : ERC721Enumerable.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "../ERC721.sol";
import "./IERC721Enumerable.sol";

/**
 * @dev This implements an optional extension of {ERC721} defined in the EIP that adds
 * enumerability of all the token ids in the contract as well as all token ids owned by each
 * account.
 */
abstract contract ERC721Enumerable is ERC721, IERC721Enumerable {
    // Mapping from owner to list of owned token IDs
    mapping(address => mapping(uint256 => uint256)) private _ownedTokens;

    // Mapping from token ID to index of the owner tokens list
    mapping(uint256 => uint256) private _ownedTokensIndex;

    // Array with all token ids, used for enumeration
    uint256[] private _allTokens;

    // Mapping from token id to position in the allTokens array
    mapping(uint256 => uint256) private _allTokensIndex;

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

    /**
     * @dev See {IERC721Enumerable-tokenOfOwnerByIndex}.
     */
    function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual override returns (uint256) {
        require(index < ERC721.balanceOf(owner), "ERC721Enumerable: owner index out of bounds");
        return _ownedTokens[owner][index];
    }

    /**
     * @dev See {IERC721Enumerable-totalSupply}.
     */
    function totalSupply() public view virtual override returns (uint256) {
        return _allTokens.length;
    }

    /**
     * @dev See {IERC721Enumerable-tokenByIndex}.
     */
    function tokenByIndex(uint256 index) public view virtual override returns (uint256) {
        require(index < ERC721Enumerable.totalSupply(), "ERC721Enumerable: global index out of bounds");
        return _allTokens[index];
    }

    /**
     * @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` cannot be the zero address.
     * - `to` cannot be the zero address.
     *
     * 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 override {
        super._beforeTokenTransfer(from, to, tokenId);

        if (from == address(0)) {
            _addTokenToAllTokensEnumeration(tokenId);
        } else if (from != to) {
            _removeTokenFromOwnerEnumeration(from, tokenId);
        }
        if (to == address(0)) {
            _removeTokenFromAllTokensEnumeration(tokenId);
        } else if (to != from) {
            _addTokenToOwnerEnumeration(to, tokenId);
        }
    }

    /**
     * @dev Private function to add a token to this extension's ownership-tracking data structures.
     * @param to address representing the new owner of the given token ID
     * @param tokenId uint256 ID of the token to be added to the tokens list of the given address
     */
    function _addTokenToOwnerEnumeration(address to, uint256 tokenId) private {
        uint256 length = ERC721.balanceOf(to);
        _ownedTokens[to][length] = tokenId;
        _ownedTokensIndex[tokenId] = length;
    }

    /**
     * @dev Private function to add a token to this extension's token tracking data structures.
     * @param tokenId uint256 ID of the token to be added to the tokens list
     */
    function _addTokenToAllTokensEnumeration(uint256 tokenId) private {
        _allTokensIndex[tokenId] = _allTokens.length;
        _allTokens.push(tokenId);
    }

    /**
     * @dev Private function to remove a token from this extension's ownership-tracking data structures. Note that
     * while the token is not assigned a new owner, the `_ownedTokensIndex` mapping is _not_ updated: this allows for
     * gas optimizations e.g. when performing a transfer operation (avoiding double writes).
     * This has O(1) time complexity, but alters the order of the _ownedTokens array.
     * @param from address representing the previous owner of the given token ID
     * @param tokenId uint256 ID of the token to be removed from the tokens list of the given address
     */
    function _removeTokenFromOwnerEnumeration(address from, uint256 tokenId) private {
        // To prevent a gap in from's tokens array, we store the last token in the index of the token to delete, and
        // then delete the last slot (swap and pop).

        uint256 lastTokenIndex = ERC721.balanceOf(from) - 1;
        uint256 tokenIndex = _ownedTokensIndex[tokenId];

        // When the token to delete is the last token, the swap operation is unnecessary
        if (tokenIndex != lastTokenIndex) {
            uint256 lastTokenId = _ownedTokens[from][lastTokenIndex];

            _ownedTokens[from][tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token
            _ownedTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index
        }

        // This also deletes the contents at the last position of the array
        delete _ownedTokensIndex[tokenId];
        delete _ownedTokens[from][lastTokenIndex];
    }

    /**
     * @dev Private function to remove a token from this extension's token tracking data structures.
     * This has O(1) time complexity, but alters the order of the _allTokens array.
     * @param tokenId uint256 ID of the token to be removed from the tokens list
     */
    function _removeTokenFromAllTokensEnumeration(uint256 tokenId) private {
        // To prevent a gap in the tokens array, we store the last token in the index of the token to delete, and
        // then delete the last slot (swap and pop).

        uint256 lastTokenIndex = _allTokens.length - 1;
        uint256 tokenIndex = _allTokensIndex[tokenId];

        // When the token to delete is the last token, the swap operation is unnecessary. However, since this occurs so
        // rarely (when the last minted token is burnt) that we still do the swap here to avoid the gas cost of adding
        // an 'if' statement (like in _removeTokenFromOwnerEnumeration)
        uint256 lastTokenId = _allTokens[lastTokenIndex];

        _allTokens[tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token
        _allTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index

        // This also deletes the contents at the last position of the array
        delete _allTokensIndex[tokenId];
        _allTokens.pop();
    }
}

File 13 of 25 : 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);
}

File 14 of 25 : IERC721.sol
// 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 15 of 25 : ERC721.sol
// 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 16 of 25 : 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;
    }
}

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

pragma solidity ^0.8.0;

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

/**
 * @dev Contract module which allows children to implement an emergency stop
 * mechanism that can be triggered by an authorized account.
 *
 * This module is used through inheritance. It will make available the
 * modifiers `whenNotPaused` and `whenPaused`, which can be applied to
 * the functions of your contract. Note that they will not be pausable by
 * simply including this module, only once the modifiers are put in place.
 */
abstract contract Pausable is Context {
    /**
     * @dev Emitted when the pause is triggered by `account`.
     */
    event Paused(address account);

    /**
     * @dev Emitted when the pause is lifted by `account`.
     */
    event Unpaused(address account);

    bool private _paused;

    /**
     * @dev Initializes the contract in unpaused state.
     */
    constructor() {
        _paused = false;
    }

    /**
     * @dev Returns true if the contract is paused, and false otherwise.
     */
    function paused() public view virtual returns (bool) {
        return _paused;
    }

    /**
     * @dev Modifier to make a function callable only when the contract is not paused.
     *
     * Requirements:
     *
     * - The contract must not be paused.
     */
    modifier whenNotPaused() {
        require(!paused(), "Pausable: paused");
        _;
    }

    /**
     * @dev Modifier to make a function callable only when the contract is paused.
     *
     * Requirements:
     *
     * - The contract must be paused.
     */
    modifier whenPaused() {
        require(paused(), "Pausable: not paused");
        _;
    }

    /**
     * @dev Triggers stopped state.
     *
     * Requirements:
     *
     * - The contract must not be paused.
     */
    function _pause() internal virtual whenNotPaused {
        _paused = true;
        emit Paused(_msgSender());
    }

    /**
     * @dev Returns to normal state.
     *
     * Requirements:
     *
     * - The contract must be paused.
     */
    function _unpause() internal virtual whenPaused {
        _paused = false;
        emit Unpaused(_msgSender());
    }
}

File 18 of 25 : PaymentSplitter.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "../utils/Address.sol";
import "../utils/Context.sol";
import "../utils/math/SafeMath.sol";

/**
 * @title PaymentSplitter
 * @dev This contract allows to split Ether payments among a group of accounts. The sender does not need to be aware
 * that the Ether will be split in this way, since it is handled transparently by the contract.
 *
 * The split can be in equal parts or in any other arbitrary proportion. The way this is specified is by assigning each
 * account to a number of shares. Of all the Ether that this contract receives, each account will then be able to claim
 * an amount proportional to the percentage of total shares they were assigned.
 *
 * `PaymentSplitter` follows a _pull payment_ model. This means that payments are not automatically forwarded to the
 * accounts but kept in this contract, and the actual transfer is triggered as a separate step by calling the {release}
 * function.
 */
contract PaymentSplitter is Context {
    event PayeeAdded(address account, uint256 shares);
    event PaymentReleased(address to, uint256 amount);
    event PaymentReceived(address from, uint256 amount);

    uint256 private _totalShares;
    uint256 private _totalReleased;

    mapping(address => uint256) private _shares;
    mapping(address => uint256) private _released;
    address[] private _payees;

    /**
     * @dev Creates an instance of `PaymentSplitter` where each account in `payees` is assigned the number of shares at
     * the matching position in the `shares` array.
     *
     * All addresses in `payees` must be non-zero. Both arrays must have the same non-zero length, and there must be no
     * duplicates in `payees`.
     */
    constructor(address[] memory payees, uint256[] memory shares_) payable {
        require(payees.length == shares_.length, "PaymentSplitter: payees and shares length mismatch");
        require(payees.length > 0, "PaymentSplitter: no payees");

        for (uint256 i = 0; i < payees.length; i++) {
            _addPayee(payees[i], shares_[i]);
        }
    }

    /**
     * @dev The Ether received will be logged with {PaymentReceived} events. Note that these events are not fully
     * reliable: it's possible for a contract to receive Ether without triggering this function. This only affects the
     * reliability of the events, and not the actual splitting of Ether.
     *
     * To learn more about this see the Solidity documentation for
     * https://solidity.readthedocs.io/en/latest/contracts.html#fallback-function[fallback
     * functions].
     */
    receive() external payable virtual {
        emit PaymentReceived(_msgSender(), msg.value);
    }

    /**
     * @dev Getter for the total shares held by payees.
     */
    function totalShares() public view returns (uint256) {
        return _totalShares;
    }

    /**
     * @dev Getter for the total amount of Ether already released.
     */
    function totalReleased() public view returns (uint256) {
        return _totalReleased;
    }

    /**
     * @dev Getter for the amount of shares held by an account.
     */
    function shares(address account) public view returns (uint256) {
        return _shares[account];
    }

    /**
     * @dev Getter for the amount of Ether already released to a payee.
     */
    function released(address account) public view returns (uint256) {
        return _released[account];
    }

    /**
     * @dev Getter for the address of the payee number `index`.
     */
    function payee(uint256 index) public view returns (address) {
        return _payees[index];
    }

    /**
     * @dev Triggers a transfer to `account` of the amount of Ether they are owed, according to their percentage of the
     * total shares and their previous withdrawals.
     */
    function release(address payable account) public virtual {
        require(_shares[account] > 0, "PaymentSplitter: account has no shares");

        uint256 totalReceived = address(this).balance + _totalReleased;
        uint256 payment = (totalReceived * _shares[account]) / _totalShares - _released[account];

        require(payment != 0, "PaymentSplitter: account is not due payment");

        _released[account] = _released[account] + payment;
        _totalReleased = _totalReleased + payment;

        Address.sendValue(account, payment);
        emit PaymentReleased(account, payment);
    }

    /**
     * @dev Add a new payee to the contract.
     * @param account The address of the payee to add.
     * @param shares_ The number of shares owned by the payee.
     */
    function _addPayee(address account, uint256 shares_) private {
        require(account != address(0), "PaymentSplitter: account is the zero address");
        require(shares_ > 0, "PaymentSplitter: shares are 0");
        require(_shares[account] == 0, "PaymentSplitter: account already has shares");

        _payees.push(account);
        _shares[account] = shares_;
        _totalShares = _totalShares + shares_;
        emit PayeeAdded(account, shares_);
    }
}

File 19 of 25 : Ownable.sol
// 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 20 of 25 : RandomAttributes.sol
// SPDX-License-Identifier: MIT
// Copyright 2021 Arran Schlosberg
pragma solidity >=0.8.0 <0.9.0;

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

/// @notice An abstract contract that allows for random allocation of attributes
/// to a set of tokens (presumably ERC721 but not limited).
/// @dev Inheriting contracts need to override two functions to define how
/// attributes are expressed (e.g. ERC721 metadata JSON).
abstract contract RandomAttributes is Ownable, Random {
    /// @notice Maximum number of tokens that will ever exist.
    /// @dev See _allocatedTo() for usage.
    uint256 immutable public MAX_TOKENS;

    constructor(uint256 maxTokens) {
        MAX_TOKENS = maxTokens;
    }

    /// @dev Override to define how TieredTraits are expressed.
    function attrForTrait(string memory trait, string memory value) virtual internal pure returns (bytes memory) {}

    /// @dev Override to define how Allocated traits are expressed.
    function attrFromName(string memory name) virtual internal pure returns (bytes memory) {}

    /// @notice Sets the entropy value used for random allocation.
    /// @dev NB See Random.sol for important considerations.
    function setEntropy(bytes32 entropy) onlyOwner external {
        Random._setEntropy(entropy);
    }

    /// @notice An attribute / trait that is allocated proportionally into
    /// Tiers. All will have the same Trait name, but different Tier names.
    /// @dev No checks are performed to ensure that the sum of all proportions
    /// <= Random.ONE. Proportions do not have to add to ONE, and any shortfall
    /// will result in that proportion of tokens not receiving this trait.
    struct TieredTrait {
        string name;
        Tier[] tiers;
    }

    /// @notice A Tier within a TieredTrait.
    /// @dev See Random.ONE, Random.PERCENT, and Random.BASIS_POINT for
    /// defining proportions. NB: As these allocations are subject to a random
    /// distribution, final proportions won't be exact. See Allocated if exact
    /// values are required, but note that they are more expensive to compute
    /// so MUST only be used for low values of k.
    struct Tier {
        string name;
        uint256 proportion;
    }

    /// @notice All TieredTraits to be assigned.
    TieredTrait[] internal _tiered;

    /// @notice Adds a new TieredTrait.
    /// @param index The expected index in the _tiered array, to guarantee
    /// idempotent calls during deployment.
    function _newTieredTrait(uint index, TieredTrait memory trait) onlyOwner external {
        // Ensure that calls are idempotent. Without this, pushing multiple
        // traits to the chain with one transaction failing could result in
        // unexpected indices.
        require(index == _tiered.length, "RandomAttributes: invalid tiered index");
        
        _tiered.push();
        _tiered[index].name = trait.name;
        _addToTieredTrait(index, 0, trait.tiers);
    }

    /// @notice Extends an existing TieredTrait with more Tiers.
    /// @param startIndex The expected index of the first Tier to be added, to
    /// guarantee idempotent calls during deployment.
    function _addToTieredTrait(uint traitIndex, uint startIndex, Tier[] memory tiers) onlyOwner public {
        // See _newTieredTrait() for logic.
        require(startIndex == _tiered[traitIndex].tiers.length, "RandomAttributes: invalid startIndex");
        
        // Solidity doesn't support copy from memory to storage for this type,
        // so push each element.
        for (uint i = 0; i < tiers.length; i++) {
            _tiered[traitIndex].tiers.push(tiers[i]);
        }
    }

    /// @notice Alias for _tieredTraitsFor() with zero-value entropy.
    function _tieredTraitsFor(uint256 tokenId, TieredTrait[] memory traits) internal view returns (bytes memory) {
        return _tieredTraitsFor(tokenId, traits, new bytes(0));
    }

    /// @notice Computes all Tiers, for all Traits, assigned to the token. The
    /// Tiers are passed to attrForTrait() and the returned values concatenated
    /// with abi.encodePacked() to be returned.
    /// @param traits The TieredTraits to be assigned. These are typically the
    /// values stored in _tiered, but MAY differ.
    /// @param _entropy Optional additional entropy for use in allocating Tiers.
    /// @dev The entropy in Random._entropy is always used, while the _entropy
    /// param is an additional source. The Random._entropy value is used to
    /// differentiate between contract instances whereas the parameter allows
    /// for different rolls of the dice within the same contract. This function
    /// SHOULD be used in a call, not a transaction, as it hasn't been optimised
    /// for gas consumption.
    function _tieredTraitsFor(uint256 tokenId, TieredTrait[] memory traits, bytes memory _entropy) internal view returns (bytes memory) {
        uint256 threshold;
        bytes memory assigned;

        for (uint i=0; i < traits.length; i++) {
            uint rand = _uniform(abi.encode(_entropy, tokenId, traits[i].name));

            // Although it would be more computationally efficient to perform a
            // binary search here, it adds code complexity that can result in a
            // bug. Testing of random functions is difficult enough as it is, so
            // we opt for simplicity for negligible gas cost (or zero given that
            // this function is intended for gas-free calls).
            threshold = 0;
            for (uint j = 0; j < traits[i].tiers.length; j++) {
                threshold += traits[i].tiers[j].proportion;
                
                if (rand <= threshold) {
                    assigned = abi.encodePacked(assigned, attrForTrait(traits[i].name, traits[i].tiers[j].name));
                    break;
                }
            }
        }

        return assigned;
    }

    /// @notice A directly allocated attribute that is assigned to exactly k
    /// tokens.
    /// @dev Allocation is very expensive, and may even cause a gas-free call to
    /// reach block limits (still enforced, just not paid). It scales roughly
    /// linearly as O(k) as long as k << MAX_TOKENS. If k approaches MAX_TOKENS
    /// then the probability of allocating to the same token on different random
    /// samplings increases and _isAllocatedTo() becomes much less efficient. If
    /// k is too large, TieredTraits SHOULD be used instead.
    struct Allocated {
        string name;
        uint256 k;
    }

    /// @notice All Allocated attributes to be assigned.
    Allocated[] internal _allocs;

    /// @notice Adds a new Allocated attribute.
    /// @param index The expected index in the _allocs array, to guarantee
    /// idempotent calls during deployment.
    function _newAllocatedTrait(uint index, Allocated memory alloc) onlyOwner external {
        require(index == _allocs.length, "RandomAttributes: invalid allocated index");
        _allocs.push(alloc);
    }

    /// @notice Alias for _allocatedTo() with zero-value entropy.
    function _allocatedTo(uint256 tokenId, Allocated[] memory allocs) internal view returns (bytes memory) {
        return _allocatedTo(tokenId, allocs, new bytes(0));
    }

    /// @notice Computes all Allocated attributes assigned to the given token.
    /// The names are passed to attrFromName() and the returned values
    /// concatenated with abi.encodePacked() to be returned.
    /// @param allocs The Allocated to be assigned. These are typically the
    /// values stored in _allocs, but MAY differ.
    /// @param _entropy Optional additional entropy for use in selecting tokens
    /// receiving Allocated attributes.
    /// @dev The entropy in Random._entropy is always used, while the _entropy
    /// param is an additional source. The Random._entropy value is used to
    /// differentiate between contract instances whereas the parameter allows
    /// for different rolls of the dice within the same contract. This function
    /// SHOULD be used in a call, not a transaction, as it hasn't been optimised
    /// for gas consumption.
    function _allocatedTo(uint256 tokenId, Allocated[] memory allocs, bytes memory _entropy) internal view returns (bytes memory) {
        // Determine how many bits of entropy are needed to choose from
        // MAX_TOKENS.
        uint256 logN = 0;
        uint256 n = MAX_TOKENS;
        assembly {
            for {} gt(n, 0) {n := shr(1, n)} {
                logN := add(logN, 1)
            }
        }
        uint256 mask = 2**logN - 1;

        bytes memory allocated;
        for (uint i=0; i < allocs.length; i++) {
            if (_isAllocatedTo(tokenId, allocs[i], logN, mask, _entropy)) {
                allocated = abi.encodePacked(allocated, attrFromName(allocs[i].name));
            }
        }
        return allocated;
    }

    /// @notice Returns whether a _specific_ Allocated attribute is assigned to
    /// the specific tokenId.
    /// @param logN An approximation of log_2(MAX_TOKENS) used to determine the
    /// number of random bits used for a single sample. MUST be the smallest
    /// integer value >log_2(MAX_TOKENS).
    /// @param mask A bitwise mask for sampling random bits. MUST be equal to
    /// 2**logN - 1, i.e. the smallest all-ones binary mask that is larger than
    /// MAX_TOKENS.
    /// @param _entropy See _allocatedTo().
    /// @dev Functions by sampling from keccak256(<entropy sources>,counter) in
    /// an unbiased fashion until either tokenId receives an Allocated trait or
    /// all traits are allocated. This function SHOULD be used in a call, not a
    /// transaction, as it hasn't been optimised for gas consumption.
    function _isAllocatedTo(uint256 tokenId, Allocated memory alloc, uint256 logN, uint256 mask, bytes memory _entropy) private view returns (bool) {
        // randSrc is a pool of entropy sourced from the hash of entropy sources
        // and a counter. When replenished, bitsRemaining is set to 256, and
        // reduced by logN after each sample.
        uint256 counter = 0;
        uint256 randSrc;
        uint256 bitsRemaining = 0;
        // The random sample [0,mask]. This is the smallest range that includes
        // MAX_TOKEN, thus improving efficiency of rejection sampling.
        uint256 rand;

        // Keeps track of the tokens other than tokenId to which this trait has
        // been allocated. Effectively a set, but Solidity doesn't support
        // mapping types out of storage, and this function MUST be `view`.
        bool[] memory already = new bool[](MAX_TOKENS);

        for (uint i = 0; i < alloc.k; i++) {
            while (true) {
                // Do we need to replenish the entropy source?
                if (bitsRemaining < logN) {
                    randSrc = uint256(keccak256(abi.encode(_entropy, Random._entropy, alloc.name, counter)));
                    counter++;
                    bitsRemaining = 256;
                }

                // Sample from randSrc.
                assembly {
                    rand := and(randSrc, mask)
                    randSrc := shr(logN, randSrc)
                    // Can never wrap because of the replenishment in the if
                    // block above.
                    bitsRemaining := sub(bitsRemaining, logN)
                }

                if (rand == tokenId) {
                    return true;
                }
                if (rand >= MAX_TOKENS) {
                    // The random value is out of range and therefore rejected.
                    // Don't use % MAX_TOKENS because this biases low-valued
                    // numbers, so instead we roll the dice again without
                    // incrementing i.
                    continue;
                }
                if (already[rand]) {
                    // Although this can be collapsed into the previous if
                    // statement, it's separated to check for test coverage.
                    // It's very hard to test random functions like this, so
                    // every bit of extra information helps.
                    continue;
                }
                already[rand] = true;
                // Note the inner loop so this allocates to the next token.
                break;
            }
        }

        return false;
    }

    /// @notice Returns the concatenation of _tieredTraitsFor() and
    /// _allocatedTo() for the specified token, using zero-value entropy and the
    /// contract-stored attributes.
    function _attributesOf(uint256 tokenId) external view returns (bytes memory) {
        TieredTrait[] memory tiered = _tiered;
        Allocated[] memory allocs = _allocs;

        return abi.encodePacked(
            _tieredTraitsFor(tokenId, tiered),
            _allocatedTo(tokenId, allocs)
        );
    }

}

File 21 of 25 : Random.sol
// SPDX-License-Identifier: MIT
// Copyright 2021 Arran Schlosberg
pragma solidity >=0.8.0 <0.9.0;

/**
 * @notice Random contracts can generate unbiased pseudorandom numbers from
 * seeds. Best practice requires only setting the `entropy` value _after_
 * user interaction, and obtaining it from a source out of the control of anyone
 * who may benefit from the outcome. Ideally a VRF would be used. If the
 * contract admin can't be trusted, they can publicly nominate a future block
 * number and use its hash; NOTE that this can be manipulated by a miner, so
 * their expected return of such an action should be considered. If the admin
 * can be trusted then they can use a commit-and-reveal approach.
 */
contract Random {
    /// @notice A base entropy source that ensures that calls to _uniform(seed)
    /// return different values to calls in another contract despite having the
    /// same seed.
    bytes32 internal _entropy;

    /// @notice Immutably sets the entropy value if not already set.
    function _setEntropy(bytes32 entropy) internal {
        require (!entropySet(), "Entropy already set");
        _entropy = entropy;
    }

    /// @notice Returns if the entropy value has been set, assuming that this
    /// value was not 0.
    function entropySet() public view returns (bool) {
        return uint256(_entropy) != 0;
    }

    /// @notice Returns the value passed to _setEntropy().
    function getEntropy() public view returns (bytes32) {
        require (entropySet(), "Entropy not set");
        return _entropy;
    }

    /**
     * @dev As we're generating random numbers from hashes, their ranges are
     * always powers of two. However we need denominators that are
     * human-friendly and therefore powers of 10. Generating a random number in
     * [0,10^59] can be performed in an unbiased manner by repeatedly sampling
     * 196 bits from keccak256(seed||counter) until it's within the range. These
     * values are chosen because 10^59/2^196 = 0.9957 so we very rarely have to
     * try again and waste computation.
     */
    uint256 private constant RAND_MASK = 2**196 - 1;
    uint256 public constant ONE = 1e59;

    /// @notice Values equivalent to 1% and 0.01%.
    uint256 public constant PERCENT = 1e57;
    uint256 public constant BASIS_POINT = 1e55;

    /// @notice Returns a uniformly distributed random number [0, ONE].
    function _uniform(bytes memory seed) internal view returns (uint256) {
        uint256 rand = RAND_MASK;
        // The loop will always run at least once because RAND_MASK > ONE.
        for (uint j = 0; rand > ONE; j++) {
            rand = uint256(keccak256(abi.encode(_entropy, seed, j)));
            assembly { rand := and(rand, RAND_MASK) }
        }
        return rand;
    }
}

File 22 of 25 : OwnerPausable.sol
// SPDX-License-Identifier: MIT
// Copyright 2021 Arran Schlosberg
pragma solidity >=0.8.0 <0.9.0;

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

/// @notice A Pausable contract that can only be toggled by the Owner.
contract OwnerPausable is Ownable, Pausable {
    /// @notice Pauses the contract.
    function pause() onlyOwner public {
        Pausable._pause();
    }

    /// @notice Unpauses the contract.
    function unpause() onlyOwner public {
        Pausable._unpause();
    }
}

File 23 of 25 : ERC721Common.sol
// SPDX-License-Identifier: MIT
// Copyright 2021 Arran Schlosberg
pragma solidity >=0.8.0 <0.9.0;

import "./BaseOpenSea.sol";
import "./OwnerPausable.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Pausable.sol";

/// @notice An ERC721 contract with common functionality:
/// - OpenSea gas-free listings
/// - OpenZeppelin Enumerable and Pausable
/// - OpenZeppelin Pausable with functions exposed to Owner only.
contract ERC721Common is BaseOpenSea, ERC721Enumerable, ERC721Pausable, OwnerPausable {
    constructor(
        string memory name,
        string memory symbol,
        address openSeaProxyRegistry
    ) ERC721(name, symbol) {
        if (openSeaProxyRegistry != address(0)) {
            BaseOpenSea._setOpenSeaRegistry(openSeaProxyRegistry);
        }
    }

    /// @notice Overrides _beforeTokenTransfer as required by inheritance.
    function _beforeTokenTransfer(
        address from,
        address to,
        uint256 tokenId
    ) internal virtual override (ERC721Enumerable, ERC721Pausable) {
        super._beforeTokenTransfer(from, to, tokenId);
    }

    /// @notice Overrides supportsInterface as required by inheritance.
    function supportsInterface(bytes4 interfaceId) public view override (ERC721, ERC721Enumerable) returns (bool) {
        return super.supportsInterface(interfaceId);
    }

    /// @notice Returns true if either standard isApprovedForAll() returns true
    /// or the operator is the OpenSea proxy for the owner.
    function isApprovedForAll(address owner, address operator) public view override returns (bool) {
        return super.isApprovedForAll(owner, operator) || BaseOpenSea.isOwnersOpenSeaProxy(owner, operator);
    }
}

File 24 of 25 : BlackSquareRandomAttributes.sol
// SPDX-License-Identifier: UNLICENSED
// Copyright 2021; All rights reserved
// Author: 0x99c520ed5a5e57b2128737531f5626d026ea39f20960b0e750077b9768543949
pragma solidity >=0.8.0 <0.9.0;

import "./RandomAttributes.sol";

/// @notice A concrete extension of the abstract RandomAttributes contract, used
/// for the BlackSquare token.
contract BlackSquareRandomAttributes is RandomAttributes {
    constructor(uint256 maxTokens) RandomAttributes(maxTokens) {}
    
    /// @notice Returns an ERC721 metadata attribute for the trait[_type] and
    /// value.
    /// @dev Assumes that there is already another attribute before this one in
    /// the JSON list.
    function attrForTrait(string memory trait, string memory value) override internal pure returns (bytes memory) {
        return abi.encodePacked(',{"trait_type": "', trait, '", "value": "', value, '"}');
    }

    /// @notice Returns attrForTrait("Looks Rare", @name).
    function attrFromName(string memory name) override internal pure returns (bytes memory) {
        return attrForTrait("Looks Rare", name);
    }

    /// @notice Returns the i'th tiered trait to allow for testing of exhaustive
    /// proportions (i.e. add to 100%).
    function tieredTrait(uint256 i) external view returns (RandomAttributes.TieredTrait memory) {
        return RandomAttributes._tiered[i];
    }

    /// @notice Returns the total number of tiered traits.
    function numTraits() external view returns (uint256) {
        return RandomAttributes._tiered.length;
    }
}

File 25 of 25 : BaseOpenSea.sol
//SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

// https://gist.github.com/dievardump/483eb43bc6ed30b14f01e01842e3339b/

/// @title OpenSea contract helper that defines a few things
/// @author Simon Fremaux (@dievardump)
/// @dev This is a contract used to add OpenSea's support for gas-less trading
///      by checking if operator is owner's proxy
contract BaseOpenSea {
    string private _contractURI;
    ProxyRegistry private _proxyRegistry;

    /// @notice Returns the contract URI function. Used on OpenSea to get details
    ///         about a contract (owner, royalties etc...)
    ///         See documentation: https://docs.opensea.io/docs/contract-level-metadata
    function contractURI() public view returns (string memory) {
        return _contractURI;
    }

    /// @notice Helper for OpenSea gas-less trading
    /// @dev Allows to check if `operator` is owner's OpenSea proxy
    /// @param owner the owner we check for
    /// @param operator the operator (proxy) we check for
    function isOwnersOpenSeaProxy(address owner, address operator)
        public
        view
        returns (bool)
    {
        ProxyRegistry proxyRegistry = _proxyRegistry;
        return
            // we have a proxy registry address
            address(proxyRegistry) != address(0) &&
            // current operator is owner's proxy address
            address(proxyRegistry.proxies(owner)) == operator;
    }

    /// @dev Internal function to set the _contractURI
    /// @param contractURI_ the new contract uri
    function _setContractURI(string memory contractURI_) internal {
        _contractURI = contractURI_;
    }

    /// @dev Internal function to set the _proxyRegistry
    /// @param proxyRegistryAddress the new proxy registry address
    function _setOpenSeaRegistry(address proxyRegistryAddress) internal {
        _proxyRegistry = ProxyRegistry(proxyRegistryAddress);
    }
}

contract OwnableDelegateProxy {}

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

Settings
{
  "remappings": [],
  "optimizer": {
    "enabled": false,
    "runs": 200
  },
  "evmVersion": "london",
  "libraries": {},
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  }
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"symbol","type":"string"},{"internalType":"address","name":"openSeaProxyRegistry","type":"address"},{"internalType":"uint256","name":"maxTokens","type":"uint256"},{"internalType":"address payable","name":"_paymentSplitter","type":"address"}],"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":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"inputs":[],"name":"MAX_PER_ADDRESS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_TOKENS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MINT_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":[],"name":"attrs","outputs":[{"internalType":"contract BlackSquareRandomAttributes","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"basisPoint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"contractURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getEntropy","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"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":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isOwnersOpenSeaProxy","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"minted","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"firstIndex","type":"uint256"},{"components":[{"internalType":"string","name":"name","type":"string"},{"internalType":"uint256","name":"k","type":"uint256"}],"internalType":"struct RandomAttributes.Allocated[]","name":"alloc","type":"tuple[]"}],"name":"newAllocatedTraits","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"},{"components":[{"internalType":"string","name":"name","type":"string"},{"components":[{"internalType":"string","name":"name","type":"string"},{"internalType":"uint256","name":"proportion","type":"uint256"}],"internalType":"struct RandomAttributes.Tier[]","name":"tiers","type":"tuple[]"}],"internalType":"struct RandomAttributes.TieredTrait","name":"trait","type":"tuple"}],"name":"newTieredTrait","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"paymentSplitter","outputs":[{"internalType":"contract PaymentSplitter","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"n","type":"uint256"}],"name":"safeMint","outputs":[],"stateMutability":"payable","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":"bytes32","name":"entropy","type":"bytes32"}],"name":"setEntropy","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address payable","name":"_paymentSplitter","type":"address"}],"name":"setPaymentSplitter","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":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenOfOwnerByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"}]

60c06040523480156200001157600080fd5b506040516200921f3803806200921f833981810160405281019062000037919062000614565b8484848282816002908051906020019062000054929190620002d4565b5080600390805190602001906200006d929190620002d4565b5050506200009062000084620001c260201b60201c565b620001ca60201b60201c565b6000600c60146101000a81548160ff021916908315150217905550600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614620000f757620000f6816200029060201b620021651760201c565b5b5050506001600d8190555081604051620001119062000365565b6200011d9190620006eb565b604051809103906000f0801580156200013a573d6000803e3d6000fd5b5073ffffffffffffffffffffffffffffffffffffffff1660a08173ffffffffffffffffffffffffffffffffffffffff168152505080600e60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550816080818152505050505050506200076d565b600033905090565b6000600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600c60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b80600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b828054620002e29062000737565b90600052602060002090601f01602090048101928262000306576000855562000352565b82601f106200032157805160ff191683800117855562000352565b8280016001018555821562000352579182015b828111156200035157825182559160200191906001019062000334565b5b50905062000361919062000373565b5090565b612bc5806200665a83390190565b5b808211156200038e57600081600090555060010162000374565b5090565b6000604051905090565b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b620003fb82620003b0565b810181811067ffffffffffffffff821117156200041d576200041c620003c1565b5b80604052505050565b60006200043262000392565b9050620004408282620003f0565b919050565b600067ffffffffffffffff821115620004635762000462620003c1565b5b6200046e82620003b0565b9050602081019050919050565b60005b838110156200049b5780820151818401526020810190506200047e565b83811115620004ab576000848401525b50505050565b6000620004c8620004c28462000445565b62000426565b905082815260208101848484011115620004e757620004e6620003ab565b5b620004f48482856200047b565b509392505050565b600082601f830112620005145762000513620003a6565b5b815162000526848260208601620004b1565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006200055c826200052f565b9050919050565b6200056e816200054f565b81146200057a57600080fd5b50565b6000815190506200058e8162000563565b92915050565b6000819050919050565b620005a98162000594565b8114620005b557600080fd5b50565b600081519050620005c9816200059e565b92915050565b6000620005dc826200052f565b9050919050565b620005ee81620005cf565b8114620005fa57600080fd5b50565b6000815190506200060e81620005e3565b92915050565b600080600080600060a086880312156200063357620006326200039c565b5b600086015167ffffffffffffffff811115620006545762000653620003a1565b5b6200066288828901620004fc565b955050602086015167ffffffffffffffff811115620006865762000685620003a1565b5b6200069488828901620004fc565b9450506040620006a7888289016200057d565b9350506060620006ba88828901620005b8565b9250506080620006cd88828901620005fd565b9150509295509295909350565b620006e58162000594565b82525050565b6000602082019050620007026000830184620006da565b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b600060028204905060018216806200075057607f821691505b6020821081141562000767576200076662000708565b5b50919050565b60805160a051615e8f620007cb60003960008181610af301528181610c43015281816111da015281816117750152818161197701528181611c7601528181611d1a0152611ee0015260008181610dfb01526121430152615e8f6000f3fe60806040526004361061021a5760003560e01c80636352211e11610123578063a22cb465116100ab578063e8a3d4851161006f578063e8a3d485146107c4578063e985e9c5146107ef578063ed4a6b0c1461082c578063f2fde38b14610857578063f47c84c5146108805761021a565b8063a22cb465146106e1578063b88d4fde1461070a578063c002d23d14610733578063c87b56dd1461075e578063e24d9e2c1461079b5761021a565b80638456cb59116100f25780638456cb59146106225780638a7ac5c7146106395780638da5cb5b1461066257806395d89b411461068d57806396b83514146106b85761021a565b80636352211e146105685780636b29b79f146105a557806370a08231146105ce578063715018a61461060b5761021a565b80632f745c59116101a657806342842e0e1161017557806342842e0e1461046f5780634f6ccce7146104985780635404bbf7146104d55780635c975abb146105005780636102de981461052b5761021a565b80632f745c59146103d45780632f7b19151461041157806331c864e81461043c5780633f4ba83a146104585761021a565b80630aaef285116101ed5780630aaef285146102ed5780630cc96d521461031857806318160ddd146103435780631e7269c51461036e57806323b872dd146103ab5761021a565b806301ffc9a71461021f57806306fdde031461025c578063081812fc14610287578063095ea7b3146102c4575b600080fd5b34801561022b57600080fd5b5061024660048036038101906102419190613744565b6108ab565b604051610253919061378c565b60405180910390f35b34801561026857600080fd5b506102716108bd565b60405161027e9190613840565b60405180910390f35b34801561029357600080fd5b506102ae60048036038101906102a99190613898565b61094f565b6040516102bb9190613906565b60405180910390f35b3480156102d057600080fd5b506102eb60048036038101906102e6919061394d565b6109d4565b005b3480156102f957600080fd5b50610302610aec565b60405161030f919061399c565b60405180910390f35b34801561032457600080fd5b5061032d610af1565b60405161033a9190613a16565b60405180910390f35b34801561034f57600080fd5b50610358610b15565b604051610365919061399c565b60405180910390f35b34801561037a57600080fd5b5061039560048036038101906103909190613a31565b610b22565b6040516103a2919061399c565b60405180910390f35b3480156103b757600080fd5b506103d260048036038101906103cd9190613a5e565b610b3a565b005b3480156103e057600080fd5b506103fb60048036038101906103f6919061394d565b610b9a565b604051610408919061399c565b60405180910390f35b34801561041d57600080fd5b50610426610c3f565b604051610433919061399c565b60405180910390f35b61045660048036038101906104519190613898565b610ce4565b005b34801561046457600080fd5b5061046d6110bf565b005b34801561047b57600080fd5b5061049660048036038101906104919190613a5e565b611145565b005b3480156104a457600080fd5b506104bf60048036038101906104ba9190613898565b611165565b6040516104cc919061399c565b60405180910390f35b3480156104e157600080fd5b506104ea6111d6565b6040516104f79190613aca565b60405180910390f35b34801561050c57600080fd5b5061051561127b565b604051610522919061378c565b60405180910390f35b34801561053757600080fd5b50610552600480360381019061054d9190613ae5565b611292565b60405161055f919061378c565b60405180910390f35b34801561057457600080fd5b5061058f600480360381019061058a9190613898565b6113b3565b60405161059c9190613906565b60405180910390f35b3480156105b157600080fd5b506105cc60048036038101906105c79190613b63565b611465565b005b3480156105da57600080fd5b506105f560048036038101906105f09190613a31565b611525565b604051610602919061399c565b60405180910390f35b34801561061757600080fd5b506106206115dd565b005b34801561062e57600080fd5b50610637611665565b005b34801561064557600080fd5b50610660600480360381019061065b9190613e21565b6116eb565b005b34801561066e57600080fd5b5061067761183d565b6040516106849190613906565b60405180910390f35b34801561069957600080fd5b506106a2611867565b6040516106af9190613840565b60405180910390f35b3480156106c457600080fd5b506106df60048036038101906106da9190614052565b6118f9565b005b3480156106ed57600080fd5b50610708600480360381019061070391906140da565b611a06565b005b34801561071657600080fd5b50610731600480360381019061072c91906141bb565b611b87565b005b34801561073f57600080fd5b50610748611be9565b604051610755919061399c565b60405180910390f35b34801561076a57600080fd5b5061078560048036038101906107809190613898565b611bf5565b6040516107929190613840565b60405180910390f35b3480156107a757600080fd5b506107c260048036038101906107bd919061426a565b611e62565b005b3480156107d057600080fd5b506107d9611f6c565b6040516107e69190613840565b60405180910390f35b3480156107fb57600080fd5b5061081660048036038101906108119190613ae5565b611ffe565b604051610823919061378c565b60405180910390f35b34801561083857600080fd5b50610841612023565b60405161084e91906142ca565b60405180910390f35b34801561086357600080fd5b5061087e60048036038101906108799190613a31565b612049565b005b34801561088c57600080fd5b50610895612141565b6040516108a2919061399c565b60405180910390f35b60006108b6826121a9565b9050919050565b6060600280546108cc90614314565b80601f01602080910402602001604051908101604052809291908181526020018280546108f890614314565b80156109455780601f1061091a57610100808354040283529160200191610945565b820191906000526020600020905b81548152906001019060200180831161092857829003601f168201915b5050505050905090565b600061095a82612223565b610999576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610990906143b8565b60405180910390fd5b6006600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b60006109df826113b3565b90508073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610a50576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a479061444a565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff16610a6f61228f565b73ffffffffffffffffffffffffffffffffffffffff161480610a9e5750610a9d81610a9861228f565b611ffe565b5b610add576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ad4906144dc565b60405180910390fd5b610ae78383612297565b505050565b600a81565b7f000000000000000000000000000000000000000000000000000000000000000081565b6000600a80549050905090565b600f6020528060005260406000206000915090505481565b610b4b610b4561228f565b82612350565b610b8a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b819061456e565b60405180910390fd5b610b9583838361242e565b505050565b6000610ba583611525565b8210610be6576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bdd90614600565b60405180910390fd5b600860008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600083815260200190815260200160002054905092915050565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663ada5f6426040518163ffffffff1660e01b815260040160206040518083038186803b158015610ca757600080fd5b505afa158015610cbb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cdf9190614635565b905090565b6002600d541415610d2a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d21906146ae565b60405180910390fd5b6002600d81905550610d7281336040518060400160405280600c81526020017f53656e646572206c696d6974000000000000000000000000000000000000000081525061268a565b90503273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610dea57610de781326040518060400160405280600c81526020017f4f726967696e206c696d6974000000000000000000000000000000000000000081525061268a565b90505b6000610df4610b15565b90506000817f0000000000000000000000000000000000000000000000000000000000000000610e2491906146fd565b905060008111610e69576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e609061477d565b60405180910390fd5b80831115610e75578092505b600067016345785d8a000084610e8b919061479d565b905080341015610ed0576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ec790614843565b60405180910390fd5b83600f60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254610f1f9190614863565b925050819055503273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610fb05783600f60003273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254610fa89190614863565b925050819055505b60008484610fbe9190614863565b90505b80841015610fe657610fd3338561273f565b8380610fde906148b9565b945050610fc1565b50600e60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f1935050505015801561104f573d6000803e3d6000fd5b50803411156110b15760003390508073ffffffffffffffffffffffffffffffffffffffff166108fc833461108391906146fd565b9081150290604051600060405180830381858888f193505050501580156110ae573d6000803e3d6000fd5b50505b5050506001600d8190555050565b6110c761228f565b73ffffffffffffffffffffffffffffffffffffffff166110e561183d565b73ffffffffffffffffffffffffffffffffffffffff161461113b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111329061494e565b60405180910390fd5b61114361275d565b565b61116083838360405180602001604052806000815250611b87565b505050565b600061116f610b15565b82106111b0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111a7906149e0565b60405180910390fd5b600a82815481106111c4576111c3614a00565b5b90600052602060002001549050919050565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16635404bbf76040518163ffffffff1660e01b815260040160206040518083038186803b15801561123e57600080fd5b505afa158015611252573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112769190614a44565b905090565b6000600c60149054906101000a900460ff16905090565b600080600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141580156113aa57508273ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1663c4552791866040518263ffffffff1660e01b81526004016113429190613906565b60206040518083038186803b15801561135a57600080fd5b505afa15801561136e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113929190614aaf565b73ffffffffffffffffffffffffffffffffffffffff16145b91505092915050565b6000806004600084815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561145c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161145390614b4e565b60405180910390fd5b80915050919050565b61146d61228f565b73ffffffffffffffffffffffffffffffffffffffff1661148b61183d565b73ffffffffffffffffffffffffffffffffffffffff16146114e1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016114d89061494e565b60405180910390fd5b80600e60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415611596576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161158d90614be0565b60405180910390fd5b600560008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b6115e561228f565b73ffffffffffffffffffffffffffffffffffffffff1661160361183d565b73ffffffffffffffffffffffffffffffffffffffff1614611659576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016116509061494e565b60405180910390fd5b61166360006127ff565b565b61166d61228f565b73ffffffffffffffffffffffffffffffffffffffff1661168b61183d565b73ffffffffffffffffffffffffffffffffffffffff16146116e1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016116d89061494e565b60405180910390fd5b6116e96128c5565b565b6116f361228f565b73ffffffffffffffffffffffffffffffffffffffff1661171161183d565b73ffffffffffffffffffffffffffffffffffffffff1614611767576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161175e9061494e565b60405180910390fd5b60005b8151811015611838577f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663217167ad82856117bb9190614863565b8484815181106117ce576117cd614a00565b5b60200260200101516040518363ffffffff1660e01b81526004016117f3929190614c96565b600060405180830381600087803b15801561180d57600080fd5b505af1158015611821573d6000803e3d6000fd5b505050508080611830906148b9565b91505061176a565b505050565b6000600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60606003805461187690614314565b80601f01602080910402602001604051908101604052809291908181526020018280546118a290614314565b80156118ef5780601f106118c4576101008083540402835291602001916118ef565b820191906000526020600020905b8154815290600101906020018083116118d257829003601f168201915b5050505050905090565b61190161228f565b73ffffffffffffffffffffffffffffffffffffffff1661191f61183d565b73ffffffffffffffffffffffffffffffffffffffff1614611975576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161196c9061494e565b60405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663a7b21d7583836040518363ffffffff1660e01b81526004016119d0929190614e09565b600060405180830381600087803b1580156119ea57600080fd5b505af11580156119fe573d6000803e3d6000fd5b505050505050565b611a0e61228f565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415611a7c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a7390614e85565b60405180910390fd5b8060076000611a8961228f565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff16611b3661228f565b73ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3183604051611b7b919061378c565b60405180910390a35050565b611b98611b9261228f565b83612350565b611bd7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611bce9061456e565b60405180910390fd5b611be384848484612968565b50505050565b67016345785d8a000081565b6060611c0082612223565b611c3f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c3690614ef1565b60405180910390fd5b6000611c496108bd565b611c52846129c4565b604051602001611c6392919061534f565b60405160208183030381529060405290507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663a0d0ddbf6040518163ffffffff1660e01b815260040160206040518083038186803b158015611cda57600080fd5b505afa158015611cee573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d1291906153f6565b15611ded57807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663922050cc856040518263ffffffff1660e01b8152600401611d71919061399c565b60006040518083038186803b158015611d8957600080fd5b505afa158015611d9d573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190611dc69190615493565b604051602001611dd7929190615595565b6040516020818303038152906040529050611e10565b80604051602001611dfe9190615610565b60405160208183030381529060405290505b80604051602001611e2191906156ca565b6040516020818303038152906040529050611e3b81612b25565b604051602001611e4b9190615743565b604051602081830303815290604052915050919050565b611e6a61228f565b73ffffffffffffffffffffffffffffffffffffffff16611e8861183d565b73ffffffffffffffffffffffffffffffffffffffff1614611ede576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ed59061494e565b60405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663e24d9e2c826040518263ffffffff1660e01b8152600401611f379190613aca565b600060405180830381600087803b158015611f5157600080fd5b505af1158015611f65573d6000803e3d6000fd5b5050505050565b606060008054611f7b90614314565b80601f0160208091040260200160405190810160405280929190818152602001828054611fa790614314565b8015611ff45780601f10611fc957610100808354040283529160200191611ff4565b820191906000526020600020905b815481529060010190602001808311611fd757829003601f168201915b5050505050905090565b600061200a8383612c9e565b8061201b575061201a8383611292565b5b905092915050565b600e60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b61205161228f565b73ffffffffffffffffffffffffffffffffffffffff1661206f61183d565b73ffffffffffffffffffffffffffffffffffffffff16146120c5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016120bc9061494e565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415612135576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161212c906157d7565b60405180910390fd5b61213e816127ff565b50565b7f000000000000000000000000000000000000000000000000000000000000000081565b80600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b60007f780e9d63000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916148061221c575061221b82612d32565b5b9050919050565b60008073ffffffffffffffffffffffffffffffffffffffff166004600084815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614159050919050565b600033905090565b816006600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff1661230a836113b3565b73ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b600061235b82612223565b61239a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161239190615869565b60405180910390fd5b60006123a5836113b3565b90508073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16148061241457508373ffffffffffffffffffffffffffffffffffffffff166123fc8461094f565b73ffffffffffffffffffffffffffffffffffffffff16145b8061242557506124248185611ffe565b5b91505092915050565b8273ffffffffffffffffffffffffffffffffffffffff1661244e826113b3565b73ffffffffffffffffffffffffffffffffffffffff16146124a4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161249b906158fb565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415612514576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161250b9061598d565b60405180910390fd5b61251f838383612e14565b61252a600082612297565b6001600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825461257a91906146fd565b925050819055506001600560008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546125d19190614863565b92505081905550816004600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4505050565b600080600f60008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054600a6126d991906146fd565b9050600081118390612721576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016127189190613840565b60405180910390fd5b50808511156127335780915050612738565b849150505b9392505050565b612759828260405180602001604052806000815250612e24565b5050565b61276561127b565b6127a4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161279b906159f9565b60405180910390fd5b6000600c60146101000a81548160ff0219169083151502179055507f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa6127e861228f565b6040516127f59190613906565b60405180910390a1565b6000600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600c60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b6128cd61127b565b1561290d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161290490615a65565b60405180910390fd5b6001600c60146101000a81548160ff0219169083151502179055507f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a25861295161228f565b60405161295e9190613906565b60405180910390a1565b61297384848461242e565b61297f84848484612e7f565b6129be576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016129b590615af7565b60405180910390fd5b50505050565b60606000821415612a0c576040518060400160405280600181526020017f30000000000000000000000000000000000000000000000000000000000000008152509050612b20565b600082905060005b60008214612a3e578080612a27906148b9565b915050600a82612a379190615b46565b9150612a14565b60008167ffffffffffffffff811115612a5a57612a59613b95565b5b6040519080825280601f01601f191660200182016040528015612a8c5781602001600182028036833780820191505090505b5090505b60008514612b1957600182612aa591906146fd565b9150600a85612ab49190615b77565b6030612ac09190614863565b60f81b818381518110612ad657612ad5614a00565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600a85612b129190615b46565b9450612a90565b8093505050505b919050565b6060600082511415612b4857604051806020016040528060008152509050612c99565b6000604051806060016040528060408152602001615e1a6040913990506000600360028551612b779190614863565b612b819190615b46565b6004612b8d919061479d565b90506000602082612b9e9190614863565b67ffffffffffffffff811115612bb757612bb6613b95565b5b6040519080825280601f01601f191660200182016040528015612be95781602001600182028036833780820191505090505b509050818152600183018586518101602084015b81831015612c58576003830192508251603f8160121c168501518253600182019150603f81600c1c168501518253600182019150603f8160061c168501518253600182019150603f8116850151825360018201915050612bfd565b600389510660018114612c725760028114612c8257612c8d565b613d3d60f01b6002830352612c8d565b603d60f81b60018303525b50505050508093505050505b919050565b6000600760008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b60007f80ac58cd000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480612dfd57507f5b5e139f000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b80612e0d5750612e0c82613016565b5b9050919050565b612e1f838383613080565b505050565b612e2e83836130d8565b612e3b6000848484612e7f565b612e7a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612e7190615af7565b60405180910390fd5b505050565b6000612ea08473ffffffffffffffffffffffffffffffffffffffff166132a6565b15613009578373ffffffffffffffffffffffffffffffffffffffff1663150b7a02612ec961228f565b8786866040518563ffffffff1660e01b8152600401612eeb9493929190615bf2565b602060405180830381600087803b158015612f0557600080fd5b505af1925050508015612f3657506040513d601f19601f82011682018060405250810190612f339190615c53565b60015b612fb9573d8060008114612f66576040519150601f19603f3d011682016040523d82523d6000602084013e612f6b565b606091505b50600081511415612fb1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612fa890615af7565b60405180910390fd5b805181602001fd5b63150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161491505061300e565b600190505b949350505050565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b61308b8383836132b9565b61309361127b565b156130d3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016130ca90615cf2565b60405180910390fd5b505050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415613148576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161313f90615d5e565b60405180910390fd5b61315181612223565b15613191576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161318890615dca565b60405180910390fd5b61319d60008383612e14565b6001600560008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546131ed9190614863565b92505081905550816004600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a45050565b600080823b905060008111915050919050565b6132c48383836133cd565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16141561330757613302816133d2565b613346565b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161461334557613344838261341b565b5b5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614156133895761338481613588565b6133c8565b8273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16146133c7576133c68282613659565b5b5b505050565b505050565b600a80549050600b600083815260200190815260200160002081905550600a81908060018154018082558091505060019003906000526020600020016000909190919091505550565b6000600161342884611525565b61343291906146fd565b9050600060096000848152602001908152602001600020549050818114613517576000600860008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600084815260200190815260200160002054905080600860008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600084815260200190815260200160002081905550816009600083815260200190815260200160002081905550505b6009600084815260200190815260200160002060009055600860008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008381526020019081526020016000206000905550505050565b60006001600a8054905061359c91906146fd565b90506000600b60008481526020019081526020016000205490506000600a83815481106135cc576135cb614a00565b5b9060005260206000200154905080600a83815481106135ee576135ed614a00565b5b906000526020600020018190555081600b600083815260200190815260200160002081905550600b600085815260200190815260200160002060009055600a80548061363d5761363c615dea565b5b6001900381819060005260206000200160009055905550505050565b600061366483611525565b905081600860008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600083815260200190815260200160002081905550806009600084815260200190815260200160002081905550505050565b6000604051905090565b600080fd5b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b613721816136ec565b811461372c57600080fd5b50565b60008135905061373e81613718565b92915050565b60006020828403121561375a576137596136e2565b5b60006137688482850161372f565b91505092915050565b60008115159050919050565b61378681613771565b82525050565b60006020820190506137a1600083018461377d565b92915050565b600081519050919050565b600082825260208201905092915050565b60005b838110156137e15780820151818401526020810190506137c6565b838111156137f0576000848401525b50505050565b6000601f19601f8301169050919050565b6000613812826137a7565b61381c81856137b2565b935061382c8185602086016137c3565b613835816137f6565b840191505092915050565b6000602082019050818103600083015261385a8184613807565b905092915050565b6000819050919050565b61387581613862565b811461388057600080fd5b50565b6000813590506138928161386c565b92915050565b6000602082840312156138ae576138ad6136e2565b5b60006138bc84828501613883565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006138f0826138c5565b9050919050565b613900816138e5565b82525050565b600060208201905061391b60008301846138f7565b92915050565b61392a816138e5565b811461393557600080fd5b50565b60008135905061394781613921565b92915050565b60008060408385031215613964576139636136e2565b5b600061397285828601613938565b925050602061398385828601613883565b9150509250929050565b61399681613862565b82525050565b60006020820190506139b1600083018461398d565b92915050565b6000819050919050565b60006139dc6139d76139d2846138c5565b6139b7565b6138c5565b9050919050565b60006139ee826139c1565b9050919050565b6000613a00826139e3565b9050919050565b613a10816139f5565b82525050565b6000602082019050613a2b6000830184613a07565b92915050565b600060208284031215613a4757613a466136e2565b5b6000613a5584828501613938565b91505092915050565b600080600060608486031215613a7757613a766136e2565b5b6000613a8586828701613938565b9350506020613a9686828701613938565b9250506040613aa786828701613883565b9150509250925092565b6000819050919050565b613ac481613ab1565b82525050565b6000602082019050613adf6000830184613abb565b92915050565b60008060408385031215613afc57613afb6136e2565b5b6000613b0a85828601613938565b9250506020613b1b85828601613938565b9150509250929050565b6000613b30826138c5565b9050919050565b613b4081613b25565b8114613b4b57600080fd5b50565b600081359050613b5d81613b37565b92915050565b600060208284031215613b7957613b786136e2565b5b6000613b8784828501613b4e565b91505092915050565b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b613bcd826137f6565b810181811067ffffffffffffffff82111715613bec57613beb613b95565b5b80604052505050565b6000613bff6136d8565b9050613c0b8282613bc4565b919050565b600067ffffffffffffffff821115613c2b57613c2a613b95565b5b602082029050602081019050919050565b600080fd5b600080fd5b600080fd5b600080fd5b600067ffffffffffffffff821115613c6b57613c6a613b95565b5b613c74826137f6565b9050602081019050919050565b82818337600083830152505050565b6000613ca3613c9e84613c50565b613bf5565b905082815260208101848484011115613cbf57613cbe613c4b565b5b613cca848285613c81565b509392505050565b600082601f830112613ce757613ce6613b90565b5b8135613cf7848260208601613c90565b91505092915050565b600060408284031215613d1657613d15613c41565b5b613d206040613bf5565b9050600082013567ffffffffffffffff811115613d4057613d3f613c46565b5b613d4c84828501613cd2565b6000830152506020613d6084828501613883565b60208301525092915050565b6000613d7f613d7a84613c10565b613bf5565b90508083825260208201905060208402830185811115613da257613da1613c3c565b5b835b81811015613de957803567ffffffffffffffff811115613dc757613dc6613b90565b5b808601613dd48982613d00565b85526020850194505050602081019050613da4565b5050509392505050565b600082601f830112613e0857613e07613b90565b5b8135613e18848260208601613d6c565b91505092915050565b60008060408385031215613e3857613e376136e2565b5b6000613e4685828601613883565b925050602083013567ffffffffffffffff811115613e6757613e666136e7565b5b613e7385828601613df3565b9150509250929050565b600067ffffffffffffffff821115613e9857613e97613b95565b5b602082029050602081019050919050565b600060408284031215613ebf57613ebe613c41565b5b613ec96040613bf5565b9050600082013567ffffffffffffffff811115613ee957613ee8613c46565b5b613ef584828501613cd2565b6000830152506020613f0984828501613883565b60208301525092915050565b6000613f28613f2384613e7d565b613bf5565b90508083825260208201905060208402830185811115613f4b57613f4a613c3c565b5b835b81811015613f9257803567ffffffffffffffff811115613f7057613f6f613b90565b5b808601613f7d8982613ea9565b85526020850194505050602081019050613f4d565b5050509392505050565b600082601f830112613fb157613fb0613b90565b5b8135613fc1848260208601613f15565b91505092915050565b600060408284031215613fe057613fdf613c41565b5b613fea6040613bf5565b9050600082013567ffffffffffffffff81111561400a57614009613c46565b5b61401684828501613cd2565b600083015250602082013567ffffffffffffffff81111561403a57614039613c46565b5b61404684828501613f9c565b60208301525092915050565b60008060408385031215614069576140686136e2565b5b600061407785828601613883565b925050602083013567ffffffffffffffff811115614098576140976136e7565b5b6140a485828601613fca565b9150509250929050565b6140b781613771565b81146140c257600080fd5b50565b6000813590506140d4816140ae565b92915050565b600080604083850312156140f1576140f06136e2565b5b60006140ff85828601613938565b9250506020614110858286016140c5565b9150509250929050565b600067ffffffffffffffff82111561413557614134613b95565b5b61413e826137f6565b9050602081019050919050565b600061415e6141598461411a565b613bf5565b90508281526020810184848401111561417a57614179613c4b565b5b614185848285613c81565b509392505050565b600082601f8301126141a2576141a1613b90565b5b81356141b284826020860161414b565b91505092915050565b600080600080608085870312156141d5576141d46136e2565b5b60006141e387828801613938565b94505060206141f487828801613938565b935050604061420587828801613883565b925050606085013567ffffffffffffffff811115614226576142256136e7565b5b6142328782880161418d565b91505092959194509250565b61424781613ab1565b811461425257600080fd5b50565b6000813590506142648161423e565b92915050565b6000602082840312156142805761427f6136e2565b5b600061428e84828501614255565b91505092915050565b60006142a2826139c1565b9050919050565b60006142b482614297565b9050919050565b6142c4816142a9565b82525050565b60006020820190506142df60008301846142bb565b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000600282049050600182168061432c57607f821691505b602082108114156143405761433f6142e5565b5b50919050565b7f4552433732313a20617070726f76656420717565727920666f72206e6f6e657860008201527f697374656e7420746f6b656e0000000000000000000000000000000000000000602082015250565b60006143a2602c836137b2565b91506143ad82614346565b604082019050919050565b600060208201905081810360008301526143d181614395565b9050919050565b7f4552433732313a20617070726f76616c20746f2063757272656e74206f776e6560008201527f7200000000000000000000000000000000000000000000000000000000000000602082015250565b60006144346021836137b2565b915061443f826143d8565b604082019050919050565b6000602082019050818103600083015261446381614427565b9050919050565b7f4552433732313a20617070726f76652063616c6c6572206973206e6f74206f7760008201527f6e6572206e6f7220617070726f76656420666f7220616c6c0000000000000000602082015250565b60006144c66038836137b2565b91506144d18261446a565b604082019050919050565b600060208201905081810360008301526144f5816144b9565b9050919050565b7f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f60008201527f776e6572206e6f7220617070726f766564000000000000000000000000000000602082015250565b60006145586031836137b2565b9150614563826144fc565b604082019050919050565b600060208201905081810360008301526145878161454b565b9050919050565b7f455243373231456e756d657261626c653a206f776e657220696e646578206f7560008201527f74206f6620626f756e6473000000000000000000000000000000000000000000602082015250565b60006145ea602b836137b2565b91506145f58261458e565b604082019050919050565b60006020820190508181036000830152614619816145dd565b9050919050565b60008151905061462f8161386c565b92915050565b60006020828403121561464b5761464a6136e2565b5b600061465984828501614620565b91505092915050565b7f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00600082015250565b6000614698601f836137b2565b91506146a382614662565b602082019050919050565b600060208201905081810360008301526146c78161468b565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061470882613862565b915061471383613862565b925082821015614726576147256146ce565b5b828203905092915050565b7f536f6c64206f7574000000000000000000000000000000000000000000000000600082015250565b60006147676008836137b2565b915061477282614731565b602082019050919050565b600060208201905081810360008301526147968161475a565b9050919050565b60006147a882613862565b91506147b383613862565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156147ec576147eb6146ce565b5b828202905092915050565b7f496e73756666696369656e74207061796d656e74000000000000000000000000600082015250565b600061482d6014836137b2565b9150614838826147f7565b602082019050919050565b6000602082019050818103600083015261485c81614820565b9050919050565b600061486e82613862565b915061487983613862565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff038211156148ae576148ad6146ce565b5b828201905092915050565b60006148c482613862565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8214156148f7576148f66146ce565b5b600182019050919050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b60006149386020836137b2565b915061494382614902565b602082019050919050565b600060208201905081810360008301526149678161492b565b9050919050565b7f455243373231456e756d657261626c653a20676c6f62616c20696e646578206f60008201527f7574206f6620626f756e64730000000000000000000000000000000000000000602082015250565b60006149ca602c836137b2565b91506149d58261496e565b604082019050919050565b600060208201905081810360008301526149f9816149bd565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600081519050614a3e8161423e565b92915050565b600060208284031215614a5a57614a596136e2565b5b6000614a6884828501614a2f565b91505092915050565b6000614a7c826138e5565b9050919050565b614a8c81614a71565b8114614a9757600080fd5b50565b600081519050614aa981614a83565b92915050565b600060208284031215614ac557614ac46136e2565b5b6000614ad384828501614a9a565b91505092915050565b7f4552433732313a206f776e657220717565727920666f72206e6f6e657869737460008201527f656e7420746f6b656e0000000000000000000000000000000000000000000000602082015250565b6000614b386029836137b2565b9150614b4382614adc565b604082019050919050565b60006020820190508181036000830152614b6781614b2b565b9050919050565b7f4552433732313a2062616c616e636520717565727920666f7220746865207a6560008201527f726f206164647265737300000000000000000000000000000000000000000000602082015250565b6000614bca602a836137b2565b9150614bd582614b6e565b604082019050919050565b60006020820190508181036000830152614bf981614bbd565b9050919050565b600082825260208201905092915050565b6000614c1c826137a7565b614c268185614c00565b9350614c368185602086016137c3565b614c3f816137f6565b840191505092915050565b614c5381613862565b82525050565b60006040830160008301518482036000860152614c768282614c11565b9150506020830151614c8b6020860182614c4a565b508091505092915050565b6000604082019050614cab600083018561398d565b8181036020830152614cbd8184614c59565b90509392505050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b60006040830160008301518482036000860152614d0f8282614c11565b9150506020830151614d246020860182614c4a565b508091505092915050565b6000614d3b8383614cf2565b905092915050565b6000602082019050919050565b6000614d5b82614cc6565b614d658185614cd1565b935083602082028501614d7785614ce2565b8060005b85811015614db35784840389528151614d948582614d2f565b9450614d9f83614d43565b925060208a01995050600181019050614d7b565b50829750879550505050505092915050565b60006040830160008301518482036000860152614de28282614c11565b91505060208301518482036020860152614dfc8282614d50565b9150508091505092915050565b6000604082019050614e1e600083018561398d565b8181036020830152614e308184614dc5565b90509392505050565b7f4552433732313a20617070726f766520746f2063616c6c657200000000000000600082015250565b6000614e6f6019836137b2565b9150614e7a82614e39565b602082019050919050565b60006020820190508181036000830152614e9e81614e62565b9050919050565b7f546f6b656e20646f65736e277420657869737400000000000000000000000000600082015250565b6000614edb6013836137b2565b9150614ee682614ea5565b602082019050919050565b60006020820190508181036000830152614f0a81614ece565b9050919050565b600081905092915050565b7f7b00000000000000000000000000000000000000000000000000000000000000600082015250565b6000614f52600183614f11565b9150614f5d82614f1c565b600182019050919050565b7f226e616d65223a20220000000000000000000000000000000000000000000000600082015250565b6000614f9e600983614f11565b9150614fa982614f68565b600982019050919050565b6000614fbf826137a7565b614fc98185614f11565b9350614fd98185602086016137c3565b80840191505092915050565b7f2023000000000000000000000000000000000000000000000000000000000000600082015250565b600061501b600283614f11565b915061502682614fe5565b600282019050919050565b7f222c000000000000000000000000000000000000000000000000000000000000600082015250565b6000615067600283614f11565b915061507282615031565b600282019050919050565b7f22696d616765223a2022646174613a696d6167652f7376672b786d6c3b62617360008201527f6536342c00000000000000000000000000000000000000000000000000000000602082015250565b60006150d9602483614f11565b91506150e48261507d565b602482019050919050565b7f50484e325a79423361575230614430694d5451774d434967614756705a32683060008201527f505349784e4441774969423462577875637a30696148523063446f764c33643360208201527f647935334d793576636d63760000000000000000000000000000000000000000604082015250565b6000615171604c83614f11565b915061517c826150ef565b604c82019050919050565b7f4d6a41774d43397a646d6369494868746247357a4f6e68736157357250534a6f60008201527f644852774f693876643364334c6e637a4c6d39795a7938784f546b354c33687360208201527f61573572496a3438636d566a0000000000000000000000000000000000000000604082015250565b6000615209604c83614f11565b915061521482615187565b604c82019050919050565b7f6443423361575230614430694d5451774d434967614756705a3268305053497860008201527f4e4441774969427a64486c735a5430695a6d6c73624470795a32496f4d43777760208201527f4c4441704f334e30636d39720000000000000000000000000000000000000000604082015250565b60006152a1604c83614f11565b91506152ac8261521f565b604c82019050919050565b7f5a53313361576c6b644767364d4349674c7a34384c334e325a7a343d222c0000600082015250565b60006152ed601e83614f11565b91506152f8826152b7565b601e82019050919050565b7f2261747472696275746573223a205b0000000000000000000000000000000000600082015250565b6000615339600f83614f11565b915061534482615303565b600f82019050919050565b600061535a82614f45565b915061536582614f91565b91506153718285614fb4565b915061537c8261500e565b91506153888284614fb4565b91506153938261505a565b915061539e826150cc565b91506153a982615164565b91506153b4826151fc565b91506153bf82615294565b91506153ca826152e0565b91506153d58261532c565b91508190509392505050565b6000815190506153f0816140ae565b92915050565b60006020828403121561540c5761540b6136e2565b5b600061541a848285016153e1565b91505092915050565b60006154366154318461411a565b613bf5565b90508281526020810184848401111561545257615451613c4b565b5b61545d8482856137c3565b509392505050565b600082601f83011261547a57615479613b90565b5b815161548a848260208601615423565b91505092915050565b6000602082840312156154a9576154a86136e2565b5b600082015167ffffffffffffffff8111156154c7576154c66136e7565b5b6154d384828501615465565b91505092915050565b600081519050919050565b600081905092915050565b60006154fd826154dc565b61550781856154e7565b93506155178185602086016137c3565b80840191505092915050565b7f7b2276616c7565223a202254686520776f726c6420697320626574746572207760008201527f69746820796f7520696e206974227d0000000000000000000000000000000000602082015250565b600061557f602f83614f11565b915061558a82615523565b602f82019050919050565b60006155a182856154f2565b91506155ac82615572565b91506155b882846154f2565b91508190509392505050565b7f7b2276616c7565223a20224157474d493f227d00000000000000000000000000600082015250565b60006155fa601383614f11565b9150615605826155c4565b601382019050919050565b600061561c82846154f2565b9150615627826155ed565b915081905092915050565b7f5d00000000000000000000000000000000000000000000000000000000000000600082015250565b6000615668600183614f11565b915061567382615632565b600182019050919050565b7f7d00000000000000000000000000000000000000000000000000000000000000600082015250565b60006156b4600183614f11565b91506156bf8261567e565b600182019050919050565b60006156d682846154f2565b91506156e18261565b565b91506156ec826156a7565b915081905092915050565b7f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c000000600082015250565b600061572d601d83614f11565b9150615738826156f7565b601d82019050919050565b600061574e82615720565b915061575a8284614fb4565b915081905092915050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b60006157c16026836137b2565b91506157cc82615765565b604082019050919050565b600060208201905081810360008301526157f0816157b4565b9050919050565b7f4552433732313a206f70657261746f7220717565727920666f72206e6f6e657860008201527f697374656e7420746f6b656e0000000000000000000000000000000000000000602082015250565b6000615853602c836137b2565b915061585e826157f7565b604082019050919050565b6000602082019050818103600083015261588281615846565b9050919050565b7f4552433732313a207472616e73666572206f6620746f6b656e2074686174206960008201527f73206e6f74206f776e0000000000000000000000000000000000000000000000602082015250565b60006158e56029836137b2565b91506158f082615889565b604082019050919050565b60006020820190508181036000830152615914816158d8565b9050919050565b7f4552433732313a207472616e7366657220746f20746865207a65726f2061646460008201527f7265737300000000000000000000000000000000000000000000000000000000602082015250565b60006159776024836137b2565b91506159828261591b565b604082019050919050565b600060208201905081810360008301526159a68161596a565b9050919050565b7f5061757361626c653a206e6f7420706175736564000000000000000000000000600082015250565b60006159e36014836137b2565b91506159ee826159ad565b602082019050919050565b60006020820190508181036000830152615a12816159d6565b9050919050565b7f5061757361626c653a2070617573656400000000000000000000000000000000600082015250565b6000615a4f6010836137b2565b9150615a5a82615a19565b602082019050919050565b60006020820190508181036000830152615a7e81615a42565b9050919050565b7f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560008201527f63656976657220696d706c656d656e7465720000000000000000000000000000602082015250565b6000615ae16032836137b2565b9150615aec82615a85565b604082019050919050565b60006020820190508181036000830152615b1081615ad4565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000615b5182613862565b9150615b5c83613862565b925082615b6c57615b6b615b17565b5b828204905092915050565b6000615b8282613862565b9150615b8d83613862565b925082615b9d57615b9c615b17565b5b828206905092915050565b600082825260208201905092915050565b6000615bc4826154dc565b615bce8185615ba8565b9350615bde8185602086016137c3565b615be7816137f6565b840191505092915050565b6000608082019050615c0760008301876138f7565b615c1460208301866138f7565b615c21604083018561398d565b8181036060830152615c338184615bb9565b905095945050505050565b600081519050615c4d81613718565b92915050565b600060208284031215615c6957615c686136e2565b5b6000615c7784828501615c3e565b91505092915050565b7f4552433732315061757361626c653a20746f6b656e207472616e73666572207760008201527f68696c6520706175736564000000000000000000000000000000000000000000602082015250565b6000615cdc602b836137b2565b9150615ce782615c80565b604082019050919050565b60006020820190508181036000830152615d0b81615ccf565b9050919050565b7f4552433732313a206d696e7420746f20746865207a65726f2061646472657373600082015250565b6000615d486020836137b2565b9150615d5382615d12565b602082019050919050565b60006020820190508181036000830152615d7781615d3b565b9050919050565b7f4552433732313a20746f6b656e20616c7265616479206d696e74656400000000600082015250565b6000615db4601c836137b2565b9150615dbf82615d7e565b602082019050919050565b60006020820190508181036000830152615de381615da7565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfe4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2fa26469706673582212205fc5c8265fb8fc07c2b26cdf8270eb45ab16aacebdeb179ace2494903ad87e5864736f6c6343000809003360a06040523480156200001157600080fd5b5060405162002bc538038062002bc5833981810160405281019062000037919062000174565b80620000586200004c6200006860201b60201c565b6200007060201b60201c565b80608081815250505050620001a6565b600033905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b600080fd5b6000819050919050565b6200014e8162000139565b81146200015a57600080fd5b50565b6000815190506200016e8162000143565b92915050565b6000602082840312156200018d576200018c62000134565b5b60006200019d848285016200015d565b91505092915050565b6080516129ee620001d760003960008181610eb5015281816112600152818161144f015261154b01526129ee6000f3fe608060405234801561001057600080fd5b50600436106101005760003560e01c8063a7b21d7511610097578063c2ee3a0811610066578063c2ee3a0814610277578063e24d9e2c14610295578063f2fde38b146102b1578063f47c84c5146102cd57610100565b8063a7b21d7514610203578063ada5f6421461021f578063ae1882fe1461023d578063b85a8b201461025957610100565b8063715018a6116100d3578063715018a61461018d5780638da5cb5b14610197578063922050cc146101b5578063a0d0ddbf146101e557610100565b8063217167ad1461010557806331aa7a70146101215780635404bbf71461015157806361ee40ab1461016f575b600080fd5b61011f600480360381019061011a91906118f4565b6102eb565b005b61013b60048036038101906101369190611950565b610407565b6040516101489190611b57565b60405180910390f35b6101596105d0565b6040516101669190611b92565b60405180910390f35b610177610621565b6040516101849190611bbc565b60405180910390f35b61019561062e565b005b61019f6106b6565b6040516101ac9190611c18565b60405180910390f35b6101cf60048036038101906101ca9190611950565b6106df565b6040516101dc9190611c88565b60405180910390f35b6101ed6109ff565b6040516101fa9190611cc5565b60405180910390f35b61021d60048036038101906102189190611eba565b610a0f565b005b610227610b42565b6040516102349190611bbc565b60405180910390f35b61025760048036038101906102529190611f16565b610b5d565b005b610261610cfa565b60405161026e9190611bbc565b60405180910390f35b61027f610d16565b60405161028c9190611bbc565b60405180910390f35b6102af60048036038101906102aa9190611fb1565b610d33565b005b6102cb60048036038101906102c6919061200a565b610dbb565b005b6102d5610eb3565b6040516102e29190611bbc565b60405180910390f35b6102f3610ed7565b73ffffffffffffffffffffffffffffffffffffffff166103116106b6565b73ffffffffffffffffffffffffffffffffffffffff1614610367576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161035e90612094565b60405180910390fd5b60038054905082146103ae576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103a590612126565b60405180910390fd5b600381908060018154018082558091505060019003906000526020600020906002020160009091909190915060008201518160000190805190602001906103f6929190611631565b506020820151816001015550505050565b61040f6116b7565b6002828154811061042357610422612146565b5b906000526020600020906002020160405180604001604052908160008201805461044c906121a4565b80601f0160208091040260200160405190810160405280929190818152602001828054610478906121a4565b80156104c55780601f1061049a576101008083540402835291602001916104c5565b820191906000526020600020905b8154815290600101906020018083116104a857829003601f168201915b5050505050815260200160018201805480602002602001604051908101604052809291908181526020016000905b828210156105c15783829060005260206000209060020201604051806040016040529081600082018054610526906121a4565b80601f0160208091040260200160405190810160405280929190818152602001828054610552906121a4565b801561059f5780601f106105745761010080835404028352916020019161059f565b820191906000526020600020905b81548152906001019060200180831161058257829003601f168201915b50505050508152602001600182015481525050815260200190600101906104f3565b50505050815250509050919050565b60006105da6109ff565b610619576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161061090612222565b60405180910390fd5b600154905090565b6000600280549050905090565b610636610ed7565b73ffffffffffffffffffffffffffffffffffffffff166106546106b6565b73ffffffffffffffffffffffffffffffffffffffff16146106aa576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106a190612094565b60405180910390fd5b6106b46000610edf565b565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b606060006002805480602002602001604051908101604052809291908181526020016000905b828210156108c45783829060005260206000209060020201604051806040016040529081600082018054610738906121a4565b80601f0160208091040260200160405190810160405280929190818152602001828054610764906121a4565b80156107b15780601f10610786576101008083540402835291602001916107b1565b820191906000526020600020905b81548152906001019060200180831161079457829003601f168201915b5050505050815260200160018201805480602002602001604051908101604052809291908181526020016000905b828210156108ad5783829060005260206000209060020201604051806040016040529081600082018054610812906121a4565b80601f016020809104026020016040519081016040528092919081815260200182805461083e906121a4565b801561088b5780601f106108605761010080835404028352916020019161088b565b820191906000526020600020905b81548152906001019060200180831161086e57829003601f168201915b50505050508152602001600182015481525050815260200190600101906107df565b505050508152505081526020019060010190610705565b50505050905060006003805480602002602001604051908101604052809291908181526020016000905b828210156109bc5783829060005260206000209060020201604051806040016040529081600082018054610921906121a4565b80601f016020809104026020016040519081016040528092919081815260200182805461094d906121a4565b801561099a5780601f1061096f5761010080835404028352916020019161099a565b820191906000526020600020905b81548152906001019060200180831161097d57829003601f168201915b50505050508152602001600182015481525050815260200190600101906108ee565b5050505090506109cc8483610fa3565b6109d68583611005565b6040516020016109e792919061227e565b60405160208183030381529060405292505050919050565b60008060015460001c1415905090565b610a17610ed7565b73ffffffffffffffffffffffffffffffffffffffff16610a356106b6565b73ffffffffffffffffffffffffffffffffffffffff1614610a8b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a8290612094565b60405180910390fd5b6002805490508214610ad2576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ac990612314565b60405180910390fd5b600260018160018154018082558091505003906000526020600020905050806000015160028381548110610b0957610b08612146565b5b90600052602060002090600202016000019080519060200190610b2d929190611631565b50610b3e8260008360200151610b5d565b5050565b766867a5a867f103b2fffa5a71fba0e7b68000000000000081565b610b65610ed7565b73ffffffffffffffffffffffffffffffffffffffff16610b836106b6565b73ffffffffffffffffffffffffffffffffffffffff1614610bd9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bd090612094565b60405180910390fd5b60028381548110610bed57610bec612146565b5b9060005260206000209060020201600101805490508214610c43576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c3a906123a6565b60405180910390fd5b60005b8151811015610cf45760028481548110610c6357610c62612146565b5b9060005260206000209060020201600101828281518110610c8757610c86612146565b5b602002602001015190806001815401808255809150506001900390600052602060002090600202016000909190919091506000820151816000019080519060200190610cd4929190611631565b506020820151816001015550508080610cec906123f5565b915050610c46565b50505050565b7728c87cb5c89a2571ebfdcb54864ada834a0000000000000081565b780fee50b7025c36a0802f236d04753d5b48e80000000000000081565b610d3b610ed7565b73ffffffffffffffffffffffffffffffffffffffff16610d596106b6565b73ffffffffffffffffffffffffffffffffffffffff1614610daf576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610da690612094565b60405180910390fd5b610db881611067565b50565b610dc3610ed7565b73ffffffffffffffffffffffffffffffffffffffff16610de16106b6565b73ffffffffffffffffffffffffffffffffffffffff1614610e37576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e2e90612094565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610ea7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e9e906124b0565b60405180910390fd5b610eb081610edf565b50565b7f000000000000000000000000000000000000000000000000000000000000000081565b600033905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b6060610ffd8383600067ffffffffffffffff811115610fc557610fc461174e565b5b6040519080825280601f01601f191660200182016040528015610ff75781602001600182028036833780820191505090505b506110b9565b905092915050565b606061105f8383600067ffffffffffffffff8111156110275761102661174e565b5b6040519080825280601f01601f1916602001820160405280156110595781602001600182028036833780820191505090505b50611259565b905092915050565b61106f6109ff565b156110af576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110a69061251c565b60405180910390fd5b8060018190555050565b60606000606060005b855181101561124c57600061111786898985815181106110e5576110e4612146565b5b60200260200101516000015160405160200161110393929190612575565b604051602081830303815290604052611360565b90506000935060005b87838151811061113357611132612146565b5b602002602001015160200151518110156112375787838151811061115a57611159612146565b5b602002602001015160200151818151811061117857611177612146565b5b6020026020010151602001518561118f91906125ba565b945084821161122457836111fd8985815181106111af576111ae612146565b5b6020026020010151600001518a86815181106111ce576111cd612146565b5b60200260200101516020015184815181106111ec576111eb612146565b5b602002602001015160000151611410565b60405160200161120e92919061227e565b6040516020818303038152906040529350611237565b808061122f906123f5565b915050611120565b50508080611244906123f5565b9150506110c2565b5080925050509392505050565b60606000807f000000000000000000000000000000000000000000000000000000000000000090505b600081111561129c576001820191508060011c9050611282565b600060018360026112ad9190612743565b6112b7919061278e565b9050606060005b8751811015611351576112ee898983815181106112de576112dd612146565b5b602002602001015187868b61143c565b1561133e578161131b89838151811061130a57611309612146565b5b6020026020010151600001516115e9565b60405160200161132c92919061227e565b60405160208183030381529060405291505b8080611349906123f5565b9150506112be565b50809450505050509392505050565b600080780fffffffffffffffffffffffffffffffffffffffffffffffff905060005b780fee50b7025c36a0802f236d04753d5b48e8000000000000008211156114065760015484826040516020016113ba939291906127c2565b6040516020818303038152906040528051906020012060001c9150780fffffffffffffffffffffffffffffffffffffffffffffffff8216915080806113fe906123f5565b915050611382565b5080915050919050565b60608282604051602001611425929190612920565b604051602081830303815290604052905092915050565b60008060009050600080600090506000807f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff8111156114875761148661174e565b5b6040519080825280602002602001820160405280156114b55781602001602082028036833780820191505090505b50905060005b8a602001518110156115d5575b6001156115c2578984101561152357876001548c60000151886040516020016114f49493929190612965565b6040516020818303038152906040528051906020012060001c9450858061151a906123f5565b96505061010093505b8885169250848a1c945089840393508b83141561154957600196505050505050506115e0565b7f00000000000000000000000000000000000000000000000000000000000000008310611575576114c8565b81838151811061158857611587612146565b5b60200260200101511561159a576114c8565b60018284815181106115af576115ae612146565b5b6020026020010190151590811515815250505b80806115cd906123f5565b9150506114bb565b506000955050505050505b95945050505050565b606061162a6040518060400160405280600a81526020017f4c6f6f6b7320526172650000000000000000000000000000000000000000000081525083611410565b9050919050565b82805461163d906121a4565b90600052602060002090601f01602090048101928261165f57600085556116a6565b82601f1061167857805160ff19168380011785556116a6565b828001600101855582156116a6579182015b828111156116a557825182559160200191906001019061168a565b5b5090506116b391906116d1565b5090565b604051806040016040528060608152602001606081525090565b5b808211156116ea5760008160009055506001016116d2565b5090565b6000604051905090565b600080fd5b600080fd5b6000819050919050565b61171581611702565b811461172057600080fd5b50565b6000813590506117328161170c565b92915050565b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6117868261173d565b810181811067ffffffffffffffff821117156117a5576117a461174e565b5b80604052505050565b60006117b86116ee565b90506117c4828261177d565b919050565b600080fd5b600080fd5b600080fd5b600067ffffffffffffffff8211156117f3576117f261174e565b5b6117fc8261173d565b9050602081019050919050565b82818337600083830152505050565b600061182b611826846117d8565b6117ae565b905082815260208101848484011115611847576118466117d3565b5b611852848285611809565b509392505050565b600082601f83011261186f5761186e6117ce565b5b813561187f848260208601611818565b91505092915050565b60006040828403121561189e5761189d611738565b5b6118a860406117ae565b9050600082013567ffffffffffffffff8111156118c8576118c76117c9565b5b6118d48482850161185a565b60008301525060206118e884828501611723565b60208301525092915050565b6000806040838503121561190b5761190a6116f8565b5b600061191985828601611723565b925050602083013567ffffffffffffffff81111561193a576119396116fd565b5b61194685828601611888565b9150509250929050565b600060208284031215611966576119656116f8565b5b600061197484828501611723565b91505092915050565b600081519050919050565b600082825260208201905092915050565b60005b838110156119b757808201518184015260208101905061199c565b838111156119c6576000848401525b50505050565b60006119d78261197d565b6119e18185611988565b93506119f1818560208601611999565b6119fa8161173d565b840191505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b611a3a81611702565b82525050565b60006040830160008301518482036000860152611a5d82826119cc565b9150506020830151611a726020860182611a31565b508091505092915050565b6000611a898383611a40565b905092915050565b6000602082019050919050565b6000611aa982611a05565b611ab38185611a10565b935083602082028501611ac585611a21565b8060005b85811015611b015784840389528151611ae28582611a7d565b9450611aed83611a91565b925060208a01995050600181019050611ac9565b50829750879550505050505092915050565b60006040830160008301518482036000860152611b3082826119cc565b91505060208301518482036020860152611b4a8282611a9e565b9150508091505092915050565b60006020820190508181036000830152611b718184611b13565b905092915050565b6000819050919050565b611b8c81611b79565b82525050565b6000602082019050611ba76000830184611b83565b92915050565b611bb681611702565b82525050565b6000602082019050611bd16000830184611bad565b92915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000611c0282611bd7565b9050919050565b611c1281611bf7565b82525050565b6000602082019050611c2d6000830184611c09565b92915050565b600081519050919050565b600082825260208201905092915050565b6000611c5a82611c33565b611c648185611c3e565b9350611c74818560208601611999565b611c7d8161173d565b840191505092915050565b60006020820190508181036000830152611ca28184611c4f565b905092915050565b60008115159050919050565b611cbf81611caa565b82525050565b6000602082019050611cda6000830184611cb6565b92915050565b600067ffffffffffffffff821115611cfb57611cfa61174e565b5b602082029050602081019050919050565b600080fd5b600060408284031215611d2757611d26611738565b5b611d3160406117ae565b9050600082013567ffffffffffffffff811115611d5157611d506117c9565b5b611d5d8482850161185a565b6000830152506020611d7184828501611723565b60208301525092915050565b6000611d90611d8b84611ce0565b6117ae565b90508083825260208201905060208402830185811115611db357611db2611d0c565b5b835b81811015611dfa57803567ffffffffffffffff811115611dd857611dd76117ce565b5b808601611de58982611d11565b85526020850194505050602081019050611db5565b5050509392505050565b600082601f830112611e1957611e186117ce565b5b8135611e29848260208601611d7d565b91505092915050565b600060408284031215611e4857611e47611738565b5b611e5260406117ae565b9050600082013567ffffffffffffffff811115611e7257611e716117c9565b5b611e7e8482850161185a565b600083015250602082013567ffffffffffffffff811115611ea257611ea16117c9565b5b611eae84828501611e04565b60208301525092915050565b60008060408385031215611ed157611ed06116f8565b5b6000611edf85828601611723565b925050602083013567ffffffffffffffff811115611f0057611eff6116fd565b5b611f0c85828601611e32565b9150509250929050565b600080600060608486031215611f2f57611f2e6116f8565b5b6000611f3d86828701611723565b9350506020611f4e86828701611723565b925050604084013567ffffffffffffffff811115611f6f57611f6e6116fd565b5b611f7b86828701611e04565b9150509250925092565b611f8e81611b79565b8114611f9957600080fd5b50565b600081359050611fab81611f85565b92915050565b600060208284031215611fc757611fc66116f8565b5b6000611fd584828501611f9c565b91505092915050565b611fe781611bf7565b8114611ff257600080fd5b50565b60008135905061200481611fde565b92915050565b6000602082840312156120205761201f6116f8565b5b600061202e84828501611ff5565b91505092915050565b600082825260208201905092915050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b600061207e602083612037565b915061208982612048565b602082019050919050565b600060208201905081810360008301526120ad81612071565b9050919050565b7f52616e646f6d417474726962757465733a20696e76616c696420616c6c6f636160008201527f74656420696e6465780000000000000000000000000000000000000000000000602082015250565b6000612110602983612037565b915061211b826120b4565b604082019050919050565b6000602082019050818103600083015261213f81612103565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b600060028204905060018216806121bc57607f821691505b602082108114156121d0576121cf612175565b5b50919050565b7f456e74726f7079206e6f74207365740000000000000000000000000000000000600082015250565b600061220c600f83612037565b9150612217826121d6565b602082019050919050565b6000602082019050818103600083015261223b816121ff565b9050919050565b600081905092915050565b600061225882611c33565b6122628185612242565b9350612272818560208601611999565b80840191505092915050565b600061228a828561224d565b9150612296828461224d565b91508190509392505050565b7f52616e646f6d417474726962757465733a20696e76616c69642074696572656460008201527f20696e6465780000000000000000000000000000000000000000000000000000602082015250565b60006122fe602683612037565b9150612309826122a2565b604082019050919050565b6000602082019050818103600083015261232d816122f1565b9050919050565b7f52616e646f6d417474726962757465733a20696e76616c69642073746172744960008201527f6e64657800000000000000000000000000000000000000000000000000000000602082015250565b6000612390602483612037565b915061239b82612334565b604082019050919050565b600060208201905081810360008301526123bf81612383565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061240082611702565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821415612433576124326123c6565b5b600182019050919050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b600061249a602683612037565b91506124a58261243e565b604082019050919050565b600060208201905081810360008301526124c98161248d565b9050919050565b7f456e74726f707920616c72656164792073657400000000000000000000000000600082015250565b6000612506601383612037565b9150612511826124d0565b602082019050919050565b60006020820190508181036000830152612535816124f9565b9050919050565b60006125478261197d565b6125518185612037565b9350612561818560208601611999565b61256a8161173d565b840191505092915050565b6000606082019050818103600083015261258f8186611c4f565b905061259e6020830185611bad565b81810360408301526125b0818461253c565b9050949350505050565b60006125c582611702565b91506125d083611702565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03821115612605576126046123c6565b5b828201905092915050565b60008160011c9050919050565b6000808291508390505b600185111561266757808604811115612643576126426123c6565b5b60018516156126525780820291505b808102905061266085612610565b9450612627565b94509492505050565b600082612680576001905061273c565b8161268e576000905061273c565b81600181146126a457600281146126ae576126dd565b600191505061273c565b60ff8411156126c0576126bf6123c6565b5b8360020a9150848211156126d7576126d66123c6565b5b5061273c565b5060208310610133831016604e8410600b84101617156127125782820a90508381111561270d5761270c6123c6565b5b61273c565b61271f848484600161261d565b92509050818404811115612736576127356123c6565b5b81810290505b9392505050565b600061274e82611702565b915061275983611702565b92506127867fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8484612670565b905092915050565b600061279982611702565b91506127a483611702565b9250828210156127b7576127b66123c6565b5b828203905092915050565b60006060820190506127d76000830186611b83565b81810360208301526127e98185611c4f565b90506127f86040830184611bad565b949350505050565b600081905092915050565b7f2c7b2274726169745f74797065223a2022000000000000000000000000000000600082015250565b6000612841601183612800565b915061284c8261280b565b601182019050919050565b60006128628261197d565b61286c8185612800565b935061287c818560208601611999565b80840191505092915050565b7f222c202276616c7565223a202200000000000000000000000000000000000000600082015250565b60006128be600d83612800565b91506128c982612888565b600d82019050919050565b7f227d000000000000000000000000000000000000000000000000000000000000600082015250565b600061290a600283612800565b9150612915826128d4565b600282019050919050565b600061292b82612834565b91506129378285612857565b9150612942826128b1565b915061294e8284612857565b9150612959826128fd565b91508190509392505050565b6000608082019050818103600083015261297f8187611c4f565b905061298e6020830186611b83565b81810360408301526129a0818561253c565b90506129af6060830184611bad565b9594505050505056fea26469706673582212205b62e392c4bf9ee02aee3493ea664070f1667ca72124c9e7ba060f01efe2af7c64736f6c6343000809003300000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000a5409ec958c83c3f309868babaca7c86dcb077c100000000000000000000000000000000000000000000000000000000000026f1000000000000000000000000be02b9ee0d4c0c13ea622fa82411033cf369dd50000000000000000000000000000000000000000000000000000000000000000c426c61636b205371756172650000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b424c41434b535155415245000000000000000000000000000000000000000000

Deployed Bytecode

0x60806040526004361061021a5760003560e01c80636352211e11610123578063a22cb465116100ab578063e8a3d4851161006f578063e8a3d485146107c4578063e985e9c5146107ef578063ed4a6b0c1461082c578063f2fde38b14610857578063f47c84c5146108805761021a565b8063a22cb465146106e1578063b88d4fde1461070a578063c002d23d14610733578063c87b56dd1461075e578063e24d9e2c1461079b5761021a565b80638456cb59116100f25780638456cb59146106225780638a7ac5c7146106395780638da5cb5b1461066257806395d89b411461068d57806396b83514146106b85761021a565b80636352211e146105685780636b29b79f146105a557806370a08231146105ce578063715018a61461060b5761021a565b80632f745c59116101a657806342842e0e1161017557806342842e0e1461046f5780634f6ccce7146104985780635404bbf7146104d55780635c975abb146105005780636102de981461052b5761021a565b80632f745c59146103d45780632f7b19151461041157806331c864e81461043c5780633f4ba83a146104585761021a565b80630aaef285116101ed5780630aaef285146102ed5780630cc96d521461031857806318160ddd146103435780631e7269c51461036e57806323b872dd146103ab5761021a565b806301ffc9a71461021f57806306fdde031461025c578063081812fc14610287578063095ea7b3146102c4575b600080fd5b34801561022b57600080fd5b5061024660048036038101906102419190613744565b6108ab565b604051610253919061378c565b60405180910390f35b34801561026857600080fd5b506102716108bd565b60405161027e9190613840565b60405180910390f35b34801561029357600080fd5b506102ae60048036038101906102a99190613898565b61094f565b6040516102bb9190613906565b60405180910390f35b3480156102d057600080fd5b506102eb60048036038101906102e6919061394d565b6109d4565b005b3480156102f957600080fd5b50610302610aec565b60405161030f919061399c565b60405180910390f35b34801561032457600080fd5b5061032d610af1565b60405161033a9190613a16565b60405180910390f35b34801561034f57600080fd5b50610358610b15565b604051610365919061399c565b60405180910390f35b34801561037a57600080fd5b5061039560048036038101906103909190613a31565b610b22565b6040516103a2919061399c565b60405180910390f35b3480156103b757600080fd5b506103d260048036038101906103cd9190613a5e565b610b3a565b005b3480156103e057600080fd5b506103fb60048036038101906103f6919061394d565b610b9a565b604051610408919061399c565b60405180910390f35b34801561041d57600080fd5b50610426610c3f565b604051610433919061399c565b60405180910390f35b61045660048036038101906104519190613898565b610ce4565b005b34801561046457600080fd5b5061046d6110bf565b005b34801561047b57600080fd5b5061049660048036038101906104919190613a5e565b611145565b005b3480156104a457600080fd5b506104bf60048036038101906104ba9190613898565b611165565b6040516104cc919061399c565b60405180910390f35b3480156104e157600080fd5b506104ea6111d6565b6040516104f79190613aca565b60405180910390f35b34801561050c57600080fd5b5061051561127b565b604051610522919061378c565b60405180910390f35b34801561053757600080fd5b50610552600480360381019061054d9190613ae5565b611292565b60405161055f919061378c565b60405180910390f35b34801561057457600080fd5b5061058f600480360381019061058a9190613898565b6113b3565b60405161059c9190613906565b60405180910390f35b3480156105b157600080fd5b506105cc60048036038101906105c79190613b63565b611465565b005b3480156105da57600080fd5b506105f560048036038101906105f09190613a31565b611525565b604051610602919061399c565b60405180910390f35b34801561061757600080fd5b506106206115dd565b005b34801561062e57600080fd5b50610637611665565b005b34801561064557600080fd5b50610660600480360381019061065b9190613e21565b6116eb565b005b34801561066e57600080fd5b5061067761183d565b6040516106849190613906565b60405180910390f35b34801561069957600080fd5b506106a2611867565b6040516106af9190613840565b60405180910390f35b3480156106c457600080fd5b506106df60048036038101906106da9190614052565b6118f9565b005b3480156106ed57600080fd5b50610708600480360381019061070391906140da565b611a06565b005b34801561071657600080fd5b50610731600480360381019061072c91906141bb565b611b87565b005b34801561073f57600080fd5b50610748611be9565b604051610755919061399c565b60405180910390f35b34801561076a57600080fd5b5061078560048036038101906107809190613898565b611bf5565b6040516107929190613840565b60405180910390f35b3480156107a757600080fd5b506107c260048036038101906107bd919061426a565b611e62565b005b3480156107d057600080fd5b506107d9611f6c565b6040516107e69190613840565b60405180910390f35b3480156107fb57600080fd5b5061081660048036038101906108119190613ae5565b611ffe565b604051610823919061378c565b60405180910390f35b34801561083857600080fd5b50610841612023565b60405161084e91906142ca565b60405180910390f35b34801561086357600080fd5b5061087e60048036038101906108799190613a31565b612049565b005b34801561088c57600080fd5b50610895612141565b6040516108a2919061399c565b60405180910390f35b60006108b6826121a9565b9050919050565b6060600280546108cc90614314565b80601f01602080910402602001604051908101604052809291908181526020018280546108f890614314565b80156109455780601f1061091a57610100808354040283529160200191610945565b820191906000526020600020905b81548152906001019060200180831161092857829003601f168201915b5050505050905090565b600061095a82612223565b610999576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610990906143b8565b60405180910390fd5b6006600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b60006109df826113b3565b90508073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610a50576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a479061444a565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff16610a6f61228f565b73ffffffffffffffffffffffffffffffffffffffff161480610a9e5750610a9d81610a9861228f565b611ffe565b5b610add576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ad4906144dc565b60405180910390fd5b610ae78383612297565b505050565b600a81565b7f0000000000000000000000006e9e94bc2fb2b129e38d322d4060da30aff0efde81565b6000600a80549050905090565b600f6020528060005260406000206000915090505481565b610b4b610b4561228f565b82612350565b610b8a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b819061456e565b60405180910390fd5b610b9583838361242e565b505050565b6000610ba583611525565b8210610be6576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bdd90614600565b60405180910390fd5b600860008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600083815260200190815260200160002054905092915050565b60007f0000000000000000000000006e9e94bc2fb2b129e38d322d4060da30aff0efde73ffffffffffffffffffffffffffffffffffffffff1663ada5f6426040518163ffffffff1660e01b815260040160206040518083038186803b158015610ca757600080fd5b505afa158015610cbb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cdf9190614635565b905090565b6002600d541415610d2a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d21906146ae565b60405180910390fd5b6002600d81905550610d7281336040518060400160405280600c81526020017f53656e646572206c696d6974000000000000000000000000000000000000000081525061268a565b90503273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610dea57610de781326040518060400160405280600c81526020017f4f726967696e206c696d6974000000000000000000000000000000000000000081525061268a565b90505b6000610df4610b15565b90506000817f00000000000000000000000000000000000000000000000000000000000026f1610e2491906146fd565b905060008111610e69576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e609061477d565b60405180910390fd5b80831115610e75578092505b600067016345785d8a000084610e8b919061479d565b905080341015610ed0576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ec790614843565b60405180910390fd5b83600f60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254610f1f9190614863565b925050819055503273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610fb05783600f60003273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254610fa89190614863565b925050819055505b60008484610fbe9190614863565b90505b80841015610fe657610fd3338561273f565b8380610fde906148b9565b945050610fc1565b50600e60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f1935050505015801561104f573d6000803e3d6000fd5b50803411156110b15760003390508073ffffffffffffffffffffffffffffffffffffffff166108fc833461108391906146fd565b9081150290604051600060405180830381858888f193505050501580156110ae573d6000803e3d6000fd5b50505b5050506001600d8190555050565b6110c761228f565b73ffffffffffffffffffffffffffffffffffffffff166110e561183d565b73ffffffffffffffffffffffffffffffffffffffff161461113b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111329061494e565b60405180910390fd5b61114361275d565b565b61116083838360405180602001604052806000815250611b87565b505050565b600061116f610b15565b82106111b0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111a7906149e0565b60405180910390fd5b600a82815481106111c4576111c3614a00565b5b90600052602060002001549050919050565b60007f0000000000000000000000006e9e94bc2fb2b129e38d322d4060da30aff0efde73ffffffffffffffffffffffffffffffffffffffff16635404bbf76040518163ffffffff1660e01b815260040160206040518083038186803b15801561123e57600080fd5b505afa158015611252573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112769190614a44565b905090565b6000600c60149054906101000a900460ff16905090565b600080600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141580156113aa57508273ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1663c4552791866040518263ffffffff1660e01b81526004016113429190613906565b60206040518083038186803b15801561135a57600080fd5b505afa15801561136e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113929190614aaf565b73ffffffffffffffffffffffffffffffffffffffff16145b91505092915050565b6000806004600084815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561145c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161145390614b4e565b60405180910390fd5b80915050919050565b61146d61228f565b73ffffffffffffffffffffffffffffffffffffffff1661148b61183d565b73ffffffffffffffffffffffffffffffffffffffff16146114e1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016114d89061494e565b60405180910390fd5b80600e60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415611596576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161158d90614be0565b60405180910390fd5b600560008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b6115e561228f565b73ffffffffffffffffffffffffffffffffffffffff1661160361183d565b73ffffffffffffffffffffffffffffffffffffffff1614611659576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016116509061494e565b60405180910390fd5b61166360006127ff565b565b61166d61228f565b73ffffffffffffffffffffffffffffffffffffffff1661168b61183d565b73ffffffffffffffffffffffffffffffffffffffff16146116e1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016116d89061494e565b60405180910390fd5b6116e96128c5565b565b6116f361228f565b73ffffffffffffffffffffffffffffffffffffffff1661171161183d565b73ffffffffffffffffffffffffffffffffffffffff1614611767576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161175e9061494e565b60405180910390fd5b60005b8151811015611838577f0000000000000000000000006e9e94bc2fb2b129e38d322d4060da30aff0efde73ffffffffffffffffffffffffffffffffffffffff1663217167ad82856117bb9190614863565b8484815181106117ce576117cd614a00565b5b60200260200101516040518363ffffffff1660e01b81526004016117f3929190614c96565b600060405180830381600087803b15801561180d57600080fd5b505af1158015611821573d6000803e3d6000fd5b505050508080611830906148b9565b91505061176a565b505050565b6000600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60606003805461187690614314565b80601f01602080910402602001604051908101604052809291908181526020018280546118a290614314565b80156118ef5780601f106118c4576101008083540402835291602001916118ef565b820191906000526020600020905b8154815290600101906020018083116118d257829003601f168201915b5050505050905090565b61190161228f565b73ffffffffffffffffffffffffffffffffffffffff1661191f61183d565b73ffffffffffffffffffffffffffffffffffffffff1614611975576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161196c9061494e565b60405180910390fd5b7f0000000000000000000000006e9e94bc2fb2b129e38d322d4060da30aff0efde73ffffffffffffffffffffffffffffffffffffffff1663a7b21d7583836040518363ffffffff1660e01b81526004016119d0929190614e09565b600060405180830381600087803b1580156119ea57600080fd5b505af11580156119fe573d6000803e3d6000fd5b505050505050565b611a0e61228f565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415611a7c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a7390614e85565b60405180910390fd5b8060076000611a8961228f565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff16611b3661228f565b73ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3183604051611b7b919061378c565b60405180910390a35050565b611b98611b9261228f565b83612350565b611bd7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611bce9061456e565b60405180910390fd5b611be384848484612968565b50505050565b67016345785d8a000081565b6060611c0082612223565b611c3f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c3690614ef1565b60405180910390fd5b6000611c496108bd565b611c52846129c4565b604051602001611c6392919061534f565b60405160208183030381529060405290507f0000000000000000000000006e9e94bc2fb2b129e38d322d4060da30aff0efde73ffffffffffffffffffffffffffffffffffffffff1663a0d0ddbf6040518163ffffffff1660e01b815260040160206040518083038186803b158015611cda57600080fd5b505afa158015611cee573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d1291906153f6565b15611ded57807f0000000000000000000000006e9e94bc2fb2b129e38d322d4060da30aff0efde73ffffffffffffffffffffffffffffffffffffffff1663922050cc856040518263ffffffff1660e01b8152600401611d71919061399c565b60006040518083038186803b158015611d8957600080fd5b505afa158015611d9d573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190611dc69190615493565b604051602001611dd7929190615595565b6040516020818303038152906040529050611e10565b80604051602001611dfe9190615610565b60405160208183030381529060405290505b80604051602001611e2191906156ca565b6040516020818303038152906040529050611e3b81612b25565b604051602001611e4b9190615743565b604051602081830303815290604052915050919050565b611e6a61228f565b73ffffffffffffffffffffffffffffffffffffffff16611e8861183d565b73ffffffffffffffffffffffffffffffffffffffff1614611ede576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ed59061494e565b60405180910390fd5b7f0000000000000000000000006e9e94bc2fb2b129e38d322d4060da30aff0efde73ffffffffffffffffffffffffffffffffffffffff1663e24d9e2c826040518263ffffffff1660e01b8152600401611f379190613aca565b600060405180830381600087803b158015611f5157600080fd5b505af1158015611f65573d6000803e3d6000fd5b5050505050565b606060008054611f7b90614314565b80601f0160208091040260200160405190810160405280929190818152602001828054611fa790614314565b8015611ff45780601f10611fc957610100808354040283529160200191611ff4565b820191906000526020600020905b815481529060010190602001808311611fd757829003601f168201915b5050505050905090565b600061200a8383612c9e565b8061201b575061201a8383611292565b5b905092915050565b600e60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b61205161228f565b73ffffffffffffffffffffffffffffffffffffffff1661206f61183d565b73ffffffffffffffffffffffffffffffffffffffff16146120c5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016120bc9061494e565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415612135576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161212c906157d7565b60405180910390fd5b61213e816127ff565b50565b7f00000000000000000000000000000000000000000000000000000000000026f181565b80600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b60007f780e9d63000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916148061221c575061221b82612d32565b5b9050919050565b60008073ffffffffffffffffffffffffffffffffffffffff166004600084815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614159050919050565b600033905090565b816006600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff1661230a836113b3565b73ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b600061235b82612223565b61239a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161239190615869565b60405180910390fd5b60006123a5836113b3565b90508073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16148061241457508373ffffffffffffffffffffffffffffffffffffffff166123fc8461094f565b73ffffffffffffffffffffffffffffffffffffffff16145b8061242557506124248185611ffe565b5b91505092915050565b8273ffffffffffffffffffffffffffffffffffffffff1661244e826113b3565b73ffffffffffffffffffffffffffffffffffffffff16146124a4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161249b906158fb565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415612514576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161250b9061598d565b60405180910390fd5b61251f838383612e14565b61252a600082612297565b6001600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825461257a91906146fd565b925050819055506001600560008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546125d19190614863565b92505081905550816004600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4505050565b600080600f60008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054600a6126d991906146fd565b9050600081118390612721576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016127189190613840565b60405180910390fd5b50808511156127335780915050612738565b849150505b9392505050565b612759828260405180602001604052806000815250612e24565b5050565b61276561127b565b6127a4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161279b906159f9565b60405180910390fd5b6000600c60146101000a81548160ff0219169083151502179055507f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa6127e861228f565b6040516127f59190613906565b60405180910390a1565b6000600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600c60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b6128cd61127b565b1561290d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161290490615a65565b60405180910390fd5b6001600c60146101000a81548160ff0219169083151502179055507f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a25861295161228f565b60405161295e9190613906565b60405180910390a1565b61297384848461242e565b61297f84848484612e7f565b6129be576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016129b590615af7565b60405180910390fd5b50505050565b60606000821415612a0c576040518060400160405280600181526020017f30000000000000000000000000000000000000000000000000000000000000008152509050612b20565b600082905060005b60008214612a3e578080612a27906148b9565b915050600a82612a379190615b46565b9150612a14565b60008167ffffffffffffffff811115612a5a57612a59613b95565b5b6040519080825280601f01601f191660200182016040528015612a8c5781602001600182028036833780820191505090505b5090505b60008514612b1957600182612aa591906146fd565b9150600a85612ab49190615b77565b6030612ac09190614863565b60f81b818381518110612ad657612ad5614a00565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600a85612b129190615b46565b9450612a90565b8093505050505b919050565b6060600082511415612b4857604051806020016040528060008152509050612c99565b6000604051806060016040528060408152602001615e1a6040913990506000600360028551612b779190614863565b612b819190615b46565b6004612b8d919061479d565b90506000602082612b9e9190614863565b67ffffffffffffffff811115612bb757612bb6613b95565b5b6040519080825280601f01601f191660200182016040528015612be95781602001600182028036833780820191505090505b509050818152600183018586518101602084015b81831015612c58576003830192508251603f8160121c168501518253600182019150603f81600c1c168501518253600182019150603f8160061c168501518253600182019150603f8116850151825360018201915050612bfd565b600389510660018114612c725760028114612c8257612c8d565b613d3d60f01b6002830352612c8d565b603d60f81b60018303525b50505050508093505050505b919050565b6000600760008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b60007f80ac58cd000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480612dfd57507f5b5e139f000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b80612e0d5750612e0c82613016565b5b9050919050565b612e1f838383613080565b505050565b612e2e83836130d8565b612e3b6000848484612e7f565b612e7a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612e7190615af7565b60405180910390fd5b505050565b6000612ea08473ffffffffffffffffffffffffffffffffffffffff166132a6565b15613009578373ffffffffffffffffffffffffffffffffffffffff1663150b7a02612ec961228f565b8786866040518563ffffffff1660e01b8152600401612eeb9493929190615bf2565b602060405180830381600087803b158015612f0557600080fd5b505af1925050508015612f3657506040513d601f19601f82011682018060405250810190612f339190615c53565b60015b612fb9573d8060008114612f66576040519150601f19603f3d011682016040523d82523d6000602084013e612f6b565b606091505b50600081511415612fb1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612fa890615af7565b60405180910390fd5b805181602001fd5b63150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161491505061300e565b600190505b949350505050565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b61308b8383836132b9565b61309361127b565b156130d3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016130ca90615cf2565b60405180910390fd5b505050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415613148576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161313f90615d5e565b60405180910390fd5b61315181612223565b15613191576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161318890615dca565b60405180910390fd5b61319d60008383612e14565b6001600560008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546131ed9190614863565b92505081905550816004600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a45050565b600080823b905060008111915050919050565b6132c48383836133cd565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16141561330757613302816133d2565b613346565b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161461334557613344838261341b565b5b5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614156133895761338481613588565b6133c8565b8273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16146133c7576133c68282613659565b5b5b505050565b505050565b600a80549050600b600083815260200190815260200160002081905550600a81908060018154018082558091505060019003906000526020600020016000909190919091505550565b6000600161342884611525565b61343291906146fd565b9050600060096000848152602001908152602001600020549050818114613517576000600860008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600084815260200190815260200160002054905080600860008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600084815260200190815260200160002081905550816009600083815260200190815260200160002081905550505b6009600084815260200190815260200160002060009055600860008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008381526020019081526020016000206000905550505050565b60006001600a8054905061359c91906146fd565b90506000600b60008481526020019081526020016000205490506000600a83815481106135cc576135cb614a00565b5b9060005260206000200154905080600a83815481106135ee576135ed614a00565b5b906000526020600020018190555081600b600083815260200190815260200160002081905550600b600085815260200190815260200160002060009055600a80548061363d5761363c615dea565b5b6001900381819060005260206000200160009055905550505050565b600061366483611525565b905081600860008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600083815260200190815260200160002081905550806009600084815260200190815260200160002081905550505050565b6000604051905090565b600080fd5b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b613721816136ec565b811461372c57600080fd5b50565b60008135905061373e81613718565b92915050565b60006020828403121561375a576137596136e2565b5b60006137688482850161372f565b91505092915050565b60008115159050919050565b61378681613771565b82525050565b60006020820190506137a1600083018461377d565b92915050565b600081519050919050565b600082825260208201905092915050565b60005b838110156137e15780820151818401526020810190506137c6565b838111156137f0576000848401525b50505050565b6000601f19601f8301169050919050565b6000613812826137a7565b61381c81856137b2565b935061382c8185602086016137c3565b613835816137f6565b840191505092915050565b6000602082019050818103600083015261385a8184613807565b905092915050565b6000819050919050565b61387581613862565b811461388057600080fd5b50565b6000813590506138928161386c565b92915050565b6000602082840312156138ae576138ad6136e2565b5b60006138bc84828501613883565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006138f0826138c5565b9050919050565b613900816138e5565b82525050565b600060208201905061391b60008301846138f7565b92915050565b61392a816138e5565b811461393557600080fd5b50565b60008135905061394781613921565b92915050565b60008060408385031215613964576139636136e2565b5b600061397285828601613938565b925050602061398385828601613883565b9150509250929050565b61399681613862565b82525050565b60006020820190506139b1600083018461398d565b92915050565b6000819050919050565b60006139dc6139d76139d2846138c5565b6139b7565b6138c5565b9050919050565b60006139ee826139c1565b9050919050565b6000613a00826139e3565b9050919050565b613a10816139f5565b82525050565b6000602082019050613a2b6000830184613a07565b92915050565b600060208284031215613a4757613a466136e2565b5b6000613a5584828501613938565b91505092915050565b600080600060608486031215613a7757613a766136e2565b5b6000613a8586828701613938565b9350506020613a9686828701613938565b9250506040613aa786828701613883565b9150509250925092565b6000819050919050565b613ac481613ab1565b82525050565b6000602082019050613adf6000830184613abb565b92915050565b60008060408385031215613afc57613afb6136e2565b5b6000613b0a85828601613938565b9250506020613b1b85828601613938565b9150509250929050565b6000613b30826138c5565b9050919050565b613b4081613b25565b8114613b4b57600080fd5b50565b600081359050613b5d81613b37565b92915050565b600060208284031215613b7957613b786136e2565b5b6000613b8784828501613b4e565b91505092915050565b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b613bcd826137f6565b810181811067ffffffffffffffff82111715613bec57613beb613b95565b5b80604052505050565b6000613bff6136d8565b9050613c0b8282613bc4565b919050565b600067ffffffffffffffff821115613c2b57613c2a613b95565b5b602082029050602081019050919050565b600080fd5b600080fd5b600080fd5b600080fd5b600067ffffffffffffffff821115613c6b57613c6a613b95565b5b613c74826137f6565b9050602081019050919050565b82818337600083830152505050565b6000613ca3613c9e84613c50565b613bf5565b905082815260208101848484011115613cbf57613cbe613c4b565b5b613cca848285613c81565b509392505050565b600082601f830112613ce757613ce6613b90565b5b8135613cf7848260208601613c90565b91505092915050565b600060408284031215613d1657613d15613c41565b5b613d206040613bf5565b9050600082013567ffffffffffffffff811115613d4057613d3f613c46565b5b613d4c84828501613cd2565b6000830152506020613d6084828501613883565b60208301525092915050565b6000613d7f613d7a84613c10565b613bf5565b90508083825260208201905060208402830185811115613da257613da1613c3c565b5b835b81811015613de957803567ffffffffffffffff811115613dc757613dc6613b90565b5b808601613dd48982613d00565b85526020850194505050602081019050613da4565b5050509392505050565b600082601f830112613e0857613e07613b90565b5b8135613e18848260208601613d6c565b91505092915050565b60008060408385031215613e3857613e376136e2565b5b6000613e4685828601613883565b925050602083013567ffffffffffffffff811115613e6757613e666136e7565b5b613e7385828601613df3565b9150509250929050565b600067ffffffffffffffff821115613e9857613e97613b95565b5b602082029050602081019050919050565b600060408284031215613ebf57613ebe613c41565b5b613ec96040613bf5565b9050600082013567ffffffffffffffff811115613ee957613ee8613c46565b5b613ef584828501613cd2565b6000830152506020613f0984828501613883565b60208301525092915050565b6000613f28613f2384613e7d565b613bf5565b90508083825260208201905060208402830185811115613f4b57613f4a613c3c565b5b835b81811015613f9257803567ffffffffffffffff811115613f7057613f6f613b90565b5b808601613f7d8982613ea9565b85526020850194505050602081019050613f4d565b5050509392505050565b600082601f830112613fb157613fb0613b90565b5b8135613fc1848260208601613f15565b91505092915050565b600060408284031215613fe057613fdf613c41565b5b613fea6040613bf5565b9050600082013567ffffffffffffffff81111561400a57614009613c46565b5b61401684828501613cd2565b600083015250602082013567ffffffffffffffff81111561403a57614039613c46565b5b61404684828501613f9c565b60208301525092915050565b60008060408385031215614069576140686136e2565b5b600061407785828601613883565b925050602083013567ffffffffffffffff811115614098576140976136e7565b5b6140a485828601613fca565b9150509250929050565b6140b781613771565b81146140c257600080fd5b50565b6000813590506140d4816140ae565b92915050565b600080604083850312156140f1576140f06136e2565b5b60006140ff85828601613938565b9250506020614110858286016140c5565b9150509250929050565b600067ffffffffffffffff82111561413557614134613b95565b5b61413e826137f6565b9050602081019050919050565b600061415e6141598461411a565b613bf5565b90508281526020810184848401111561417a57614179613c4b565b5b614185848285613c81565b509392505050565b600082601f8301126141a2576141a1613b90565b5b81356141b284826020860161414b565b91505092915050565b600080600080608085870312156141d5576141d46136e2565b5b60006141e387828801613938565b94505060206141f487828801613938565b935050604061420587828801613883565b925050606085013567ffffffffffffffff811115614226576142256136e7565b5b6142328782880161418d565b91505092959194509250565b61424781613ab1565b811461425257600080fd5b50565b6000813590506142648161423e565b92915050565b6000602082840312156142805761427f6136e2565b5b600061428e84828501614255565b91505092915050565b60006142a2826139c1565b9050919050565b60006142b482614297565b9050919050565b6142c4816142a9565b82525050565b60006020820190506142df60008301846142bb565b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000600282049050600182168061432c57607f821691505b602082108114156143405761433f6142e5565b5b50919050565b7f4552433732313a20617070726f76656420717565727920666f72206e6f6e657860008201527f697374656e7420746f6b656e0000000000000000000000000000000000000000602082015250565b60006143a2602c836137b2565b91506143ad82614346565b604082019050919050565b600060208201905081810360008301526143d181614395565b9050919050565b7f4552433732313a20617070726f76616c20746f2063757272656e74206f776e6560008201527f7200000000000000000000000000000000000000000000000000000000000000602082015250565b60006144346021836137b2565b915061443f826143d8565b604082019050919050565b6000602082019050818103600083015261446381614427565b9050919050565b7f4552433732313a20617070726f76652063616c6c6572206973206e6f74206f7760008201527f6e6572206e6f7220617070726f76656420666f7220616c6c0000000000000000602082015250565b60006144c66038836137b2565b91506144d18261446a565b604082019050919050565b600060208201905081810360008301526144f5816144b9565b9050919050565b7f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f60008201527f776e6572206e6f7220617070726f766564000000000000000000000000000000602082015250565b60006145586031836137b2565b9150614563826144fc565b604082019050919050565b600060208201905081810360008301526145878161454b565b9050919050565b7f455243373231456e756d657261626c653a206f776e657220696e646578206f7560008201527f74206f6620626f756e6473000000000000000000000000000000000000000000602082015250565b60006145ea602b836137b2565b91506145f58261458e565b604082019050919050565b60006020820190508181036000830152614619816145dd565b9050919050565b60008151905061462f8161386c565b92915050565b60006020828403121561464b5761464a6136e2565b5b600061465984828501614620565b91505092915050565b7f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00600082015250565b6000614698601f836137b2565b91506146a382614662565b602082019050919050565b600060208201905081810360008301526146c78161468b565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061470882613862565b915061471383613862565b925082821015614726576147256146ce565b5b828203905092915050565b7f536f6c64206f7574000000000000000000000000000000000000000000000000600082015250565b60006147676008836137b2565b915061477282614731565b602082019050919050565b600060208201905081810360008301526147968161475a565b9050919050565b60006147a882613862565b91506147b383613862565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156147ec576147eb6146ce565b5b828202905092915050565b7f496e73756666696369656e74207061796d656e74000000000000000000000000600082015250565b600061482d6014836137b2565b9150614838826147f7565b602082019050919050565b6000602082019050818103600083015261485c81614820565b9050919050565b600061486e82613862565b915061487983613862565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff038211156148ae576148ad6146ce565b5b828201905092915050565b60006148c482613862565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8214156148f7576148f66146ce565b5b600182019050919050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b60006149386020836137b2565b915061494382614902565b602082019050919050565b600060208201905081810360008301526149678161492b565b9050919050565b7f455243373231456e756d657261626c653a20676c6f62616c20696e646578206f60008201527f7574206f6620626f756e64730000000000000000000000000000000000000000602082015250565b60006149ca602c836137b2565b91506149d58261496e565b604082019050919050565b600060208201905081810360008301526149f9816149bd565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600081519050614a3e8161423e565b92915050565b600060208284031215614a5a57614a596136e2565b5b6000614a6884828501614a2f565b91505092915050565b6000614a7c826138e5565b9050919050565b614a8c81614a71565b8114614a9757600080fd5b50565b600081519050614aa981614a83565b92915050565b600060208284031215614ac557614ac46136e2565b5b6000614ad384828501614a9a565b91505092915050565b7f4552433732313a206f776e657220717565727920666f72206e6f6e657869737460008201527f656e7420746f6b656e0000000000000000000000000000000000000000000000602082015250565b6000614b386029836137b2565b9150614b4382614adc565b604082019050919050565b60006020820190508181036000830152614b6781614b2b565b9050919050565b7f4552433732313a2062616c616e636520717565727920666f7220746865207a6560008201527f726f206164647265737300000000000000000000000000000000000000000000602082015250565b6000614bca602a836137b2565b9150614bd582614b6e565b604082019050919050565b60006020820190508181036000830152614bf981614bbd565b9050919050565b600082825260208201905092915050565b6000614c1c826137a7565b614c268185614c00565b9350614c368185602086016137c3565b614c3f816137f6565b840191505092915050565b614c5381613862565b82525050565b60006040830160008301518482036000860152614c768282614c11565b9150506020830151614c8b6020860182614c4a565b508091505092915050565b6000604082019050614cab600083018561398d565b8181036020830152614cbd8184614c59565b90509392505050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b60006040830160008301518482036000860152614d0f8282614c11565b9150506020830151614d246020860182614c4a565b508091505092915050565b6000614d3b8383614cf2565b905092915050565b6000602082019050919050565b6000614d5b82614cc6565b614d658185614cd1565b935083602082028501614d7785614ce2565b8060005b85811015614db35784840389528151614d948582614d2f565b9450614d9f83614d43565b925060208a01995050600181019050614d7b565b50829750879550505050505092915050565b60006040830160008301518482036000860152614de28282614c11565b91505060208301518482036020860152614dfc8282614d50565b9150508091505092915050565b6000604082019050614e1e600083018561398d565b8181036020830152614e308184614dc5565b90509392505050565b7f4552433732313a20617070726f766520746f2063616c6c657200000000000000600082015250565b6000614e6f6019836137b2565b9150614e7a82614e39565b602082019050919050565b60006020820190508181036000830152614e9e81614e62565b9050919050565b7f546f6b656e20646f65736e277420657869737400000000000000000000000000600082015250565b6000614edb6013836137b2565b9150614ee682614ea5565b602082019050919050565b60006020820190508181036000830152614f0a81614ece565b9050919050565b600081905092915050565b7f7b00000000000000000000000000000000000000000000000000000000000000600082015250565b6000614f52600183614f11565b9150614f5d82614f1c565b600182019050919050565b7f226e616d65223a20220000000000000000000000000000000000000000000000600082015250565b6000614f9e600983614f11565b9150614fa982614f68565b600982019050919050565b6000614fbf826137a7565b614fc98185614f11565b9350614fd98185602086016137c3565b80840191505092915050565b7f2023000000000000000000000000000000000000000000000000000000000000600082015250565b600061501b600283614f11565b915061502682614fe5565b600282019050919050565b7f222c000000000000000000000000000000000000000000000000000000000000600082015250565b6000615067600283614f11565b915061507282615031565b600282019050919050565b7f22696d616765223a2022646174613a696d6167652f7376672b786d6c3b62617360008201527f6536342c00000000000000000000000000000000000000000000000000000000602082015250565b60006150d9602483614f11565b91506150e48261507d565b602482019050919050565b7f50484e325a79423361575230614430694d5451774d434967614756705a32683060008201527f505349784e4441774969423462577875637a30696148523063446f764c33643360208201527f647935334d793576636d63760000000000000000000000000000000000000000604082015250565b6000615171604c83614f11565b915061517c826150ef565b604c82019050919050565b7f4d6a41774d43397a646d6369494868746247357a4f6e68736157357250534a6f60008201527f644852774f693876643364334c6e637a4c6d39795a7938784f546b354c33687360208201527f61573572496a3438636d566a0000000000000000000000000000000000000000604082015250565b6000615209604c83614f11565b915061521482615187565b604c82019050919050565b7f6443423361575230614430694d5451774d434967614756705a3268305053497860008201527f4e4441774969427a64486c735a5430695a6d6c73624470795a32496f4d43777760208201527f4c4441704f334e30636d39720000000000000000000000000000000000000000604082015250565b60006152a1604c83614f11565b91506152ac8261521f565b604c82019050919050565b7f5a53313361576c6b644767364d4349674c7a34384c334e325a7a343d222c0000600082015250565b60006152ed601e83614f11565b91506152f8826152b7565b601e82019050919050565b7f2261747472696275746573223a205b0000000000000000000000000000000000600082015250565b6000615339600f83614f11565b915061534482615303565b600f82019050919050565b600061535a82614f45565b915061536582614f91565b91506153718285614fb4565b915061537c8261500e565b91506153888284614fb4565b91506153938261505a565b915061539e826150cc565b91506153a982615164565b91506153b4826151fc565b91506153bf82615294565b91506153ca826152e0565b91506153d58261532c565b91508190509392505050565b6000815190506153f0816140ae565b92915050565b60006020828403121561540c5761540b6136e2565b5b600061541a848285016153e1565b91505092915050565b60006154366154318461411a565b613bf5565b90508281526020810184848401111561545257615451613c4b565b5b61545d8482856137c3565b509392505050565b600082601f83011261547a57615479613b90565b5b815161548a848260208601615423565b91505092915050565b6000602082840312156154a9576154a86136e2565b5b600082015167ffffffffffffffff8111156154c7576154c66136e7565b5b6154d384828501615465565b91505092915050565b600081519050919050565b600081905092915050565b60006154fd826154dc565b61550781856154e7565b93506155178185602086016137c3565b80840191505092915050565b7f7b2276616c7565223a202254686520776f726c6420697320626574746572207760008201527f69746820796f7520696e206974227d0000000000000000000000000000000000602082015250565b600061557f602f83614f11565b915061558a82615523565b602f82019050919050565b60006155a182856154f2565b91506155ac82615572565b91506155b882846154f2565b91508190509392505050565b7f7b2276616c7565223a20224157474d493f227d00000000000000000000000000600082015250565b60006155fa601383614f11565b9150615605826155c4565b601382019050919050565b600061561c82846154f2565b9150615627826155ed565b915081905092915050565b7f5d00000000000000000000000000000000000000000000000000000000000000600082015250565b6000615668600183614f11565b915061567382615632565b600182019050919050565b7f7d00000000000000000000000000000000000000000000000000000000000000600082015250565b60006156b4600183614f11565b91506156bf8261567e565b600182019050919050565b60006156d682846154f2565b91506156e18261565b565b91506156ec826156a7565b915081905092915050565b7f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c000000600082015250565b600061572d601d83614f11565b9150615738826156f7565b601d82019050919050565b600061574e82615720565b915061575a8284614fb4565b915081905092915050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b60006157c16026836137b2565b91506157cc82615765565b604082019050919050565b600060208201905081810360008301526157f0816157b4565b9050919050565b7f4552433732313a206f70657261746f7220717565727920666f72206e6f6e657860008201527f697374656e7420746f6b656e0000000000000000000000000000000000000000602082015250565b6000615853602c836137b2565b915061585e826157f7565b604082019050919050565b6000602082019050818103600083015261588281615846565b9050919050565b7f4552433732313a207472616e73666572206f6620746f6b656e2074686174206960008201527f73206e6f74206f776e0000000000000000000000000000000000000000000000602082015250565b60006158e56029836137b2565b91506158f082615889565b604082019050919050565b60006020820190508181036000830152615914816158d8565b9050919050565b7f4552433732313a207472616e7366657220746f20746865207a65726f2061646460008201527f7265737300000000000000000000000000000000000000000000000000000000602082015250565b60006159776024836137b2565b91506159828261591b565b604082019050919050565b600060208201905081810360008301526159a68161596a565b9050919050565b7f5061757361626c653a206e6f7420706175736564000000000000000000000000600082015250565b60006159e36014836137b2565b91506159ee826159ad565b602082019050919050565b60006020820190508181036000830152615a12816159d6565b9050919050565b7f5061757361626c653a2070617573656400000000000000000000000000000000600082015250565b6000615a4f6010836137b2565b9150615a5a82615a19565b602082019050919050565b60006020820190508181036000830152615a7e81615a42565b9050919050565b7f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560008201527f63656976657220696d706c656d656e7465720000000000000000000000000000602082015250565b6000615ae16032836137b2565b9150615aec82615a85565b604082019050919050565b60006020820190508181036000830152615b1081615ad4565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000615b5182613862565b9150615b5c83613862565b925082615b6c57615b6b615b17565b5b828204905092915050565b6000615b8282613862565b9150615b8d83613862565b925082615b9d57615b9c615b17565b5b828206905092915050565b600082825260208201905092915050565b6000615bc4826154dc565b615bce8185615ba8565b9350615bde8185602086016137c3565b615be7816137f6565b840191505092915050565b6000608082019050615c0760008301876138f7565b615c1460208301866138f7565b615c21604083018561398d565b8181036060830152615c338184615bb9565b905095945050505050565b600081519050615c4d81613718565b92915050565b600060208284031215615c6957615c686136e2565b5b6000615c7784828501615c3e565b91505092915050565b7f4552433732315061757361626c653a20746f6b656e207472616e73666572207760008201527f68696c6520706175736564000000000000000000000000000000000000000000602082015250565b6000615cdc602b836137b2565b9150615ce782615c80565b604082019050919050565b60006020820190508181036000830152615d0b81615ccf565b9050919050565b7f4552433732313a206d696e7420746f20746865207a65726f2061646472657373600082015250565b6000615d486020836137b2565b9150615d5382615d12565b602082019050919050565b60006020820190508181036000830152615d7781615d3b565b9050919050565b7f4552433732313a20746f6b656e20616c7265616479206d696e74656400000000600082015250565b6000615db4601c836137b2565b9150615dbf82615d7e565b602082019050919050565b60006020820190508181036000830152615de381615da7565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfe4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2fa26469706673582212205fc5c8265fb8fc07c2b26cdf8270eb45ab16aacebdeb179ace2494903ad87e5864736f6c63430008090033

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

00000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000a5409ec958c83c3f309868babaca7c86dcb077c100000000000000000000000000000000000000000000000000000000000026f1000000000000000000000000be02b9ee0d4c0c13ea622fa82411033cf369dd50000000000000000000000000000000000000000000000000000000000000000c426c61636b205371756172650000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b424c41434b535155415245000000000000000000000000000000000000000000

-----Decoded View---------------
Arg [0] : name (string): Black Square
Arg [1] : symbol (string): BLACKSQUARE
Arg [2] : openSeaProxyRegistry (address): 0xa5409ec958C83C3f309868babACA7c86DCB077c1
Arg [3] : maxTokens (uint256): 9969
Arg [4] : _paymentSplitter (address): 0xbe02b9Ee0d4c0c13ea622Fa82411033cF369dD50

-----Encoded View---------------
9 Constructor Arguments found :
Arg [0] : 00000000000000000000000000000000000000000000000000000000000000a0
Arg [1] : 00000000000000000000000000000000000000000000000000000000000000e0
Arg [2] : 000000000000000000000000a5409ec958c83c3f309868babaca7c86dcb077c1
Arg [3] : 00000000000000000000000000000000000000000000000000000000000026f1
Arg [4] : 000000000000000000000000be02b9ee0d4c0c13ea622fa82411033cf369dd50
Arg [5] : 000000000000000000000000000000000000000000000000000000000000000c
Arg [6] : 426c61636b205371756172650000000000000000000000000000000000000000
Arg [7] : 000000000000000000000000000000000000000000000000000000000000000b
Arg [8] : 424c41434b535155415245000000000000000000000000000000000000000000


Loading...
Loading
Loading...
Loading
[ Download: CSV Export  ]
[ Download: CSV Export  ]

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