Contract 0x9d27527Ada2CF29fBDAB2973cfa243845a08Bd3F

 
 
Txn Hash
Method
Block
From
To
Value
0xd035c4c0c11382eaaf1db5a92f35f7267390a14eb4d759f07073505348b0ec1eSafe Transfer Fr...157726242022-10-18 4:32:3539 days 17 hrs ago0x83a02ea2176473ebcaf5ba4f03c929f79c63d871 IN  0x9d27527ada2cf29fbdab2973cfa243845a08bd3f0 Ether0.00240327 16.94032251
0x696e04025755e537d4c2b3cb9d4b8797f631eb9dab71326d517000701640c561Set Approval For...153895242022-08-22 9:39:2196 days 12 hrs agoENS Name jameschu.eth IN  0x9d27527ada2cf29fbdab2973cfa243845a08bd3f0 Ether0.00042305 9.15650887
0xa9d1695a37938290496a249730cfc951473eb48bb2c43d6fa8baa90c79ddb6c6Set Approval For...153258192022-08-12 7:58:16106 days 13 hrs agoENS Name kkkou2022.eth IN  0x9d27527ada2cf29fbdab2973cfa243845a08bd3f0 Ether0.00076502 16.58800918
0x7331c327ca38ab4810e04065d16b778a4eab86c37ea2af02c242d46992e8c3a7Safe Transfer Fr...152701862022-08-03 15:14:23115 days 6 hrs ago0xb19bc46c52a1352a071fe2389503b6fe1abd50ff IN  0x9d27527ada2cf29fbdab2973cfa243845a08bd3f0 Ether0.00265434 18.70854082
0xbcbb5ae8511130fb3473828ae43c7da61b4d70c92303091b21f251c86797e2f7Transfer From152582482022-08-01 18:20:17117 days 3 hrs ago0xc887fadc6baaa8cd234d9104a65b37265522b024 IN  0x9d27527ada2cf29fbdab2973cfa243845a08bd3f0 Ether0.00172524 16.02565896
0x0910249c3294b53eabb67c1d9645a5416f77b8e4993bb3c0a083586d45e18e84Set Approval For...151205762022-07-11 9:37:13138 days 12 hrs ago0xcbf340596c0c85cd737397fe81aa0e30f4dcb534 IN  0x9d27527ada2cf29fbdab2973cfa243845a08bd3f0 Ether0.00046114 9.99895486
0xc5f531a50d75e28a47eaaca8ddf9ffbe6e09fe0f144e4db3a09c541f374e12f7Delegate150411712022-06-28 19:10:20151 days 2 hrs agoENS Name 6120.eth IN  0x9d27527ada2cf29fbdab2973cfa243845a08bd3f0 Ether0.00196876 40.33273206
0x68222e1cc27e064a0934e12415a0331713b30dbbb9114e69d0cd42b5b4c5f50bSet Approval For...149909942022-06-19 13:25:38160 days 8 hrs agoENS Name firumu.eth IN  0x9d27527ada2cf29fbdab2973cfa243845a08bd3f0 Ether0.00138071 29.93799113
0x3678f9f68fc098a80366e38d23c735935eab39a727c9a317a35609eb09298d5fTransfer From148480402022-05-26 12:48:39184 days 8 hrs ago0xc887fadc6baaa8cd234d9104a65b37265522b024 IN  0x9d27527ada2cf29fbdab2973cfa243845a08bd3f0 Ether0.01001484 69.59199407
0x2173dd19c519a888a819ef990fe2f9f5dda5378d77b2768e6b4994c823cafc5bSet Approval For...147058322022-05-03 16:54:31207 days 4 hrs agoENS Name hk1.eth IN  0x9d27527ada2cf29fbdab2973cfa243845a08bd3f0 Ether0.0018218275
0x362c46c415d32648dc450b45a8906f511183b15a5444f8f374de72da9d3ad648Transfer From145933632022-04-16 1:16:48224 days 20 hrs agoENS Name nickholo.eth IN  0x9d27527ada2cf29fbdab2973cfa243845a08bd3f0 Ether0.0068002 48.88854681
0x618dac6438bd764c6da5c994f12b6d56c399cff0c8aee26f7e5092b498fed12aSet Approval For...145118412022-04-03 7:26:51237 days 14 hrs agoENS Name ardana.eth IN  0x9d27527ada2cf29fbdab2973cfa243845a08bd3f0 Ether0.00164522 35.60857926
0x15ab7d5b683fe3e54164d7c938647f7c6b03219e024b46cc329b83d9d4fc96e1Transfer From144736752022-03-28 8:38:03243 days 13 hrs agoENS Name tankbottoms.eth IN  0x9d27527ada2cf29fbdab2973cfa243845a08bd3f0 Ether0.00433467 30.12368324
0x4a8ffc8221eec0d564a9c94b75258528a40c61dde0011bf6b8f0186f5e192a04Safe Transfer Fr...144423922022-03-23 11:55:31248 days 9 hrs agoENS Name silicium.eth IN  0x9d27527ada2cf29fbdab2973cfa243845a08bd3f0 Ether0.00279304 19.68778161
0x610b5001a57cbb67a2222d0ac8eda192ef2a34758f0af0619bed321afeb4fa3cSafe Transfer Fr...144038482022-03-17 11:48:25254 days 9 hrs ago0x230eb64900d027dfe372786b3342bd6178ec37d1 IN  0x9d27527ada2cf29fbdab2973cfa243845a08bd3f0 Ether0.00223092 20.20505606
0x3757ae912c6460be47eaa4a0b05bd4fe41a8ca05712a0bf64c4b2121bfd719adSet Approval For...142379862022-02-19 18:09:06280 days 3 hrs ago0x925f40905fa191f623e905bdbe18d25c5d465734 IN  0x9d27527ada2cf29fbdab2973cfa243845a08bd3f0 Ether0.00371537 80.41416657
0xc339fa719e67e91c4c32ccd217f733dc0c64209456b04da9e8f9458b259ab06eSet Approval For...142379192022-02-19 17:57:03280 days 3 hrs ago0x925f40905fa191f623e905bdbe18d25c5d465734 IN  0x9d27527ada2cf29fbdab2973cfa243845a08bd3f0 Ether0.00360423 78.00874285
0x8791a5cdd573487c4dcffd0109317a9297b22774b28678b157d1c973176efc53Set Approval For...142162792022-02-16 9:17:58283 days 12 hrs ago0xbce41c9c58e0ad33f0f975ea1a89ec070bf94df3 IN  0x9d27527ada2cf29fbdab2973cfa243845a08bd3f0 Ether0.00260346 56.34841092
0x6ec1ee7eeba9c73a7929207e02d47f8b17826d542571ce8a379df4ce838975d2Set Approval For...142158842022-02-16 7:42:16283 days 14 hrs agoENS Name jonathanc.eth IN  0x9d27527ada2cf29fbdab2973cfa243845a08bd3f0 Ether0.0021674 46.9104155
0x584212f910ddf55d330ed858acbd52b5ebdd0c3f9bf5b9438809ad92b2e501b6Transfer From141529002022-02-06 13:54:07293 days 7 hrs ago0x0a26e8a4305ad5d9e6844e9d2aad05262b1285e6 IN  0x9d27527ada2cf29fbdab2973cfa243845a08bd3f0 Ether0.00727293 67.55777751
0xa5778945f94bb220ad42af56010e9e6b712de93077e3c16c334f4a0bf694017aSet Approval For...139839752022-01-11 11:36:35319 days 10 hrs agoENS Name jameschu.eth IN  0x9d27527ada2cf29fbdab2973cfa243845a08bd3f0 Ether0.00541298 117.15650392
0x1feac515924861f7d37b7dc1946c06a381ebb415354cd5d0f27ad26bf64d2535Set Approval For...139787382022-01-10 16:04:59320 days 5 hrs agoENS Name sulemain.eth IN  0x9d27527ada2cf29fbdab2973cfa243845a08bd3f0 Ether0.01123641 243.19666496
0x5d87be7f537e6590e841d114dd47cbc01e3ec48c3580b1cddfc3908c6068ef3eSet Approval For...139772912022-01-10 10:42:19320 days 11 hrs agoENS Name hk1.eth IN  0x9d27527ada2cf29fbdab2973cfa243845a08bd3f0 Ether0.01637194 354.34804768
0xacb23d0fd8e5a5c8efd1d073af70482c6f9fe390454bbad457cd590e22931ed3Set Approval For...139772492022-01-10 10:31:48320 days 11 hrs agoENS Name kaibao.eth IN  0x9d27527ada2cf29fbdab2973cfa243845a08bd3f0 Ether0.01284015 277.907369
0x075700672466207ccccd29b23bd3b678888c26bdd6aed283454b522024f81cc9Set Approval For...139771692022-01-10 10:14:38320 days 11 hrs ago0xb616340a10f14218e5db19cdadda686a9557658b IN  0x9d27527ada2cf29fbdab2973cfa243845a08bd3f0 Ether0.0096555 208.98009945
[ Download CSV Export 
View more zero value Internal Transactions in Advanced View mode
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.

Contract Source Code Verified (Exact Match)

Contract Name:
Bleeps

Compiler Version
v0.8.9+commit.e5eed63a

Optimization Enabled:
Yes with 999999 runs

Other Settings:
default evmVersion, MIT license
File 1 of 17 : IERC1271.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC1271 standard signature validation method for
 * contracts as defined in https://eips.ethereum.org/EIPS/eip-1271[ERC-1271].
 *
 * _Available since v4.1._
 */
interface IERC1271 {
    /**
     * @dev Should return whether the signature provided is valid for the provided data
     * @param hash      Hash of the data to be signed
     * @param signature Signature byte array associated with _data
     */
    function isValidSignature(bytes32 hash, bytes memory signature) external view returns (bytes4 magicValue);
}

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

pragma solidity ^0.8.0;

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

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

pragma solidity ^0.8.0;

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

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

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

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

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

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

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

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

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

pragma solidity ^0.8.0;

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

File 6 of 17 : 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 7 of 17 : ECDSA.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

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

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

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

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

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

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

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

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

        return (signer, RecoverError.NoError);
    }

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

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

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

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

pragma solidity ^0.8.0;

import "./ECDSA.sol";
import "../Address.sol";
import "../../interfaces/IERC1271.sol";

/**
 * @dev Signature verification helper: Provide a single mechanism to verify both private-key (EOA) ECDSA signature and
 * ERC1271 contract sigantures. Using this instead of ECDSA.recover in your contract will make them compatible with
 * smart contract wallets such as Argent and Gnosis.
 *
 * Note: unlike ECDSA signatures, contract signature's are revocable, and the outcome of this function can thus change
 * through time. It could return true at block N and false at block N+1 (or the opposite).
 *
 * _Available since v4.1._
 */
library SignatureChecker {
    function isValidSignatureNow(
        address signer,
        bytes32 hash,
        bytes memory signature
    ) internal view returns (bool) {
        (address recovered, ECDSA.RecoverError error) = ECDSA.tryRecover(hash, signature);
        if (error == ECDSA.RecoverError.NoError && recovered == signer) {
            return true;
        }

        (bool success, bytes memory result) = signer.staticcall(
            abi.encodeWithSelector(IERC1271.isValidSignature.selector, hash, signature)
        );
        return (success && result.length == 32 && abi.decode(result, (bytes4)) == IERC1271.isValidSignature.selector);
    }
}

File 9 of 17 : 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 10 of 17 : ERC721Base.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.9;

import "@openzeppelin/contracts/utils/Address.sol";
import "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol";
import "@openzeppelin/contracts/token/ERC721/IERC721.sol";
import "@openzeppelin/contracts/interfaces/IERC165.sol";

abstract contract ERC721Base is IERC165, IERC721 {
    using Address for address;

    bytes4 internal constant ERC721_RECEIVED = 0x150b7a02;
    bytes4 internal constant ERC165ID = 0x01ffc9a7;

    uint256 internal constant OPERATOR_FLAG = 0x8000000000000000000000000000000000000000000000000000000000000000;
    uint256 internal constant NOT_OPERATOR_FLAG = 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;

    mapping(uint256 => uint256) internal _owners;
    mapping(address => uint256) internal _balances;
    mapping(address => mapping(address => bool)) internal _operatorsForAll;
    mapping(uint256 => address) internal _operators;

    function name() public pure virtual returns (string memory) {
        revert("NOT_IMPLEMENTED");
    }

    /// @notice Approve an operator to transfer a specific token on the senders behalf.
    /// @param operator The address receiving the approval.
    /// @param id The id of the token.
    function approve(address operator, uint256 id) external override {
        (address owner, uint256 blockNumber) = _ownerAndBlockNumberOf(id);
        require(owner != address(0), "NONEXISTENT_TOKEN");
        require(msg.sender == owner || isApprovedForAll(owner, msg.sender), "UNAUTHORIZED_APPROVAL");
        _approveFor(owner, blockNumber, operator, id);
    }

    /// @notice Transfer a token between 2 addresses.
    /// @param from The sender of the token.
    /// @param to The recipient of the token.
    /// @param id The id of the token.
    function transferFrom(
        address from,
        address to,
        uint256 id
    ) external override {
        (address owner, bool operatorEnabled) = _ownerAndOperatorEnabledOf(id);
        require(owner != address(0), "NONEXISTENT_TOKEN");
        require(owner == from, "NOT_OWNER");
        require(to != address(0), "NOT_TO_ZEROADDRESS");
        require(to != address(this), "NOT_TO_THIS");
        if (msg.sender != from) {
            require(
                (operatorEnabled && _operators[id] == msg.sender) || isApprovedForAll(from, msg.sender),
                "UNAUTHORIZED_TRANSFER"
            );
        }
        _transferFrom(from, to, id);
    }

    /// @notice Transfer a token between 2 addresses letting the receiver know of the transfer.
    /// @param from The send of the token.
    /// @param to The recipient of the token.
    /// @param id The id of the token.
    function safeTransferFrom(
        address from,
        address to,
        uint256 id
    ) external override {
        safeTransferFrom(from, to, id, "");
    }

    /// @notice Set the approval for an operator to manage all the tokens of the sender.
    /// @param operator The address receiving the approval.
    /// @param approved The determination of the approval.
    function setApprovalForAll(address operator, bool approved) external override {
        _setApprovalForAll(msg.sender, operator, approved);
    }

    /// @notice Get the number of tokens owned by an address.
    /// @param owner The address to look for.
    /// @return balance The number of tokens owned by the address.
    function balanceOf(address owner) public view override returns (uint256 balance) {
        require(owner != address(0), "ZERO_ADDRESS_OWNER");
        balance = _balances[owner];
    }

    /// @notice Get the owner of a token.
    /// @param id The id of the token.
    /// @return owner The address of the token owner.
    function ownerOf(uint256 id) external view override returns (address owner) {
        owner = _ownerOf(id);
        require(owner != address(0), "NONEXISTENT_TOKEN");
    }

    /// @notice Get the owner of a token and the blockNumber of the last transfer, useful to voting mechanism.
    /// @param id The id of the token.
    /// @return owner The address of the token owner.
    /// @return blockNumber The blocknumber at which the last transfer of that id happened.
    function ownerAndLastTransferBlockNumberOf(uint256 id) internal view returns (address owner, uint256 blockNumber) {
        return _ownerAndBlockNumberOf(id);
    }

    struct OwnerData {
        address owner;
        uint256 lastTransferBlockNumber;
    }

    /// @notice Get the list of owner of a token and the blockNumber of its last transfer, useful to voting mechanism.
    /// @param ids The list of token ids to check.
    /// @return ownersData The list of (owner, lastTransferBlockNumber) for each ids given as input.
    function ownerAndLastTransferBlockNumberList(uint256[] calldata ids)
        external
        view
        returns (OwnerData[] memory ownersData)
    {
        ownersData = new OwnerData[](ids.length);
        for (uint256 i = 0; i < ids.length; i++) {
            uint256 data = _owners[ids[i]];
            ownersData[i].owner = address(uint160(data));
            ownersData[i].lastTransferBlockNumber = (data >> 160) & 0xFFFFFFFFFFFFFFFFFFFFFF;
        }
    }

    /// @notice Get the approved operator for a specific token.
    /// @param id The id of the token.
    /// @return The address of the operator.
    function getApproved(uint256 id) external view override returns (address) {
        (address owner, bool operatorEnabled) = _ownerAndOperatorEnabledOf(id);
        require(owner != address(0), "NONEXISTENT_TOKEN");
        if (operatorEnabled) {
            return _operators[id];
        } else {
            return address(0);
        }
    }

    /// @notice Check if the sender approved the operator.
    /// @param owner The address of the owner.
    /// @param operator The address of the operator.
    /// @return isOperator The status of the approval.
    function isApprovedForAll(address owner, address operator) public view virtual override returns (bool isOperator) {
        return _operatorsForAll[owner][operator];
    }

    /// @notice Transfer a token between 2 addresses letting the receiver knows of the transfer.
    /// @param from The sender of the token.
    /// @param to The recipient of the token.
    /// @param id The id of the token.
    /// @param data Additional data.
    function safeTransferFrom(
        address from,
        address to,
        uint256 id,
        bytes memory data
    ) public override {
        (address owner, bool operatorEnabled) = _ownerAndOperatorEnabledOf(id);
        require(owner != address(0), "NONEXISTENT_TOKEN");
        require(owner == from, "NOT_OWNER");
        require(to != address(0), "NOT_TO_ZEROADDRESS");
        require(to != address(this), "NOT_TO_THIS");
        if (msg.sender != from) {
            require(
                (operatorEnabled && _operators[id] == msg.sender) || isApprovedForAll(from, msg.sender),
                "UNAUTHORIZED_TRANSFER"
            );
        }
        _safeTransferFrom(from, to, id, data);
    }

    /// @notice Check if the contract supports an interface.
    /// @param id The id of the interface.
    /// @return Whether the interface is supported.
    function supportsInterface(bytes4 id) public pure virtual override returns (bool) {
        /// 0x01ffc9a7 is ERC165.
        /// 0x80ac58cd is ERC721
        /// 0x5b5e139f is for ERC721 metadata
        return id == 0x01ffc9a7 || id == 0x80ac58cd || id == 0x5b5e139f;
    }

    function _safeTransferFrom(
        address from,
        address to,
        uint256 id,
        bytes memory data
    ) internal {
        _transferFrom(from, to, id);
        if (to.isContract()) {
            require(_checkOnERC721Received(msg.sender, from, to, id, data), "ERC721_TRANSFER_REJECTED");
        }
    }

    function _beforeTokenTransfer(
        address from,
        address to,
        uint256 id
    ) internal virtual {}

    function _transferFrom(
        address from,
        address to,
        uint256 id
    ) internal {
        _beforeTokenTransfer(from, to, id);
        unchecked {
            _balances[to]++;
            if (from != address(0)) {
                _balances[from]--;
            }
        }
        _owners[id] = (block.number << 160) | uint256(uint160(to));
        emit Transfer(from, to, id);
    }

    /// @dev See approve.
    function _approveFor(
        address owner,
        uint256 blockNumber,
        address operator,
        uint256 id
    ) internal {
        if (operator == address(0)) {
            _owners[id] = (blockNumber << 160) | uint256(uint160(owner));
        } else {
            _owners[id] = OPERATOR_FLAG | (blockNumber << 160) | uint256(uint160(owner));
            _operators[id] = operator;
        }
        emit Approval(owner, operator, id);
    }

    /// @dev See setApprovalForAll.
    function _setApprovalForAll(
        address sender,
        address operator,
        bool approved
    ) internal {
        _operatorsForAll[sender][operator] = approved;

        emit ApprovalForAll(sender, operator, approved);
    }

    /// @dev Check if receiving contract accepts erc721 transfers.
    /// @param operator The address of the operator.
    /// @param from The from address, may be different from msg.sender.
    /// @param to The adddress we want to transfer to.
    /// @param id The id of the token we would like to transfer.
    /// @param _data Any additional data to send with the transfer.
    /// @return Whether the expected value of 0x150b7a02 is returned.
    function _checkOnERC721Received(
        address operator,
        address from,
        address to,
        uint256 id,
        bytes memory _data
    ) internal returns (bool) {
        bytes4 retval = IERC721Receiver(to).onERC721Received(operator, from, id, _data);
        return (retval == ERC721_RECEIVED);
    }

    /// @dev See ownerOf
    function _ownerOf(uint256 id) internal view returns (address owner) {
        return address(uint160(_owners[id]));
    }

    /// @dev Get the owner and operatorEnabled status of a token.
    /// @param id The token to query.
    /// @return owner The owner of the token.
    /// @return operatorEnabled Whether or not operators are enabled for this token.
    function _ownerAndOperatorEnabledOf(uint256 id) internal view returns (address owner, bool operatorEnabled) {
        uint256 data = _owners[id];
        owner = address(uint160(data));
        operatorEnabled = (data & OPERATOR_FLAG) == OPERATOR_FLAG;
    }

    // @dev Get the owner and operatorEnabled status of a token.
    /// @param id The token to query.
    /// @return owner The owner of the token.
    /// @return blockNumber the blockNumber at which the owner became the owner (last transfer).
    function _ownerAndBlockNumberOf(uint256 id) internal view returns (address owner, uint256 blockNumber) {
        uint256 data = _owners[id];
        owner = address(uint160(data));
        blockNumber = (data >> 160) & 0xFFFFFFFFFFFFFFFFFFFFFF;
    }

    // from https://github.com/Uniswap/v3-periphery/blob/main/contracts/base/Multicall.sol
    /// @notice Call multiple functions in the current contract and return the data from all of them if they all succeed.
    /// @dev The `msg.value` should not be trusted for any method callable from multicall.
    /// @param data The encoded function data for each of the calls to make to this contract.
    /// @return results The results from each of the calls passed in via data.
    function multicall(bytes[] calldata data) public payable returns (bytes[] memory results) {
        results = new bytes[](data.length);
        for (uint256 i = 0; i < data.length; i++) {
            (bool success, bytes memory result) = address(this).delegatecall(data[i]);

            if (!success) {
                // Next 5 lines from https://ethereum.stackexchange.com/a/83577
                if (result.length < 68) revert();
                assembly {
                    result := add(result, 0x04)
                }
                revert(abi.decode(result, (string)));
            }

            results[i] = result;
        }
    }
}

File 11 of 17 : ERC721BaseWithERC4494Permit.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.9;

import "./ERC721Base.sol";
import "@openzeppelin/contracts/utils/Address.sol";
import "@openzeppelin/contracts/utils/cryptography/SignatureChecker.sol";
import "./IERC4494.sol";

abstract contract ERC721BaseWithERC4494Permit is ERC721Base {
    using Address for address;

    bytes32 public constant PERMIT_TYPEHASH =
        keccak256("Permit(address spender,uint256 tokenId,uint256 nonce,uint256 deadline)");
    bytes32 public constant PERMIT_FOR_ALL_TYPEHASH =
        keccak256("PermitForAll(address spender,uint256 nonce,uint256 deadline)");
    bytes32 public constant DOMAIN_TYPEHASH =
        keccak256("EIP712Domain(string name,uint256 chainId,address verifyingContract)");

    uint256 private immutable _deploymentChainId;
    bytes32 private immutable _deploymentDomainSeparator;

    mapping(address => uint256) internal _userNonces;

    constructor() {
        uint256 chainId;
        //solhint-disable-next-line no-inline-assembly
        assembly {
            chainId := chainid()
        }
        _deploymentChainId = chainId;
        _deploymentDomainSeparator = _calculateDomainSeparator(chainId);
    }

    /// @dev Return the DOMAIN_SEPARATOR.
    function DOMAIN_SEPARATOR() external view returns (bytes32) {
        return _DOMAIN_SEPARATOR();
    }

    /// @notice return the account nonce, used for approvalForAll permit or other account related matter
    /// @param account the account to query
    /// @return nonce
    function nonces(address account) external view virtual returns (uint256 nonce) {
        return _userNonces[account];
    }

    /// @notice return the token nonce, used for individual approve permit or other token related matter
    /// @param id token id to query
    /// @return nonce
    function nonces(uint256 id) public view virtual returns (uint256 nonce) {
        (address owner, uint256 blockNumber) = _ownerAndBlockNumberOf(id);
        require(owner != address(0), "NONEXISTENT_TOKEN");
        return blockNumber;
    }

    /// @notice return the token nonce, used for individual approve permit or other token related matter
    /// @param id token id to query
    /// @return nonce
    function tokenNonces(uint256 id) external view returns (uint256 nonce) {
        return nonces(id);
    }

    function permit(
        address spender,
        uint256 tokenId,
        uint256 deadline,
        bytes memory sig
    ) external {
        require(deadline >= block.timestamp, "PERMIT_DEADLINE_EXPIRED");

        (address owner, uint256 blockNumber) = _ownerAndBlockNumberOf(tokenId);
        require(owner != address(0), "NONEXISTENT_TOKEN");

        // We use blockNumber as nonce as we already store it per tokens. It can thus act as an increasing transfer counter.
        // while technically multiple transfer could happen in the same block, the signed message would be using a previous block.
        // And the transfer would use then a more recent blockNumber, invalidating that message when transfer is executed.
        _requireValidPermit(owner, spender, tokenId, deadline, blockNumber, sig);

        _approveFor(owner, blockNumber, spender, tokenId);
    }

    function permitForAll(
        address signer,
        address spender,
        uint256 deadline,
        bytes memory sig
    ) external {
        require(deadline >= block.timestamp, "PERMIT_DEADLINE_EXPIRED");

        _requireValidPermitForAll(signer, spender, deadline, _userNonces[signer]++, sig);

        _setApprovalForAll(signer, spender, true);
    }

    /// @notice Check if the contract supports an interface.
    /// @param id The id of the interface.
    /// @return Whether the interface is supported.
    function supportsInterface(bytes4 id) public pure virtual override returns (bool) {
        return
            super.supportsInterface(id) ||
            id == type(IERC4494).interfaceId ||
            id == type(IERC4494Alternative).interfaceId;
    }

    // -------------------------------------------------------- INTERNAL --------------------------------------------------------------------

    function _requireValidPermit(
        address signer,
        address spender,
        uint256 id,
        uint256 deadline,
        uint256 nonce,
        bytes memory sig
    ) internal view {
        bytes32 digest = keccak256(
            abi.encodePacked(
                "\x19\x01",
                _DOMAIN_SEPARATOR(),
                keccak256(abi.encode(PERMIT_TYPEHASH, spender, id, nonce, deadline))
            )
        );
        require(SignatureChecker.isValidSignatureNow(signer, digest, sig), "INVALID_SIGNATURE");
    }

    function _requireValidPermitForAll(
        address signer,
        address spender,
        uint256 deadline,
        uint256 nonce,
        bytes memory sig
    ) internal view {
        bytes32 digest = keccak256(
            abi.encodePacked(
                "\x19\x01",
                _DOMAIN_SEPARATOR(),
                keccak256(abi.encode(PERMIT_FOR_ALL_TYPEHASH, spender, nonce, deadline))
            )
        );
        require(SignatureChecker.isValidSignatureNow(signer, digest, sig), "INVALID_SIGNATURE");
    }

    /// @dev Return the DOMAIN_SEPARATOR.
    function _DOMAIN_SEPARATOR() internal view returns (bytes32) {
        uint256 chainId;
        //solhint-disable-next-line no-inline-assembly
        assembly {
            chainId := chainid()
        }

        // in case a fork happen, to support the chain that had to change its chainId,, we compute the domain operator
        return chainId == _deploymentChainId ? _deploymentDomainSeparator : _calculateDomainSeparator(chainId);
    }

    /// @dev Calculate the DOMAIN_SEPARATOR.
    function _calculateDomainSeparator(uint256 chainId) private view returns (bytes32) {
        return keccak256(abi.encode(DOMAIN_TYPEHASH, keccak256(bytes(name())), chainId, address(this)));
    }
}

File 12 of 17 : ERC721Checkpointable.sol
// SPDX-License-Identifier: BSD-3-Clause

/// @title Vote checkpointing for an ERC-721 token

/*********************************
 * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ *
 * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ *
 * ░░░░░░█████████░░█████████░░░ *
 * ░░░░░░██░░░████░░██░░░████░░░ *
 * ░░██████░░░████████░░░████░░░ *
 * ░░██░░██░░░████░░██░░░████░░░ *
 * ░░██░░██░░░████░░██░░░████░░░ *
 * ░░░░░░█████████░░█████████░░░ *
 * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ *
 * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ *
 *********************************/

// LICENSE
// ERC721Checkpointable.sol uses and modifies part of Compound Lab's Comp.sol:
// https://github.com/compound-finance/compound-protocol/blob/ae4388e780a8d596d97619d9704a931a2752c2bc/contracts/Governance/Comp.sol
//
// Comp.sol source code Copyright 2020 Compound Labs, Inc. licensed under the BSD-3-Clause license.
// With modifications by Nounders DAO.
//
// Additional conditions of BSD-3-Clause can be found here: https://opensource.org/licenses/BSD-3-Clause
//
// MODIFICATIONS
// Checkpointing logic from Comp.sol has been used with the following modifications:
// - `delegates` is renamed to `_delegates` and is set to private
// - `delegates` is a public function that uses the `_delegates` mapping look-up, but unlike
//   Comp.sol, returns the delegator's own address if there is no delegate.
//   This avoids the delegator needing to "delegate to self" with an additional transaction
// - `_transferTokens()` is renamed `_beforeTokenTransfer()` and adapted to hook into OpenZeppelin's ERC721 hooks.

pragma solidity 0.8.9;

import "./ERC721BaseWithERC4494Permit.sol";

abstract contract ERC721Checkpointable is ERC721BaseWithERC4494Permit {
    bool internal _useCheckpoints = true; // can only be disabled and never re-enabled

    /// @notice Defines decimals as per ERC-20 convention to make integrations with 3rd party governance platforms easier
    uint8 public constant decimals = 0;

    /// @notice A record of each accounts delegate
    mapping(address => address) private _delegates;

    /// @notice A checkpoint for marking number of votes from a given block
    struct Checkpoint {
        uint32 fromBlock;
        uint96 votes;
    }

    /// @notice A record of votes checkpoints for each account, by index
    mapping(address => mapping(uint32 => Checkpoint)) public checkpoints;

    /// @notice The number of checkpoints for each account
    mapping(address => uint32) public numCheckpoints;

    /// @notice The EIP-712 typehash for the delegation struct used by the contract
    bytes32 public constant DELEGATION_TYPEHASH =
        keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)");

    /// @notice An event thats emitted when an account changes its delegate
    event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);

    /// @notice An event thats emitted when a delegate account's vote balance changes
    event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance);

    /**
     * @notice The votes a delegator can delegate, which is the current balance of the delegator.
     * @dev Used when calling `_delegate()`
     */
    function votesToDelegate(address delegator) public view returns (uint96) {
        return safe96(balanceOf(delegator), "ERC721Checkpointable::votesToDelegate: amount exceeds 96 bits");
    }

    /**
     * @notice Overrides the standard `Comp.sol` delegates mapping to return
     * the delegator's own address if they haven't delegated.
     * This avoids having to delegate to oneself.
     */
    function delegates(address delegator) public view returns (address) {
        address current = _delegates[delegator];
        return current == address(0) ? delegator : current;
    }

    /**
     * @notice Adapted from `_transferTokens()` in `Comp.sol` to update delegate votes.
     * @dev hooks into ERC721Base's `ERC721._transfer`
     */
    function _beforeTokenTransfer(
        address from,
        address to,
        uint256 tokenId
    ) internal override {
        super._beforeTokenTransfer(from, to, tokenId);
        if (_useCheckpoints) {
            /// @notice Differs from `_transferTokens()` to use `delegates` override method to simulate auto-delegation
            _moveDelegates(delegates(from), delegates(to), 1);
        }
    }

    /**
     * @notice Delegate votes from `msg.sender` to `delegatee`
     * @param delegatee The address to delegate votes to
     */
    function delegate(address delegatee) public {
        if (delegatee == address(0)) delegatee = msg.sender;
        return _delegate(msg.sender, delegatee);
    }

    /**
     * @notice Delegates votes from signatory to `delegatee`
     * @param delegatee The address to delegate votes to
     * @param nonce The contract state required to match the signature
     * @param expiry The time at which to expire the signature
     * @param v The recovery byte of the signature
     * @param r Half of the ECDSA signature pair
     * @param s Half of the ECDSA signature pair
     */
    function delegateBySig(
        address delegatee,
        uint256 nonce,
        uint256 expiry,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) public {
        bytes32 digest = keccak256(
            abi.encodePacked(
                "\x19\x01",
                _DOMAIN_SEPARATOR(),
                keccak256(abi.encode(DELEGATION_TYPEHASH, delegatee, nonce, expiry))
            )
        );
        // TODO support smart contract wallet via IERC721, require change in function signature to know which signer to call first
        address signatory = ecrecover(digest, v, r, s);
        require(signatory != address(0), "ERC721Checkpointable::delegateBySig: invalid signature");
        require(nonce == _userNonces[signatory]++, "ERC721Checkpointable::delegateBySig: invalid nonce");
        require(block.timestamp <= expiry, "ERC721Checkpointable::delegateBySig: signature expired");
        return _delegate(signatory, delegatee);
    }

    /**
     * @notice Gets the current votes balance for `account`
     * @param account The address to get votes balance
     * @return The number of current votes for `account`
     */
    function getCurrentVotes(address account) public view returns (uint96) {
        uint32 nCheckpoints = numCheckpoints[account];
        return nCheckpoints > 0 ? checkpoints[account][nCheckpoints - 1].votes : 0;
    }

    /**
     * @notice Gets the current votes balance for `account`
     * @param account The address to get votes balance
     * @return The number of current votes for `account`
     */
    function getVotes(address account) external view returns (uint96) {
        return getCurrentVotes(account);
    }

    /**
     * @notice Determine the prior number of votes for an account as of a block number
     * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.
     * @param account The address of the account to check
     * @param blockNumber The block number to get the vote balance at
     * @return The number of votes the account had as of the given block
     */
    function getPriorVotes(address account, uint256 blockNumber) public view returns (uint96) {
        require(blockNumber < block.number, "ERC721Checkpointable::getPriorVotes: not yet determined");

        uint32 nCheckpoints = numCheckpoints[account];
        if (nCheckpoints == 0) {
            return 0;
        }

        // First check most recent balance
        if (checkpoints[account][nCheckpoints - 1].fromBlock <= blockNumber) {
            return checkpoints[account][nCheckpoints - 1].votes;
        }

        // Next check implicit zero balance
        if (checkpoints[account][0].fromBlock > blockNumber) {
            return 0;
        }

        uint32 lower = 0;
        uint32 upper = nCheckpoints - 1;
        while (upper > lower) {
            uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow
            Checkpoint memory cp = checkpoints[account][center];
            if (cp.fromBlock == blockNumber) {
                return cp.votes;
            } else if (cp.fromBlock < blockNumber) {
                lower = center;
            } else {
                upper = center - 1;
            }
        }
        return checkpoints[account][lower].votes;
    }

    /**
     * @notice Determine the prior number of votes for an account as of a block number
     * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.
     * @param account The address of the account to check
     * @param blockNumber The block number to get the vote balance at
     * @return The number of votes the account had as of the given block
     */
    function getPastVotes(address account, uint256 blockNumber) external view returns (uint96) {
        return this.getPriorVotes(account, blockNumber);
    }

    function _delegate(address delegator, address delegatee) internal {
        /// @notice differs from `_delegate()` in `Comp.sol` to use `delegates` override method to simulate auto-delegation
        address currentDelegate = delegates(delegator);

        _delegates[delegator] = delegatee;

        emit DelegateChanged(delegator, currentDelegate, delegatee);

        uint96 amount = votesToDelegate(delegator);

        _moveDelegates(currentDelegate, delegatee, amount);
    }

    function _moveDelegates(
        address srcRep,
        address dstRep,
        uint96 amount
    ) internal {
        if (srcRep != dstRep && amount > 0) {
            if (srcRep != address(0)) {
                uint32 srcRepNum = numCheckpoints[srcRep];
                uint96 srcRepOld = srcRepNum > 0 ? checkpoints[srcRep][srcRepNum - 1].votes : 0;
                uint96 srcRepNew = sub96(srcRepOld, amount, "ERC721Checkpointable::_moveDelegates: amount underflows");
                _writeCheckpoint(srcRep, srcRepNum, srcRepOld, srcRepNew);
            }

            if (dstRep != address(0)) {
                uint32 dstRepNum = numCheckpoints[dstRep];
                uint96 dstRepOld = dstRepNum > 0 ? checkpoints[dstRep][dstRepNum - 1].votes : 0;
                uint96 dstRepNew = add96(dstRepOld, amount, "ERC721Checkpointable::_moveDelegates: amount overflows");
                _writeCheckpoint(dstRep, dstRepNum, dstRepOld, dstRepNew);
            }
        }
    }

    function _writeCheckpoint(
        address delegatee,
        uint32 nCheckpoints,
        uint96 oldVotes,
        uint96 newVotes
    ) internal {
        uint32 blockNumber = safe32(
            block.number,
            "ERC721Checkpointable::_writeCheckpoint: block number exceeds 32 bits"
        );

        if (nCheckpoints > 0 && checkpoints[delegatee][nCheckpoints - 1].fromBlock == blockNumber) {
            checkpoints[delegatee][nCheckpoints - 1].votes = newVotes;
        } else {
            checkpoints[delegatee][nCheckpoints] = Checkpoint(blockNumber, newVotes);
            numCheckpoints[delegatee] = nCheckpoints + 1;
        }

        emit DelegateVotesChanged(delegatee, oldVotes, newVotes);
    }

    function safe32(uint256 n, string memory errorMessage) internal pure returns (uint32) {
        require(n < 2**32, errorMessage);
        return uint32(n);
    }

    function safe96(uint256 n, string memory errorMessage) internal pure returns (uint96) {
        require(n < 2**96, errorMessage);
        return uint96(n);
    }

    function add96(
        uint96 a,
        uint96 b,
        string memory errorMessage
    ) internal pure returns (uint96) {
        uint96 c = a + b;
        require(c >= a, errorMessage);
        return c;
    }

    function sub96(
        uint96 a,
        uint96 b,
        string memory errorMessage
    ) internal pure returns (uint96) {
        require(b <= a, errorMessage);
        return a - b;
    }
}

File 13 of 17 : IERC4494.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.9;

interface IERC4494 {
    function DOMAIN_SEPARATOR() external view returns (bytes32);

    /// @notice Allows to retrieve current nonce for token
    /// @param tokenId token id
    /// @return current token nonce
    function nonces(uint256 tokenId) external view returns (uint256);

    /// @notice function to be called by anyone to approve `spender` using a Permit signature
    /// @dev Anyone can call this to approve `spender`, even a third-party
    /// @param spender the actor to approve
    /// @param tokenId the token id
    /// @param deadline the deadline for the permit to be used
    /// @param signature permit
    function permit(
        address spender,
        uint256 tokenId,
        uint256 deadline,
        bytes memory signature
    ) external;
}

interface IERC4494Alternative {
    function DOMAIN_SEPARATOR() external view returns (bytes32);

    /// @notice Allows to retrieve current nonce for token
    /// @param tokenId token id
    /// @return current token nonce
    function tokenNonces(uint256 tokenId) external view returns (uint256);

    /// @notice function to be called by anyone to approve `spender` using a Permit signature
    /// @dev Anyone can call this to approve `spender`, even a third-party
    /// @param spender the actor to approve
    /// @param tokenId the token id
    /// @param deadline the deadline for the permit to be used
    /// @param signature permit
    function permit(
        address spender,
        uint256 tokenId,
        uint256 deadline,
        bytes memory signature
    ) external;
}

File 14 of 17 : WithSupportForOpenSeaProxies.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.9;

contract OwnableDelegateProxy {}

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

abstract contract WithSupportForOpenSeaProxies {
    address internal immutable _proxyRegistryAddress;

    constructor(address proxyRegistryAddress) {
        _proxyRegistryAddress = proxyRegistryAddress;
    }

    function _isOpenSeaProxy(address owner, address operator) internal view returns (bool) {
        if (_proxyRegistryAddress == address(0)) {
            return false;
        }
        // Whitelist OpenSea proxy contract for easy trading.
        ProxyRegistry proxyRegistry = ProxyRegistry(_proxyRegistryAddress);
        return address(proxyRegistry.proxies(owner)) == operator;
    }
}

File 15 of 17 : Bleeps.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.9;

import "./BleepsRoles.sol";
import "../base/ERC721Checkpointable.sol";

import "../interfaces/ITokenURI.sol";
import "@openzeppelin/contracts/token/ERC721/IERC721.sol";

import "../base/WithSupportForOpenSeaProxies.sol";

contract Bleeps is IERC721, WithSupportForOpenSeaProxies, ERC721Checkpointable, BleepsRoles {
    event RoyaltySet(address receiver, uint256 royaltyPer10Thousands);
    event TokenURIContractSet(ITokenURI newTokenURIContract);
    event CheckpointingDisablerSet(address newCheckpointingDisabler);
    event CheckpointingDisabled();

    /// @notice the contract that actually generate the sound (and all metadata via the a data: uri via tokenURI call).
    ITokenURI public tokenURIContract;

    struct Royalty {
        address receiver;
        uint96 per10Thousands;
    }

    Royalty internal _royalty;

    /// @dev address that is able to switch off the use of checkpointing, this will make token transfers much cheaper in term of gas, but require the design of a new governance system.
    address public checkpointingDisabler;

    /// @dev Create the Bleeps contract
    /// @param ens ENS address for the network the contract is deployed to
    /// @param initialOwner address that can set the ENS name of the contract and that can witthdraw ERC20 tokens sent by mistake here.
    /// @param initialTokenURIAdmin admin able to update the tokenURI contract.
    /// @param initialMinterAdmin admin able to set the minter contract.
    /// @param initialRoyaltyAdmin admin able to update the royalty receiver and rates.
    /// @param initialGuardian guardian able to immortalize rules
    /// @param openseaProxyRegistry allow Bleeps to be sold on opensea without prior approval tx as long as the user have already an opensea proxy.
    /// @param initialRoyaltyReceiver receiver of royalties
    /// @param imitialRoyaltyPer10Thousands amount of royalty in 10,000 basis point
    /// @param initialTokenURIContract initial tokenURI contract that generate the metadata including the wav file.
    /// @param initialCheckpointingDisabler admin able to cancel checkpointing
    constructor(
        address ens,
        address initialOwner,
        address initialTokenURIAdmin,
        address initialMinterAdmin,
        address initialRoyaltyAdmin,
        address initialGuardian,
        address openseaProxyRegistry,
        address initialRoyaltyReceiver,
        uint96 imitialRoyaltyPer10Thousands,
        ITokenURI initialTokenURIContract,
        address initialCheckpointingDisabler
    )
        WithSupportForOpenSeaProxies(openseaProxyRegistry)
        BleepsRoles(ens, initialOwner, initialTokenURIAdmin, initialMinterAdmin, initialRoyaltyAdmin, initialGuardian)
    {
        tokenURIContract = initialTokenURIContract;
        emit TokenURIContractSet(initialTokenURIContract);
        checkpointingDisabler = initialCheckpointingDisabler;
        emit CheckpointingDisablerSet(initialCheckpointingDisabler);

        _royalty.receiver = initialRoyaltyReceiver;
        _royalty.per10Thousands = imitialRoyaltyPer10Thousands;
        emit RoyaltySet(initialRoyaltyReceiver, imitialRoyaltyPer10Thousands);
    }

    /// @notice A descriptive name for a collection of NFTs in this contract.
    function name() public pure override returns (string memory) {
        return "Bleeps";
    }

    /// @notice An abbreviated name for NFTs in this contract.
    function symbol() external pure returns (string memory) {
        return "BLEEP";
    }

    /// @notice Returns the Uniform Resource Identifier (URI) for the token collection.
    function contractURI() external view returns (string memory) {
        return tokenURIContract.contractURI(_royalty.receiver, _royalty.per10Thousands);
    }

    /// @notice Returns the Uniform Resource Identifier (URI) for token `id`.
    function tokenURI(uint256 id) external view returns (string memory) {
        return tokenURIContract.tokenURI(id);
    }

    /// @notice set a new tokenURI contract, that generate the metadata including the wav file, Can only be set by the `tokenURIAdmin`.
    /// @param newTokenURIContract The address of the new tokenURI contract.
    function setTokenURIContract(ITokenURI newTokenURIContract) external {
        require(msg.sender == tokenURIAdmin, "NOT_AUTHORIZED");
        tokenURIContract = newTokenURIContract;
        emit TokenURIContractSet(newTokenURIContract);
    }

    /// @notice give the list of owners for the list of ids given.
    /// @param ids The list if token ids to check.
    /// @return addresses The list of addresses, corresponding to the list of ids.
    function owners(uint256[] calldata ids) external view returns (address[] memory addresses) {
        addresses = new address[](ids.length);
        for (uint256 i = 0; i < ids.length; i++) {
            uint256 id = ids[i];
            addresses[i] = address(uint160(_owners[id]));
        }
    }

    /// @notice Check if the sender approved the operator.
    /// @param owner The address of the owner.
    /// @param operator The address of the operator.
    /// @return isOperator The status of the approval.
    function isApprovedForAll(address owner, address operator)
        public
        view
        virtual
        override(ERC721Base, IERC721)
        returns (bool isOperator)
    {
        return super.isApprovedForAll(owner, operator) || _isOpenSeaProxy(owner, operator);
    }

    /// @notice Check if the contract supports an interface.
    /// @param id The id of the interface.
    /// @return Whether the interface is supported.
    function supportsInterface(bytes4 id)
        public
        pure
        virtual
        override(ERC721BaseWithERC4494Permit, IERC165)
        returns (bool)
    {
        return super.supportsInterface(id) || id == 0x2a55205a; /// 0x2a55205a is ERC2981 (royalty standard)
    }

    /// @notice Called with the sale price to determine how much royalty is owed and to whom.
    /// @param id - the token queried for royalty information.
    /// @param salePrice - the sale price of the token specified by id.
    /// @return receiver - address of who should be sent the royalty payment.
    /// @return royaltyAmount - the royalty payment amount for salePrice.
    function royaltyInfo(uint256 id, uint256 salePrice)
        external
        view
        returns (address receiver, uint256 royaltyAmount)
    {
        receiver = _royalty.receiver;
        royaltyAmount = (salePrice * uint256(_royalty.per10Thousands)) / 10000;
    }

    /// @notice set a new royalty receiver and rate, Can only be set by the `royaltyAdmin`.
    /// @param newReceiver the address that should receive the royalty proceeds.
    /// @param royaltyPer10Thousands the share of the salePrice (in 1/10000) given to the receiver.
    function setRoyaltyParameters(address newReceiver, uint96 royaltyPer10Thousands) external {
        require(msg.sender == royaltyAdmin, "NOT_AUTHORIZED");
        // require(royaltyPer10Thousands <= 50, "ROYALTY_TOO_HIGH"); ?
        _royalty.receiver = newReceiver;
        _royalty.per10Thousands = royaltyPer10Thousands;
        emit RoyaltySet(newReceiver, royaltyPer10Thousands);
    }

    /// @notice disable checkpointing overhead
    /// This can be used if the governance system can switch to use ownerAndLastTransferBlockNumberOf instead of checkpoints
    function disableTheUseOfCheckpoints() external {
        require(msg.sender == checkpointingDisabler, "NOT_AUTHORIZED");
        _useCheckpoints = false;
        checkpointingDisabler = address(0);
        emit CheckpointingDisablerSet(address(0));
        emit CheckpointingDisabled();
    }

    /// @notice update the address that can disable the use of checkpinting, can be used to disable it entirely.
    /// @param newCheckpointingDisabler new address that can disable the use of checkpointing. can be the zero address to remove the ability to change.
    function setCheckpointingDisabler(address newCheckpointingDisabler) external {
        require(msg.sender == checkpointingDisabler, "NOT_AUTHORIZED");
        checkpointingDisabler = newCheckpointingDisabler;
        emit CheckpointingDisablerSet(newCheckpointingDisabler);
    }

    /// @notice mint one of bleep if not already minted. Can only be called by `minter`.
    /// @param id bleep id which represent a pair of (note, instrument).
    /// @param to address that will receive the Bleep.
    function mint(uint16 id, address to) external {
        require(msg.sender == minter, "ONLY_MINTER_ALLOWED");
        require(id < 1024, "INVALID_BLEEP");

        require(to != address(0), "NOT_TO_ZEROADDRESS");
        require(to != address(this), "NOT_TO_THIS");
        address owner = _ownerOf(id);
        require(owner == address(0), "ALREADY_CREATED");
        _safeTransferFrom(address(0), to, id, "");
    }

    /// @notice mint multiple bleeps if not already minted. Can only be called by `minter`.
    /// @param ids list of bleep id which represent each a pair of (note, instrument).
    /// @param tos addresses that will receive the Bleeps. (if only one, use for all)
    function multiMint(uint16[] calldata ids, address[] calldata tos) external {
        require(msg.sender == minter, "ONLY_MINTER_ALLOWED");

        address to;
        if (tos.length == 1) {
            to = tos[0];
        }
        for (uint256 i = 0; i < ids.length; i++) {
            uint256 id = ids[i];
            if (tos.length > 1) {
                to = tos[i];
            }
            require(to != address(0), "NOT_TO_ZEROADDRESS");
            require(to != address(this), "NOT_TO_THIS");
            require(id < 1024, "INVALID_BLEEP");
            address owner = _ownerOf(id);
            require(owner == address(0), "ALREADY_CREATED");
            _safeTransferFrom(address(0), to, id, "");
        }
    }

    /// @notice gives the note and instrument for a particular Bleep id.
    /// @param id bleep id which represent a pair of (note, instrument).
    /// @return note the note index (0 to 63) starting from C2 to D#7
    /// @return instrument the instrument index (0 to 16). At launch there is only 9 instrument but the DAO could add more (up to 16 in total).
    function sound(uint256 id) external pure returns (uint8 note, uint8 instrument) {
        note = uint8(id & 0x3F);
        instrument = uint8(uint256(id >> 6) & 0x0F);
    }
}

File 16 of 17 : BleepsRoles.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.9;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";

interface ReverseRegistrar {
    function setName(string memory name) external returns (bytes32);
}

interface ENS {
    function owner(bytes32 node) external view returns (address);
}

contract BleepsRoles {
    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    event TokenURIAdminSet(address newTokenURIAdmin);
    event RoyaltyAdminSet(address newRoyaltyAdmin);
    event MinterAdminSet(address newMinterAdmin);
    event GuardianSet(address newGuardian);
    event MinterSet(address newMinter);

    bytes32 internal constant ADDR_REVERSE_NODE = 0x91d1777781884d03a6757a803996e38de2a42967fb37eeaca72729271025a9e2;
    ENS internal immutable _ens;

    ///@notice the address of the current owner, that is able to set ENS names and withdraw ERC20 owned by the contract.
    address public owner;

    /// @notice tokenURIAdmin can update the tokenURI contract, this is intended to be relinquished once the tokenURI has been heavily tested in the wild and that no modification are needed.
    address public tokenURIAdmin;

    /// @notice address allowed to set royalty parameters
    address public royaltyAdmin;

    /// @notice minterAdmin can update the minter. At the time being there is 576 Bleeps but there is space for extra instrument and the upper limit is 1024.
    /// could be given to the DAO later so instrument can be added, the sale of these new bleeps could benenfit the DAO too and add new members.
    address public minterAdmin;

    /// @notice address allowed to mint, allow the sale contract to be separated from the token contract that can focus on the core logic
    /// Once all 1024 potential bleeps (there could be less, at minimum there are 576 bleeps) are minted, no minter can mint anymore
    address public minter;

    /// @notice guardian has some special vetoing power to guide the direction of the DAO. It can only remove rights from the DAO. It could be used to immortalize rules.
    /// For example: the royalty setup could be frozen.
    address public guardian;

    constructor(
        address ens,
        address initialOwner,
        address initialTokenURIAdmin,
        address initialMinterAdmin,
        address initialRoyaltyAdmin,
        address initialGuardian
    ) {
        _ens = ENS(ens);
        owner = initialOwner;
        tokenURIAdmin = initialTokenURIAdmin;
        royaltyAdmin = initialRoyaltyAdmin;
        minterAdmin = initialMinterAdmin;
        guardian = initialGuardian;
        emit OwnershipTransferred(address(0), initialOwner);
        emit TokenURIAdminSet(initialTokenURIAdmin);
        emit RoyaltyAdminSet(initialRoyaltyAdmin);
        emit MinterAdminSet(initialMinterAdmin);
        emit GuardianSet(initialGuardian);
    }

    function setENSName(string memory name) external {
        require(msg.sender == owner, "NOT_AUTHORIZED");
        ReverseRegistrar reverseRegistrar = ReverseRegistrar(_ens.owner(ADDR_REVERSE_NODE));
        reverseRegistrar.setName(name);
    }

    function withdrawERC20(IERC20 token, address to) external {
        require(msg.sender == owner, "NOT_AUTHORIZED");
        token.transfer(to, token.balanceOf(address(this)));
    }

    /**
     * @notice Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) external {
        address oldOwner = owner;
        require(msg.sender == oldOwner);
        owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }

    /**
     * @notice set the new tokenURIAdmin that can change the tokenURI
     * Can only be called by the current tokenURI admin.
     */
    function setTokenURIAdmin(address newTokenURIAdmin) external {
        require(
            msg.sender == tokenURIAdmin || (msg.sender == guardian && newTokenURIAdmin == address(0)),
            "NOT_AUTHORIZED"
        );
        tokenURIAdmin = newTokenURIAdmin;
        emit TokenURIAdminSet(newTokenURIAdmin);
    }

    /**
     * @notice set the new royaltyAdmin that can change the royalties
     * Can only be called by the current royalty admin.
     */
    function setRoyaltyAdmin(address newRoyaltyAdmin) external {
        require(
            msg.sender == royaltyAdmin || (msg.sender == guardian && newRoyaltyAdmin == address(0)),
            "NOT_AUTHORIZED"
        );
        royaltyAdmin = newRoyaltyAdmin;
        emit RoyaltyAdminSet(newRoyaltyAdmin);
    }

    /**
     * @notice set the new minterAdmin that can set the minter for Bleeps
     * Can only be called by the current minter admin.
     */
    function setMinterAdmin(address newMinterAdmin) external {
        require(
            msg.sender == minterAdmin || (msg.sender == guardian && newMinterAdmin == address(0)),
            "NOT_AUTHORIZED"
        );
        minterAdmin = newMinterAdmin;
        emit MinterAdminSet(newMinterAdmin);
    }

    /**
     * @notice set the new guardian that can freeze the other admins (except owner).
     * Can only be called by the current guardian.
     */
    function setGuardian(address newGuardian) external {
        require(msg.sender == guardian, "NOT_AUTHORIZED");
        guardian = newGuardian;
        emit GuardianSet(newGuardian);
    }

    /**
     * @notice set the new minter that can mint Bleeps (up to 1024).
     * Can only be called by the minter admin.
     */
    function setMinter(address newMinter) external {
        require(msg.sender == minterAdmin, "NOT_AUTHORIZED");
        minter = newMinter;
        emit MinterSet(newMinter);
    }
}

File 17 of 17 : ITokenURI.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.9;

interface ITokenURI {
    function tokenURI(uint256 id) external view returns (string memory);

    function contractURI(address receiver, uint96 per10Thousands) external view returns (string memory);
}

Settings
{
  "evmVersion": "london",
  "libraries": {},
  "metadata": {
    "bytecodeHash": "ipfs",
    "useLiteralContent": true
  },
  "optimizer": {
    "enabled": true,
    "runs": 999999
  },
  "remappings": [],
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  }
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"ens","type":"address"},{"internalType":"address","name":"initialOwner","type":"address"},{"internalType":"address","name":"initialTokenURIAdmin","type":"address"},{"internalType":"address","name":"initialMinterAdmin","type":"address"},{"internalType":"address","name":"initialRoyaltyAdmin","type":"address"},{"internalType":"address","name":"initialGuardian","type":"address"},{"internalType":"address","name":"openseaProxyRegistry","type":"address"},{"internalType":"address","name":"initialRoyaltyReceiver","type":"address"},{"internalType":"uint96","name":"imitialRoyaltyPer10Thousands","type":"uint96"},{"internalType":"contract ITokenURI","name":"initialTokenURIContract","type":"address"},{"internalType":"address","name":"initialCheckpointingDisabler","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":[],"name":"CheckpointingDisabled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newCheckpointingDisabler","type":"address"}],"name":"CheckpointingDisablerSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"delegator","type":"address"},{"indexed":true,"internalType":"address","name":"fromDelegate","type":"address"},{"indexed":true,"internalType":"address","name":"toDelegate","type":"address"}],"name":"DelegateChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"delegate","type":"address"},{"indexed":false,"internalType":"uint256","name":"previousBalance","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newBalance","type":"uint256"}],"name":"DelegateVotesChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newGuardian","type":"address"}],"name":"GuardianSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newMinterAdmin","type":"address"}],"name":"MinterAdminSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newMinter","type":"address"}],"name":"MinterSet","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":"newRoyaltyAdmin","type":"address"}],"name":"RoyaltyAdminSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"receiver","type":"address"},{"indexed":false,"internalType":"uint256","name":"royaltyPer10Thousands","type":"uint256"}],"name":"RoyaltySet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newTokenURIAdmin","type":"address"}],"name":"TokenURIAdminSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"contract ITokenURI","name":"newTokenURIContract","type":"address"}],"name":"TokenURIContractSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"DELEGATION_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DOMAIN_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PERMIT_FOR_ALL_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PERMIT_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"balance","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"checkpointingDisabler","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint32","name":"","type":"uint32"}],"name":"checkpoints","outputs":[{"internalType":"uint32","name":"fromBlock","type":"uint32"},{"internalType":"uint96","name":"votes","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"contractURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"delegatee","type":"address"}],"name":"delegate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"delegatee","type":"address"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"expiry","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"delegateBySig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"delegator","type":"address"}],"name":"delegates","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"disableTheUseOfCheckpoints","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"getCurrentVotes","outputs":[{"internalType":"uint96","name":"","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"blockNumber","type":"uint256"}],"name":"getPastVotes","outputs":[{"internalType":"uint96","name":"","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"blockNumber","type":"uint256"}],"name":"getPriorVotes","outputs":[{"internalType":"uint96","name":"","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"getVotes","outputs":[{"internalType":"uint96","name":"","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"guardian","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"isOperator","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"id","type":"uint16"},{"internalType":"address","name":"to","type":"address"}],"name":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"minter","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minterAdmin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16[]","name":"ids","type":"uint16[]"},{"internalType":"address[]","name":"tos","type":"address[]"}],"name":"multiMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes[]","name":"data","type":"bytes[]"}],"name":"multicall","outputs":[{"internalType":"bytes[]","name":"results","type":"bytes[]"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"nonce","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"nonce","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"numCheckpoints","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"ids","type":"uint256[]"}],"name":"ownerAndLastTransferBlockNumberList","outputs":[{"components":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"lastTransferBlockNumber","type":"uint256"}],"internalType":"struct ERC721Base.OwnerData[]","name":"ownersData","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"owner","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"ids","type":"uint256[]"}],"name":"owners","outputs":[{"internalType":"address[]","name":"addresses","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bytes","name":"sig","type":"bytes"}],"name":"permit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"signer","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bytes","name":"sig","type":"bytes"}],"name":"permitForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"royaltyAdmin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"salePrice","type":"uint256"}],"name":"royaltyInfo","outputs":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"royaltyAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","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":"id","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newCheckpointingDisabler","type":"address"}],"name":"setCheckpointingDisabler","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"name","type":"string"}],"name":"setENSName","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newGuardian","type":"address"}],"name":"setGuardian","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newMinter","type":"address"}],"name":"setMinter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newMinterAdmin","type":"address"}],"name":"setMinterAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newRoyaltyAdmin","type":"address"}],"name":"setRoyaltyAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newReceiver","type":"address"},{"internalType":"uint96","name":"royaltyPer10Thousands","type":"uint96"}],"name":"setRoyaltyParameters","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newTokenURIAdmin","type":"address"}],"name":"setTokenURIAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract ITokenURI","name":"newTokenURIContract","type":"address"}],"name":"setTokenURIContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"sound","outputs":[{"internalType":"uint8","name":"note","type":"uint8"},{"internalType":"uint8","name":"instrument","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes4","name":"id","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"tokenNonces","outputs":[{"internalType":"uint256","name":"nonce","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tokenURIAdmin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tokenURIContract","outputs":[{"internalType":"contract ITokenURI","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"delegator","type":"address"}],"name":"votesToDelegate","outputs":[{"internalType":"uint96","name":"","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"token","type":"address"},{"internalType":"address","name":"to","type":"address"}],"name":"withdrawERC20","outputs":[],"stateMutability":"nonpayable","type":"function"}]

6101006040526005805460ff191660011790553480156200001f57600080fd5b50604051620063f8380380620063f88339810160408190526200004291620003bc565b6001600160a01b0385166080524660a08190528b908b908b908b908b908b906200006c8162000303565b60c052506001600160a01b0386811660e052600980546001600160a01b0319908116888416908117909255600a80548216888516179055600b80548216868516179055600c80548216878516179055600e8054909116928416929092179091556040516000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a36040516001600160a01b03851681527f89de65ceb8cdf195a0b50021ed65dd305b54d3b744a0e283bd98c6058e2edd789060200160405180910390a16040516001600160a01b03831681527fb17416b845258d996b82b66c3c9166088ec5edf592b35fcce47c62a73d61ef419060200160405180910390a16040516001600160a01b03841681527fb8e0165b6664b7af8f9563c66e3d6b987c2d06fe192539d7123a0777b41a7c899060200160405180910390a16040516001600160a01b03821681527fe6c09ffe4572dc9ceaa5ddde4ae41befa655d6fdfe8052077af0970f700e942e9060200160405180910390a15050600f80546001600160a01b0319166001600160a01b0388169081179091556040519081527f6bf5b09f847c9c9e97addeaf1ea9d5fd44ff6ae2c9c4aaf55fb476eca421a45d945060200192506200023e915050565b60405180910390a1601180546001600160a01b0319166001600160a01b0383169081179091556040519081527f4b70ff24654603d6961acf6a0cf30db833fc126dac63891114f984fefcc2b0649060200160405180910390a16001600160a01b038416600160a01b6001600160601b03851690810282176010556040805192835260208301919091527fb744dc8fdcd17f69ad99fdabe0fe0ed8fea41193727ed2123d997550eaae918f910160405180910390a15050505050505050505050620004c4565b60007f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a8666200034a604080518082019091526006815265426c6565707360d01b602082015290565b80516020918201206040805192830193909352918101919091526060810183905230608082015260a001604051602081830303815290604052805190602001209050919050565b6001600160a01b0381168114620003a757600080fd5b50565b8051620003b78162000391565b919050565b60008060008060008060008060008060006101608c8e031215620003df57600080fd5b8b51620003ec8162000391565b60208d0151909b50620003ff8162000391565b60408d0151909a50620004128162000391565b60608d0151909950620004258162000391565b60808d0151909850620004388162000391565b60a08d01519097506200044b8162000391565b60c08d01519096506200045e8162000391565b60e08d0151909550620004718162000391565b6101008d01519094506001600160601b03811681146200049057600080fd5b9250620004a16101208d01620003aa565b9150620004b26101408d01620003aa565b90509295989b509295989b9093969950565b60805160a05160c05160e051615ef3620005056000396000611f810152600061409a015260006140650152600081816144eb01526145710152615ef36000f3fe6080604052600436106103ad5760003560e01c80637ba9638b116101e7578063ab84ee6f1161010d578063e7a324dc116100a0578063f1127ed81161006f578063f1127ed814610cf6578063f2fde38b14610d75578063f394528214610d95578063fca3b5aa14610dc257600080fd5b8063e7a324dc14610c6d578063e8a3d48514610ca1578063e9580e9114610cb6578063e985e9c514610cd657600080fd5b8063b88d4fde116100dc578063b88d4fde14610bf8578063c3cda52014610c18578063c87b56dd14610c38578063e6b34e8614610c5857600080fd5b8063ab84ee6f14610b78578063ac9650d814610b98578063adc5fcc214610bb8578063b4b5ea5714610bd857600080fd5b80639456fbcc116101855780639c205513116101545780639c20551314610ade578063a0554c2614610afe578063a22cb46514610b2b578063a754d48f14610b4b57600080fd5b80639456fbcc14610a3857806395d89b4114610a5857806399235f3914610a9e5780639ab24eb014610abe57600080fd5b8063894e851f116101c1578063894e851f146109915780638a0dac4a146109be5780638cc66011146109de5780638da5cb5b14610a0b57600080fd5b80637ba9638b1461090e5780637ecebe001461092e57806382fc31471461097157600080fd5b80633644e515116102d75780636352211e1161026a57806370a082311161023957806370a082311461088e578063745a41bc146108ae57806377dd4ac3146108ce578063782d6fe1146108ee57600080fd5b80636352211e146107d9578063639147af146107f9578063698f87be146108195780636fcfff451461084657600080fd5b80634d687821116102a65780634d68782114610745578063585956d614610765578063587cde1e146107995780635c19a95c146107b957600080fd5b80633644e515146106a65780633a46b1a8146106bb57806342842e0e146106f8578063452a93201461071857600080fd5b806320606b701161034f5780632a55205a1161031e5780632a55205a146105d257806330adf81f1461061e578063313ce5671461065257806334dd800d1461067957600080fd5b806320606b701461051857806323b872dd1461054c57806324d42fe71461056c5780632954dbfa1461058c57600080fd5b8063081812fc1161038b578063081812fc14610488578063095ea7b3146104a8578063141a468c146104ca5780631d57fb6e146104f857600080fd5b806301ffc9a7146103b257806306fdde03146103e75780630754617214610436575b600080fd5b3480156103be57600080fd5b506103d26103cd366004615256565b610de2565b60405190151581526020015b60405180910390f35b3480156103f357600080fd5b5060408051808201909152600681527f426c65657073000000000000000000000000000000000000000000000000000060208201525b6040516103de91906152e9565b34801561044257600080fd5b50600d546104639073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016103de565b34801561049457600080fd5b506104636104a33660046152fc565b610e3f565b3480156104b457600080fd5b506104c86104c3366004615337565b610f30565b005b3480156104d657600080fd5b506104ea6104e53660046152fc565b61106f565b6040519081526020016103de565b34801561050457600080fd5b506104c86105133660046153a8565b611114565b34801561052457600080fd5b506104ea7f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a86681565b34801561055857600080fd5b506104c8610567366004615414565b611466565b34801561057857600080fd5b506104c861058736600461546f565b61177e565b34801561059857600080fd5b506105b86105a73660046152fc565b603f81169160069190911c600f1690565b6040805160ff9384168152929091166020830152016103de565b3480156105de57600080fd5b506105f26105ed3660046154a8565b611881565b6040805173ffffffffffffffffffffffffffffffffffffffff90931683526020830191909152016103de565b34801561062a57600080fd5b506104ea7f49ecf333e5b8c95c40fdafc95c1ad136e8914a8fb55e9dc8bb01eaa83a2df9ad81565b34801561065e57600080fd5b50610667600081565b60405160ff90911681526020016103de565b34801561068557600080fd5b50600a546104639073ffffffffffffffffffffffffffffffffffffffff1681565b3480156106b257600080fd5b506104ea6118e6565b3480156106c757600080fd5b506106db6106d6366004615337565b6118f5565b6040516bffffffffffffffffffffffff90911681526020016103de565b34801561070457600080fd5b506104c8610713366004615414565b61199c565b34801561072457600080fd5b50600e546104639073ffffffffffffffffffffffffffffffffffffffff1681565b34801561075157600080fd5b506104c86107603660046154ca565b6119bc565b34801561077157600080fd5b506104ea7f29795620f29ed5790c945e3f419a1b3e2381aa07751ccffe5b81231639d74cd581565b3480156107a557600080fd5b506104636107b43660046154ca565b611ab7565b3480156107c557600080fd5b506104c86107d43660046154ca565b611af4565b3480156107e557600080fd5b506104636107f43660046152fc565b611b1f565b34801561080557600080fd5b506104c86108143660046154ca565b611bb0565b34801561082557600080fd5b50600f546104639073ffffffffffffffffffffffffffffffffffffffff1681565b34801561085257600080fd5b506108796108613660046154ca565b60086020526000908152604090205463ffffffff1681565b60405163ffffffff90911681526020016103de565b34801561089a57600080fd5b506104ea6108a93660046154ca565b611ce5565b3480156108ba57600080fd5b506104c86108c9366004615609565b611d8d565b3480156108da57600080fd5b506104c86108e936600461566c565b611eaf565b3480156108fa57600080fd5b506106db610909366004615337565b6120b7565b34801561091a57600080fd5b506104c86109293660046154ca565b6123ce565b34801561093a57600080fd5b506104ea6109493660046154ca565b73ffffffffffffffffffffffffffffffffffffffff1660009081526004602052604090205490565b34801561097d57600080fd5b506104c861098c3660046154ca565b612503565b34801561099d57600080fd5b50600b546104639073ffffffffffffffffffffffffffffffffffffffff1681565b3480156109ca57600080fd5b506104c86109d93660046154ca565b6125f7565b3480156109ea57600080fd5b506011546104639073ffffffffffffffffffffffffffffffffffffffff1681565b348015610a1757600080fd5b506009546104639073ffffffffffffffffffffffffffffffffffffffff1681565b348015610a4457600080fd5b506104c8610a533660046156b5565b6126eb565b348015610a6457600080fd5b5060408051808201909152600581527f424c4545500000000000000000000000000000000000000000000000000000006020820152610429565b348015610aaa57600080fd5b506104c8610ab93660046154ca565b6128b6565b348015610aca57600080fd5b506106db610ad93660046154ca565b6129eb565b348015610aea57600080fd5b506104c8610af93660046156f5565b6129f6565b348015610b0a57600080fd5b50610b1e610b19366004615711565b612c95565b6040516103de9190615753565b348015610b3757600080fd5b506104c8610b463660046157bb565b612d68565b348015610b5757600080fd5b50600c546104639073ffffffffffffffffffffffffffffffffffffffff1681565b348015610b8457600080fd5b506104c8610b933660046157e9565b612d77565b610bab610ba6366004615711565b612e34565b6040516103de919061583d565b348015610bc457600080fd5b506104ea610bd33660046152fc565b612f9f565b348015610be457600080fd5b506106db610bf33660046154ca565b612faa565b348015610c0457600080fd5b506104c8610c133660046157e9565b613047565b348015610c2457600080fd5b506104c8610c333660046158bd565b613359565b348015610c4457600080fd5b50610429610c533660046152fc565b6136d2565b348015610c6457600080fd5b506104c8613797565b348015610c7957600080fd5b506104ea7fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf81565b348015610cad57600080fd5b506104296138c7565b348015610cc257600080fd5b506106db610cd13660046154ca565b6139bf565b348015610ce257600080fd5b506103d2610cf13660046156b5565b6139eb565b348015610d0257600080fd5b50610d4c610d1136600461591f565b600760209081526000928352604080842090915290825290205463ffffffff81169064010000000090046bffffffffffffffffffffffff1682565b6040805163ffffffff90931683526bffffffffffffffffffffffff9091166020830152016103de565b348015610d8157600080fd5b506104c8610d903660046154ca565b613a33565b348015610da157600080fd5b50610db5610db0366004615711565b613ace565b6040516103de9190615956565b348015610dce57600080fd5b506104c8610ddd3660046154ca565b613c01565b6000610ded82613cf5565b80610e3957507f2a55205a000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316145b92915050565b6000818152602081905260408120547f80000000000000000000000000000000000000000000000000000000000000008082161473ffffffffffffffffffffffffffffffffffffffff8216610ef5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f4e4f4e4558495354454e545f544f4b454e00000000000000000000000000000060448201526064015b60405180910390fd5b8015610f265750505060009081526003602052604090205473ffffffffffffffffffffffffffffffffffffffff1690565b5060009392505050565b6000818152602081905260409020546affffffffffffffffffffff60a082901c1673ffffffffffffffffffffffffffffffffffffffff8216610fce576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f4e4f4e4558495354454e545f544f4b454e0000000000000000000000000000006044820152606401610eec565b3373ffffffffffffffffffffffffffffffffffffffff83161480610ff75750610ff782336139eb565b61105d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f554e415554484f52495a45445f415050524f56414c00000000000000000000006044820152606401610eec565b61106982828686613d9d565b50505050565b6000818152602081905260408120546affffffffffffffffffffff60a082901c1673ffffffffffffffffffffffffffffffffffffffff821661110d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f4e4f4e4558495354454e545f544f4b454e0000000000000000000000000000006044820152606401610eec565b9392505050565b600d5473ffffffffffffffffffffffffffffffffffffffff163314611195576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f4f4e4c595f4d494e5445525f414c4c4f574544000000000000000000000000006044820152606401610eec565b600060018214156111cb57828260008181106111b3576111b36159bb565b90506020020160208101906111c891906154ca565b90505b60005b8481101561145e5760008686838181106111ea576111ea6159bb565b90506020020160208101906111ff91906159ea565b61ffff169050600184111561123857848483818110611220576112206159bb565b905060200201602081019061123591906154ca565b92505b73ffffffffffffffffffffffffffffffffffffffff83166112b5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f4e4f545f544f5f5a45524f4144445245535300000000000000000000000000006044820152606401610eec565b73ffffffffffffffffffffffffffffffffffffffff8316301415611335576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f4e4f545f544f5f544849530000000000000000000000000000000000000000006044820152606401610eec565b61040081106113a0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f494e56414c49445f424c454550000000000000000000000000000000000000006044820152606401610eec565b60008181526020819052604090205473ffffffffffffffffffffffffffffffffffffffff81161561142d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f414c52454144595f4352454154454400000000000000000000000000000000006044820152606401610eec565b6114496000858460405180602001604052806000815250613ed6565b5050808061145690615a34565b9150506111ce565b505050505050565b6000818152602081905260409020547f80000000000000000000000000000000000000000000000000000000000000008082161473ffffffffffffffffffffffffffffffffffffffff8216611517576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f4e4f4e4558495354454e545f544f4b454e0000000000000000000000000000006044820152606401610eec565b8473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16146115ac576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f4e4f545f4f574e455200000000000000000000000000000000000000000000006044820152606401610eec565b73ffffffffffffffffffffffffffffffffffffffff8416611629576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f4e4f545f544f5f5a45524f4144445245535300000000000000000000000000006044820152606401610eec565b73ffffffffffffffffffffffffffffffffffffffff84163014156116a9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f4e4f545f544f5f544849530000000000000000000000000000000000000000006044820152606401610eec565b3373ffffffffffffffffffffffffffffffffffffffff86161461176c578080156116f6575060008381526003602052604090205473ffffffffffffffffffffffffffffffffffffffff1633145b80611706575061170685336139eb565b61176c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f554e415554484f52495a45445f5452414e5346455200000000000000000000006044820152606401610eec565b611777858585613f71565b5050505050565b600b5473ffffffffffffffffffffffffffffffffffffffff1633146117ff576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f4e4f545f415554484f52495a45440000000000000000000000000000000000006044820152606401610eec565b73ffffffffffffffffffffffffffffffffffffffff8216740100000000000000000000000000000000000000006bffffffffffffffffffffffff831690810282176010556040805192835260208301919091527fb744dc8fdcd17f69ad99fdabe0fe0ed8fea41193727ed2123d997550eaae918f910160405180910390a15050565b60105473ffffffffffffffffffffffffffffffffffffffff811690600090612710906118d3907401000000000000000000000000000000000000000090046bffffffffffffffffffffffff1685615a6d565b6118dd9190615ad9565b90509250929050565b60006118f0614060565b905090565b6040517f782d6fe100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8316600482015260248101829052600090309063782d6fe19060440160206040518083038186803b15801561196457600080fd5b505afa158015611978573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061110d9190615aed565b6119b783838360405180602001604052806000815250613047565b505050565b60115473ffffffffffffffffffffffffffffffffffffffff163314611a3d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f4e4f545f415554484f52495a45440000000000000000000000000000000000006044820152606401610eec565b601180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527f4b70ff24654603d6961acf6a0cf30db833fc126dac63891114f984fefcc2b064906020015b60405180910390a150565b73ffffffffffffffffffffffffffffffffffffffff8082166000908152600660205260408120549091168015611aed578061110d565b5090919050565b73ffffffffffffffffffffffffffffffffffffffff8116611b125750335b611b1c33826140c0565b50565b60008181526020819052604090205473ffffffffffffffffffffffffffffffffffffffff8116611bab576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f4e4f4e4558495354454e545f544f4b454e0000000000000000000000000000006044820152606401610eec565b919050565b600a5473ffffffffffffffffffffffffffffffffffffffff16331480611c0c5750600e5473ffffffffffffffffffffffffffffffffffffffff1633148015611c0c575073ffffffffffffffffffffffffffffffffffffffff8116155b611c72576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f4e4f545f415554484f52495a45440000000000000000000000000000000000006044820152606401610eec565b600a80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527f89de65ceb8cdf195a0b50021ed65dd305b54d3b744a0e283bd98c6058e2edd7890602001611aac565b600073ffffffffffffffffffffffffffffffffffffffff8216611d64576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f5a45524f5f414444524553535f4f574e455200000000000000000000000000006044820152606401610eec565b5073ffffffffffffffffffffffffffffffffffffffff1660009081526001602052604090205490565b42821015611df7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f5045524d49545f444541444c494e455f455850495245440000000000000000006044820152606401610eec565b6000838152602081905260409020546affffffffffffffffffffff60a082901c1673ffffffffffffffffffffffffffffffffffffffff8216611e95576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f4e4f4e4558495354454e545f544f4b454e0000000000000000000000000000006044820152606401610eec565b611ea3828787878588614165565b61145e82828888613d9d565b60095473ffffffffffffffffffffffffffffffffffffffff163314611f30576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f4e4f545f415554484f52495a45440000000000000000000000000000000000006044820152606401610eec565b6040517f02571be30000000000000000000000000000000000000000000000000000000081527f91d1777781884d03a6757a803996e38de2a42967fb37eeaca72729271025a9e260048201526000907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906302571be39060240160206040518083038186803b158015611fd857600080fd5b505afa158015611fec573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120109190615b0a565b6040517fc47f002700000000000000000000000000000000000000000000000000000000815290915073ffffffffffffffffffffffffffffffffffffffff82169063c47f0027906120659085906004016152e9565b602060405180830381600087803b15801561207f57600080fd5b505af1158015612093573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119b79190615b27565b6000438210612148576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f455243373231436865636b706f696e7461626c653a3a6765745072696f72566f60448201527f7465733a206e6f74207965742064657465726d696e65640000000000000000006064820152608401610eec565b73ffffffffffffffffffffffffffffffffffffffff831660009081526008602052604090205463ffffffff1680612183576000915050610e39565b73ffffffffffffffffffffffffffffffffffffffff8416600090815260076020526040812084916121b5600185615b40565b63ffffffff9081168252602082019290925260400160002054161161223b5773ffffffffffffffffffffffffffffffffffffffff8416600090815260076020526040812090612205600184615b40565b63ffffffff16815260208101919091526040016000205464010000000090046bffffffffffffffffffffffff169150610e399050565b73ffffffffffffffffffffffffffffffffffffffff8416600090815260076020908152604080832083805290915290205463ffffffff16831015612283576000915050610e39565b600080612291600184615b40565b90505b8163ffffffff168163ffffffff16111561237657600060026122b68484615b40565b6122c09190615b65565b6122ca9083615b40565b73ffffffffffffffffffffffffffffffffffffffff8816600090815260076020908152604080832063ffffffff8581168552908352928190208151808301909252549283168082526401000000009093046bffffffffffffffffffffffff169181019190915291925087141561234a57602001519450610e399350505050565b805163ffffffff168711156123615781935061236f565b61236c600183615b40565b92505b5050612294565b5073ffffffffffffffffffffffffffffffffffffffff8516600090815260076020908152604080832063ffffffff909416835292905220546bffffffffffffffffffffffff6401000000009091041691505092915050565b600b5473ffffffffffffffffffffffffffffffffffffffff1633148061242a5750600e5473ffffffffffffffffffffffffffffffffffffffff163314801561242a575073ffffffffffffffffffffffffffffffffffffffff8116155b612490576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f4e4f545f415554484f52495a45440000000000000000000000000000000000006044820152606401610eec565b600b80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527fb17416b845258d996b82b66c3c9166088ec5edf592b35fcce47c62a73d61ef4190602001611aac565b600a5473ffffffffffffffffffffffffffffffffffffffff163314612584576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f4e4f545f415554484f52495a45440000000000000000000000000000000000006044820152606401610eec565b600f80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527f6bf5b09f847c9c9e97addeaf1ea9d5fd44ff6ae2c9c4aaf55fb476eca421a45d90602001611aac565b600e5473ffffffffffffffffffffffffffffffffffffffff163314612678576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f4e4f545f415554484f52495a45440000000000000000000000000000000000006044820152606401610eec565b600e80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527fe6c09ffe4572dc9ceaa5ddde4ae41befa655d6fdfe8052077af0970f700e942e90602001611aac565b60095473ffffffffffffffffffffffffffffffffffffffff16331461276c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f4e4f545f415554484f52495a45440000000000000000000000000000000000006044820152606401610eec565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff83169063a9059cbb90839083906370a082319060240160206040518083038186803b1580156127db57600080fd5b505afa1580156127ef573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128139190615b27565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815273ffffffffffffffffffffffffffffffffffffffff90921660048301526024820152604401602060405180830381600087803b15801561287e57600080fd5b505af1158015612892573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119b79190615b88565b600c5473ffffffffffffffffffffffffffffffffffffffff163314806129125750600e5473ffffffffffffffffffffffffffffffffffffffff1633148015612912575073ffffffffffffffffffffffffffffffffffffffff8116155b612978576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f4e4f545f415554484f52495a45440000000000000000000000000000000000006044820152606401610eec565b600c80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527fb8e0165b6664b7af8f9563c66e3d6b987c2d06fe192539d7123a0777b41a7c8990602001611aac565b6000610e3982612faa565b600d5473ffffffffffffffffffffffffffffffffffffffff163314612a77576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f4f4e4c595f4d494e5445525f414c4c4f574544000000000000000000000000006044820152606401610eec565b6104008261ffff1610612ae6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f494e56414c49445f424c454550000000000000000000000000000000000000006044820152606401610eec565b73ffffffffffffffffffffffffffffffffffffffff8116612b63576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f4e4f545f544f5f5a45524f4144445245535300000000000000000000000000006044820152606401610eec565b73ffffffffffffffffffffffffffffffffffffffff8116301415612be3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f4e4f545f544f5f544849530000000000000000000000000000000000000000006044820152606401610eec565b61ffff821660009081526020819052604090205473ffffffffffffffffffffffffffffffffffffffff811615612c75576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f414c52454144595f4352454154454400000000000000000000000000000000006044820152606401610eec565b6119b76000838561ffff1660405180602001604052806000815250613ed6565b60608167ffffffffffffffff811115612cb057612cb06154e7565b604051908082528060200260200182016040528015612cd9578160200160208202803683370190505b50905060005b82811015612d61576000848483818110612cfb57612cfb6159bb565b90506020020135905060008082815260200190815260200160002054838381518110612d2957612d296159bb565b73ffffffffffffffffffffffffffffffffffffffff909216602092830291909101909101525080612d5981615a34565b915050612cdf565b5092915050565b612d733383836142b9565b5050565b42821015612de1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f5045524d49545f444541444c494e455f455850495245440000000000000000006044820152606401610eec565b73ffffffffffffffffffffffffffffffffffffffff841660009081526004602052604081208054612e2892879287928792909190612e1e83615a34565b9190505585614351565b611069848460016142b9565b60608167ffffffffffffffff811115612e4f57612e4f6154e7565b604051908082528060200260200182016040528015612e8257816020015b6060815260200190600190039081612e6d5790505b50905060005b82811015612d615760008030868685818110612ea657612ea66159bb565b9050602002810190612eb89190615ba5565b604051612ec6929190615c0a565b600060405180830381855af49150503d8060008114612f01576040519150601f19603f3d011682016040523d82523d6000602084013e612f06565b606091505b509150915081612f6c57604481511015612f1f57600080fd5b60048101905080806020019051810190612f399190615c1a565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610eec91906152e9565b80848481518110612f7f57612f7f6159bb565b602002602001018190525050508080612f9790615a34565b915050612e88565b6000610e398261106f565b73ffffffffffffffffffffffffffffffffffffffff811660009081526008602052604081205463ffffffff1680612fe257600061110d565b73ffffffffffffffffffffffffffffffffffffffff8316600090815260076020526040812090613013600184615b40565b63ffffffff16815260208101919091526040016000205464010000000090046bffffffffffffffffffffffff169392505050565b6000828152602081905260409020547f80000000000000000000000000000000000000000000000000000000000000008082161473ffffffffffffffffffffffffffffffffffffffff82166130f8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f4e4f4e4558495354454e545f544f4b454e0000000000000000000000000000006044820152606401610eec565b8573ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161461318d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f4e4f545f4f574e455200000000000000000000000000000000000000000000006044820152606401610eec565b73ffffffffffffffffffffffffffffffffffffffff851661320a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f4e4f545f544f5f5a45524f4144445245535300000000000000000000000000006044820152606401610eec565b73ffffffffffffffffffffffffffffffffffffffff851630141561328a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f4e4f545f544f5f544849530000000000000000000000000000000000000000006044820152606401610eec565b3373ffffffffffffffffffffffffffffffffffffffff87161461334d578080156132d7575060008481526003602052604090205473ffffffffffffffffffffffffffffffffffffffff1633145b806132e757506132e786336139eb565b61334d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f554e415554484f52495a45445f5452414e5346455200000000000000000000006044820152606401610eec565b61145e86868686613ed6565b6000613363614060565b604080517fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf602082015273ffffffffffffffffffffffffffffffffffffffff8a1691810191909152606081018890526080810187905260a001604051602081830303815290604052805190602001206040516020016134149291907f190100000000000000000000000000000000000000000000000000000000000081526002810192909252602282015260420190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181528282528051602091820120600080855291840180845281905260ff88169284019290925260608301869052608083018590529092509060019060a0016020604051602081039080840390855afa15801561349d573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff811661356b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f455243373231436865636b706f696e7461626c653a3a64656c6567617465427960448201527f5369673a20696e76616c6964207369676e6174757265000000000000000000006064820152608401610eec565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260046020526040812080549161359c83615a34565b91905055871461362e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f455243373231436865636b706f696e7461626c653a3a64656c6567617465427960448201527f5369673a20696e76616c6964206e6f6e636500000000000000000000000000006064820152608401610eec565b854211156136be576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f455243373231436865636b706f696e7461626c653a3a64656c6567617465427960448201527f5369673a207369676e61747572652065787069726564000000000000000000006064820152608401610eec565b6136c881896140c0565b5050505050505050565b600f546040517fc87b56dd0000000000000000000000000000000000000000000000000000000081526004810183905260609173ffffffffffffffffffffffffffffffffffffffff169063c87b56dd9060240160006040518083038186803b15801561373d57600080fd5b505afa158015613751573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052610e399190810190615c1a565b60115473ffffffffffffffffffffffffffffffffffffffff163314613818576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f4e4f545f415554484f52495a45440000000000000000000000000000000000006044820152606401610eec565b600580547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055601180547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055604051600081527f4b70ff24654603d6961acf6a0cf30db833fc126dac63891114f984fefcc2b0649060200160405180910390a16040517f3355f5c11ec5fbd9909c4fbd232bf8592a749dba18405f16df892fa6b40eddae90600090a1565b600f546010546040517fcc4c332400000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8083166004830152740100000000000000000000000000000000000000009092046bffffffffffffffffffffffff166024820152606092919091169063cc4c33249060440160006040518083038186803b15801561396557600080fd5b505afa158015613979573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526118f09190810190615c1a565b6000610e396139cd83611ce5565b6040518060600160405280603d8152602001615e4a603d9139614495565b73ffffffffffffffffffffffffffffffffffffffff808316600090815260026020908152604080832093851683529290529081205460ff168061110d575061110d83836144e7565b60095473ffffffffffffffffffffffffffffffffffffffff16338114613a5857600080fd5b600980547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff84811691821790925560405190918316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60608167ffffffffffffffff811115613ae957613ae96154e7565b604051908082528060200260200182016040528015613b2e57816020015b6040805180820190915260008082526020820152815260200190600190039081613b075790505b50905060005b82811015612d61576000806000868685818110613b5357613b536159bb565b90506020020135815260200190815260200160002054905080838381518110613b7e57613b7e6159bb565b60200260200101516000019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505060a081901c6affffffffffffffffffffff16838381518110613be057613be06159bb565b60209081029190910181015101525080613bf981615a34565b915050613b34565b600c5473ffffffffffffffffffffffffffffffffffffffff163314613c82576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f4e4f545f415554484f52495a45440000000000000000000000000000000000006044820152606401610eec565b600d80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527f726b590ef91a8c76ad05bbe91a57ef84605276528f49cd47d787f558a4e755b690602001611aac565b6000613d0082614610565b80613d4c57507fffffffff0000000000000000000000000000000000000000000000000000000082167f5604e22500000000000000000000000000000000000000000000000000000000145b80610e3957507fffffffff0000000000000000000000000000000000000000000000000000000082167fefdb586b000000000000000000000000000000000000000000000000000000001492915050565b73ffffffffffffffffffffffffffffffffffffffff8216613dea57600081815260208190526040902060a084901b73ffffffffffffffffffffffffffffffffffffffff8616179055613e75565b6000818152602081815260408083207f800000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff89811660a08a901b1791909117909155600390925290912080547fffffffffffffffffffffffff0000000000000000000000000000000000000000169184169190911790555b808273ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a450505050565b613ee1848484613f71565b73ffffffffffffffffffffffffffffffffffffffff83163b1561106957613f0b33858585856146f1565b611069576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4552433732315f5452414e534645525f52454a454354454400000000000000006044820152606401610eec565b613f7c8383836147d5565b73ffffffffffffffffffffffffffffffffffffffff808316600090815260016020819052604090912080549091019055831615613fff5773ffffffffffffffffffffffffffffffffffffffff8316600090815260016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190555b6000818152602081905260408082204360a01b73ffffffffffffffffffffffffffffffffffffffff80871691821790925591518493918716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b6000467f0000000000000000000000000000000000000000000000000000000000000000811461409857614093816147fc565b6140ba565b7f00000000000000000000000000000000000000000000000000000000000000005b91505090565b60006140cb83611ab7565b73ffffffffffffffffffffffffffffffffffffffff84811660008181526006602052604080822080547fffffffffffffffffffffffff000000000000000000000000000000000000000016888616908117909155905194955093928516927f3134e8a2e6d97e929a7e54011ea5485d7d196dd5f0ba4d4ef95803e8e3fc257f9190a46000614158846139bf565b90506110698284836148a0565b600061416f614060565b604080517f49ecf333e5b8c95c40fdafc95c1ad136e8914a8fb55e9dc8bb01eaa83a2df9ad602082015273ffffffffffffffffffffffffffffffffffffffff891691810191909152606081018790526080810185905260a0810186905260c001604051602081830303815290604052805190602001206040516020016142279291907f190100000000000000000000000000000000000000000000000000000000000081526002810192909252602282015260420190565b60405160208183030381529060405280519060200120905061424a878284614ac5565b6142b0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f494e56414c49445f5349474e41545552450000000000000000000000000000006044820152606401610eec565b50505050505050565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526002602090815260408083209487168084529482529182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b600061435b614060565b604080517f29795620f29ed5790c945e3f419a1b3e2381aa07751ccffe5b81231639d74cd5602082015273ffffffffffffffffffffffffffffffffffffffff881691810191909152606081018590526080810186905260a0016040516020818303038152906040528051906020012060405160200161440c9291907f190100000000000000000000000000000000000000000000000000000000000081526002810192909252602282015260420190565b60405160208183030381529060405280519060200120905061442f868284614ac5565b61145e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f494e56414c49445f5349474e41545552450000000000000000000000000000006044820152606401610eec565b6000816c0100000000000000000000000084106144df576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610eec91906152e9565b509192915050565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1661452c57506000610e39565b6040517fc455279100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84811660048301527f0000000000000000000000000000000000000000000000000000000000000000918482169183169063c45527919060240160206040518083038186803b1580156145b957600080fd5b505afa1580156145cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906145f19190615b0a565b73ffffffffffffffffffffffffffffffffffffffff1614949350505050565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000831614806146a357507f80ac58cd000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316145b80610e395750507fffffffff00000000000000000000000000000000000000000000000000000000167f5b5e139f000000000000000000000000000000000000000000000000000000001490565b6000808473ffffffffffffffffffffffffffffffffffffffff1663150b7a02888887876040518563ffffffff1660e01b81526004016147339493929190615c91565b602060405180830381600087803b15801561474d57600080fd5b505af1158015614761573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906147859190615cda565b7fffffffff00000000000000000000000000000000000000000000000000000000167f150b7a02000000000000000000000000000000000000000000000000000000001491505095945050505050565b60055460ff16156119b7576119b76147ec84611ab7565b6147f584611ab7565b60016148a0565b60007f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a86661485960408051808201909152600681527f426c656570730000000000000000000000000000000000000000000000000000602082015290565b80516020918201206040805192830193909352918101919091526060810183905230608082015260a001604051602081830303815290604052805190602001209050919050565b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16141580156148ea57506000816bffffffffffffffffffffffff16115b156119b75773ffffffffffffffffffffffffffffffffffffffff8316156149dc5773ffffffffffffffffffffffffffffffffffffffff831660009081526008602052604081205463ffffffff1690816149445760006149a3565b73ffffffffffffffffffffffffffffffffffffffff8516600090815260076020526040812090614975600185615b40565b63ffffffff16815260208101919091526040016000205464010000000090046bffffffffffffffffffffffff165b905060006149ca8285604051806060016040528060378152602001615e8760379139614cb4565b90506149d886848484614d22565b5050505b73ffffffffffffffffffffffffffffffffffffffff8216156119b75773ffffffffffffffffffffffffffffffffffffffff821660009081526008602052604081205463ffffffff169081614a31576000614a90565b73ffffffffffffffffffffffffffffffffffffffff8416600090815260076020526040812090614a62600185615b40565b63ffffffff16815260208101919091526040016000205464010000000090046bffffffffffffffffffffffff165b90506000614ab78285604051806060016040528060368152602001615dd060369139614fa5565b905061145e85848484614d22565b6000806000614ad48585615016565b90925090506000816004811115614aed57614aed615cf7565b148015614b2557508573ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b15614b355760019250505061110d565b6000808773ffffffffffffffffffffffffffffffffffffffff16631626ba7e60e01b8888604051602401614b6a929190615d26565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909416939093179092529051614bf39190615d3f565b600060405180830381855afa9150503d8060008114614c2e576040519150601f19603f3d011682016040523d82523d6000602084013e614c33565b606091505b5091509150818015614c46575080516020145b8015614ca8575080517f1626ba7e0000000000000000000000000000000000000000000000000000000090614c849083016020908101908401615cda565b7fffffffff0000000000000000000000000000000000000000000000000000000016145b98975050505050505050565b6000836bffffffffffffffffffffffff16836bffffffffffffffffffffffff1611158290614d0f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610eec91906152e9565b50614d1a8385615d5b565b949350505050565b6000614d4643604051806080016040528060448152602001615e0660449139615086565b905060008463ffffffff16118015614dad575073ffffffffffffffffffffffffffffffffffffffff8516600090815260076020526040812063ffffffff831691614d91600188615b40565b63ffffffff908116825260208201929092526040016000205416145b15614e435773ffffffffffffffffffffffffffffffffffffffff851660009081526007602052604081208391614de4600188615b40565b63ffffffff168152602081019190915260400160002080546bffffffffffffffffffffffff92909216640100000000027fffffffffffffffffffffffffffffffff000000000000000000000000ffffffff909216919091179055614f3e565b60408051808201825263ffffffff80841682526bffffffffffffffffffffffff808616602080850191825273ffffffffffffffffffffffffffffffffffffffff8b166000908152600782528681208b8616825290915294909420925183549451909116640100000000027fffffffffffffffffffffffffffffffff00000000000000000000000000000000909416911617919091179055614ee5846001615d80565b73ffffffffffffffffffffffffffffffffffffffff8616600090815260086020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000001663ffffffff929092169190911790555b604080516bffffffffffffffffffffffff80861682528416602082015273ffffffffffffffffffffffffffffffffffffffff8716917fdec2bacdd2f05b59de34da9b523dff8be42e5e38e818c82fdb0bae774387a724910160405180910390a25050505050565b600080614fb28486615da8565b9050846bffffffffffffffffffffffff16816bffffffffffffffffffffffff161015839061500d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610eec91906152e9565b50949350505050565b60008082516041141561504d5760208301516040840151606085015160001a615041878285856150c8565b9450945050505061507f565b825160401415615077576020830151604084015161506c8683836151e0565b93509350505061507f565b506000905060025b9250929050565b60008164010000000084106144df576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610eec91906152e9565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08311156150ff57506000905060036151d7565b8460ff16601b1415801561511757508460ff16601c14155b1561512857506000905060046151d7565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa15801561517c573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff81166151d0576000600192509250506151d7565b9150600090505b94509492505050565b6000807f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff831660ff84901c601b0161521a878288856150c8565b935093505050935093915050565b7fffffffff0000000000000000000000000000000000000000000000000000000081168114611b1c57600080fd5b60006020828403121561526857600080fd5b813561110d81615228565b60005b8381101561528e578181015183820152602001615276565b838111156110695750506000910152565b600081518084526152b7816020860160208601615273565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061110d602083018461529f565b60006020828403121561530e57600080fd5b5035919050565b73ffffffffffffffffffffffffffffffffffffffff81168114611b1c57600080fd5b6000806040838503121561534a57600080fd5b823561535581615315565b946020939093013593505050565b60008083601f84011261537557600080fd5b50813567ffffffffffffffff81111561538d57600080fd5b6020830191508360208260051b850101111561507f57600080fd5b600080600080604085870312156153be57600080fd5b843567ffffffffffffffff808211156153d657600080fd5b6153e288838901615363565b909650945060208701359150808211156153fb57600080fd5b5061540887828801615363565b95989497509550505050565b60008060006060848603121561542957600080fd5b833561543481615315565b9250602084013561544481615315565b929592945050506040919091013590565b6bffffffffffffffffffffffff81168114611b1c57600080fd5b6000806040838503121561548257600080fd5b823561548d81615315565b9150602083013561549d81615455565b809150509250929050565b600080604083850312156154bb57600080fd5b50508035926020909101359150565b6000602082840312156154dc57600080fd5b813561110d81615315565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561555d5761555d6154e7565b604052919050565b600067ffffffffffffffff82111561557f5761557f6154e7565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b60006155be6155b984615565565b615516565b90508281528383830111156155d257600080fd5b828260208301376000602084830101529392505050565b600082601f8301126155fa57600080fd5b61110d838335602085016155ab565b6000806000806080858703121561561f57600080fd5b843561562a81615315565b93506020850135925060408501359150606085013567ffffffffffffffff81111561565457600080fd5b615660878288016155e9565b91505092959194509250565b60006020828403121561567e57600080fd5b813567ffffffffffffffff81111561569557600080fd5b8201601f810184136156a657600080fd5b614d1a848235602084016155ab565b600080604083850312156156c857600080fd5b82356156d381615315565b9150602083013561549d81615315565b803561ffff81168114611bab57600080fd5b6000806040838503121561570857600080fd5b6156d3836156e3565b6000806020838503121561572457600080fd5b823567ffffffffffffffff81111561573b57600080fd5b61574785828601615363565b90969095509350505050565b6020808252825182820181905260009190848201906040850190845b818110156157a157835173ffffffffffffffffffffffffffffffffffffffff168352928401929184019160010161576f565b50909695505050505050565b8015158114611b1c57600080fd5b600080604083850312156157ce57600080fd5b82356157d981615315565b9150602083013561549d816157ad565b600080600080608085870312156157ff57600080fd5b843561580a81615315565b9350602085013561581a81615315565b925060408501359150606085013567ffffffffffffffff81111561565457600080fd5b6000602080830181845280855180835260408601915060408160051b870101925083870160005b828110156158b0577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc088860301845261589e85835161529f565b94509285019290850190600101615864565b5092979650505050505050565b60008060008060008060c087890312156158d657600080fd5b86356158e181615315565b95506020870135945060408701359350606087013560ff8116811461590557600080fd5b9598949750929560808101359460a0909101359350915050565b6000806040838503121561593257600080fd5b823561593d81615315565b9150602083013563ffffffff8116811461549d57600080fd5b602080825282518282018190526000919060409081850190868401855b828110156159ae578151805173ffffffffffffffffffffffffffffffffffffffff168552860151868501529284019290850190600101615973565b5091979650505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000602082840312156159fc57600080fd5b61110d826156e3565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821415615a6657615a66615a05565b5060010190565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615615aa557615aa5615a05565b500290565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082615ae857615ae8615aaa565b500490565b600060208284031215615aff57600080fd5b815161110d81615455565b600060208284031215615b1c57600080fd5b815161110d81615315565b600060208284031215615b3957600080fd5b5051919050565b600063ffffffff83811690831681811015615b5d57615b5d615a05565b039392505050565b600063ffffffff80841680615b7c57615b7c615aaa565b92169190910492915050565b600060208284031215615b9a57600080fd5b815161110d816157ad565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112615bda57600080fd5b83018035915067ffffffffffffffff821115615bf557600080fd5b60200191503681900382131561507f57600080fd5b8183823760009101908152919050565b600060208284031215615c2c57600080fd5b815167ffffffffffffffff811115615c4357600080fd5b8201601f81018413615c5457600080fd5b8051615c626155b982615565565b818152856020838501011115615c7757600080fd5b615c88826020830160208601615273565b95945050505050565b600073ffffffffffffffffffffffffffffffffffffffff808716835280861660208401525083604083015260806060830152615cd0608083018461529f565b9695505050505050565b600060208284031215615cec57600080fd5b815161110d81615228565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b828152604060208201526000614d1a604083018461529f565b60008251615d51818460208701615273565b9190910192915050565b60006bffffffffffffffffffffffff83811690831681811015615b5d57615b5d615a05565b600063ffffffff808316818516808303821115615d9f57615d9f615a05565b01949350505050565b60006bffffffffffffffffffffffff808316818516808303821115615d9f57615d9f615a0556fe455243373231436865636b706f696e7461626c653a3a5f6d6f766544656c6567617465733a20616d6f756e74206f766572666c6f7773455243373231436865636b706f696e7461626c653a3a5f7772697465436865636b706f696e743a20626c6f636b206e756d62657220657863656564732033322062697473455243373231436865636b706f696e7461626c653a3a766f746573546f44656c65676174653a20616d6f756e7420657863656564732039362062697473455243373231436865636b706f696e7461626c653a3a5f6d6f766544656c6567617465733a20616d6f756e7420756e646572666c6f7773a2646970667358221220c3ff90fb34d51bc27eb361c6be4390dc86aa5db0caca6c7b8f4bba03b8b6d8d064736f6c6343000809003300000000000000000000000000000000000c2e074ec69a0dfb2997ba6c7d2e1e0000000000000000000000007773ae67403d2e30102a84c48cc939919c4c881c000000000000000000000000dca9d1fa839bb9fe65ddc4de5161bca43751d4b40000000000000000000000007773ae67403d2e30102a84c48cc939919c4c881c000000000000000000000000dca9d1fa839bb9fe65ddc4de5161bca43751d4b4000000000000000000000000dca9d1fa839bb9fe65ddc4de5161bca43751d4b4000000000000000000000000a5409ec958c83c3f309868babaca7c86dcb077c10000000000000000000000008350c9989ef11325b36ce6f7549004d418dbcee700000000000000000000000000000000000000000000000000000000000001f4000000000000000000000000e114dce59a333f8d351371f54188f92c287b73e6000000000000000000000000dca9d1fa839bb9fe65ddc4de5161bca43751d4b4

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

00000000000000000000000000000000000c2e074ec69a0dfb2997ba6c7d2e1e0000000000000000000000007773ae67403d2e30102a84c48cc939919c4c881c000000000000000000000000dca9d1fa839bb9fe65ddc4de5161bca43751d4b40000000000000000000000007773ae67403d2e30102a84c48cc939919c4c881c000000000000000000000000dca9d1fa839bb9fe65ddc4de5161bca43751d4b4000000000000000000000000dca9d1fa839bb9fe65ddc4de5161bca43751d4b4000000000000000000000000a5409ec958c83c3f309868babaca7c86dcb077c10000000000000000000000008350c9989ef11325b36ce6f7549004d418dbcee700000000000000000000000000000000000000000000000000000000000001f4000000000000000000000000e114dce59a333f8d351371f54188f92c287b73e6000000000000000000000000dca9d1fa839bb9fe65ddc4de5161bca43751d4b4

-----Decoded View---------------
Arg [0] : ens (address): 0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e
Arg [1] : initialOwner (address): 0x7773Ae67403d2E30102a84c48cc939919C4C881c
Arg [2] : initialTokenURIAdmin (address): 0xdcA9d1FA839bB9Fe65DDC4de5161BCA43751D4B4
Arg [3] : initialMinterAdmin (address): 0x7773Ae67403d2E30102a84c48cc939919C4C881c
Arg [4] : initialRoyaltyAdmin (address): 0xdcA9d1FA839bB9Fe65DDC4de5161BCA43751D4B4
Arg [5] : initialGuardian (address): 0xdcA9d1FA839bB9Fe65DDC4de5161BCA43751D4B4
Arg [6] : openseaProxyRegistry (address): 0xa5409ec958C83C3f309868babACA7c86DCB077c1
Arg [7] : initialRoyaltyReceiver (address): 0x8350C9989EF11325b36Ce6f7549004D418dbcEE7
Arg [8] : imitialRoyaltyPer10Thousands (uint96): 500
Arg [9] : initialTokenURIContract (address): 0xE114DCe59A333f8D351371F54188F92C287b73E6
Arg [10] : initialCheckpointingDisabler (address): 0xdcA9d1FA839bB9Fe65DDC4de5161BCA43751D4B4

-----Encoded View---------------
11 Constructor Arguments found :
Arg [0] : 00000000000000000000000000000000000c2e074ec69a0dfb2997ba6c7d2e1e
Arg [1] : 0000000000000000000000007773ae67403d2e30102a84c48cc939919c4c881c
Arg [2] : 000000000000000000000000dca9d1fa839bb9fe65ddc4de5161bca43751d4b4
Arg [3] : 0000000000000000000000007773ae67403d2e30102a84c48cc939919c4c881c
Arg [4] : 000000000000000000000000dca9d1fa839bb9fe65ddc4de5161bca43751d4b4
Arg [5] : 000000000000000000000000dca9d1fa839bb9fe65ddc4de5161bca43751d4b4
Arg [6] : 000000000000000000000000a5409ec958c83c3f309868babaca7c86dcb077c1
Arg [7] : 0000000000000000000000008350c9989ef11325b36ce6f7549004d418dbcee7
Arg [8] : 00000000000000000000000000000000000000000000000000000000000001f4
Arg [9] : 000000000000000000000000e114dce59a333f8d351371f54188f92c287b73e6
Arg [10] : 000000000000000000000000dca9d1fa839bb9fe65ddc4de5161bca43751d4b4


Block Transaction Difficulty Gas Used Reward
Block Uncle Number Difficulty Gas Used Reward
Loading
Loading
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.

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