ETH Price: $3,884.81 (+2.05%)

Token

ERC-20: zkMerkly (ZMER)

Overview

Max Total Supply

0 ZMER

Holders

6,483

Market

Volume (24H)

N/A

Min Price (24H)

N/A

Max Price (24H)

N/A
Balance
1 ZMER
0x58ef9606869eb254fa9bed7f55111bf030ae3a7c
Loading...
Loading
Loading...
Loading
Loading...
Loading

Click here to update the token information / general information

Contract Source Code Verified (Exact Match)

Contract Name:
zkMerklyONFT

Compiler Version
v0.8.19+commit.7dd6d404

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, None license

Contract Source Code (Solidity)

/**
 *Submitted for verification at optimistic.etherscan.io on 2024-05-23
*/

/**
 *Submitted for verification at polygonscan.com on 2023-09-25
*/

// SPDX-License-Identifier: BUSL-1.1

pragma solidity ^0.8.0;

//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@Q&Rdq6qKDWQ@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@QRXt<~'`          ._^cag@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@k*,                         `!jQ@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@U;                                 ,}Q@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@g;                                     'w@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@i                                         ~Q@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@L                  '*Ij}i~                  :@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@k                  7@@@@@@@D                  =@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@!                  k@@@@@@@@                  `Q@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@;                  k@@@@@@@@                  `Q@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@;                  k@@@@@@@@                  `Q@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@t^^^^^^^^^^^^;~'`  k@@@@@@@@                  `Q@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@QUz+:'`    k@@@@@@@@                  '@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@K?'           k@@@@@@@@                  X@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@b;              k@@@@@@@@                 f@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@Q;                k@@@@@@@@               =Q@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@Q'                 k@@@@@@@@           `;5Q@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@7                  k@@@@@@@@       ,~|ZQ@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@;                  k@@@@@@@@  `',;><<<<<<<<<<<?@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@;                  k@@@@@@@@                  `Q@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@;                  k@@@@@@@@                  `Q@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@!                  k@@@@@@@@                  `Q@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@f                  y@@@@@@@Q                  ~@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@;                  +obDdhL`                 `Q@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@?                                         :Q@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@a'                                     `L@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@k;                                 ,YQ@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@QP>'                         `;}Q@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@Rj7^,`             `';iZWQ@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@Q#RdqAAKDWQ@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)

/**
 * @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);
}

/**
 * @dev Interface of the ONFT Core standard
 */
interface IONFT721Core is IERC165 {
    /**
     * @dev Emitted when `_tokenIds[]` are moved from the `_sender` to (`_dstChainId`, `_toAddress`)
     * `_nonce` is the outbound nonce from
     */
    event SendToChain(uint16 indexed _dstChainId, address indexed _from, bytes indexed _toAddress, uint[] _tokenIds);
    event ReceiveFromChain(uint16 indexed _srcChainId, bytes indexed _srcAddress, address indexed _toAddress, uint[] _tokenIds);
    event SetMinGasToTransferAndStore(uint256 _minGasToTransferAndStore);
    event SetDstChainIdToTransferGas(uint16 _dstChainId, uint256 _dstChainIdToTransferGas);
    event SetDstChainIdToBatchLimit(uint16 _dstChainId, uint256 _dstChainIdToBatchLimit);

    /**
     * @dev Emitted when `_payload` was received from lz, but not enough gas to deliver all tokenIds
     */
    event CreditStored(bytes32 _hashedPayload, bytes _payload);
    /**
     * @dev Emitted when `_hashedPayload` has been completely delivered
     */
    event CreditCleared(bytes32 _hashedPayload);

    /**
     * @dev send token `_tokenId` to (`_dstChainId`, `_toAddress`) from `_from`
     * `_toAddress` can be any size depending on the `dstChainId`.
     * `_zroPaymentAddress` set to address(0x0) if not paying in ZRO (LayerZero Token)
     * `_adapterParams` is a flexible bytes array to indicate messaging adapter services
     */
    function sendFrom(address _from, uint16 _dstChainId, bytes calldata _toAddress, uint _tokenId, address payable _refundAddress, address _zroPaymentAddress, bytes calldata _adapterParams) external payable;
    /**
     * @dev send tokens `_tokenIds[]` to (`_dstChainId`, `_toAddress`) from `_from`
     * `_toAddress` can be any size depending on the `dstChainId`.
     * `_zroPaymentAddress` set to address(0x0) if not paying in ZRO (LayerZero Token)
     * `_adapterParams` is a flexible bytes array to indicate messaging adapter services
     */
    function sendBatchFrom(address _from, uint16 _dstChainId, bytes calldata _toAddress, uint[] calldata _tokenIds, address payable _refundAddress, address _zroPaymentAddress, bytes calldata _adapterParams) external payable;

    /**
     * @dev estimate send token `_tokenId` to (`_dstChainId`, `_toAddress`)
     * _dstChainId - L0 defined chain id to send tokens too
     * _toAddress - dynamic bytes array which contains the address to whom you are sending tokens to on the dstChain
     * _tokenId - token Id to transfer
     * _useZro - indicates to use zro to pay L0 fees
     * _adapterParams - flexible bytes array to indicate messaging adapter services in L0
     */
    function estimateSendFee(uint16 _dstChainId, bytes calldata _toAddress, uint _tokenId, bool _useZro, bytes calldata _adapterParams) external view returns (uint nativeFee, uint zroFee);
    /**
     * @dev estimate send token `_tokenId` to (`_dstChainId`, `_toAddress`)
     * _dstChainId - L0 defined chain id to send tokens too
     * _toAddress - dynamic bytes array which contains the address to whom you are sending tokens to on the dstChain
     * _tokenIds[] - token Ids to transfer
     * _useZro - indicates to use zro to pay L0 fees
     * _adapterParams - flexible bytes array to indicate messaging adapter services in L0
     */
    function estimateSendBatchFee(uint16 _dstChainId, bytes calldata _toAddress, uint[] calldata _tokenIds, bool _useZro, bytes calldata _adapterParams) external view returns (uint nativeFee, uint zroFee);
}

// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC721/IERC721.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`.
     *
     * 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;

    /**
     * @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 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: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721
     * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must
     * understand this adds an external call which potentially creates a reentrancy vulnerability.
     *
     * 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 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 the account approved for `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function getApproved(uint256 tokenId) external view returns (address operator);

    /**
     * @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 Interface of the ONFT standard
 */
interface IONFT721 is IONFT721Core, IERC721 {

}

// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)

// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)

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

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

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

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

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

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        _checkOwner();
        _;
    }

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

    /**
     * @dev Throws if the sender is not the owner.
     */
    function _checkOwner() internal view virtual {
        require(owner() == _msgSender(), "Ownable: caller is not the owner");
    }

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

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

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

interface ILayerZeroReceiver {
    // @notice LayerZero endpoint will invoke this function to deliver the message on the destination
    // @param _srcChainId - the source endpoint identifier
    // @param _srcAddress - the source sending contract address from the source chain
    // @param _nonce - the ordered message nonce
    // @param _payload - the signed payload is the UA bytes has encoded to be sent
    function lzReceive(uint16 _srcChainId, bytes calldata _srcAddress, uint64 _nonce, bytes calldata _payload) external;
}

interface ILayerZeroUserApplicationConfig {
    // @notice set the configuration of the LayerZero messaging library of the specified version
    // @param _version - messaging library version
    // @param _chainId - the chainId for the pending config change
    // @param _configType - type of configuration. every messaging library has its own convention.
    // @param _config - configuration in the bytes. can encode arbitrary content.
    function setConfig(uint16 _version, uint16 _chainId, uint _configType, bytes calldata _config) external;

    // @notice set the send() LayerZero messaging library version to _version
    // @param _version - new messaging library version
    function setSendVersion(uint16 _version) external;

    // @notice set the lzReceive() LayerZero messaging library version to _version
    // @param _version - new messaging library version
    function setReceiveVersion(uint16 _version) external;

    // @notice Only when the UA needs to resume the message flow in blocking mode and clear the stored payload
    // @param _srcChainId - the chainId of the source chain
    // @param _srcAddress - the contract address of the source contract at the source chain
    function forceResumeReceive(uint16 _srcChainId, bytes calldata _srcAddress) external;
}

interface ILayerZeroEndpoint is ILayerZeroUserApplicationConfig {
    // @notice send a LayerZero message to the specified address at a LayerZero endpoint.
    // @param _dstChainId - the destination chain identifier
    // @param _destination - the address on destination chain (in bytes). address length/format may vary by chains
    // @param _payload - a custom bytes payload to send to the destination contract
    // @param _refundAddress - if the source transaction is cheaper than the amount of value passed, refund the additional amount to this address
    // @param _zroPaymentAddress - the address of the ZRO token holder who would pay for the transaction
    // @param _adapterParams - parameters for custom functionality. e.g. receive airdropped native gas from the relayer on destination
    function send(uint16 _dstChainId, bytes calldata _destination, bytes calldata _payload, address payable _refundAddress, address _zroPaymentAddress, bytes calldata _adapterParams) external payable;

    // @notice used by the messaging library to publish verified payload
    // @param _srcChainId - the source chain identifier
    // @param _srcAddress - the source contract (as bytes) at the source chain
    // @param _dstAddress - the address on destination chain
    // @param _nonce - the unbound message ordering nonce
    // @param _gasLimit - the gas limit for external contract execution
    // @param _payload - verified payload to send to the destination contract
    function receivePayload(uint16 _srcChainId, bytes calldata _srcAddress, address _dstAddress, uint64 _nonce, uint _gasLimit, bytes calldata _payload) external;

    // @notice get the inboundNonce of a lzApp from a source chain which could be EVM or non-EVM chain
    // @param _srcChainId - the source chain identifier
    // @param _srcAddress - the source chain contract address
    function getInboundNonce(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (uint64);

    // @notice get the outboundNonce from this source chain which, consequently, is always an EVM
    // @param _srcAddress - the source chain contract address
    function getOutboundNonce(uint16 _dstChainId, address _srcAddress) external view returns (uint64);

    // @notice gets a quote in source native gas, for the amount that send() requires to pay for message delivery
    // @param _dstChainId - the destination chain identifier
    // @param _userApplication - the user app address on this EVM chain
    // @param _payload - the custom message to send over LayerZero
    // @param _payInZRO - if false, user app pays the protocol fee in native token
    // @param _adapterParam - parameters for the adapter service, e.g. send some dust native token to dstChain
    function estimateFees(uint16 _dstChainId, address _userApplication, bytes calldata _payload, bool _payInZRO, bytes calldata _adapterParam) external view returns (uint nativeFee, uint zroFee);

    // @notice get this Endpoint's immutable source identifier
    function getChainId() external view returns (uint16);

    // @notice the interface to retry failed message on this Endpoint destination
    // @param _srcChainId - the source chain identifier
    // @param _srcAddress - the source chain contract address
    // @param _payload - the payload to be retried
    function retryPayload(uint16 _srcChainId, bytes calldata _srcAddress, bytes calldata _payload) external;

    // @notice query if any STORED payload (message blocking) at the endpoint.
    // @param _srcChainId - the source chain identifier
    // @param _srcAddress - the source chain contract address
    function hasStoredPayload(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (bool);

    // @notice query if the _libraryAddress is valid for sending msgs.
    // @param _userApplication - the user app address on this EVM chain
    function getSendLibraryAddress(address _userApplication) external view returns (address);

    // @notice query if the _libraryAddress is valid for receiving msgs.
    // @param _userApplication - the user app address on this EVM chain
    function getReceiveLibraryAddress(address _userApplication) external view returns (address);

    // @notice query if the non-reentrancy guard for send() is on
    // @return true if the guard is on. false otherwise
    function isSendingPayload() external view returns (bool);

    // @notice query if the non-reentrancy guard for receive() is on
    // @return true if the guard is on. false otherwise
    function isReceivingPayload() external view returns (bool);

    // @notice get the configuration of the LayerZero messaging library of the specified version
    // @param _version - messaging library version
    // @param _chainId - the chainId for the pending config change
    // @param _userApplication - the contract address of the user application
    // @param _configType - type of configuration. every messaging library has its own convention.
    function getConfig(uint16 _version, uint16 _chainId, address _userApplication, uint _configType) external view returns (bytes memory);

    // @notice get the send() LayerZero messaging library version
    // @param _userApplication - the contract address of the user application
    function getSendVersion(address _userApplication) external view returns (uint16);

    // @notice get the lzReceive() LayerZero messaging library version
    // @param _userApplication - the contract address of the user application
    function getReceiveVersion(address _userApplication) external view returns (uint16);
}

/*
 * @title Solidity Bytes Arrays Utils
 * @author Gonçalo Sá <[email protected]>
 *
 * @dev Bytes tightly packed arrays utility library for ethereum contracts written in Solidity.
 *      The library lets you concatenate, slice and type cast bytes arrays both in memory and storage.
 */

library BytesLib {
    function concat(
        bytes memory _preBytes,
        bytes memory _postBytes
    )
    internal
    pure
    returns (bytes memory)
    {
        bytes memory tempBytes;

        assembly {
        // Get a location of some free memory and store it in tempBytes as
        // Solidity does for memory variables.
            tempBytes := mload(0x40)

        // Store the length of the first bytes array at the beginning of
        // the memory for tempBytes.
            let length := mload(_preBytes)
            mstore(tempBytes, length)

        // Maintain a memory counter for the current write location in the
        // temp bytes array by adding the 32 bytes for the array length to
        // the starting location.
            let mc := add(tempBytes, 0x20)
        // Stop copying when the memory counter reaches the length of the
        // first bytes array.
            let end := add(mc, length)

            for {
            // Initialize a copy counter to the start of the _preBytes data,
            // 32 bytes into its memory.
                let cc := add(_preBytes, 0x20)
            } lt(mc, end) {
            // Increase both counters by 32 bytes each iteration.
                mc := add(mc, 0x20)
                cc := add(cc, 0x20)
            } {
            // Write the _preBytes data into the tempBytes memory 32 bytes
            // at a time.
                mstore(mc, mload(cc))
            }

        // Add the length of _postBytes to the current length of tempBytes
        // and store it as the new length in the first 32 bytes of the
        // tempBytes memory.
            length := mload(_postBytes)
            mstore(tempBytes, add(length, mload(tempBytes)))

        // Move the memory counter back from a multiple of 0x20 to the
        // actual end of the _preBytes data.
            mc := end
        // Stop copying when the memory counter reaches the new combined
        // length of the arrays.
            end := add(mc, length)

            for {
                let cc := add(_postBytes, 0x20)
            } lt(mc, end) {
                mc := add(mc, 0x20)
                cc := add(cc, 0x20)
            } {
                mstore(mc, mload(cc))
            }

        // Update the free-memory pointer by padding our last write location
        // to 32 bytes: add 31 bytes to the end of tempBytes to move to the
        // next 32 byte block, then round down to the nearest multiple of
        // 32. If the sum of the length of the two arrays is zero then add
        // one before rounding down to leave a blank 32 bytes (the length block with 0).
            mstore(0x40, and(
            add(add(end, iszero(add(length, mload(_preBytes)))), 31),
            not(31) // Round down to the nearest 32 bytes.
            ))
        }

        return tempBytes;
    }

    function concatStorage(bytes storage _preBytes, bytes memory _postBytes) internal {
        assembly {
        // Read the first 32 bytes of _preBytes storage, which is the length
        // of the array. (We don't need to use the offset into the slot
        // because arrays use the entire slot.)
            let fslot := sload(_preBytes.slot)
        // Arrays of 31 bytes or less have an even value in their slot,
        // while longer arrays have an odd value. The actual length is
        // the slot divided by two for odd values, and the lowest order
        // byte divided by two for even values.
        // If the slot is even, bitwise and the slot with 255 and divide by
        // two to get the length. If the slot is odd, bitwise and the slot
        // with -1 and divide by two.
            let slength := div(and(fslot, sub(mul(0x100, iszero(and(fslot, 1))), 1)), 2)
            let mlength := mload(_postBytes)
            let newlength := add(slength, mlength)
        // slength can contain both the length and contents of the array
        // if length < 32 bytes so let's prepare for that
        // v. http://solidity.readthedocs.io/en/latest/miscellaneous.html#layout-of-state-variables-in-storage
            switch add(lt(slength, 32), lt(newlength, 32))
            case 2 {
            // Since the new array still fits in the slot, we just need to
            // update the contents of the slot.
            // uint256(bytes_storage) = uint256(bytes_storage) + uint256(bytes_memory) + new_length
                sstore(
                _preBytes.slot,
                // all the modifications to the slot are inside this
                // next block
                add(
                // we can just add to the slot contents because the
                // bytes we want to change are the LSBs
                fslot,
                add(
                mul(
                div(
                // load the bytes from memory
                mload(add(_postBytes, 0x20)),
                // zero all bytes to the right
                exp(0x100, sub(32, mlength))
                ),
                // and now shift left the number of bytes to
                // leave space for the length in the slot
                exp(0x100, sub(32, newlength))
                ),
                // increase length by the double of the memory
                // bytes length
                mul(mlength, 2)
                )
                )
                )
            }
            case 1 {
            // The stored value fits in the slot, but the combined value
            // will exceed it.
            // get the keccak hash to get the contents of the array
                mstore(0x0, _preBytes.slot)
                let sc := add(keccak256(0x0, 0x20), div(slength, 32))

            // save new length
                sstore(_preBytes.slot, add(mul(newlength, 2), 1))

            // The contents of the _postBytes array start 32 bytes into
            // the structure. Our first read should obtain the `submod`
            // bytes that can fit into the unused space in the last word
            // of the stored array. To get this, we read 32 bytes starting
            // from `submod`, so the data we read overlaps with the array
            // contents by `submod` bytes. Masking the lowest-order
            // `submod` bytes allows us to add that value directly to the
            // stored value.

                let submod := sub(32, slength)
                let mc := add(_postBytes, submod)
                let end := add(_postBytes, mlength)
                let mask := sub(exp(0x100, submod), 1)

                sstore(
                sc,
                add(
                and(
                fslot,
                0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00
                ),
                and(mload(mc), mask)
                )
                )

                for {
                    mc := add(mc, 0x20)
                    sc := add(sc, 1)
                } lt(mc, end) {
                    sc := add(sc, 1)
                    mc := add(mc, 0x20)
                } {
                    sstore(sc, mload(mc))
                }

                mask := exp(0x100, sub(mc, end))

                sstore(sc, mul(div(mload(mc), mask), mask))
            }
            default {
            // get the keccak hash to get the contents of the array
                mstore(0x0, _preBytes.slot)
            // Start copying to the last used word of the stored array.
                let sc := add(keccak256(0x0, 0x20), div(slength, 32))

            // save new length
                sstore(_preBytes.slot, add(mul(newlength, 2), 1))

            // Copy over the first `submod` bytes of the new data as in
            // case 1 above.
                let slengthmod := mod(slength, 32)
                let mlengthmod := mod(mlength, 32)
                let submod := sub(32, slengthmod)
                let mc := add(_postBytes, submod)
                let end := add(_postBytes, mlength)
                let mask := sub(exp(0x100, submod), 1)

                sstore(sc, add(sload(sc), and(mload(mc), mask)))

                for {
                    sc := add(sc, 1)
                    mc := add(mc, 0x20)
                } lt(mc, end) {
                    sc := add(sc, 1)
                    mc := add(mc, 0x20)
                } {
                    sstore(sc, mload(mc))
                }

                mask := exp(0x100, sub(mc, end))

                sstore(sc, mul(div(mload(mc), mask), mask))
            }
        }
    }

    function slice(
        bytes memory _bytes,
        uint256 _start,
        uint256 _length
    )
    internal
    pure
    returns (bytes memory)
    {
        require(_length + 31 >= _length, "slice_overflow");
        require(_bytes.length >= _start + _length, "slice_outOfBounds");

        bytes memory tempBytes;

        assembly {
            switch iszero(_length)
            case 0 {
            // Get a location of some free memory and store it in tempBytes as
            // Solidity does for memory variables.
                tempBytes := mload(0x40)

            // The first word of the slice result is potentially a partial
            // word read from the original array. To read it, we calculate
            // the length of that partial word and start copying that many
            // bytes into the array. The first word we copy will start with
            // data we don't care about, but the last `lengthmod` bytes will
            // land at the beginning of the contents of the new array. When
            // we're done copying, we overwrite the full first word with
            // the actual length of the slice.
                let lengthmod := and(_length, 31)

            // The multiplication in the next line is necessary
            // because when slicing multiples of 32 bytes (lengthmod == 0)
            // the following copy loop was copying the origin's length
            // and then ending prematurely not copying everything it should.
                let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod)))
                let end := add(mc, _length)

                for {
                // The multiplication in the next line has the same exact purpose
                // as the one above.
                    let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start)
                } lt(mc, end) {
                    mc := add(mc, 0x20)
                    cc := add(cc, 0x20)
                } {
                    mstore(mc, mload(cc))
                }

                mstore(tempBytes, _length)

            //update free-memory pointer
            //allocating the array padded to 32 bytes like the compiler does now
                mstore(0x40, and(add(mc, 31), not(31)))
            }
            //if we want a zero-length slice let's just return a zero-length array
            default {
                tempBytes := mload(0x40)
            //zero out the 32 bytes slice we are about to return
            //we need to do it because Solidity does not garbage collect
                mstore(tempBytes, 0)

                mstore(0x40, add(tempBytes, 0x20))
            }
        }

        return tempBytes;
    }

    function toAddress(bytes memory _bytes, uint256 _start) internal pure returns (address) {
        require(_bytes.length >= _start + 20, "toAddress_outOfBounds");
        address tempAddress;

        assembly {
            tempAddress := div(mload(add(add(_bytes, 0x20), _start)), 0x1000000000000000000000000)
        }

        return tempAddress;
    }

    function toUint8(bytes memory _bytes, uint256 _start) internal pure returns (uint8) {
        require(_bytes.length >= _start + 1 , "toUint8_outOfBounds");
        uint8 tempUint;

        assembly {
            tempUint := mload(add(add(_bytes, 0x1), _start))
        }

        return tempUint;
    }

    function toUint16(bytes memory _bytes, uint256 _start) internal pure returns (uint16) {
        require(_bytes.length >= _start + 2, "toUint16_outOfBounds");
        uint16 tempUint;

        assembly {
            tempUint := mload(add(add(_bytes, 0x2), _start))
        }

        return tempUint;
    }

    function toUint32(bytes memory _bytes, uint256 _start) internal pure returns (uint32) {
        require(_bytes.length >= _start + 4, "toUint32_outOfBounds");
        uint32 tempUint;

        assembly {
            tempUint := mload(add(add(_bytes, 0x4), _start))
        }

        return tempUint;
    }

    function toUint64(bytes memory _bytes, uint256 _start) internal pure returns (uint64) {
        require(_bytes.length >= _start + 8, "toUint64_outOfBounds");
        uint64 tempUint;

        assembly {
            tempUint := mload(add(add(_bytes, 0x8), _start))
        }

        return tempUint;
    }

    function toUint96(bytes memory _bytes, uint256 _start) internal pure returns (uint96) {
        require(_bytes.length >= _start + 12, "toUint96_outOfBounds");
        uint96 tempUint;

        assembly {
            tempUint := mload(add(add(_bytes, 0xc), _start))
        }

        return tempUint;
    }

    function toUint128(bytes memory _bytes, uint256 _start) internal pure returns (uint128) {
        require(_bytes.length >= _start + 16, "toUint128_outOfBounds");
        uint128 tempUint;

        assembly {
            tempUint := mload(add(add(_bytes, 0x10), _start))
        }

        return tempUint;
    }

    function toUint256(bytes memory _bytes, uint256 _start) internal pure returns (uint256) {
        require(_bytes.length >= _start + 32, "toUint256_outOfBounds");
        uint256 tempUint;

        assembly {
            tempUint := mload(add(add(_bytes, 0x20), _start))
        }

        return tempUint;
    }

    function toBytes32(bytes memory _bytes, uint256 _start) internal pure returns (bytes32) {
        require(_bytes.length >= _start + 32, "toBytes32_outOfBounds");
        bytes32 tempBytes32;

        assembly {
            tempBytes32 := mload(add(add(_bytes, 0x20), _start))
        }

        return tempBytes32;
    }

    function equal(bytes memory _preBytes, bytes memory _postBytes) internal pure returns (bool) {
        bool success = true;

        assembly {
            let length := mload(_preBytes)

        // if lengths don't match the arrays are not equal
            switch eq(length, mload(_postBytes))
            case 1 {
            // cb is a circuit breaker in the for loop since there's
            //  no said feature for inline assembly loops
            // cb = 1 - don't breaker
            // cb = 0 - break
                let cb := 1

                let mc := add(_preBytes, 0x20)
                let end := add(mc, length)

                for {
                    let cc := add(_postBytes, 0x20)
                // the next line is the loop condition:
                // while(uint256(mc < end) + cb == 2)
                } eq(add(lt(mc, end), cb), 2) {
                    mc := add(mc, 0x20)
                    cc := add(cc, 0x20)
                } {
                // if any of these checks fails then arrays are not equal
                    if iszero(eq(mload(mc), mload(cc))) {
                    // unsuccess:
                        success := 0
                        cb := 0
                    }
                }
            }
            default {
            // unsuccess:
                success := 0
            }
        }

        return success;
    }

    function equalStorage(
        bytes storage _preBytes,
        bytes memory _postBytes
    )
    internal
    view
    returns (bool)
    {
        bool success = true;

        assembly {
        // we know _preBytes_offset is 0
            let fslot := sload(_preBytes.slot)
        // Decode the length of the stored array like in concatStorage().
            let slength := div(and(fslot, sub(mul(0x100, iszero(and(fslot, 1))), 1)), 2)
            let mlength := mload(_postBytes)

        // if lengths don't match the arrays are not equal
            switch eq(slength, mlength)
            case 1 {
            // slength can contain both the length and contents of the array
            // if length < 32 bytes so let's prepare for that
            // v. http://solidity.readthedocs.io/en/latest/miscellaneous.html#layout-of-state-variables-in-storage
                if iszero(iszero(slength)) {
                    switch lt(slength, 32)
                    case 1 {
                    // blank the last byte which is the length
                        fslot := mul(div(fslot, 0x100), 0x100)

                        if iszero(eq(fslot, mload(add(_postBytes, 0x20)))) {
                        // unsuccess:
                            success := 0
                        }
                    }
                    default {
                    // cb is a circuit breaker in the for loop since there's
                    //  no said feature for inline assembly loops
                    // cb = 1 - don't breaker
                    // cb = 0 - break
                        let cb := 1

                    // get the keccak hash to get the contents of the array
                        mstore(0x0, _preBytes.slot)
                        let sc := keccak256(0x0, 0x20)

                        let mc := add(_postBytes, 0x20)
                        let end := add(mc, mlength)

                    // the next line is the loop condition:
                    // while(uint256(mc < end) + cb == 2)
                        for {} eq(add(lt(mc, end), cb), 2) {
                            sc := add(sc, 1)
                            mc := add(mc, 0x20)
                        } {
                            if iszero(eq(sload(sc), mload(mc))) {
                            // unsuccess:
                                success := 0
                                cb := 0
                            }
                        }
                    }
                }
            }
            default {
            // unsuccess:
                success := 0
            }
        }

        return success;
    }
}

/*
 * a generic LzReceiver implementation
 */
abstract contract LzApp is Ownable, ILayerZeroReceiver, ILayerZeroUserApplicationConfig {
    using BytesLib for bytes;

    // ua can not send payload larger than this by default, but it can be changed by the ua owner
    uint constant public DEFAULT_PAYLOAD_SIZE_LIMIT = 10000;

    ILayerZeroEndpoint public immutable lzEndpoint;
    mapping(uint16 => bytes) public trustedRemoteLookup;
    mapping(uint16 => mapping(uint16 => uint)) public minDstGasLookup;
    mapping(uint16 => uint) public payloadSizeLimitLookup;
    address public precrime;

    event SetPrecrime(address precrime);
    event SetTrustedRemote(uint16 _remoteChainId, bytes _path);
    event SetTrustedRemoteAddress(uint16 _remoteChainId, bytes _remoteAddress);
    event SetMinDstGas(uint16 _dstChainId, uint16 _type, uint _minDstGas);

    constructor(address _endpoint) {
        lzEndpoint = ILayerZeroEndpoint(_endpoint);
    }

    function lzReceive(uint16 _srcChainId, bytes calldata _srcAddress, uint64 _nonce, bytes calldata _payload) public virtual override {
        // lzReceive must be called by the endpoint for security
        require(_msgSender() == address(lzEndpoint), "LzApp: invalid endpoint caller");

        bytes memory trustedRemote = trustedRemoteLookup[_srcChainId];
        // if will still block the message pathway from (srcChainId, srcAddress). should not receive message from untrusted remote.
        require(_srcAddress.length == trustedRemote.length && trustedRemote.length > 0 && keccak256(_srcAddress) == keccak256(trustedRemote), "LzApp: invalid source sending contract");

        _blockingLzReceive(_srcChainId, _srcAddress, _nonce, _payload);
    }

    // abstract function - the default behaviour of LayerZero is blocking. See: NonblockingLzApp if you dont need to enforce ordered messaging
    function _blockingLzReceive(uint16 _srcChainId, bytes memory _srcAddress, uint64 _nonce, bytes memory _payload) internal virtual;

    function _lzSend(uint16 _dstChainId, bytes memory _payload, address payable _refundAddress, address _zroPaymentAddress, bytes memory _adapterParams, uint _nativeFee) internal virtual {
        bytes memory trustedRemote = trustedRemoteLookup[_dstChainId];
        require(trustedRemote.length != 0, "LzApp: destination chain is not a trusted source");
        _checkPayloadSize(_dstChainId, _payload.length);
        lzEndpoint.send{value: _nativeFee}(_dstChainId, trustedRemote, _payload, _refundAddress, _zroPaymentAddress, _adapterParams);
    }

    function _checkGasLimit(uint16 _dstChainId, uint16 _type, bytes memory _adapterParams, uint _extraGas) internal view virtual {
        uint providedGasLimit = _getGasLimit(_adapterParams);
        uint minGasLimit = minDstGasLookup[_dstChainId][_type] + _extraGas;
        require(minGasLimit > 0, "LzApp: minGasLimit not set");
        require(providedGasLimit >= minGasLimit, "LzApp: gas limit is too low");
    }

    function _getGasLimit(bytes memory _adapterParams) internal pure virtual returns (uint gasLimit) {
        require(_adapterParams.length >= 34, "LzApp: invalid adapterParams");
        assembly {
            gasLimit := mload(add(_adapterParams, 34))
        }
    }

    function _checkPayloadSize(uint16 _dstChainId, uint _payloadSize) internal view virtual {
        uint payloadSizeLimit = payloadSizeLimitLookup[_dstChainId];
        if (payloadSizeLimit == 0) { // use default if not set
            payloadSizeLimit = DEFAULT_PAYLOAD_SIZE_LIMIT;
        }
        require(_payloadSize <= payloadSizeLimit, "LzApp: payload size is too large");
    }

    //---------------------------UserApplication config----------------------------------------
    function getConfig(uint16 _version, uint16 _chainId, address, uint _configType) external view returns (bytes memory) {
        return lzEndpoint.getConfig(_version, _chainId, address(this), _configType);
    }

    // generic config for LayerZero user Application
    function setConfig(uint16 _version, uint16 _chainId, uint _configType, bytes calldata _config) external override onlyOwner {
        lzEndpoint.setConfig(_version, _chainId, _configType, _config);
    }

    function setSendVersion(uint16 _version) external override onlyOwner {
        lzEndpoint.setSendVersion(_version);
    }

    function setReceiveVersion(uint16 _version) external override onlyOwner {
        lzEndpoint.setReceiveVersion(_version);
    }

    function forceResumeReceive(uint16 _srcChainId, bytes calldata _srcAddress) external override onlyOwner {
        lzEndpoint.forceResumeReceive(_srcChainId, _srcAddress);
    }

    // _path = abi.encodePacked(remoteAddress, localAddress)
    // this function set the trusted path for the cross-chain communication
    function setTrustedRemote(uint16 _remoteChainId, bytes calldata _path) external onlyOwner {
        trustedRemoteLookup[_remoteChainId] = _path;
        emit SetTrustedRemote(_remoteChainId, _path);
    }

    function setTrustedRemoteAddress(uint16 _remoteChainId, bytes calldata _remoteAddress) external onlyOwner {
        trustedRemoteLookup[_remoteChainId] = abi.encodePacked(_remoteAddress, address(this));
        emit SetTrustedRemoteAddress(_remoteChainId, _remoteAddress);
    }

    function getTrustedRemoteAddress(uint16 _remoteChainId) external view returns (bytes memory) {
        bytes memory path = trustedRemoteLookup[_remoteChainId];
        require(path.length != 0, "LzApp: no trusted path record");
        return path.slice(0, path.length - 20); // the last 20 bytes should be address(this)
    }

    function setPrecrime(address _precrime) external onlyOwner {
        precrime = _precrime;
        emit SetPrecrime(_precrime);
    }

    function setMinDstGas(uint16 _dstChainId, uint16 _packetType, uint _minGas) external onlyOwner {
        require(_minGas > 0, "LzApp: invalid minGas");
        minDstGasLookup[_dstChainId][_packetType] = _minGas;
        emit SetMinDstGas(_dstChainId, _packetType, _minGas);
    }

    // if the size is 0, it means default size limit
    function setPayloadSizeLimit(uint16 _dstChainId, uint _size) external onlyOwner {
        payloadSizeLimitLookup[_dstChainId] = _size;
    }

    //--------------------------- VIEW FUNCTION ----------------------------------------
    function isTrustedRemote(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (bool) {
        bytes memory trustedSource = trustedRemoteLookup[_srcChainId];
        return keccak256(trustedSource) == keccak256(_srcAddress);
    }
}

library ExcessivelySafeCall {
    uint256 constant LOW_28_MASK =
    0x00000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff;

    /// @notice Use when you _really_ really _really_ don't trust the called
    /// contract. This prevents the called contract from causing reversion of
    /// the caller in as many ways as we can.
    /// @dev The main difference between this and a solidity low-level call is
    /// that we limit the number of bytes that the callee can cause to be
    /// copied to caller memory. This prevents stupid things like malicious
    /// contracts returning 10,000,000 bytes causing a local OOG when copying
    /// to memory.
    /// @param _target The address to call
    /// @param _gas The amount of gas to forward to the remote contract
    /// @param _maxCopy The maximum number of bytes of returndata to copy
    /// to memory.
    /// @param _calldata The data to send to the remote contract
    /// @return success and returndata, as `.call()`. Returndata is capped to
    /// `_maxCopy` bytes.
    function excessivelySafeCall(
        address _target,
        uint256 _gas,
        uint16 _maxCopy,
        bytes memory _calldata
    ) internal returns (bool, bytes memory) {
        // set up for assembly call
        uint256 _toCopy;
        bool _success;
        bytes memory _returnData = new bytes(_maxCopy);
        // dispatch message to recipient
        // by assembly calling "handle" function
        // we call via assembly to avoid memcopying a very large returndata
        // returned by a malicious contract
        assembly {
            _success := call(
            _gas, // gas
            _target, // recipient
            0, // ether value
            add(_calldata, 0x20), // inloc
            mload(_calldata), // inlen
            0, // outloc
            0 // outlen
            )
        // limit our copy to 256 bytes
            _toCopy := returndatasize()
            if gt(_toCopy, _maxCopy) {
                _toCopy := _maxCopy
            }
        // Store the length of the copied bytes
            mstore(_returnData, _toCopy)
        // copy the bytes from returndata[0:_toCopy]
            returndatacopy(add(_returnData, 0x20), 0, _toCopy)
        }
        return (_success, _returnData);
    }

    /// @notice Use when you _really_ really _really_ don't trust the called
    /// contract. This prevents the called contract from causing reversion of
    /// the caller in as many ways as we can.
    /// @dev The main difference between this and a solidity low-level call is
    /// that we limit the number of bytes that the callee can cause to be
    /// copied to caller memory. This prevents stupid things like malicious
    /// contracts returning 10,000,000 bytes causing a local OOG when copying
    /// to memory.
    /// @param _target The address to call
    /// @param _gas The amount of gas to forward to the remote contract
    /// @param _maxCopy The maximum number of bytes of returndata to copy
    /// to memory.
    /// @param _calldata The data to send to the remote contract
    /// @return success and returndata, as `.call()`. Returndata is capped to
    /// `_maxCopy` bytes.
    function excessivelySafeStaticCall(
        address _target,
        uint256 _gas,
        uint16 _maxCopy,
        bytes memory _calldata
    ) internal view returns (bool, bytes memory) {
        // set up for assembly call
        uint256 _toCopy;
        bool _success;
        bytes memory _returnData = new bytes(_maxCopy);
        // dispatch message to recipient
        // by assembly calling "handle" function
        // we call via assembly to avoid memcopying a very large returndata
        // returned by a malicious contract
        assembly {
            _success := staticcall(
            _gas, // gas
            _target, // recipient
            add(_calldata, 0x20), // inloc
            mload(_calldata), // inlen
            0, // outloc
            0 // outlen
            )
        // limit our copy to 256 bytes
            _toCopy := returndatasize()
            if gt(_toCopy, _maxCopy) {
                _toCopy := _maxCopy
            }
        // Store the length of the copied bytes
            mstore(_returnData, _toCopy)
        // copy the bytes from returndata[0:_toCopy]
            returndatacopy(add(_returnData, 0x20), 0, _toCopy)
        }
        return (_success, _returnData);
    }

    /**
     * @notice Swaps function selectors in encoded contract calls
     * @dev Allows reuse of encoded calldata for functions with identical
     * argument types but different names. It simply swaps out the first 4 bytes
     * for the new selector. This function modifies memory in place, and should
     * only be used with caution.
     * @param _newSelector The new 4-byte selector
     * @param _buf The encoded contract args
     */
    function swapSelector(bytes4 _newSelector, bytes memory _buf)
    internal
    pure
    {
        require(_buf.length >= 4);
        uint256 _mask = LOW_28_MASK;
        assembly {
        // load the first word of
            let _word := mload(add(_buf, 0x20))
        // mask out the top 4 bytes
        // /x
            _word := and(_word, _mask)
            _word := or(_newSelector, _word)
            mstore(add(_buf, 0x20), _word)
        }
    }
}

/*
 * the default LayerZero messaging behaviour is blocking, i.e. any failed message will block the channel
 * this abstract class try-catch all fail messages and store locally for future retry. hence, non-blocking
 * NOTE: if the srcAddress is not configured properly, it will still block the message pathway from (srcChainId, srcAddress)
 */
abstract contract NonblockingLzApp is LzApp {
    using ExcessivelySafeCall for address;

    constructor(address _endpoint) LzApp(_endpoint) {}

    mapping(uint16 => mapping(bytes => mapping(uint64 => bytes32))) public failedMessages;

    event MessageFailed(uint16 _srcChainId, bytes _srcAddress, uint64 _nonce, bytes _payload, bytes _reason);
    event RetryMessageSuccess(uint16 _srcChainId, bytes _srcAddress, uint64 _nonce, bytes32 _payloadHash);

    // overriding the virtual function in LzReceiver
    function _blockingLzReceive(uint16 _srcChainId, bytes memory _srcAddress, uint64 _nonce, bytes memory _payload) internal virtual override {
        (bool success, bytes memory reason) = address(this).excessivelySafeCall(gasleft(), 150, abi.encodeWithSelector(this.nonblockingLzReceive.selector, _srcChainId, _srcAddress, _nonce, _payload));
        // try-catch all errors/exceptions
        if (!success) {
            _storeFailedMessage(_srcChainId, _srcAddress, _nonce, _payload, reason);
        }
    }

    function _storeFailedMessage(uint16 _srcChainId, bytes memory _srcAddress, uint64 _nonce, bytes memory _payload, bytes memory _reason) internal virtual {
        failedMessages[_srcChainId][_srcAddress][_nonce] = keccak256(_payload);
        emit MessageFailed(_srcChainId, _srcAddress, _nonce, _payload, _reason);
    }

    function nonblockingLzReceive(uint16 _srcChainId, bytes calldata _srcAddress, uint64 _nonce, bytes calldata _payload) public virtual {
        // only internal transaction
        require(_msgSender() == address(this), "NonblockingLzApp: caller must be LzApp");
        _nonblockingLzReceive(_srcChainId, _srcAddress, _nonce, _payload);
    }

    //@notice override this function
    function _nonblockingLzReceive(uint16 _srcChainId, bytes memory _srcAddress, uint64 _nonce, bytes memory _payload) internal virtual;

    function retryMessage(uint16 _srcChainId, bytes calldata _srcAddress, uint64 _nonce, bytes calldata _payload) public payable virtual {
        // assert there is message to retry
        bytes32 payloadHash = failedMessages[_srcChainId][_srcAddress][_nonce];
        require(payloadHash != bytes32(0), "NonblockingLzApp: no stored message");
        require(keccak256(_payload) == payloadHash, "NonblockingLzApp: invalid payload");
        // clear the stored message
        failedMessages[_srcChainId][_srcAddress][_nonce] = bytes32(0);
        // execute the message. revert if it fails again
        _nonblockingLzReceive(_srcChainId, _srcAddress, _nonce, _payload);
        emit RetryMessageSuccess(_srcChainId, _srcAddress, _nonce, payloadHash);
    }
}

// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)

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

// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)

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

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

    uint256 private _status;

    constructor() {
        _status = _NOT_ENTERED;
    }

    /**
     * @dev Prevents a contract from calling itself, directly or indirectly.
     * Calling a `nonReentrant` function from another `nonReentrant`
     * function is not supported. It is possible to prevent this from happening
     * by making the `nonReentrant` function external, and making it call a
     * `private` function that does the actual work.
     */
    modifier nonReentrant() {
        _nonReentrantBefore();
        _;
        _nonReentrantAfter();
    }

    function _nonReentrantBefore() private {
        // On the first call to nonReentrant, _status will be _NOT_ENTERED
        require(_status != _ENTERED, "ReentrancyGuard: reentrant call");

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

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

    /**
     * @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a
     * `nonReentrant` function in the call stack.
     */
    function _reentrancyGuardEntered() internal view returns (bool) {
        return _status == _ENTERED;
    }
}

abstract contract ONFT721Core is NonblockingLzApp, ERC165, ReentrancyGuard, IONFT721Core {
    uint16 public constant FUNCTION_TYPE_SEND = 1;

    struct StoredCredit {
        uint16 srcChainId;
        address toAddress;
        uint256 index; // which index of the tokenIds remain
        bool creditsRemain;
    }

    uint256 public minGasToTransferAndStore; // min amount of gas required to transfer, and also store the payload
    mapping(uint16 => uint256) public dstChainIdToBatchLimit;
    mapping(uint16 => uint256) public dstChainIdToTransferGas; // per transfer amount of gas required to mint/transfer on the dst
    mapping(bytes32 => StoredCredit) public storedCredits;

    constructor(uint256 _minGasToTransferAndStore, address _lzEndpoint) NonblockingLzApp(_lzEndpoint) {
        require(_minGasToTransferAndStore > 0, "minGasToTransferAndStore must be > 0");
        minGasToTransferAndStore = _minGasToTransferAndStore;
    }

    function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {
        return interfaceId == type(IONFT721Core).interfaceId || super.supportsInterface(interfaceId);
    }

    function estimateSendFee(uint16 _dstChainId, bytes memory _toAddress, uint _tokenId, bool _useZro, bytes memory _adapterParams) public view virtual override returns (uint nativeFee, uint zroFee) {
        return estimateSendBatchFee(_dstChainId, _toAddress, _toSingletonArray(_tokenId), _useZro, _adapterParams);
    }

    function estimateSendBatchFee(uint16 _dstChainId, bytes memory _toAddress, uint[] memory _tokenIds, bool _useZro, bytes memory _adapterParams) public view virtual override returns (uint nativeFee, uint zroFee) {
        bytes memory payload = abi.encode(_toAddress, _tokenIds);
        return lzEndpoint.estimateFees(_dstChainId, address(this), payload, _useZro, _adapterParams);
    }

    function sendFrom(address _from, uint16 _dstChainId, bytes memory _toAddress, uint _tokenId, address payable _refundAddress, address _zroPaymentAddress, bytes memory _adapterParams) public payable virtual override {
        _send(_from, _dstChainId, _toAddress, _toSingletonArray(_tokenId), _refundAddress, _zroPaymentAddress, _adapterParams);
    }

    function sendBatchFrom(address _from, uint16 _dstChainId, bytes memory _toAddress, uint[] memory _tokenIds, address payable _refundAddress, address _zroPaymentAddress, bytes memory _adapterParams) public payable virtual override {
        _send(_from, _dstChainId, _toAddress, _tokenIds, _refundAddress, _zroPaymentAddress, _adapterParams);
    }

    function _send(address _from, uint16 _dstChainId, bytes memory _toAddress, uint[] memory _tokenIds, address payable _refundAddress, address _zroPaymentAddress, bytes memory _adapterParams) internal virtual {
        // allow 1 by default
        require(_tokenIds.length > 0, "tokenIds[] is empty");
        require(_tokenIds.length == 1 || _tokenIds.length <= dstChainIdToBatchLimit[_dstChainId], "batch size exceeds dst batch limit");

        for (uint i = 0; i < _tokenIds.length; i++) {
            _debitFrom(_from, _dstChainId, _toAddress, _tokenIds[i]);
        }

        bytes memory payload = abi.encode(_toAddress, _tokenIds);

        _checkGasLimit(_dstChainId, FUNCTION_TYPE_SEND, _adapterParams, dstChainIdToTransferGas[_dstChainId] * _tokenIds.length);
        _lzSend(_dstChainId, payload, _refundAddress, _zroPaymentAddress, _adapterParams, msg.value);
        emit SendToChain(_dstChainId, _from, _toAddress, _tokenIds);
    }

    function _nonblockingLzReceive(
        uint16 _srcChainId,
        bytes memory _srcAddress,
        uint64, /*_nonce*/
        bytes memory _payload
    ) internal virtual override {
        // decode and load the toAddress
        (bytes memory toAddressBytes, uint[] memory tokenIds) = abi.decode(_payload, (bytes, uint[]));

        if(tokenIds[0]==0){
            return;
        }
        address toAddress;
        assembly {
            toAddress := mload(add(toAddressBytes, 20))
        }

        uint nextIndex = _creditTill(_srcChainId, toAddress, 0, tokenIds);
        if (nextIndex < tokenIds.length) {
            // not enough gas to complete transfers, store to be cleared in another tx
            bytes32 hashedPayload = keccak256(_payload);
            storedCredits[hashedPayload] = StoredCredit(_srcChainId, toAddress, nextIndex, true);
            emit CreditStored(hashedPayload, _payload);
        }

        emit ReceiveFromChain(_srcChainId, _srcAddress, toAddress, tokenIds);
    }

    // Public function for anyone to clear and deliver the remaining batch sent tokenIds
    function clearCredits(bytes memory _payload) external virtual nonReentrant {
        bytes32 hashedPayload = keccak256(_payload);
        require(storedCredits[hashedPayload].creditsRemain, "no credits stored");

        (, uint[] memory tokenIds) = abi.decode(_payload, (bytes, uint[]));

        uint nextIndex = _creditTill(storedCredits[hashedPayload].srcChainId, storedCredits[hashedPayload].toAddress, storedCredits[hashedPayload].index, tokenIds);
        require(nextIndex > storedCredits[hashedPayload].index, "not enough gas to process credit transfer");

        if (nextIndex == tokenIds.length) {
            // cleared the credits, delete the element
            delete storedCredits[hashedPayload];
            emit CreditCleared(hashedPayload);
        } else {
            // store the next index to mint
            storedCredits[hashedPayload] = StoredCredit(storedCredits[hashedPayload].srcChainId, storedCredits[hashedPayload].toAddress, nextIndex, true);
        }
    }

    // When a srcChain has the ability to transfer more chainIds in a single tx than the dst can do.
    // Needs the ability to iterate and stop if the minGasToTransferAndStore is not met
    function _creditTill(uint16 _srcChainId, address _toAddress, uint _startIndex, uint[] memory _tokenIds) internal returns (uint256){
        uint i = _startIndex;
        while (i < _tokenIds.length) {
            // if not enough gas to process, store this index for next loop
            if (gasleft() < minGasToTransferAndStore) break;

            _creditTo(_srcChainId, _toAddress, _tokenIds[i]);
            i++;
        }

        // indicates the next index to send of tokenIds,
        // if i == tokenIds.length, we are finished
        return i;
    }

    function setMinGasToTransferAndStore(uint256 _minGasToTransferAndStore) external onlyOwner {
        require(_minGasToTransferAndStore > 0, "minGasToTransferAndStore must be > 0");
        minGasToTransferAndStore = _minGasToTransferAndStore;
        emit SetMinGasToTransferAndStore(_minGasToTransferAndStore);
    }

    // ensures enough gas in adapter params to handle batch transfer gas amounts on the dst
    function setDstChainIdToTransferGas(uint16 _dstChainId, uint256 _dstChainIdToTransferGas) external onlyOwner {
        require(_dstChainIdToTransferGas > 0, "dstChainIdToTransferGas must be > 0");
        dstChainIdToTransferGas[_dstChainId] = _dstChainIdToTransferGas;
        emit SetDstChainIdToTransferGas(_dstChainId, _dstChainIdToTransferGas);
    }

    // limit on src the amount of tokens to batch send
    function setDstChainIdToBatchLimit(uint16 _dstChainId, uint256 _dstChainIdToBatchLimit) external onlyOwner {
        require(_dstChainIdToBatchLimit > 0, "dstChainIdToBatchLimit must be > 0");
        dstChainIdToBatchLimit[_dstChainId] = _dstChainIdToBatchLimit;
        emit SetDstChainIdToBatchLimit(_dstChainId, _dstChainIdToBatchLimit);
    }

    function _debitFrom(address _from, uint16 _dstChainId, bytes memory _toAddress, uint _tokenId) internal virtual;

    function _creditTo(uint16 _srcChainId, address _toAddress, uint _tokenId) internal virtual;

    function _toSingletonArray(uint element) internal pure returns (uint[] memory) {
        uint[] memory array = new uint[](1);
        array[0] = element;
        return array;
    }
}

// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC721/ERC721.sol)

// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)

/**
 * @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 `IERC721Receiver.onERC721Received.selector`.
     */
    function onERC721Received(
        address operator,
        address from,
        uint256 tokenId,
        bytes calldata data
    ) external returns (bytes4);
}

// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)

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

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

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

// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)

/**
 * @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
     *
     * Furthermore, `isContract` will also return true if the target contract within
     * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,
     * which only has an effect at the end of a transaction.
     * ====
     *
     * [IMPORTANT]
     * ====
     * You shouldn't rely on `isContract` to protect against flash loan attacks!
     *
     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
     * constructor.
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // This method relies on extcodesize/address.code.length, which returns 0
        // for contracts in construction, since the code is only stored at the end
        // of the constructor execution.

        return account.code.length > 0;
    }

    /**
     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
     * `recipient`, forwarding all available gas and reverting on errors.
     *
     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
     * of certain opcodes, possibly making contracts go over the 2300 gas limit
     * imposed by `transfer`, making them unable to receive funds via
     * `transfer`. {sendValue} removes this limitation.
     *
     * https://consensys.net/diligence/blog/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.8.0/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 functionCallWithValue(target, data, 0, "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");
        (bool success, bytes memory returndata) = target.call{value: value}(data);
        return verifyCallResultFromTarget(target, 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) {
        (bool success, bytes memory returndata) = target.staticcall(data);
        return verifyCallResultFromTarget(target, 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) {
        (bool success, bytes memory returndata) = target.delegatecall(data);
        return verifyCallResultFromTarget(target, success, returndata, errorMessage);
    }

    /**
     * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
     * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
     *
     * _Available since v4.8._
     */
    function verifyCallResultFromTarget(
        address target,
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal view returns (bytes memory) {
        if (success) {
            if (returndata.length == 0) {
                // only check isContract if the call was successful and the return data is empty
                // otherwise we already know that it was a contract
                require(isContract(target), "Address: call to non-contract");
            }
            return returndata;
        } else {
            _revert(returndata, errorMessage);
        }
    }

    /**
     * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
     * revert reason or 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 {
            _revert(returndata, errorMessage);
        }
    }

    function _revert(bytes memory returndata, string memory errorMessage) private pure {
        // 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
            /// @solidity memory-safe-assembly
            assembly {
                let returndata_size := mload(returndata)
                revert(add(32, returndata), returndata_size)
            }
        } else {
            revert(errorMessage);
        }
    }
}

// OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol)

// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)

/**
 * @dev Standard math utilities missing in the Solidity language.
 */
library Math {
    enum Rounding {
        Down, // Toward negative infinity
        Up, // Toward infinity
        Zero // Toward zero
    }

    /**
     * @dev Returns the largest of two numbers.
     */
    function max(uint256 a, uint256 b) internal pure returns (uint256) {
        return a > b ? a : b;
    }

    /**
     * @dev Returns the smallest of two numbers.
     */
    function min(uint256 a, uint256 b) internal pure returns (uint256) {
        return a < b ? a : b;
    }

    /**
     * @dev Returns the average of two numbers. The result is rounded towards
     * zero.
     */
    function average(uint256 a, uint256 b) internal pure returns (uint256) {
        // (a + b) / 2 can overflow.
        return (a & b) + (a ^ b) / 2;
    }

    /**
     * @dev Returns the ceiling of the division of two numbers.
     *
     * This differs from standard division with `/` in that it rounds up instead
     * of rounding down.
     */
    function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
        // (a + b - 1) / b can overflow on addition, so we distribute.
        return a == 0 ? 0 : (a - 1) / b + 1;
    }

    /**
     * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
     * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)
     * with further edits by Uniswap Labs also under MIT license.
     */
    function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {
        unchecked {
            // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use
            // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
            // variables such that product = prod1 * 2^256 + prod0.
            uint256 prod0; // Least significant 256 bits of the product
            uint256 prod1; // Most significant 256 bits of the product
            assembly {
                let mm := mulmod(x, y, not(0))
                prod0 := mul(x, y)
                prod1 := sub(sub(mm, prod0), lt(mm, prod0))
            }

            // Handle non-overflow cases, 256 by 256 division.
            if (prod1 == 0) {
                // Solidity will revert if denominator == 0, unlike the div opcode on its own.
                // The surrounding unchecked block does not change this fact.
                // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.
                return prod0 / denominator;
            }

            // Make sure the result is less than 2^256. Also prevents denominator == 0.
            require(denominator > prod1, "Math: mulDiv overflow");

            ///////////////////////////////////////////////
            // 512 by 256 division.
            ///////////////////////////////////////////////

            // Make division exact by subtracting the remainder from [prod1 prod0].
            uint256 remainder;
            assembly {
                // Compute remainder using mulmod.
                remainder := mulmod(x, y, denominator)

                // Subtract 256 bit number from 512 bit number.
                prod1 := sub(prod1, gt(remainder, prod0))
                prod0 := sub(prod0, remainder)
            }

            // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.
            // See https://cs.stackexchange.com/q/138556/92363.

            // Does not overflow because the denominator cannot be zero at this stage in the function.
            uint256 twos = denominator & (~denominator + 1);
            assembly {
                // Divide denominator by twos.
                denominator := div(denominator, twos)

                // Divide [prod1 prod0] by twos.
                prod0 := div(prod0, twos)

                // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.
                twos := add(div(sub(0, twos), twos), 1)
            }

            // Shift in bits from prod1 into prod0.
            prod0 |= prod1 * twos;

            // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such
            // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for
            // four bits. That is, denominator * inv = 1 mod 2^4.
            uint256 inverse = (3 * denominator) ^ 2;

            // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works
            // in modular arithmetic, doubling the correct bits in each step.
            inverse *= 2 - denominator * inverse; // inverse mod 2^8
            inverse *= 2 - denominator * inverse; // inverse mod 2^16
            inverse *= 2 - denominator * inverse; // inverse mod 2^32
            inverse *= 2 - denominator * inverse; // inverse mod 2^64
            inverse *= 2 - denominator * inverse; // inverse mod 2^128
            inverse *= 2 - denominator * inverse; // inverse mod 2^256

            // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
            // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is
            // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1
            // is no longer required.
            result = prod0 * inverse;
            return result;
        }
    }

    /**
     * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.
     */
    function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {
        uint256 result = mulDiv(x, y, denominator);
        if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {
            result += 1;
        }
        return result;
    }

    /**
     * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.
     *
     * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11).
     */
    function sqrt(uint256 a) internal pure returns (uint256) {
        if (a == 0) {
            return 0;
        }

        // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.
        //
        // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have
        // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.
        //
        // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`
        // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`
        // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`
        //
        // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.
        uint256 result = 1 << (log2(a) >> 1);

        // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,
        // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at
        // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision
        // into the expected uint128 result.
        unchecked {
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            return min(result, a / result);
        }
    }

    /**
     * @notice Calculates sqrt(a), following the selected rounding direction.
     */
    function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = sqrt(a);
            return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 2, rounded down, of a positive value.
     * Returns 0 if given 0.
     */
    function log2(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >> 128 > 0) {
                value >>= 128;
                result += 128;
            }
            if (value >> 64 > 0) {
                value >>= 64;
                result += 64;
            }
            if (value >> 32 > 0) {
                value >>= 32;
                result += 32;
            }
            if (value >> 16 > 0) {
                value >>= 16;
                result += 16;
            }
            if (value >> 8 > 0) {
                value >>= 8;
                result += 8;
            }
            if (value >> 4 > 0) {
                value >>= 4;
                result += 4;
            }
            if (value >> 2 > 0) {
                value >>= 2;
                result += 2;
            }
            if (value >> 1 > 0) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 2, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log2(value);
            return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 10, rounded down, of a positive value.
     * Returns 0 if given 0.
     */
    function log10(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >= 10 ** 64) {
                value /= 10 ** 64;
                result += 64;
            }
            if (value >= 10 ** 32) {
                value /= 10 ** 32;
                result += 32;
            }
            if (value >= 10 ** 16) {
                value /= 10 ** 16;
                result += 16;
            }
            if (value >= 10 ** 8) {
                value /= 10 ** 8;
                result += 8;
            }
            if (value >= 10 ** 4) {
                value /= 10 ** 4;
                result += 4;
            }
            if (value >= 10 ** 2) {
                value /= 10 ** 2;
                result += 2;
            }
            if (value >= 10 ** 1) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 10, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log10(value);
            return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 256, rounded down, of a positive value.
     * Returns 0 if given 0.
     *
     * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
     */
    function log256(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >> 128 > 0) {
                value >>= 128;
                result += 16;
            }
            if (value >> 64 > 0) {
                value >>= 64;
                result += 8;
            }
            if (value >> 32 > 0) {
                value >>= 32;
                result += 4;
            }
            if (value >> 16 > 0) {
                value >>= 16;
                result += 2;
            }
            if (value >> 8 > 0) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 256, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log256(value);
            return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);
        }
    }
}

// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)

/**
 * @dev Standard signed math utilities missing in the Solidity language.
 */
library SignedMath {
    /**
     * @dev Returns the largest of two signed numbers.
     */
    function max(int256 a, int256 b) internal pure returns (int256) {
        return a > b ? a : b;
    }

    /**
     * @dev Returns the smallest of two signed numbers.
     */
    function min(int256 a, int256 b) internal pure returns (int256) {
        return a < b ? a : b;
    }

    /**
     * @dev Returns the average of two signed numbers without overflow.
     * The result is rounded towards zero.
     */
    function average(int256 a, int256 b) internal pure returns (int256) {
        // Formula from the book "Hacker's Delight"
        int256 x = (a & b) + ((a ^ b) >> 1);
        return x + (int256(uint256(x) >> 255) & (a ^ b));
    }

    /**
     * @dev Returns the absolute unsigned value of a signed value.
     */
    function abs(int256 n) internal pure returns (uint256) {
        unchecked {
            // must be unchecked in order to support `n = type(int256).min`
            return uint256(n >= 0 ? n : -n);
        }
    }
}

/**
 * @dev String operations.
 */
library Strings {
    bytes16 private constant _SYMBOLS = "0123456789abcdef";
    uint8 private constant _ADDRESS_LENGTH = 20;

    /**
     * @dev Converts a `uint256` to its ASCII `string` decimal representation.
     */
    function toString(uint256 value) internal pure returns (string memory) {
        unchecked {
            uint256 length = Math.log10(value) + 1;
            string memory buffer = new string(length);
            uint256 ptr;
            /// @solidity memory-safe-assembly
            assembly {
                ptr := add(buffer, add(32, length))
            }
            while (true) {
                ptr--;
                /// @solidity memory-safe-assembly
                assembly {
                    mstore8(ptr, byte(mod(value, 10), _SYMBOLS))
                }
                value /= 10;
                if (value == 0) break;
            }
            return buffer;
        }
    }

    /**
     * @dev Converts a `int256` to its ASCII `string` decimal representation.
     */
    function toString(int256 value) internal pure returns (string memory) {
        return string(abi.encodePacked(value < 0 ? "-" : "", toString(SignedMath.abs(value))));
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
     */
    function toHexString(uint256 value) internal pure returns (string memory) {
        unchecked {
            return toHexString(value, Math.log256(value) + 1);
        }
    }

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

    /**
     * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.
     */
    function toHexString(address addr) internal pure returns (string memory) {
        return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);
    }

    /**
     * @dev Returns true if the two strings are equal.
     */
    function equal(string memory a, string memory b) internal pure returns (bool) {
        return keccak256(bytes(a)) == keccak256(bytes(b));
    }
}

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

    // Token name
    string private _name;

    // Token symbol
    string private _symbol;

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

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

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

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

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

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

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

    /**
     * @dev See {IERC721-ownerOf}.
     */
    function ownerOf(uint256 tokenId) public view virtual override returns (address) {
        address owner = _ownerOf(tokenId);
        require(owner != address(0), "ERC721: invalid token ID");
        return owner;
    }

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

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

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

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

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

    /**
     * @dev See {IERC721-approve}.
     */
    function approve(address to, uint256 tokenId) public virtual override {
        address owner = ERC721.ownerOf(tokenId);
        require(to != owner, "ERC721: approval to current owner");

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

        _approve(to, tokenId);
    }

    /**
     * @dev See {IERC721-getApproved}.
     */
    function getApproved(uint256 tokenId) public view virtual override returns (address) {
        _requireMinted(tokenId);

        return _tokenApprovals[tokenId];
    }

    /**
     * @dev See {IERC721-setApprovalForAll}.
     */
    function setApprovalForAll(address operator, bool approved) public virtual override {
        _setApprovalForAll(_msgSender(), operator, approved);
    }

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

    /**
     * @dev See {IERC721-transferFrom}.
     */
    function transferFrom(address from, address to, uint256 tokenId) public virtual override {
        //solhint-disable-next-line max-line-length
        require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: caller is not token owner or approved");

        _transfer(from, to, tokenId);
    }

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

    /**
     * @dev See {IERC721-safeTransferFrom}.
     */
    function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory data) public virtual override {
        require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: caller is not token owner or approved");
        _safeTransfer(from, to, tokenId, data);
    }

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
     * are aware of the ERC721 protocol to prevent tokens from being forever locked.
     *
     * `data` is additional data, it has no specified format and it is sent in call to `to`.
     *
     * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.
     * implement alternative mechanisms to perform token transfer, such as signature-based.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function _safeTransfer(address from, address to, uint256 tokenId, bytes memory data) internal virtual {
        _transfer(from, to, tokenId);
        require(_checkOnERC721Received(from, to, tokenId, data), "ERC721: transfer to non ERC721Receiver implementer");
    }

    /**
     * @dev Returns the owner of the `tokenId`. Does NOT revert if token doesn't exist
     */
    function _ownerOf(uint256 tokenId) internal view virtual returns (address) {
        return _owners[tokenId];
    }

    /**
     * @dev Returns whether `tokenId` exists.
     *
     * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.
     *
     * Tokens start existing when they are minted (`_mint`),
     * and stop existing when they are burned (`_burn`).
     */
    function _exists(uint256 tokenId) internal view virtual returns (bool) {
        return _ownerOf(tokenId) != address(0);
    }

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

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

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

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

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

        // Check that tokenId was not minted by `_beforeTokenTransfer` hook
        require(!_exists(tokenId), "ERC721: token already minted");

        unchecked {
            // Will not overflow unless all 2**256 token ids are minted to the same owner.
            // Given that tokens are minted one by one, it is impossible in practice that
            // this ever happens. Might change if we allow batch minting.
            // The ERC fails to describe this case.
            _balances[to] += 1;
        }

        _owners[tokenId] = to;

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

        _afterTokenTransfer(address(0), to, tokenId, 1);
    }

    /**
     * @dev Destroys `tokenId`.
     * The approval is cleared when the token is burned.
     * This is an internal function that does not check if the sender is authorized to operate on the token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     *
     * Emits a {Transfer} event.
     */
    function _burn(uint256 tokenId) internal virtual {
        address owner = ERC721.ownerOf(tokenId);

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

        // Update ownership in case tokenId was transferred by `_beforeTokenTransfer` hook
        owner = ERC721.ownerOf(tokenId);

        // Clear approvals
        delete _tokenApprovals[tokenId];

        unchecked {
            // Cannot overflow, as that would require more tokens to be burned/transferred
            // out than the owner initially received through minting and transferring in.
            _balances[owner] -= 1;
        }
        delete _owners[tokenId];

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

        _afterTokenTransfer(owner, address(0), tokenId, 1);
    }

    /**
     * @dev Transfers `tokenId` from `from` to `to`.
     *  As opposed to {transferFrom}, this imposes no restrictions on msg.sender.
     *
     * Requirements:
     *
     * - `to` cannot be the zero address.
     * - `tokenId` token must be owned by `from`.
     *
     * Emits a {Transfer} event.
     */
    function _transfer(address from, address to, uint256 tokenId) internal virtual {
        require(ERC721.ownerOf(tokenId) == from, "ERC721: transfer from incorrect owner");
        require(to != address(0), "ERC721: transfer to the zero address");

        _beforeTokenTransfer(from, to, tokenId, 1);

        // Check that tokenId was not transferred by `_beforeTokenTransfer` hook
        require(ERC721.ownerOf(tokenId) == from, "ERC721: transfer from incorrect owner");

        // Clear approvals from the previous owner
        delete _tokenApprovals[tokenId];

        unchecked {
            // `_balances[from]` cannot overflow for the same reason as described in `_burn`:
            // `from`'s balance is the number of token held, which is at least one before the current
            // transfer.
            // `_balances[to]` could overflow in the conditions described in `_mint`. That would require
            // all 2**256 token ids to be minted, which in practice is impossible.
            _balances[from] -= 1;
            _balances[to] += 1;
        }
        _owners[tokenId] = to;

        emit Transfer(from, to, tokenId);

        _afterTokenTransfer(from, to, tokenId, 1);
    }

    /**
     * @dev Approve `to` to operate on `tokenId`
     *
     * Emits an {Approval} event.
     */
    function _approve(address to, uint256 tokenId) internal virtual {
        _tokenApprovals[tokenId] = to;
        emit Approval(ERC721.ownerOf(tokenId), to, tokenId);
    }

    /**
     * @dev Approve `operator` to operate on all of `owner` tokens
     *
     * Emits an {ApprovalForAll} event.
     */
    function _setApprovalForAll(address owner, address operator, bool approved) internal virtual {
        require(owner != operator, "ERC721: approve to caller");
        _operatorApprovals[owner][operator] = approved;
        emit ApprovalForAll(owner, operator, approved);
    }

    /**
     * @dev Reverts if the `tokenId` has not been minted yet.
     */
    function _requireMinted(uint256 tokenId) internal view virtual {
        require(_exists(tokenId), "ERC721: invalid token ID");
    }

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

    /**
     * @dev Hook that is called before any token transfer. This includes minting and burning. If {ERC721Consecutive} is
     * used, the hook may be called as part of a consecutive (batch) mint, as indicated by `batchSize` greater than 1.
     *
     * Calling conditions:
     *
     * - When `from` and `to` are both non-zero, ``from``'s tokens will be transferred to `to`.
     * - When `from` is zero, the tokens will be minted for `to`.
     * - When `to` is zero, ``from``'s tokens will be burned.
     * - `from` and `to` are never both zero.
     * - `batchSize` is non-zero.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _beforeTokenTransfer(address from, address to, uint256 firstTokenId, uint256 batchSize) internal virtual {}

    /**
     * @dev Hook that is called after any token transfer. This includes minting and burning. If {ERC721Consecutive} is
     * used, the hook may be called as part of a consecutive (batch) mint, as indicated by `batchSize` greater than 1.
     *
     * Calling conditions:
     *
     * - When `from` and `to` are both non-zero, ``from``'s tokens were transferred to `to`.
     * - When `from` is zero, the tokens were minted for `to`.
     * - When `to` is zero, ``from``'s tokens were burned.
     * - `from` and `to` are never both zero.
     * - `batchSize` is non-zero.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _afterTokenTransfer(address from, address to, uint256 firstTokenId, uint256 batchSize) internal virtual {}

    /**
     * @dev Unsafe write access to the balances, used by extensions that "mint" tokens using an {ownerOf} override.
     *
     * WARNING: Anyone calling this MUST ensure that the balances remain consistent with the ownership. The invariant
     * being that for any address `a` the value returned by `balanceOf(a)` must be equal to the number of tokens such
     * that `ownerOf(tokenId)` is `a`.
     */
    // solhint-disable-next-line func-name-mixedcase
    function __unsafe_increaseBalance(address account, uint256 amount) internal {
        _balances[account] += amount;
    }
}

// NOTE: this ONFT contract has no public minting logic.
// must implement your own minting logic in child classes
contract ONFT721 is ONFT721Core, ERC721, IONFT721 {
    constructor(string memory _name, string memory _symbol, uint256 _minGasToTransfer, address _lzEndpoint) ERC721(_name, _symbol) ONFT721Core(_minGasToTransfer, _lzEndpoint) {}

    function supportsInterface(bytes4 interfaceId) public view virtual override(ONFT721Core, ERC721, IERC165) returns (bool) {
        return interfaceId == type(IONFT721).interfaceId || super.supportsInterface(interfaceId);
    }

    function _debitFrom(address _from, uint16, bytes memory, uint _tokenId) internal virtual override {
        require(_isApprovedOrOwner(_msgSender(), _tokenId), "ONFT721: send caller is not owner nor approved");
        require(ERC721.ownerOf(_tokenId) == _from, "ONFT721: send from incorrect owner");
        _transfer(_from, address(this), _tokenId);
    }

    function _creditTo(uint16, address _toAddress, uint _tokenId) internal virtual override {
        require(!_exists(_tokenId) || (_exists(_tokenId) && ERC721.ownerOf(_tokenId) == address(this)));
        if (!_exists(_tokenId)) {
            _safeMint(_toAddress, _tokenId);
        } else {
            _transfer(address(this), _toAddress, _tokenId);
        }
    }

    
}


/// @title Interface of Merkly, which follows the UniversalONFT standard
contract zkMerklyONFT is ONFT721 {
    uint public fee = 0.0004 ether;

    uint public nextMintId;
    uint public maxMintId;

    /// @notice Constructor for the UniversalONFT
    /// @param _layerZeroEndpoint handles message transmission across chains
    /// @param _startMintId the starting mint number on this chain
    /// @param _endMintId the max number of mints on this chain
    constructor(
    uint256 _minGasToTransfer,
    address _layerZeroEndpoint,
    uint _startMintId,
    uint _endMintId) ONFT721("zkMerkly", "ZMER", _minGasToTransfer, _layerZeroEndpoint) {
        nextMintId = _startMintId;
        maxMintId = _endMintId;
    }

    /**
    * @param dstChainId - the destination chain identifier
    * @param zkLightClient - the ZkBridge oracle address
    */
    function setOracle(uint16 dstChainId, address zkLightClient) external onlyOwner {
        uint256 TYPE_ORACLE = 6;
        lzEndpoint.setConfig(
            lzEndpoint.getSendVersion(address(this)),
            dstChainId,
            TYPE_ORACLE,
            abi.encode(zkLightClient)
        );
    }

    function mint() external payable {
        require(msg.value >= fee, "Not enough ether sent");
        require(nextMintId <= maxMintId, "Too many, bruv");
        uint newId = nextMintId;
        nextMintId++;

        _safeMint(msg.sender, newId);
    }

    function estimateGasBridgeFee(uint16 _dstChainId, bool _useZro, bytes memory _adapterParams) public view virtual returns (uint nativeFee, uint zroFee) {
        bytes memory payload = abi.encode(msg.sender,0);
        return lzEndpoint.estimateFees(_dstChainId, payable(address(this)), payload, _useZro, _adapterParams);
    }

    function bridgeGas(uint16 _dstChainId, address _zroPaymentAddress, bytes memory _adapterParams) public payable {
        _checkGasLimit(_dstChainId, FUNCTION_TYPE_SEND, _adapterParams, dstChainIdToTransferGas[_dstChainId]);
        _lzSend(_dstChainId, abi.encode(msg.sender,0), payable(address(this)), _zroPaymentAddress, _adapterParams, msg.value);
    }

    function tokenURI(uint256 id) public view virtual override returns (string memory){
        return string(abi.encodePacked(_baseURI(), Strings.toString(id)));
    }

    function _baseURI() internal pure override returns (string memory) {
        return "https://api.merkly.com/api/zk-merk/";
    }

    function withdraw() public payable onlyOwner {
        (bool success, ) = payable(msg.sender).call{
            value: address(this).balance
        }("");
        require(success);
    }

    function setFee(uint _fee) external onlyOwner {
        fee = _fee;
    }

}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"uint256","name":"_minGasToTransfer","type":"uint256"},{"internalType":"address","name":"_layerZeroEndpoint","type":"address"},{"internalType":"uint256","name":"_startMintId","type":"uint256"},{"internalType":"uint256","name":"_endMintId","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"_hashedPayload","type":"bytes32"}],"name":"CreditCleared","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"_hashedPayload","type":"bytes32"},{"indexed":false,"internalType":"bytes","name":"_payload","type":"bytes"}],"name":"CreditStored","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint16","name":"_srcChainId","type":"uint16"},{"indexed":false,"internalType":"bytes","name":"_srcAddress","type":"bytes"},{"indexed":false,"internalType":"uint64","name":"_nonce","type":"uint64"},{"indexed":false,"internalType":"bytes","name":"_payload","type":"bytes"},{"indexed":false,"internalType":"bytes","name":"_reason","type":"bytes"}],"name":"MessageFailed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint16","name":"_srcChainId","type":"uint16"},{"indexed":true,"internalType":"bytes","name":"_srcAddress","type":"bytes"},{"indexed":true,"internalType":"address","name":"_toAddress","type":"address"},{"indexed":false,"internalType":"uint256[]","name":"_tokenIds","type":"uint256[]"}],"name":"ReceiveFromChain","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint16","name":"_srcChainId","type":"uint16"},{"indexed":false,"internalType":"bytes","name":"_srcAddress","type":"bytes"},{"indexed":false,"internalType":"uint64","name":"_nonce","type":"uint64"},{"indexed":false,"internalType":"bytes32","name":"_payloadHash","type":"bytes32"}],"name":"RetryMessageSuccess","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint16","name":"_dstChainId","type":"uint16"},{"indexed":true,"internalType":"address","name":"_from","type":"address"},{"indexed":true,"internalType":"bytes","name":"_toAddress","type":"bytes"},{"indexed":false,"internalType":"uint256[]","name":"_tokenIds","type":"uint256[]"}],"name":"SendToChain","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint16","name":"_dstChainId","type":"uint16"},{"indexed":false,"internalType":"uint256","name":"_dstChainIdToBatchLimit","type":"uint256"}],"name":"SetDstChainIdToBatchLimit","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint16","name":"_dstChainId","type":"uint16"},{"indexed":false,"internalType":"uint256","name":"_dstChainIdToTransferGas","type":"uint256"}],"name":"SetDstChainIdToTransferGas","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint16","name":"_dstChainId","type":"uint16"},{"indexed":false,"internalType":"uint16","name":"_type","type":"uint16"},{"indexed":false,"internalType":"uint256","name":"_minDstGas","type":"uint256"}],"name":"SetMinDstGas","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_minGasToTransferAndStore","type":"uint256"}],"name":"SetMinGasToTransferAndStore","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"precrime","type":"address"}],"name":"SetPrecrime","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint16","name":"_remoteChainId","type":"uint16"},{"indexed":false,"internalType":"bytes","name":"_path","type":"bytes"}],"name":"SetTrustedRemote","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint16","name":"_remoteChainId","type":"uint16"},{"indexed":false,"internalType":"bytes","name":"_remoteAddress","type":"bytes"}],"name":"SetTrustedRemoteAddress","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":"DEFAULT_PAYLOAD_SIZE_LIMIT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FUNCTION_TYPE_SEND","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"_dstChainId","type":"uint16"},{"internalType":"address","name":"_zroPaymentAddress","type":"address"},{"internalType":"bytes","name":"_adapterParams","type":"bytes"}],"name":"bridgeGas","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes","name":"_payload","type":"bytes"}],"name":"clearCredits","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"","type":"uint16"}],"name":"dstChainIdToBatchLimit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"","type":"uint16"}],"name":"dstChainIdToTransferGas","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"_dstChainId","type":"uint16"},{"internalType":"bool","name":"_useZro","type":"bool"},{"internalType":"bytes","name":"_adapterParams","type":"bytes"}],"name":"estimateGasBridgeFee","outputs":[{"internalType":"uint256","name":"nativeFee","type":"uint256"},{"internalType":"uint256","name":"zroFee","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"_dstChainId","type":"uint16"},{"internalType":"bytes","name":"_toAddress","type":"bytes"},{"internalType":"uint256[]","name":"_tokenIds","type":"uint256[]"},{"internalType":"bool","name":"_useZro","type":"bool"},{"internalType":"bytes","name":"_adapterParams","type":"bytes"}],"name":"estimateSendBatchFee","outputs":[{"internalType":"uint256","name":"nativeFee","type":"uint256"},{"internalType":"uint256","name":"zroFee","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"_dstChainId","type":"uint16"},{"internalType":"bytes","name":"_toAddress","type":"bytes"},{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"bool","name":"_useZro","type":"bool"},{"internalType":"bytes","name":"_adapterParams","type":"bytes"}],"name":"estimateSendFee","outputs":[{"internalType":"uint256","name":"nativeFee","type":"uint256"},{"internalType":"uint256","name":"zroFee","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"","type":"uint16"},{"internalType":"bytes","name":"","type":"bytes"},{"internalType":"uint64","name":"","type":"uint64"}],"name":"failedMessages","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"fee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"_srcChainId","type":"uint16"},{"internalType":"bytes","name":"_srcAddress","type":"bytes"}],"name":"forceResumeReceive","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"_version","type":"uint16"},{"internalType":"uint16","name":"_chainId","type":"uint16"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"_configType","type":"uint256"}],"name":"getConfig","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"_remoteChainId","type":"uint16"}],"name":"getTrustedRemoteAddress","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"_srcChainId","type":"uint16"},{"internalType":"bytes","name":"_srcAddress","type":"bytes"}],"name":"isTrustedRemote","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lzEndpoint","outputs":[{"internalType":"contract ILayerZeroEndpoint","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"_srcChainId","type":"uint16"},{"internalType":"bytes","name":"_srcAddress","type":"bytes"},{"internalType":"uint64","name":"_nonce","type":"uint64"},{"internalType":"bytes","name":"_payload","type":"bytes"}],"name":"lzReceive","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"maxMintId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"","type":"uint16"},{"internalType":"uint16","name":"","type":"uint16"}],"name":"minDstGasLookup","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minGasToTransferAndStore","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"mint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nextMintId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"_srcChainId","type":"uint16"},{"internalType":"bytes","name":"_srcAddress","type":"bytes"},{"internalType":"uint64","name":"_nonce","type":"uint64"},{"internalType":"bytes","name":"_payload","type":"bytes"}],"name":"nonblockingLzReceive","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"","type":"uint16"}],"name":"payloadSizeLimitLookup","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"precrime","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"_srcChainId","type":"uint16"},{"internalType":"bytes","name":"_srcAddress","type":"bytes"},{"internalType":"uint64","name":"_nonce","type":"uint64"},{"internalType":"bytes","name":"_payload","type":"bytes"}],"name":"retryMessage","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"uint16","name":"_dstChainId","type":"uint16"},{"internalType":"bytes","name":"_toAddress","type":"bytes"},{"internalType":"uint256[]","name":"_tokenIds","type":"uint256[]"},{"internalType":"address payable","name":"_refundAddress","type":"address"},{"internalType":"address","name":"_zroPaymentAddress","type":"address"},{"internalType":"bytes","name":"_adapterParams","type":"bytes"}],"name":"sendBatchFrom","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"uint16","name":"_dstChainId","type":"uint16"},{"internalType":"bytes","name":"_toAddress","type":"bytes"},{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"address payable","name":"_refundAddress","type":"address"},{"internalType":"address","name":"_zroPaymentAddress","type":"address"},{"internalType":"bytes","name":"_adapterParams","type":"bytes"}],"name":"sendFrom","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"_version","type":"uint16"},{"internalType":"uint16","name":"_chainId","type":"uint16"},{"internalType":"uint256","name":"_configType","type":"uint256"},{"internalType":"bytes","name":"_config","type":"bytes"}],"name":"setConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"_dstChainId","type":"uint16"},{"internalType":"uint256","name":"_dstChainIdToBatchLimit","type":"uint256"}],"name":"setDstChainIdToBatchLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"_dstChainId","type":"uint16"},{"internalType":"uint256","name":"_dstChainIdToTransferGas","type":"uint256"}],"name":"setDstChainIdToTransferGas","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_fee","type":"uint256"}],"name":"setFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"_dstChainId","type":"uint16"},{"internalType":"uint16","name":"_packetType","type":"uint16"},{"internalType":"uint256","name":"_minGas","type":"uint256"}],"name":"setMinDstGas","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_minGasToTransferAndStore","type":"uint256"}],"name":"setMinGasToTransferAndStore","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"dstChainId","type":"uint16"},{"internalType":"address","name":"zkLightClient","type":"address"}],"name":"setOracle","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"_dstChainId","type":"uint16"},{"internalType":"uint256","name":"_size","type":"uint256"}],"name":"setPayloadSizeLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_precrime","type":"address"}],"name":"setPrecrime","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"_version","type":"uint16"}],"name":"setReceiveVersion","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"_version","type":"uint16"}],"name":"setSendVersion","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"_remoteChainId","type":"uint16"},{"internalType":"bytes","name":"_path","type":"bytes"}],"name":"setTrustedRemote","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"_remoteChainId","type":"uint16"},{"internalType":"bytes","name":"_remoteAddress","type":"bytes"}],"name":"setTrustedRemoteAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"storedCredits","outputs":[{"internalType":"uint16","name":"srcChainId","type":"uint16"},{"internalType":"address","name":"toAddress","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"bool","name":"creditsRemain","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"","type":"uint16"}],"name":"trustedRemoteLookup","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"withdraw","outputs":[],"stateMutability":"payable","type":"function"}]

60a060405266016bcc41e900006011553480156200001c57600080fd5b506040516200500a3803806200500a8339810160408190526200003f916200019d565b604051806040016040528060088152602001677a6b4d65726b6c7960c01b815250604051806040016040528060048152602001632d26a2a960e11b81525085858383838380806200009f620000996200014960201b60201c565b6200014d565b6001600160a01b0316608052506001600655816200010f5760405162461bcd60e51b8152602060048201526024808201527f6d696e476173546f5472616e73666572416e6453746f7265206d7573742062656044820152630203e20360e41b606482015260840160405180910390fd5b50600755600b6200012183826200028f565b50600c6200013082826200028f565b505050601295909555505050601355506200035b915050565b3390565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60008060008060808587031215620001b457600080fd5b845160208601519094506001600160a01b0381168114620001d457600080fd5b6040860151606090960151949790965092505050565b634e487b7160e01b600052604160045260246000fd5b600181811c908216806200021557607f821691505b6020821081036200023657634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200028a57600081815260208120601f850160051c81016020861015620002655750805b601f850160051c820191505b81811015620002865782815560010162000271565b5050505b505050565b81516001600160401b03811115620002ab57620002ab620001ea565b620002c381620002bc845462000200565b846200023c565b602080601f831160018114620002fb5760008415620002e25750858301515b600019600386901b1c1916600185901b17855562000286565b600085815260208120601f198616915b828110156200032c578886015182559484019460019091019084016200030b565b50858210156200034b5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b608051614c4d620003bd6000396000818161098a01528181610bb101528181610eb501528181611139015281816113de0152818161146501528181611dc00152818161212f0152818161233a0152818161246d0152612aef0152614c4d6000f3fe6080604052600436106103965760003560e01c80637533d788116101dc578063c446183411610102578063df2a5b3b116100a0578063f23536411161006f578063f235364114610b21578063f2fde38b14610b41578063f5ecbdbc14610b61578063fa25f9b614610b8157600080fd5b8063df2a5b3b14610aab578063e1d4c87014610acb578063e985e9c514610ae1578063eb8d72b714610b0157600080fd5b8063d12473a5116100dc578063d12473a514610a42578063d1deba1f14610a62578063da09f15d14610a75578063ddca3f4314610a9557600080fd5b8063c4461834146109ec578063c87b56dd14610a02578063cbed8b9c14610a2257600080fd5b80639f38369a1161017a578063af3fb21c11610149578063af3fb21c14610950578063b353aaa714610978578063b88d4fde146109ac578063baf3292d146109cc57600080fd5b80639f38369a146108dd578063a22cb465146108fd578063a6c3d1651461091d578063ab3ffb931461093d57600080fd5b80638ffa1f2a116101b65780638ffa1f2a14610868578063950c8a741461088857806395d89b41146108a85780639ea5d6b1146108bd57600080fd5b80637533d788146107f25780638cfd8f5c146108125780638da5cb5b1461084a57600080fd5b80633f1f4fa4116102c1578063519056361161025f57806369fe0e2d1161022e57806369fe0e2d146107875780636aa99da3146107a757806370a08231146107bd578063715018a6146107dd57600080fd5b806351905636146106e55780635b8c41e6146106f85780636352211e1461074757806366ad5c8a1461076757600080fd5b8063482881901161029b578063482881901461066f578063492e527e146106855780634ac3f4ff146106a55780635154c0b4146106d257600080fd5b80633f1f4fa4146105f457806342842e0e1461062f57806342d65a8d1461064f57600080fd5b80630df374831161033957806323b872dd1161030857806323b872dd146105775780632a205e3d146105975780633ccfd60b146105cc5780633d8b38f6146105d457600080fd5b80630df37483146104ac57806310ddb137146104cc5780631249c58b146104ec57806322a3ecf9146104f457600080fd5b806307e0db171161037557806307e0db1714610414578063081812fc14610434578063095ea7b31461046c5780630b4cad4c1461048c57600080fd5b80621d35671461039b57806301ffc9a7146103bd57806306fdde03146103f2575b600080fd5b3480156103a757600080fd5b506103bb6103b63660046139ee565b610bae565b005b3480156103c957600080fd5b506103dd6103d8366004613a99565b610ddf565b60405190151581526020015b60405180910390f35b3480156103fe57600080fd5b50610407610e02565b6040516103e99190613b06565b34801561042057600080fd5b506103bb61042f366004613b19565b610e94565b34801561044057600080fd5b5061045461044f366004613b36565b610f1d565b6040516001600160a01b0390911681526020016103e9565b34801561047857600080fd5b506103bb610487366004613b6f565b610f44565b34801561049857600080fd5b506103bb6104a7366004613b36565b611059565b3480156104b857600080fd5b506103bb6104c7366004613b9b565b6110f9565b3480156104d857600080fd5b506103bb6104e7366004613b19565b611118565b6103bb611170565b34801561050057600080fd5b5061054861050f366004613b36565b600a6020526000908152604090208054600182015460029092015461ffff821692620100009092046001600160a01b0316919060ff1684565b6040805161ffff90951685526001600160a01b03909316602085015291830152151560608201526080016103e9565b34801561058357600080fd5b506103bb610592366004613bb9565b611223565b3480156105a357600080fd5b506105b76105b2366004613ccd565b611255565b604080519283526020830191909152016103e9565b6103bb61127b565b3480156105e057600080fd5b506103dd6105ef366004613d5d565b6112d8565b34801561060057600080fd5b5061062161060f366004613b19565b60036020526000908152604090205481565b6040519081526020016103e9565b34801561063b57600080fd5b506103bb61064a366004613bb9565b6113a4565b34801561065b57600080fd5b506103bb61066a366004613d5d565b6113bf565b34801561067b57600080fd5b5061062160075481565b34801561069157600080fd5b506103bb6106a0366004613db1565b611445565b3480156106b157600080fd5b506106216106c0366004613b19565b60086020526000908152604090205481565b6103bb6106e0366004613dea565b611526565b6103bb6106f3366004613e4b565b61157a565b34801561070457600080fd5b50610621610713366004613f06565b6005602090815260009384526040808520845180860184018051928152908401958401959095209452929052825290205481565b34801561075357600080fd5b50610454610762366004613b36565b611591565b34801561077357600080fd5b506103bb6107823660046139ee565b6115f1565b34801561079357600080fd5b506103bb6107a2366004613b36565b6116cd565b3480156107b357600080fd5b5061062160125481565b3480156107c957600080fd5b506106216107d8366004613f65565b6116da565b3480156107e957600080fd5b506103bb611760565b3480156107fe57600080fd5b5061040761080d366004613b19565b611774565b34801561081e57600080fd5b5061062161082d366004613f82565b600260209081526000928352604080842090915290825290205481565b34801561085657600080fd5b506000546001600160a01b0316610454565b34801561087457600080fd5b506103bb610883366004613fb0565b61180e565b34801561089457600080fd5b50600454610454906001600160a01b031681565b3480156108b457600080fd5b50610407611a56565b3480156108c957600080fd5b506103bb6108d8366004613b9b565b611a65565b3480156108e957600080fd5b506104076108f8366004613b19565b611b1c565b34801561090957600080fd5b506103bb610918366004613fe4565b611c32565b34801561092957600080fd5b506103bb610938366004613d5d565b611c41565b6103bb61094b3660046140a2565b611cca565b34801561095c57600080fd5b50610965600181565b60405161ffff90911681526020016103e9565b34801561098457600080fd5b506104547f000000000000000000000000000000000000000000000000000000000000000081565b3480156109b857600080fd5b506103bb6109c7366004614154565b611cd9565b3480156109d857600080fd5b506103bb6109e7366004613f65565b611d11565b3480156109f857600080fd5b5061062161271081565b348015610a0e57600080fd5b50610407610a1d366004613b36565b611d67565b348015610a2e57600080fd5b506103bb610a3d3660046141bf565b611da1565b348015610a4e57600080fd5b506103bb610a5d366004613b9b565b611e36565b6103bb610a703660046139ee565b611ee6565b348015610a8157600080fd5b506105b7610a90366004614231565b6120fc565b348015610aa157600080fd5b5061062160115481565b348015610ab757600080fd5b506103bb610ac636600461425f565b6121c1565b348015610ad757600080fd5b5061062160135481565b348015610aed57600080fd5b506103dd610afc36600461428f565b612273565b348015610b0d57600080fd5b506103bb610b1c366004613d5d565b6122a1565b348015610b2d57600080fd5b506105b7610b3c3660046142ad565b6122fb565b348015610b4d57600080fd5b506103bb610b5c366004613f65565b6123c6565b348015610b6d57600080fd5b50610407610b7c366004614328565b61243c565b348015610b8d57600080fd5b50610621610b9c366004613b19565b60096020526000908152604090205481565b337f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031614610c2b5760405162461bcd60e51b815260206004820152601e60248201527f4c7a4170703a20696e76616c696420656e64706f696e742063616c6c6572000060448201526064015b60405180910390fd5b61ffff861660009081526001602052604081208054610c4990614379565b80601f0160208091040260200160405190810160405280929190818152602001828054610c7590614379565b8015610cc25780601f10610c9757610100808354040283529160200191610cc2565b820191906000526020600020905b815481529060010190602001808311610ca557829003601f168201915b50505050509050805186869050148015610cdd575060008151115b8015610d05575080516020820120604051610cfb90889088906143b3565b6040518091039020145b610d605760405162461bcd60e51b815260206004820152602660248201527f4c7a4170703a20696e76616c696420736f757263652073656e64696e6720636f6044820152651b9d1c9858dd60d21b6064820152608401610c22565b610dd68787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f8a018190048102820181019092528881528a9350915088908890819084018382808284376000920191909152506124ef92505050565b50505050505050565b60006001600160e01b031982161580610dfc5750610dfc82612568565b92915050565b6060600b8054610e1190614379565b80601f0160208091040260200160405190810160405280929190818152602001828054610e3d90614379565b8015610e8a5780601f10610e5f57610100808354040283529160200191610e8a565b820191906000526020600020905b815481529060010190602001808311610e6d57829003601f168201915b5050505050905090565b610e9c6125a8565b6040516307e0db1760e01b815261ffff821660048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906307e0db17906024015b600060405180830381600087803b158015610f0257600080fd5b505af1158015610f16573d6000803e3d6000fd5b5050505050565b6000610f2882612602565b506000908152600f60205260409020546001600160a01b031690565b6000610f4f82611591565b9050806001600160a01b0316836001600160a01b031603610fbc5760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e656044820152603960f91b6064820152608401610c22565b336001600160a01b0382161480610fd85750610fd88133612273565b61104a5760405162461bcd60e51b815260206004820152603d60248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f7420746f60448201527f6b656e206f776e6572206f7220617070726f76656420666f7220616c6c0000006064820152608401610c22565b6110548383612652565b505050565b6110616125a8565b600081116110bd5760405162461bcd60e51b8152602060048201526024808201527f6d696e476173546f5472616e73666572416e6453746f7265206d7573742062656044820152630203e20360e41b6064820152608401610c22565b60078190556040518181527ffebbc4f8bb9ec2313950c718d43123124b15778efda4c1f1d529de2995b4f34d906020015b60405180910390a150565b6111016125a8565b61ffff909116600090815260036020526040902055565b6111206125a8565b6040516310ddb13760e01b815261ffff821660048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906310ddb13790602401610ee8565b6011543410156111ba5760405162461bcd60e51b8152602060048201526015602482015274139bdd08195b9bdd59da08195d1a195c881cd95b9d605a1b6044820152606401610c22565b60135460125411156111ff5760405162461bcd60e51b815260206004820152600e60248201526d2a37b79036b0b73c961031393abb60911b6044820152606401610c22565b601280549081906000611211836143d9565b919050555061122033826126c0565b50565b61122e335b826126da565b61124a5760405162461bcd60e51b8152600401610c22906143f2565b611054838383612738565b60008061126d87876112668861289c565b87876122fb565b915091509550959350505050565b6112836125a8565b604051600090339047908381818185875af1925050503d80600081146112c5576040519150601f19603f3d011682016040523d82523d6000602084013e6112ca565b606091505b505090508061122057600080fd5b61ffff8316600090815260016020526040812080548291906112f990614379565b80601f016020809104026020016040519081016040528092919081815260200182805461132590614379565b80156113725780601f1061134757610100808354040283529160200191611372565b820191906000526020600020905b81548152906001019060200180831161135557829003601f168201915b5050505050905083836040516113899291906143b3565b60405180910390208180519060200120149150509392505050565b61105483838360405180602001604052806000815250611cd9565b6113c76125a8565b6040516342d65a8d60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906342d65a8d9061141790869086908690600401614468565b600060405180830381600087803b15801561143157600080fd5b505af1158015610dd6573d6000803e3d6000fd5b61144d6125a8565b6040516304b2b47b60e11b81523060048201526006907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063cbed8b9c90829063096568f690602401602060405180830381865afa1580156114bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114e09190614486565b604080516001600160a01b038716602082015287918691016040516020818303038152906040526040518563ffffffff1660e01b815260040161141794939291906144a3565b61ffff831660009081526009602052604090205461154a90849060019084906128e7565b604080513360208201526000818301528151808203830181526060909101909152611054908490308585346129c6565b610dd68787876115898861289c565b878787612b6b565b6000818152600d60205260408120546001600160a01b031680610dfc5760405162461bcd60e51b8152602060048201526018602482015277115490cdcc8c4e881a5b9d985b1a59081d1bdad95b88125160421b6044820152606401610c22565b33301461164f5760405162461bcd60e51b815260206004820152602660248201527f4e6f6e626c6f636b696e674c7a4170703a2063616c6c6572206d7573742062656044820152650204c7a4170760d41b6064820152608401610c22565b6116c58686868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f890181900481028201810190925287815289935091508790879081908401838280828437600092019190915250612d3f92505050565b505050505050565b6116d56125a8565b601155565b60006001600160a01b0382166117445760405162461bcd60e51b815260206004820152602960248201527f4552433732313a2061646472657373207a65726f206973206e6f7420612076616044820152683634b21037bbb732b960b91b6064820152608401610c22565b506001600160a01b03166000908152600e602052604090205490565b6117686125a8565b6117726000612ebe565b565b6001602052600090815260409020805461178d90614379565b80601f01602080910402602001604051908101604052809291908181526020018280546117b990614379565b80156118065780601f106117db57610100808354040283529160200191611806565b820191906000526020600020905b8154815290600101906020018083116117e957829003601f168201915b505050505081565b611816612f0e565b80516020808301919091206000818152600a90925260409091206002015460ff166118775760405162461bcd60e51b81526020600482015260116024820152701b9bc818dc99591a5d1cc81cdd1bdc9959607a1b6044820152606401610c22565b60008280602001905181019061188d919061451f565b6000848152600a6020526040812080546001909101549294509092506118c99161ffff8216916201000090046001600160a01b03169085612f67565b6000848152600a6020526040902060010154909150811161193e5760405162461bcd60e51b815260206004820152602960248201527f6e6f7420656e6f7567682067617320746f2070726f6365737320637265646974604482015268103a3930b739b332b960b91b6064820152608401610c22565b815181036119b5576000838152600a602052604080822080546001600160b01b031916815560018101929092556002909101805460ff19169055517fd7be02b8dd0d27bd0517a9cb4d7469ce27df4313821ae5ec1ff69acc594ba233906119a89085815260200190565b60405180910390a1611a49565b604080516080810182526000858152600a6020818152848320805461ffff80821687526001600160a01b03620100008084048216868a019081529989018b8152600160608b01818152998f90529790965297519851169096026001600160b01b03199091169690951695909517939093178455915191830191909155516002909101805491151560ff199092169190911790555b5050506112206001600655565b6060600c8054610e1190614379565b611a6d6125a8565b60008111611ac85760405162461bcd60e51b815260206004820152602260248201527f647374436861696e4964546f42617463684c696d6974206d757374206265203e604482015261020360f41b6064820152608401610c22565b61ffff8216600081815260086020908152604091829020849055815192835282018390527f7315f7654d594ead24a30160ed9ba2d23247f543016b918343591e93d7afdb6d91015b60405180910390a15050565b61ffff8116600090815260016020526040812080546060929190611b3f90614379565b80601f0160208091040260200160405190810160405280929190818152602001828054611b6b90614379565b8015611bb85780601f10611b8d57610100808354040283529160200191611bb8565b820191906000526020600020905b815481529060010190602001808311611b9b57829003601f168201915b505050505090508051600003611c105760405162461bcd60e51b815260206004820152601d60248201527f4c7a4170703a206e6f20747275737465642070617468207265636f72640000006044820152606401610c22565b611c2b600060148351611c2391906145d9565b839190612fb3565b9392505050565b611c3d3383836130c0565b5050565b611c496125a8565b818130604051602001611c5e939291906145ec565b60408051601f1981840301815291815261ffff8516600090815260016020522090611c899082614658565b507f8c0400cfe2d1199b1a725c78960bcc2a344d869b80590d0f2bd005db15a572ce838383604051611cbd93929190614468565b60405180910390a1505050565b610dd687878787878787612b6b565b611ce333836126da565b611cff5760405162461bcd60e51b8152600401610c22906143f2565b611d0b8484848461318e565b50505050565b611d196125a8565b600480546001600160a01b0319166001600160a01b0383169081179091556040519081527f5db758e995a17ec1ad84bdef7e8c3293a0bd6179bcce400dff5d4c3d87db726b906020016110ee565b6060611d716131c1565b611d7a836131e1565b604051602001611d8b929190614717565b6040516020818303038152906040529050919050565b611da96125a8565b6040516332fb62e760e21b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063cbed8b9c90611dfd9088908890889088908890600401614746565b600060405180830381600087803b158015611e1757600080fd5b505af1158015611e2b573d6000803e3d6000fd5b505050505050505050565b611e3e6125a8565b60008111611e9a5760405162461bcd60e51b815260206004820152602360248201527f647374436861696e4964546f5472616e73666572476173206d7573742062652060448201526203e20360ec1b6064820152608401610c22565b61ffff8216600081815260096020908152604091829020849055815192835282018390527fc46df2983228ac2d9754e94a0d565e6671665dc8ad38602bc8e544f0685a29fb9101611b10565b61ffff86166000908152600560205260408082209051611f0990889088906143b3565b90815260408051602092819003830190206001600160401b03871660009081529252902054905080611f895760405162461bcd60e51b815260206004820152602360248201527f4e6f6e626c6f636b696e674c7a4170703a206e6f2073746f726564206d65737360448201526261676560e81b6064820152608401610c22565b808383604051611f9a9291906143b3565b604051809103902014611ff95760405162461bcd60e51b815260206004820152602160248201527f4e6f6e626c6f636b696e674c7a4170703a20696e76616c6964207061796c6f616044820152601960fa1b6064820152608401610c22565b61ffff8716600090815260056020526040808220905161201c90899089906143b3565b90815260408051602092819003830181206001600160401b038916600090815290845282902093909355601f880182900482028301820190528682526120b4918991899089908190840183828082843760009201919091525050604080516020601f8a018190048102820181019092528881528a935091508890889081908401838280828437600092019190915250612d3f92505050565b7fc264d91f3adc5588250e1551f547752ca0cfa8f6b530d243b9f9f4cab10ea8e587878787856040516120eb95949392919061477f565b60405180910390a150505050505050565b604080513360208201526000818301819052825180830384018152606083019384905263040a7bb160e41b9093529182917f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906340a7bb1090612174908990309086908b908b906064016147ba565b6040805180830381865afa158015612190573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121b4919061480e565b9250925050935093915050565b6121c96125a8565b600081116122115760405162461bcd60e51b81526020600482015260156024820152744c7a4170703a20696e76616c6964206d696e47617360581b6044820152606401610c22565b61ffff83811660008181526002602090815260408083209487168084529482529182902085905581519283528201929092529081018290527f9d5c7c0b934da8fefa9c7760c98383778a12dfbfc0c3b3106518f43fb9508ac090606001611cbd565b6001600160a01b03918216600090815260106020908152604080832093909416825291909152205460ff1690565b6122a96125a8565b61ffff831660009081526001602052604090206122c7828483614832565b507ffa41487ad5d6728f0b19276fa1eddc16558578f5109fc39d2dc33c3230470dab838383604051611cbd93929190614468565b6000806000868660405160200161231392919061492c565b60408051601f198184030181529082905263040a7bb160e41b825291506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906340a7bb1090612377908b90309086908b908b906004016147ba565b6040805180830381865afa158015612393573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123b7919061480e565b92509250509550959350505050565b6123ce6125a8565b6001600160a01b0381166124335760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610c22565b61122081612ebe565b604051633d7b2f6f60e21b815261ffff808616600483015284166024820152306044820152606481018290526060907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063f5ecbdbc90608401600060405180830381865afa1580156124bc573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526124e4919081019061495a565b90505b949350505050565b6000806125525a60966366ad5c8a60e01b89898989604051602401612517949392919061498e565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915230929190613273565b91509150816116c5576116c586868686856132fd565b60006001600160e01b031982166380ac58cd60e01b148061259957506001600160e01b03198216635b5e139f60e01b145b80610dfc5750610dfc8261339a565b6000546001600160a01b031633146117725760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610c22565b61260b816133cf565b6112205760405162461bcd60e51b8152602060048201526018602482015277115490cdcc8c4e881a5b9d985b1a59081d1bdad95b88125160421b6044820152606401610c22565b6000818152600f6020526040902080546001600160a01b0319166001600160a01b038416908117909155819061268782611591565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b611c3d8282604051806020016040528060008152506133ec565b6000806126e683611591565b9050806001600160a01b0316846001600160a01b0316148061270d575061270d8185612273565b806124e75750836001600160a01b031661272684610f1d565b6001600160a01b031614949350505050565b826001600160a01b031661274b82611591565b6001600160a01b0316146127715760405162461bcd60e51b8152600401610c22906149cc565b6001600160a01b0382166127d35760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f206164646044820152637265737360e01b6064820152608401610c22565b826001600160a01b03166127e682611591565b6001600160a01b03161461280c5760405162461bcd60e51b8152600401610c22906149cc565b6000818152600f6020908152604080832080546001600160a01b03199081169091556001600160a01b03878116808652600e8552838620805460001901905590871680865283862080546001019055868652600d90945282852080549092168417909155905184937fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b604080516001808252818301909252606091600091906020808301908036833701905050905082816000815181106128d6576128d6614a11565b602090810291909101015292915050565b60006128f28361341f565b61ffff808716600090815260026020908152604080832093891683529290529081205491925090612924908490614a27565b9050600081116129765760405162461bcd60e51b815260206004820152601a60248201527f4c7a4170703a206d696e4761734c696d6974206e6f74207365740000000000006044820152606401610c22565b808210156116c55760405162461bcd60e51b815260206004820152601b60248201527f4c7a4170703a20676173206c696d697420697320746f6f206c6f7700000000006044820152606401610c22565b61ffff8616600090815260016020526040812080546129e490614379565b80601f0160208091040260200160405190810160405280929190818152602001828054612a1090614379565b8015612a5d5780601f10612a3257610100808354040283529160200191612a5d565b820191906000526020600020905b815481529060010190602001808311612a4057829003601f168201915b505050505090508051600003612ace5760405162461bcd60e51b815260206004820152603060248201527f4c7a4170703a2064657374696e6174696f6e20636861696e206973206e6f742060448201526f61207472757374656420736f7572636560801b6064820152608401610c22565b612ad987875161347b565b60405162c5803160e81b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063c5803100908490612b30908b9086908c908c908c908c90600401614a3a565b6000604051808303818588803b158015612b4957600080fd5b505af1158015612b5d573d6000803e3d6000fd5b505050505050505050505050565b6000845111612bb25760405162461bcd60e51b8152602060048201526013602482015272746f6b656e4964735b5d20697320656d70747960681b6044820152606401610c22565b835160011480612bd6575061ffff8616600090815260086020526040902054845111155b612c2d5760405162461bcd60e51b815260206004820152602260248201527f62617463682073697a65206578636565647320647374206261746368206c696d6044820152611a5d60f21b6064820152608401610c22565b60005b8451811015612c7057612c5e888888888581518110612c5157612c51614a11565b60200260200101516134ec565b80612c68816143d9565b915050612c30565b5060008585604051602001612c8692919061492c565b6040516020818303038152906040529050612ccb876001848851600960008d61ffff1661ffff16815260200190815260200160002054612cc69190614aa1565b6128e7565b612cd98782868686346129c6565b85604051612ce79190614ab8565b6040518091039020886001600160a01b03168861ffff167fe1b87c47fdeb4f9cbadbca9df3af7aba453bb6e501075d0440d88125b711522a88604051612d2d9190614ad4565b60405180910390a45050505050505050565b60008082806020019051810190612d56919061451f565b9150915080600081518110612d6d57612d6d614a11565b6020026020010151600003612d83575050611d0b565b60148201516000612d9688838386612f67565b90508251811015612e6a5784516020808701919091206040805160808101825261ffff808d1682526001600160a01b038088168387019081528385018881526001606086018181526000898152600a909a529887902095518654935190941662010000026001600160b01b03199093169390941692909217178355519082015592516002909301805493151560ff199094169390931790925590517f10e0b70d256bccc84b7027506978bd8b68984a870788b93b479def144c839ad790612e609083908990614ae7565b60405180910390a1505b816001600160a01b031687604051612e829190614ab8565b60405180910390208961ffff167f5b821db8a46f8ecbe1941ba2f51cfeea9643268b56631f70d45e2a745d99026586604051612d2d9190614ad4565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b600260065403612f605760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610c22565b6002600655565b6000825b82518110156124e4576007545a106124e457612fa18686858481518110612f9457612f94614a11565b60200260200101516135d7565b80612fab816143d9565b915050612f6b565b606081612fc181601f614a27565b10156130005760405162461bcd60e51b815260206004820152600e60248201526d736c6963655f6f766572666c6f7760901b6044820152606401610c22565b61300a8284614a27565b8451101561304e5760405162461bcd60e51b8152602060048201526011602482015270736c6963655f6f75744f66426f756e647360781b6044820152606401610c22565b60608215801561306d57604051915060008252602082016040526130b7565b6040519150601f8416801560200281840101858101878315602002848b0101015b818310156130a657805183526020928301920161308e565b5050858452601f01601f1916604052505b50949350505050565b816001600160a01b0316836001600160a01b0316036131215760405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c6572000000000000006044820152606401610c22565b6001600160a01b03838116600081815260106020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b613199848484612738565b6131a584848484613637565b611d0b5760405162461bcd60e51b8152600401610c2290614b00565b6060604051806060016040528060238152602001614bf560239139905090565b606060006131ee83613735565b60010190506000816001600160401b0381111561320d5761320d613bfa565b6040519080825280601f01601f191660200182016040528015613237576020820181803683370190505b5090508181016020015b600019016f181899199a1a9b1b9c1cb0b131b232b360811b600a86061a8153600a850494508461324157509392505050565b6000606060008060008661ffff166001600160401b0381111561329857613298613bfa565b6040519080825280601f01601f1916602001820160405280156132c2576020820181803683370190505b50905060008087516020890160008d8df191503d9250868311156132e4578692505b828152826000602083013e909890975095505050505050565b8180519060200120600560008761ffff1661ffff1681526020019081526020016000208560405161332e9190614ab8565b9081526040805191829003602090810183206001600160401b0388166000908152915220919091557fe183f33de2837795525b4792ca4cd60535bd77c53b7e7030060bfcf5734d6b0c9061338b9087908790879087908790614b52565b60405180910390a15050505050565b60006001600160e01b031982166322bac5d960e01b1480610dfc57506301ffc9a760e01b6001600160e01b0319831614610dfc565b6000908152600d60205260409020546001600160a01b0316151590565b6133f6838361380d565b6134036000848484613637565b6110545760405162461bcd60e51b8152600401610c2290614b00565b60006022825110156134735760405162461bcd60e51b815260206004820152601c60248201527f4c7a4170703a20696e76616c69642061646170746572506172616d73000000006044820152606401610c22565b506022015190565b61ffff82166000908152600360205260408120549081900361349c57506127105b808211156110545760405162461bcd60e51b815260206004820181905260248201527f4c7a4170703a207061796c6f61642073697a6520697320746f6f206c617267656044820152606401610c22565b6134f533611228565b6135585760405162461bcd60e51b815260206004820152602e60248201527f4f4e46543732313a2073656e642063616c6c6572206973206e6f74206f776e6560448201526d1c881b9bdc88185c1c1c9bdd995960921b6064820152608401610c22565b836001600160a01b031661356b82611591565b6001600160a01b0316146135cc5760405162461bcd60e51b815260206004820152602260248201527f4f4e46543732313a2073656e642066726f6d20696e636f7272656374206f776e60448201526132b960f11b6064820152608401610c22565b611d0b843083612738565b6135e0816133cf565b158061360c57506135f0816133cf565b801561360c57503061360182611591565b6001600160a01b0316145b61361557600080fd5b61361e816133cf565b61362c5761105482826126c0565b611054308383612738565b60006001600160a01b0384163b1561372d57604051630a85bd0160e11b81526001600160a01b0385169063150b7a029061367b903390899088908890600401614ba4565b6020604051808303816000875af19250505080156136b6575060408051601f3d908101601f191682019092526136b391810190614bd7565b60015b613713573d8080156136e4576040519150601f19603f3d011682016040523d82523d6000602084013e6136e9565b606091505b50805160000361370b5760405162461bcd60e51b8152600401610c2290614b00565b805181602001fd5b6001600160e01b031916630a85bd0160e11b1490506124e7565b5060016124e7565b60008072184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b83106137745772184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b830492506040015b6d04ee2d6d415b85acef810000000083106137a0576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc1000083106137be57662386f26fc10000830492506010015b6305f5e10083106137d6576305f5e100830492506008015b61271083106137ea57612710830492506004015b606483106137fc576064830492506002015b600a8310610dfc5760010192915050565b6001600160a01b0382166138635760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f20616464726573736044820152606401610c22565b61386c816133cf565b156138b95760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e746564000000006044820152606401610c22565b6138c2816133cf565b1561390f5760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e746564000000006044820152606401610c22565b6001600160a01b0382166000818152600e6020908152604080832080546001019055848352600d90915280822080546001600160a01b0319168417905551839291907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b61ffff8116811461122057600080fd5b60008083601f84011261399c57600080fd5b5081356001600160401b038111156139b357600080fd5b6020830191508360208285010111156139cb57600080fd5b9250929050565b80356001600160401b03811681146139e957600080fd5b919050565b60008060008060008060808789031215613a0757600080fd5b8635613a128161397a565b955060208701356001600160401b0380821115613a2e57600080fd5b613a3a8a838b0161398a565b9097509550859150613a4e60408a016139d2565b94506060890135915080821115613a6457600080fd5b50613a7189828a0161398a565b979a9699509497509295939492505050565b6001600160e01b03198116811461122057600080fd5b600060208284031215613aab57600080fd5b8135611c2b81613a83565b60005b83811015613ad1578181015183820152602001613ab9565b50506000910152565b60008151808452613af2816020860160208601613ab6565b601f01601f19169290920160200192915050565b602081526000611c2b6020830184613ada565b600060208284031215613b2b57600080fd5b8135611c2b8161397a565b600060208284031215613b4857600080fd5b5035919050565b6001600160a01b038116811461122057600080fd5b80356139e981613b4f565b60008060408385031215613b8257600080fd5b8235613b8d81613b4f565b946020939093013593505050565b60008060408385031215613bae57600080fd5b8235613b8d8161397a565b600080600060608486031215613bce57600080fd5b8335613bd981613b4f565b92506020840135613be981613b4f565b929592945050506040919091013590565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b0381118282101715613c3857613c38613bfa565b604052919050565b60006001600160401b03821115613c5957613c59613bfa565b50601f01601f191660200190565b600082601f830112613c7857600080fd5b8135613c8b613c8682613c40565b613c10565b818152846020838601011115613ca057600080fd5b816020850160208301376000918101602001919091529392505050565b803580151581146139e957600080fd5b600080600080600060a08688031215613ce557600080fd5b8535613cf08161397a565b945060208601356001600160401b0380821115613d0c57600080fd5b613d1889838a01613c67565b955060408801359450613d2d60608901613cbd565b93506080880135915080821115613d4357600080fd5b50613d5088828901613c67565b9150509295509295909350565b600080600060408486031215613d7257600080fd5b8335613d7d8161397a565b925060208401356001600160401b03811115613d9857600080fd5b613da48682870161398a565b9497909650939450505050565b60008060408385031215613dc457600080fd5b8235613dcf8161397a565b91506020830135613ddf81613b4f565b809150509250929050565b600080600060608486031215613dff57600080fd5b8335613e0a8161397a565b92506020840135613e1a81613b4f565b915060408401356001600160401b03811115613e3557600080fd5b613e4186828701613c67565b9150509250925092565b600080600080600080600060e0888a031215613e6657600080fd5b8735613e7181613b4f565b96506020880135613e818161397a565b955060408801356001600160401b0380821115613e9d57600080fd5b613ea98b838c01613c67565b965060608a0135955060808a01359150613ec282613b4f565b90935060a089013590613ed482613b4f565b90925060c08901359080821115613eea57600080fd5b50613ef78a828b01613c67565b91505092959891949750929550565b600080600060608486031215613f1b57600080fd5b8335613f268161397a565b925060208401356001600160401b03811115613f4157600080fd5b613f4d86828701613c67565b925050613f5c604085016139d2565b90509250925092565b600060208284031215613f7757600080fd5b8135611c2b81613b4f565b60008060408385031215613f9557600080fd5b8235613fa08161397a565b91506020830135613ddf8161397a565b600060208284031215613fc257600080fd5b81356001600160401b03811115613fd857600080fd5b6124e784828501613c67565b60008060408385031215613ff757600080fd5b823561400281613b4f565b915061401060208401613cbd565b90509250929050565b60006001600160401b0382111561403257614032613bfa565b5060051b60200190565b600082601f83011261404d57600080fd5b8135602061405d613c8683614019565b82815260059290921b8401810191818101908684111561407c57600080fd5b8286015b848110156140975780358352918301918301614080565b509695505050505050565b600080600080600080600060e0888a0312156140bd57600080fd5b87356140c881613b4f565b965060208801356140d88161397a565b955060408801356001600160401b03808211156140f457600080fd5b6141008b838c01613c67565b965060608a013591508082111561411657600080fd5b6141228b838c0161403c565b955061413060808b01613b64565b945061413e60a08b01613b64565b935060c08a0135915080821115613eea57600080fd5b6000806000806080858703121561416a57600080fd5b843561417581613b4f565b9350602085013561418581613b4f565b92506040850135915060608501356001600160401b038111156141a757600080fd5b6141b387828801613c67565b91505092959194509250565b6000806000806000608086880312156141d757600080fd5b85356141e28161397a565b945060208601356141f28161397a565b93506040860135925060608601356001600160401b0381111561421457600080fd5b6142208882890161398a565b969995985093965092949392505050565b60008060006060848603121561424657600080fd5b83356142518161397a565b9250613e1a60208501613cbd565b60008060006060848603121561427457600080fd5b833561427f8161397a565b92506020840135613be98161397a565b600080604083850312156142a257600080fd5b8235613dcf81613b4f565b600080600080600060a086880312156142c557600080fd5b85356142d08161397a565b945060208601356001600160401b03808211156142ec57600080fd5b6142f889838a01613c67565b9550604088013591508082111561430e57600080fd5b61431a89838a0161403c565b9450613d2d60608901613cbd565b6000806000806080858703121561433e57600080fd5b84356143498161397a565b935060208501356143598161397a565b9250604085013561436981613b4f565b9396929550929360600135925050565b600181811c9082168061438d57607f821691505b6020821081036143ad57634e487b7160e01b600052602260045260246000fd5b50919050565b8183823760009101908152919050565b634e487b7160e01b600052601160045260246000fd5b6000600182016143eb576143eb6143c3565b5060010190565b6020808252602d908201527f4552433732313a2063616c6c6572206973206e6f7420746f6b656e206f776e6560408201526c1c881bdc88185c1c1c9bdd9959609a1b606082015260800190565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b61ffff841681526040602082015260006124e460408301848661443f565b60006020828403121561449857600080fd5b8151611c2b8161397a565b600061ffff8087168352808616602084015250836040830152608060608301526144d06080830184613ada565b9695505050505050565b600082601f8301126144eb57600080fd5b81516144f9613c8682613c40565b81815284602083860101111561450e57600080fd5b6124e7826020830160208701613ab6565b6000806040838503121561453257600080fd5b82516001600160401b038082111561454957600080fd5b614555868387016144da565b935060209150818501518181111561456c57600080fd5b85019050601f8101861361457f57600080fd5b805161458d613c8682614019565b81815260059190911b820183019083810190888311156145ac57600080fd5b928401925b828410156145ca578351825292840192908401906145b1565b80955050505050509250929050565b81810381811115610dfc57610dfc6143c3565b8284823760609190911b6bffffffffffffffffffffffff19169101908152601401919050565b601f82111561105457600081815260208120601f850160051c810160208610156146395750805b601f850160051c820191505b818110156116c557828155600101614645565b81516001600160401b0381111561467157614671613bfa565b6146858161467f8454614379565b84614612565b602080601f8311600181146146ba57600084156146a25750858301515b600019600386901b1c1916600185901b1785556116c5565b600085815260208120601f198616915b828110156146e9578886015182559484019460019091019084016146ca565b50858210156147075787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60008351614729818460208801613ab6565b83519083019061473d818360208801613ab6565b01949350505050565b600061ffff80881683528087166020840152508460408301526080606083015261477460808301848661443f565b979650505050505050565b61ffff8616815260806020820152600061479d60808301868861443f565b6001600160401b0394909416604083015250606001529392505050565b61ffff861681526001600160a01b038516602082015260a0604082018190526000906147e890830186613ada565b841515606084015282810360808401526148028185613ada565b98975050505050505050565b6000806040838503121561482157600080fd5b505080516020909101519092909150565b6001600160401b0383111561484957614849613bfa565b61485d836148578354614379565b83614612565b6000601f84116001811461489157600085156148795750838201355b600019600387901b1c1916600186901b178355610f16565b600083815260209020601f19861690835b828110156148c257868501358255602094850194600190920191016148a2565b50868210156148df5760001960f88860031b161c19848701351681555b505060018560011b0183555050505050565b600081518084526020808501945080840160005b8381101561492157815187529582019590820190600101614905565b509495945050505050565b60408152600061493f6040830185613ada565b828103602084015261495181856148f1565b95945050505050565b60006020828403121561496c57600080fd5b81516001600160401b0381111561498257600080fd5b6124e7848285016144da565b61ffff851681526080602082015260006149ab6080830186613ada565b6001600160401b038516604084015282810360608401526147748185613ada565b60208082526025908201527f4552433732313a207472616e736665722066726f6d20696e636f72726563742060408201526437bbb732b960d91b606082015260800190565b634e487b7160e01b600052603260045260246000fd5b80820180821115610dfc57610dfc6143c3565b61ffff8716815260c060208201526000614a5760c0830188613ada565b8281036040840152614a698188613ada565b6001600160a01b0387811660608601528616608085015283810360a08501529050614a948185613ada565b9998505050505050505050565b8082028115828204841417610dfc57610dfc6143c3565b60008251614aca818460208701613ab6565b9190910192915050565b602081526000611c2b60208301846148f1565b8281526040602082015260006124e76040830184613ada565b60208082526032908201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b606082015260800190565b61ffff8616815260a060208201526000614b6f60a0830187613ada565b6001600160401b03861660408401528281036060840152614b908186613ada565b905082810360808401526148028185613ada565b6001600160a01b03858116825284166020820152604081018390526080606082018190526000906144d090830184613ada565b600060208284031215614be957600080fd5b8151611c2b81613a8356fe68747470733a2f2f6170692e6d65726b6c792e636f6d2f6170692f7a6b2d6d65726b2fa2646970667358221220f76858e4b7bb5fab3ae912ee6c6d5fe87cfc482499e6fc998b4ef12a250eb1cf64736f6c634300081300330000000000000000000000000000000000000000000000000000000000004e200000000000000000000000003c2269811836af69497e5f486a85d7316753cf6200000000000000000000000000000000000000000000000000000000003d090000000000000000000000000000000000000000000000000000000000004c4b3f

Deployed Bytecode

0x6080604052600436106103965760003560e01c80637533d788116101dc578063c446183411610102578063df2a5b3b116100a0578063f23536411161006f578063f235364114610b21578063f2fde38b14610b41578063f5ecbdbc14610b61578063fa25f9b614610b8157600080fd5b8063df2a5b3b14610aab578063e1d4c87014610acb578063e985e9c514610ae1578063eb8d72b714610b0157600080fd5b8063d12473a5116100dc578063d12473a514610a42578063d1deba1f14610a62578063da09f15d14610a75578063ddca3f4314610a9557600080fd5b8063c4461834146109ec578063c87b56dd14610a02578063cbed8b9c14610a2257600080fd5b80639f38369a1161017a578063af3fb21c11610149578063af3fb21c14610950578063b353aaa714610978578063b88d4fde146109ac578063baf3292d146109cc57600080fd5b80639f38369a146108dd578063a22cb465146108fd578063a6c3d1651461091d578063ab3ffb931461093d57600080fd5b80638ffa1f2a116101b65780638ffa1f2a14610868578063950c8a741461088857806395d89b41146108a85780639ea5d6b1146108bd57600080fd5b80637533d788146107f25780638cfd8f5c146108125780638da5cb5b1461084a57600080fd5b80633f1f4fa4116102c1578063519056361161025f57806369fe0e2d1161022e57806369fe0e2d146107875780636aa99da3146107a757806370a08231146107bd578063715018a6146107dd57600080fd5b806351905636146106e55780635b8c41e6146106f85780636352211e1461074757806366ad5c8a1461076757600080fd5b8063482881901161029b578063482881901461066f578063492e527e146106855780634ac3f4ff146106a55780635154c0b4146106d257600080fd5b80633f1f4fa4146105f457806342842e0e1461062f57806342d65a8d1461064f57600080fd5b80630df374831161033957806323b872dd1161030857806323b872dd146105775780632a205e3d146105975780633ccfd60b146105cc5780633d8b38f6146105d457600080fd5b80630df37483146104ac57806310ddb137146104cc5780631249c58b146104ec57806322a3ecf9146104f457600080fd5b806307e0db171161037557806307e0db1714610414578063081812fc14610434578063095ea7b31461046c5780630b4cad4c1461048c57600080fd5b80621d35671461039b57806301ffc9a7146103bd57806306fdde03146103f2575b600080fd5b3480156103a757600080fd5b506103bb6103b63660046139ee565b610bae565b005b3480156103c957600080fd5b506103dd6103d8366004613a99565b610ddf565b60405190151581526020015b60405180910390f35b3480156103fe57600080fd5b50610407610e02565b6040516103e99190613b06565b34801561042057600080fd5b506103bb61042f366004613b19565b610e94565b34801561044057600080fd5b5061045461044f366004613b36565b610f1d565b6040516001600160a01b0390911681526020016103e9565b34801561047857600080fd5b506103bb610487366004613b6f565b610f44565b34801561049857600080fd5b506103bb6104a7366004613b36565b611059565b3480156104b857600080fd5b506103bb6104c7366004613b9b565b6110f9565b3480156104d857600080fd5b506103bb6104e7366004613b19565b611118565b6103bb611170565b34801561050057600080fd5b5061054861050f366004613b36565b600a6020526000908152604090208054600182015460029092015461ffff821692620100009092046001600160a01b0316919060ff1684565b6040805161ffff90951685526001600160a01b03909316602085015291830152151560608201526080016103e9565b34801561058357600080fd5b506103bb610592366004613bb9565b611223565b3480156105a357600080fd5b506105b76105b2366004613ccd565b611255565b604080519283526020830191909152016103e9565b6103bb61127b565b3480156105e057600080fd5b506103dd6105ef366004613d5d565b6112d8565b34801561060057600080fd5b5061062161060f366004613b19565b60036020526000908152604090205481565b6040519081526020016103e9565b34801561063b57600080fd5b506103bb61064a366004613bb9565b6113a4565b34801561065b57600080fd5b506103bb61066a366004613d5d565b6113bf565b34801561067b57600080fd5b5061062160075481565b34801561069157600080fd5b506103bb6106a0366004613db1565b611445565b3480156106b157600080fd5b506106216106c0366004613b19565b60086020526000908152604090205481565b6103bb6106e0366004613dea565b611526565b6103bb6106f3366004613e4b565b61157a565b34801561070457600080fd5b50610621610713366004613f06565b6005602090815260009384526040808520845180860184018051928152908401958401959095209452929052825290205481565b34801561075357600080fd5b50610454610762366004613b36565b611591565b34801561077357600080fd5b506103bb6107823660046139ee565b6115f1565b34801561079357600080fd5b506103bb6107a2366004613b36565b6116cd565b3480156107b357600080fd5b5061062160125481565b3480156107c957600080fd5b506106216107d8366004613f65565b6116da565b3480156107e957600080fd5b506103bb611760565b3480156107fe57600080fd5b5061040761080d366004613b19565b611774565b34801561081e57600080fd5b5061062161082d366004613f82565b600260209081526000928352604080842090915290825290205481565b34801561085657600080fd5b506000546001600160a01b0316610454565b34801561087457600080fd5b506103bb610883366004613fb0565b61180e565b34801561089457600080fd5b50600454610454906001600160a01b031681565b3480156108b457600080fd5b50610407611a56565b3480156108c957600080fd5b506103bb6108d8366004613b9b565b611a65565b3480156108e957600080fd5b506104076108f8366004613b19565b611b1c565b34801561090957600080fd5b506103bb610918366004613fe4565b611c32565b34801561092957600080fd5b506103bb610938366004613d5d565b611c41565b6103bb61094b3660046140a2565b611cca565b34801561095c57600080fd5b50610965600181565b60405161ffff90911681526020016103e9565b34801561098457600080fd5b506104547f0000000000000000000000003c2269811836af69497e5f486a85d7316753cf6281565b3480156109b857600080fd5b506103bb6109c7366004614154565b611cd9565b3480156109d857600080fd5b506103bb6109e7366004613f65565b611d11565b3480156109f857600080fd5b5061062161271081565b348015610a0e57600080fd5b50610407610a1d366004613b36565b611d67565b348015610a2e57600080fd5b506103bb610a3d3660046141bf565b611da1565b348015610a4e57600080fd5b506103bb610a5d366004613b9b565b611e36565b6103bb610a703660046139ee565b611ee6565b348015610a8157600080fd5b506105b7610a90366004614231565b6120fc565b348015610aa157600080fd5b5061062160115481565b348015610ab757600080fd5b506103bb610ac636600461425f565b6121c1565b348015610ad757600080fd5b5061062160135481565b348015610aed57600080fd5b506103dd610afc36600461428f565b612273565b348015610b0d57600080fd5b506103bb610b1c366004613d5d565b6122a1565b348015610b2d57600080fd5b506105b7610b3c3660046142ad565b6122fb565b348015610b4d57600080fd5b506103bb610b5c366004613f65565b6123c6565b348015610b6d57600080fd5b50610407610b7c366004614328565b61243c565b348015610b8d57600080fd5b50610621610b9c366004613b19565b60096020526000908152604090205481565b337f0000000000000000000000003c2269811836af69497e5f486a85d7316753cf626001600160a01b031614610c2b5760405162461bcd60e51b815260206004820152601e60248201527f4c7a4170703a20696e76616c696420656e64706f696e742063616c6c6572000060448201526064015b60405180910390fd5b61ffff861660009081526001602052604081208054610c4990614379565b80601f0160208091040260200160405190810160405280929190818152602001828054610c7590614379565b8015610cc25780601f10610c9757610100808354040283529160200191610cc2565b820191906000526020600020905b815481529060010190602001808311610ca557829003601f168201915b50505050509050805186869050148015610cdd575060008151115b8015610d05575080516020820120604051610cfb90889088906143b3565b6040518091039020145b610d605760405162461bcd60e51b815260206004820152602660248201527f4c7a4170703a20696e76616c696420736f757263652073656e64696e6720636f6044820152651b9d1c9858dd60d21b6064820152608401610c22565b610dd68787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f8a018190048102820181019092528881528a9350915088908890819084018382808284376000920191909152506124ef92505050565b50505050505050565b60006001600160e01b031982161580610dfc5750610dfc82612568565b92915050565b6060600b8054610e1190614379565b80601f0160208091040260200160405190810160405280929190818152602001828054610e3d90614379565b8015610e8a5780601f10610e5f57610100808354040283529160200191610e8a565b820191906000526020600020905b815481529060010190602001808311610e6d57829003601f168201915b5050505050905090565b610e9c6125a8565b6040516307e0db1760e01b815261ffff821660048201527f0000000000000000000000003c2269811836af69497e5f486a85d7316753cf626001600160a01b0316906307e0db17906024015b600060405180830381600087803b158015610f0257600080fd5b505af1158015610f16573d6000803e3d6000fd5b5050505050565b6000610f2882612602565b506000908152600f60205260409020546001600160a01b031690565b6000610f4f82611591565b9050806001600160a01b0316836001600160a01b031603610fbc5760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e656044820152603960f91b6064820152608401610c22565b336001600160a01b0382161480610fd85750610fd88133612273565b61104a5760405162461bcd60e51b815260206004820152603d60248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f7420746f60448201527f6b656e206f776e6572206f7220617070726f76656420666f7220616c6c0000006064820152608401610c22565b6110548383612652565b505050565b6110616125a8565b600081116110bd5760405162461bcd60e51b8152602060048201526024808201527f6d696e476173546f5472616e73666572416e6453746f7265206d7573742062656044820152630203e20360e41b6064820152608401610c22565b60078190556040518181527ffebbc4f8bb9ec2313950c718d43123124b15778efda4c1f1d529de2995b4f34d906020015b60405180910390a150565b6111016125a8565b61ffff909116600090815260036020526040902055565b6111206125a8565b6040516310ddb13760e01b815261ffff821660048201527f0000000000000000000000003c2269811836af69497e5f486a85d7316753cf626001600160a01b0316906310ddb13790602401610ee8565b6011543410156111ba5760405162461bcd60e51b8152602060048201526015602482015274139bdd08195b9bdd59da08195d1a195c881cd95b9d605a1b6044820152606401610c22565b60135460125411156111ff5760405162461bcd60e51b815260206004820152600e60248201526d2a37b79036b0b73c961031393abb60911b6044820152606401610c22565b601280549081906000611211836143d9565b919050555061122033826126c0565b50565b61122e335b826126da565b61124a5760405162461bcd60e51b8152600401610c22906143f2565b611054838383612738565b60008061126d87876112668861289c565b87876122fb565b915091509550959350505050565b6112836125a8565b604051600090339047908381818185875af1925050503d80600081146112c5576040519150601f19603f3d011682016040523d82523d6000602084013e6112ca565b606091505b505090508061122057600080fd5b61ffff8316600090815260016020526040812080548291906112f990614379565b80601f016020809104026020016040519081016040528092919081815260200182805461132590614379565b80156113725780601f1061134757610100808354040283529160200191611372565b820191906000526020600020905b81548152906001019060200180831161135557829003601f168201915b5050505050905083836040516113899291906143b3565b60405180910390208180519060200120149150509392505050565b61105483838360405180602001604052806000815250611cd9565b6113c76125a8565b6040516342d65a8d60e01b81526001600160a01b037f0000000000000000000000003c2269811836af69497e5f486a85d7316753cf6216906342d65a8d9061141790869086908690600401614468565b600060405180830381600087803b15801561143157600080fd5b505af1158015610dd6573d6000803e3d6000fd5b61144d6125a8565b6040516304b2b47b60e11b81523060048201526006907f0000000000000000000000003c2269811836af69497e5f486a85d7316753cf626001600160a01b03169063cbed8b9c90829063096568f690602401602060405180830381865afa1580156114bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114e09190614486565b604080516001600160a01b038716602082015287918691016040516020818303038152906040526040518563ffffffff1660e01b815260040161141794939291906144a3565b61ffff831660009081526009602052604090205461154a90849060019084906128e7565b604080513360208201526000818301528151808203830181526060909101909152611054908490308585346129c6565b610dd68787876115898861289c565b878787612b6b565b6000818152600d60205260408120546001600160a01b031680610dfc5760405162461bcd60e51b8152602060048201526018602482015277115490cdcc8c4e881a5b9d985b1a59081d1bdad95b88125160421b6044820152606401610c22565b33301461164f5760405162461bcd60e51b815260206004820152602660248201527f4e6f6e626c6f636b696e674c7a4170703a2063616c6c6572206d7573742062656044820152650204c7a4170760d41b6064820152608401610c22565b6116c58686868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f890181900481028201810190925287815289935091508790879081908401838280828437600092019190915250612d3f92505050565b505050505050565b6116d56125a8565b601155565b60006001600160a01b0382166117445760405162461bcd60e51b815260206004820152602960248201527f4552433732313a2061646472657373207a65726f206973206e6f7420612076616044820152683634b21037bbb732b960b91b6064820152608401610c22565b506001600160a01b03166000908152600e602052604090205490565b6117686125a8565b6117726000612ebe565b565b6001602052600090815260409020805461178d90614379565b80601f01602080910402602001604051908101604052809291908181526020018280546117b990614379565b80156118065780601f106117db57610100808354040283529160200191611806565b820191906000526020600020905b8154815290600101906020018083116117e957829003601f168201915b505050505081565b611816612f0e565b80516020808301919091206000818152600a90925260409091206002015460ff166118775760405162461bcd60e51b81526020600482015260116024820152701b9bc818dc99591a5d1cc81cdd1bdc9959607a1b6044820152606401610c22565b60008280602001905181019061188d919061451f565b6000848152600a6020526040812080546001909101549294509092506118c99161ffff8216916201000090046001600160a01b03169085612f67565b6000848152600a6020526040902060010154909150811161193e5760405162461bcd60e51b815260206004820152602960248201527f6e6f7420656e6f7567682067617320746f2070726f6365737320637265646974604482015268103a3930b739b332b960b91b6064820152608401610c22565b815181036119b5576000838152600a602052604080822080546001600160b01b031916815560018101929092556002909101805460ff19169055517fd7be02b8dd0d27bd0517a9cb4d7469ce27df4313821ae5ec1ff69acc594ba233906119a89085815260200190565b60405180910390a1611a49565b604080516080810182526000858152600a6020818152848320805461ffff80821687526001600160a01b03620100008084048216868a019081529989018b8152600160608b01818152998f90529790965297519851169096026001600160b01b03199091169690951695909517939093178455915191830191909155516002909101805491151560ff199092169190911790555b5050506112206001600655565b6060600c8054610e1190614379565b611a6d6125a8565b60008111611ac85760405162461bcd60e51b815260206004820152602260248201527f647374436861696e4964546f42617463684c696d6974206d757374206265203e604482015261020360f41b6064820152608401610c22565b61ffff8216600081815260086020908152604091829020849055815192835282018390527f7315f7654d594ead24a30160ed9ba2d23247f543016b918343591e93d7afdb6d91015b60405180910390a15050565b61ffff8116600090815260016020526040812080546060929190611b3f90614379565b80601f0160208091040260200160405190810160405280929190818152602001828054611b6b90614379565b8015611bb85780601f10611b8d57610100808354040283529160200191611bb8565b820191906000526020600020905b815481529060010190602001808311611b9b57829003601f168201915b505050505090508051600003611c105760405162461bcd60e51b815260206004820152601d60248201527f4c7a4170703a206e6f20747275737465642070617468207265636f72640000006044820152606401610c22565b611c2b600060148351611c2391906145d9565b839190612fb3565b9392505050565b611c3d3383836130c0565b5050565b611c496125a8565b818130604051602001611c5e939291906145ec565b60408051601f1981840301815291815261ffff8516600090815260016020522090611c899082614658565b507f8c0400cfe2d1199b1a725c78960bcc2a344d869b80590d0f2bd005db15a572ce838383604051611cbd93929190614468565b60405180910390a1505050565b610dd687878787878787612b6b565b611ce333836126da565b611cff5760405162461bcd60e51b8152600401610c22906143f2565b611d0b8484848461318e565b50505050565b611d196125a8565b600480546001600160a01b0319166001600160a01b0383169081179091556040519081527f5db758e995a17ec1ad84bdef7e8c3293a0bd6179bcce400dff5d4c3d87db726b906020016110ee565b6060611d716131c1565b611d7a836131e1565b604051602001611d8b929190614717565b6040516020818303038152906040529050919050565b611da96125a8565b6040516332fb62e760e21b81526001600160a01b037f0000000000000000000000003c2269811836af69497e5f486a85d7316753cf62169063cbed8b9c90611dfd9088908890889088908890600401614746565b600060405180830381600087803b158015611e1757600080fd5b505af1158015611e2b573d6000803e3d6000fd5b505050505050505050565b611e3e6125a8565b60008111611e9a5760405162461bcd60e51b815260206004820152602360248201527f647374436861696e4964546f5472616e73666572476173206d7573742062652060448201526203e20360ec1b6064820152608401610c22565b61ffff8216600081815260096020908152604091829020849055815192835282018390527fc46df2983228ac2d9754e94a0d565e6671665dc8ad38602bc8e544f0685a29fb9101611b10565b61ffff86166000908152600560205260408082209051611f0990889088906143b3565b90815260408051602092819003830190206001600160401b03871660009081529252902054905080611f895760405162461bcd60e51b815260206004820152602360248201527f4e6f6e626c6f636b696e674c7a4170703a206e6f2073746f726564206d65737360448201526261676560e81b6064820152608401610c22565b808383604051611f9a9291906143b3565b604051809103902014611ff95760405162461bcd60e51b815260206004820152602160248201527f4e6f6e626c6f636b696e674c7a4170703a20696e76616c6964207061796c6f616044820152601960fa1b6064820152608401610c22565b61ffff8716600090815260056020526040808220905161201c90899089906143b3565b90815260408051602092819003830181206001600160401b038916600090815290845282902093909355601f880182900482028301820190528682526120b4918991899089908190840183828082843760009201919091525050604080516020601f8a018190048102820181019092528881528a935091508890889081908401838280828437600092019190915250612d3f92505050565b7fc264d91f3adc5588250e1551f547752ca0cfa8f6b530d243b9f9f4cab10ea8e587878787856040516120eb95949392919061477f565b60405180910390a150505050505050565b604080513360208201526000818301819052825180830384018152606083019384905263040a7bb160e41b9093529182917f0000000000000000000000003c2269811836af69497e5f486a85d7316753cf626001600160a01b0316906340a7bb1090612174908990309086908b908b906064016147ba565b6040805180830381865afa158015612190573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121b4919061480e565b9250925050935093915050565b6121c96125a8565b600081116122115760405162461bcd60e51b81526020600482015260156024820152744c7a4170703a20696e76616c6964206d696e47617360581b6044820152606401610c22565b61ffff83811660008181526002602090815260408083209487168084529482529182902085905581519283528201929092529081018290527f9d5c7c0b934da8fefa9c7760c98383778a12dfbfc0c3b3106518f43fb9508ac090606001611cbd565b6001600160a01b03918216600090815260106020908152604080832093909416825291909152205460ff1690565b6122a96125a8565b61ffff831660009081526001602052604090206122c7828483614832565b507ffa41487ad5d6728f0b19276fa1eddc16558578f5109fc39d2dc33c3230470dab838383604051611cbd93929190614468565b6000806000868660405160200161231392919061492c565b60408051601f198184030181529082905263040a7bb160e41b825291506001600160a01b037f0000000000000000000000003c2269811836af69497e5f486a85d7316753cf6216906340a7bb1090612377908b90309086908b908b906004016147ba565b6040805180830381865afa158015612393573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123b7919061480e565b92509250509550959350505050565b6123ce6125a8565b6001600160a01b0381166124335760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610c22565b61122081612ebe565b604051633d7b2f6f60e21b815261ffff808616600483015284166024820152306044820152606481018290526060907f0000000000000000000000003c2269811836af69497e5f486a85d7316753cf626001600160a01b03169063f5ecbdbc90608401600060405180830381865afa1580156124bc573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526124e4919081019061495a565b90505b949350505050565b6000806125525a60966366ad5c8a60e01b89898989604051602401612517949392919061498e565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915230929190613273565b91509150816116c5576116c586868686856132fd565b60006001600160e01b031982166380ac58cd60e01b148061259957506001600160e01b03198216635b5e139f60e01b145b80610dfc5750610dfc8261339a565b6000546001600160a01b031633146117725760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610c22565b61260b816133cf565b6112205760405162461bcd60e51b8152602060048201526018602482015277115490cdcc8c4e881a5b9d985b1a59081d1bdad95b88125160421b6044820152606401610c22565b6000818152600f6020526040902080546001600160a01b0319166001600160a01b038416908117909155819061268782611591565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b611c3d8282604051806020016040528060008152506133ec565b6000806126e683611591565b9050806001600160a01b0316846001600160a01b0316148061270d575061270d8185612273565b806124e75750836001600160a01b031661272684610f1d565b6001600160a01b031614949350505050565b826001600160a01b031661274b82611591565b6001600160a01b0316146127715760405162461bcd60e51b8152600401610c22906149cc565b6001600160a01b0382166127d35760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f206164646044820152637265737360e01b6064820152608401610c22565b826001600160a01b03166127e682611591565b6001600160a01b03161461280c5760405162461bcd60e51b8152600401610c22906149cc565b6000818152600f6020908152604080832080546001600160a01b03199081169091556001600160a01b03878116808652600e8552838620805460001901905590871680865283862080546001019055868652600d90945282852080549092168417909155905184937fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b604080516001808252818301909252606091600091906020808301908036833701905050905082816000815181106128d6576128d6614a11565b602090810291909101015292915050565b60006128f28361341f565b61ffff808716600090815260026020908152604080832093891683529290529081205491925090612924908490614a27565b9050600081116129765760405162461bcd60e51b815260206004820152601a60248201527f4c7a4170703a206d696e4761734c696d6974206e6f74207365740000000000006044820152606401610c22565b808210156116c55760405162461bcd60e51b815260206004820152601b60248201527f4c7a4170703a20676173206c696d697420697320746f6f206c6f7700000000006044820152606401610c22565b61ffff8616600090815260016020526040812080546129e490614379565b80601f0160208091040260200160405190810160405280929190818152602001828054612a1090614379565b8015612a5d5780601f10612a3257610100808354040283529160200191612a5d565b820191906000526020600020905b815481529060010190602001808311612a4057829003601f168201915b505050505090508051600003612ace5760405162461bcd60e51b815260206004820152603060248201527f4c7a4170703a2064657374696e6174696f6e20636861696e206973206e6f742060448201526f61207472757374656420736f7572636560801b6064820152608401610c22565b612ad987875161347b565b60405162c5803160e81b81526001600160a01b037f0000000000000000000000003c2269811836af69497e5f486a85d7316753cf62169063c5803100908490612b30908b9086908c908c908c908c90600401614a3a565b6000604051808303818588803b158015612b4957600080fd5b505af1158015612b5d573d6000803e3d6000fd5b505050505050505050505050565b6000845111612bb25760405162461bcd60e51b8152602060048201526013602482015272746f6b656e4964735b5d20697320656d70747960681b6044820152606401610c22565b835160011480612bd6575061ffff8616600090815260086020526040902054845111155b612c2d5760405162461bcd60e51b815260206004820152602260248201527f62617463682073697a65206578636565647320647374206261746368206c696d6044820152611a5d60f21b6064820152608401610c22565b60005b8451811015612c7057612c5e888888888581518110612c5157612c51614a11565b60200260200101516134ec565b80612c68816143d9565b915050612c30565b5060008585604051602001612c8692919061492c565b6040516020818303038152906040529050612ccb876001848851600960008d61ffff1661ffff16815260200190815260200160002054612cc69190614aa1565b6128e7565b612cd98782868686346129c6565b85604051612ce79190614ab8565b6040518091039020886001600160a01b03168861ffff167fe1b87c47fdeb4f9cbadbca9df3af7aba453bb6e501075d0440d88125b711522a88604051612d2d9190614ad4565b60405180910390a45050505050505050565b60008082806020019051810190612d56919061451f565b9150915080600081518110612d6d57612d6d614a11565b6020026020010151600003612d83575050611d0b565b60148201516000612d9688838386612f67565b90508251811015612e6a5784516020808701919091206040805160808101825261ffff808d1682526001600160a01b038088168387019081528385018881526001606086018181526000898152600a909a529887902095518654935190941662010000026001600160b01b03199093169390941692909217178355519082015592516002909301805493151560ff199094169390931790925590517f10e0b70d256bccc84b7027506978bd8b68984a870788b93b479def144c839ad790612e609083908990614ae7565b60405180910390a1505b816001600160a01b031687604051612e829190614ab8565b60405180910390208961ffff167f5b821db8a46f8ecbe1941ba2f51cfeea9643268b56631f70d45e2a745d99026586604051612d2d9190614ad4565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b600260065403612f605760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610c22565b6002600655565b6000825b82518110156124e4576007545a106124e457612fa18686858481518110612f9457612f94614a11565b60200260200101516135d7565b80612fab816143d9565b915050612f6b565b606081612fc181601f614a27565b10156130005760405162461bcd60e51b815260206004820152600e60248201526d736c6963655f6f766572666c6f7760901b6044820152606401610c22565b61300a8284614a27565b8451101561304e5760405162461bcd60e51b8152602060048201526011602482015270736c6963655f6f75744f66426f756e647360781b6044820152606401610c22565b60608215801561306d57604051915060008252602082016040526130b7565b6040519150601f8416801560200281840101858101878315602002848b0101015b818310156130a657805183526020928301920161308e565b5050858452601f01601f1916604052505b50949350505050565b816001600160a01b0316836001600160a01b0316036131215760405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c6572000000000000006044820152606401610c22565b6001600160a01b03838116600081815260106020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b613199848484612738565b6131a584848484613637565b611d0b5760405162461bcd60e51b8152600401610c2290614b00565b6060604051806060016040528060238152602001614bf560239139905090565b606060006131ee83613735565b60010190506000816001600160401b0381111561320d5761320d613bfa565b6040519080825280601f01601f191660200182016040528015613237576020820181803683370190505b5090508181016020015b600019016f181899199a1a9b1b9c1cb0b131b232b360811b600a86061a8153600a850494508461324157509392505050565b6000606060008060008661ffff166001600160401b0381111561329857613298613bfa565b6040519080825280601f01601f1916602001820160405280156132c2576020820181803683370190505b50905060008087516020890160008d8df191503d9250868311156132e4578692505b828152826000602083013e909890975095505050505050565b8180519060200120600560008761ffff1661ffff1681526020019081526020016000208560405161332e9190614ab8565b9081526040805191829003602090810183206001600160401b0388166000908152915220919091557fe183f33de2837795525b4792ca4cd60535bd77c53b7e7030060bfcf5734d6b0c9061338b9087908790879087908790614b52565b60405180910390a15050505050565b60006001600160e01b031982166322bac5d960e01b1480610dfc57506301ffc9a760e01b6001600160e01b0319831614610dfc565b6000908152600d60205260409020546001600160a01b0316151590565b6133f6838361380d565b6134036000848484613637565b6110545760405162461bcd60e51b8152600401610c2290614b00565b60006022825110156134735760405162461bcd60e51b815260206004820152601c60248201527f4c7a4170703a20696e76616c69642061646170746572506172616d73000000006044820152606401610c22565b506022015190565b61ffff82166000908152600360205260408120549081900361349c57506127105b808211156110545760405162461bcd60e51b815260206004820181905260248201527f4c7a4170703a207061796c6f61642073697a6520697320746f6f206c617267656044820152606401610c22565b6134f533611228565b6135585760405162461bcd60e51b815260206004820152602e60248201527f4f4e46543732313a2073656e642063616c6c6572206973206e6f74206f776e6560448201526d1c881b9bdc88185c1c1c9bdd995960921b6064820152608401610c22565b836001600160a01b031661356b82611591565b6001600160a01b0316146135cc5760405162461bcd60e51b815260206004820152602260248201527f4f4e46543732313a2073656e642066726f6d20696e636f7272656374206f776e60448201526132b960f11b6064820152608401610c22565b611d0b843083612738565b6135e0816133cf565b158061360c57506135f0816133cf565b801561360c57503061360182611591565b6001600160a01b0316145b61361557600080fd5b61361e816133cf565b61362c5761105482826126c0565b611054308383612738565b60006001600160a01b0384163b1561372d57604051630a85bd0160e11b81526001600160a01b0385169063150b7a029061367b903390899088908890600401614ba4565b6020604051808303816000875af19250505080156136b6575060408051601f3d908101601f191682019092526136b391810190614bd7565b60015b613713573d8080156136e4576040519150601f19603f3d011682016040523d82523d6000602084013e6136e9565b606091505b50805160000361370b5760405162461bcd60e51b8152600401610c2290614b00565b805181602001fd5b6001600160e01b031916630a85bd0160e11b1490506124e7565b5060016124e7565b60008072184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b83106137745772184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b830492506040015b6d04ee2d6d415b85acef810000000083106137a0576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc1000083106137be57662386f26fc10000830492506010015b6305f5e10083106137d6576305f5e100830492506008015b61271083106137ea57612710830492506004015b606483106137fc576064830492506002015b600a8310610dfc5760010192915050565b6001600160a01b0382166138635760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f20616464726573736044820152606401610c22565b61386c816133cf565b156138b95760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e746564000000006044820152606401610c22565b6138c2816133cf565b1561390f5760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e746564000000006044820152606401610c22565b6001600160a01b0382166000818152600e6020908152604080832080546001019055848352600d90915280822080546001600160a01b0319168417905551839291907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b61ffff8116811461122057600080fd5b60008083601f84011261399c57600080fd5b5081356001600160401b038111156139b357600080fd5b6020830191508360208285010111156139cb57600080fd5b9250929050565b80356001600160401b03811681146139e957600080fd5b919050565b60008060008060008060808789031215613a0757600080fd5b8635613a128161397a565b955060208701356001600160401b0380821115613a2e57600080fd5b613a3a8a838b0161398a565b9097509550859150613a4e60408a016139d2565b94506060890135915080821115613a6457600080fd5b50613a7189828a0161398a565b979a9699509497509295939492505050565b6001600160e01b03198116811461122057600080fd5b600060208284031215613aab57600080fd5b8135611c2b81613a83565b60005b83811015613ad1578181015183820152602001613ab9565b50506000910152565b60008151808452613af2816020860160208601613ab6565b601f01601f19169290920160200192915050565b602081526000611c2b6020830184613ada565b600060208284031215613b2b57600080fd5b8135611c2b8161397a565b600060208284031215613b4857600080fd5b5035919050565b6001600160a01b038116811461122057600080fd5b80356139e981613b4f565b60008060408385031215613b8257600080fd5b8235613b8d81613b4f565b946020939093013593505050565b60008060408385031215613bae57600080fd5b8235613b8d8161397a565b600080600060608486031215613bce57600080fd5b8335613bd981613b4f565b92506020840135613be981613b4f565b929592945050506040919091013590565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b0381118282101715613c3857613c38613bfa565b604052919050565b60006001600160401b03821115613c5957613c59613bfa565b50601f01601f191660200190565b600082601f830112613c7857600080fd5b8135613c8b613c8682613c40565b613c10565b818152846020838601011115613ca057600080fd5b816020850160208301376000918101602001919091529392505050565b803580151581146139e957600080fd5b600080600080600060a08688031215613ce557600080fd5b8535613cf08161397a565b945060208601356001600160401b0380821115613d0c57600080fd5b613d1889838a01613c67565b955060408801359450613d2d60608901613cbd565b93506080880135915080821115613d4357600080fd5b50613d5088828901613c67565b9150509295509295909350565b600080600060408486031215613d7257600080fd5b8335613d7d8161397a565b925060208401356001600160401b03811115613d9857600080fd5b613da48682870161398a565b9497909650939450505050565b60008060408385031215613dc457600080fd5b8235613dcf8161397a565b91506020830135613ddf81613b4f565b809150509250929050565b600080600060608486031215613dff57600080fd5b8335613e0a8161397a565b92506020840135613e1a81613b4f565b915060408401356001600160401b03811115613e3557600080fd5b613e4186828701613c67565b9150509250925092565b600080600080600080600060e0888a031215613e6657600080fd5b8735613e7181613b4f565b96506020880135613e818161397a565b955060408801356001600160401b0380821115613e9d57600080fd5b613ea98b838c01613c67565b965060608a0135955060808a01359150613ec282613b4f565b90935060a089013590613ed482613b4f565b90925060c08901359080821115613eea57600080fd5b50613ef78a828b01613c67565b91505092959891949750929550565b600080600060608486031215613f1b57600080fd5b8335613f268161397a565b925060208401356001600160401b03811115613f4157600080fd5b613f4d86828701613c67565b925050613f5c604085016139d2565b90509250925092565b600060208284031215613f7757600080fd5b8135611c2b81613b4f565b60008060408385031215613f9557600080fd5b8235613fa08161397a565b91506020830135613ddf8161397a565b600060208284031215613fc257600080fd5b81356001600160401b03811115613fd857600080fd5b6124e784828501613c67565b60008060408385031215613ff757600080fd5b823561400281613b4f565b915061401060208401613cbd565b90509250929050565b60006001600160401b0382111561403257614032613bfa565b5060051b60200190565b600082601f83011261404d57600080fd5b8135602061405d613c8683614019565b82815260059290921b8401810191818101908684111561407c57600080fd5b8286015b848110156140975780358352918301918301614080565b509695505050505050565b600080600080600080600060e0888a0312156140bd57600080fd5b87356140c881613b4f565b965060208801356140d88161397a565b955060408801356001600160401b03808211156140f457600080fd5b6141008b838c01613c67565b965060608a013591508082111561411657600080fd5b6141228b838c0161403c565b955061413060808b01613b64565b945061413e60a08b01613b64565b935060c08a0135915080821115613eea57600080fd5b6000806000806080858703121561416a57600080fd5b843561417581613b4f565b9350602085013561418581613b4f565b92506040850135915060608501356001600160401b038111156141a757600080fd5b6141b387828801613c67565b91505092959194509250565b6000806000806000608086880312156141d757600080fd5b85356141e28161397a565b945060208601356141f28161397a565b93506040860135925060608601356001600160401b0381111561421457600080fd5b6142208882890161398a565b969995985093965092949392505050565b60008060006060848603121561424657600080fd5b83356142518161397a565b9250613e1a60208501613cbd565b60008060006060848603121561427457600080fd5b833561427f8161397a565b92506020840135613be98161397a565b600080604083850312156142a257600080fd5b8235613dcf81613b4f565b600080600080600060a086880312156142c557600080fd5b85356142d08161397a565b945060208601356001600160401b03808211156142ec57600080fd5b6142f889838a01613c67565b9550604088013591508082111561430e57600080fd5b61431a89838a0161403c565b9450613d2d60608901613cbd565b6000806000806080858703121561433e57600080fd5b84356143498161397a565b935060208501356143598161397a565b9250604085013561436981613b4f565b9396929550929360600135925050565b600181811c9082168061438d57607f821691505b6020821081036143ad57634e487b7160e01b600052602260045260246000fd5b50919050565b8183823760009101908152919050565b634e487b7160e01b600052601160045260246000fd5b6000600182016143eb576143eb6143c3565b5060010190565b6020808252602d908201527f4552433732313a2063616c6c6572206973206e6f7420746f6b656e206f776e6560408201526c1c881bdc88185c1c1c9bdd9959609a1b606082015260800190565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b61ffff841681526040602082015260006124e460408301848661443f565b60006020828403121561449857600080fd5b8151611c2b8161397a565b600061ffff8087168352808616602084015250836040830152608060608301526144d06080830184613ada565b9695505050505050565b600082601f8301126144eb57600080fd5b81516144f9613c8682613c40565b81815284602083860101111561450e57600080fd5b6124e7826020830160208701613ab6565b6000806040838503121561453257600080fd5b82516001600160401b038082111561454957600080fd5b614555868387016144da565b935060209150818501518181111561456c57600080fd5b85019050601f8101861361457f57600080fd5b805161458d613c8682614019565b81815260059190911b820183019083810190888311156145ac57600080fd5b928401925b828410156145ca578351825292840192908401906145b1565b80955050505050509250929050565b81810381811115610dfc57610dfc6143c3565b8284823760609190911b6bffffffffffffffffffffffff19169101908152601401919050565b601f82111561105457600081815260208120601f850160051c810160208610156146395750805b601f850160051c820191505b818110156116c557828155600101614645565b81516001600160401b0381111561467157614671613bfa565b6146858161467f8454614379565b84614612565b602080601f8311600181146146ba57600084156146a25750858301515b600019600386901b1c1916600185901b1785556116c5565b600085815260208120601f198616915b828110156146e9578886015182559484019460019091019084016146ca565b50858210156147075787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60008351614729818460208801613ab6565b83519083019061473d818360208801613ab6565b01949350505050565b600061ffff80881683528087166020840152508460408301526080606083015261477460808301848661443f565b979650505050505050565b61ffff8616815260806020820152600061479d60808301868861443f565b6001600160401b0394909416604083015250606001529392505050565b61ffff861681526001600160a01b038516602082015260a0604082018190526000906147e890830186613ada565b841515606084015282810360808401526148028185613ada565b98975050505050505050565b6000806040838503121561482157600080fd5b505080516020909101519092909150565b6001600160401b0383111561484957614849613bfa565b61485d836148578354614379565b83614612565b6000601f84116001811461489157600085156148795750838201355b600019600387901b1c1916600186901b178355610f16565b600083815260209020601f19861690835b828110156148c257868501358255602094850194600190920191016148a2565b50868210156148df5760001960f88860031b161c19848701351681555b505060018560011b0183555050505050565b600081518084526020808501945080840160005b8381101561492157815187529582019590820190600101614905565b509495945050505050565b60408152600061493f6040830185613ada565b828103602084015261495181856148f1565b95945050505050565b60006020828403121561496c57600080fd5b81516001600160401b0381111561498257600080fd5b6124e7848285016144da565b61ffff851681526080602082015260006149ab6080830186613ada565b6001600160401b038516604084015282810360608401526147748185613ada565b60208082526025908201527f4552433732313a207472616e736665722066726f6d20696e636f72726563742060408201526437bbb732b960d91b606082015260800190565b634e487b7160e01b600052603260045260246000fd5b80820180821115610dfc57610dfc6143c3565b61ffff8716815260c060208201526000614a5760c0830188613ada565b8281036040840152614a698188613ada565b6001600160a01b0387811660608601528616608085015283810360a08501529050614a948185613ada565b9998505050505050505050565b8082028115828204841417610dfc57610dfc6143c3565b60008251614aca818460208701613ab6565b9190910192915050565b602081526000611c2b60208301846148f1565b8281526040602082015260006124e76040830184613ada565b60208082526032908201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b606082015260800190565b61ffff8616815260a060208201526000614b6f60a0830187613ada565b6001600160401b03861660408401528281036060840152614b908186613ada565b905082810360808401526148028185613ada565b6001600160a01b03858116825284166020820152604081018390526080606082018190526000906144d090830184613ada565b600060208284031215614be957600080fd5b8151611c2b81613a8356fe68747470733a2f2f6170692e6d65726b6c792e636f6d2f6170692f7a6b2d6d65726b2fa2646970667358221220f76858e4b7bb5fab3ae912ee6c6d5fe87cfc482499e6fc998b4ef12a250eb1cf64736f6c63430008130033

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

0000000000000000000000000000000000000000000000000000000000004e200000000000000000000000003c2269811836af69497e5f486a85d7316753cf6200000000000000000000000000000000000000000000000000000000003d090000000000000000000000000000000000000000000000000000000000004c4b3f

-----Decoded View---------------
Arg [0] : _minGasToTransfer (uint256): 20000
Arg [1] : _layerZeroEndpoint (address): 0x3c2269811836af69497E5F486A85D7316753cf62
Arg [2] : _startMintId (uint256): 4000000
Arg [3] : _endMintId (uint256): 4999999

-----Encoded View---------------
4 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000004e20
Arg [1] : 0000000000000000000000003c2269811836af69497e5f486a85d7316753cf62
Arg [2] : 00000000000000000000000000000000000000000000000000000000003d0900
Arg [3] : 00000000000000000000000000000000000000000000000000000000004c4b3f


Deployed Bytecode Sourcemap

118495:2694:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;45204:762;;;;;;;;;;-1:-1:-1;45204:762:0;;;;;:::i;:::-;;:::i;:::-;;117426:228;;;;;;;;;;-1:-1:-1;117426:228:0;;;;;:::i;:::-;;:::i;:::-;;;2143:14:1;;2136:22;2118:41;;2106:2;2091:18;117426:228:0;;;;;;;;102146:100;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;48502:123::-;;;;;;;;;;-1:-1:-1;48502:123:0;;;;;:::i;:::-;;:::i;103658:171::-;;;;;;;;;;-1:-1:-1;103658:171:0;;;;;:::i;:::-;;:::i;:::-;;;-1:-1:-1;;;;;3525:32:1;;;3507:51;;3495:2;3480:18;103658:171:0;3361:203:1;103176:416:0;;;;;;;;;;-1:-1:-1;103176:416:0;;;;;:::i;:::-;;:::i;70032:321::-;;;;;;;;;;-1:-1:-1;70032:321:0;;;;;:::i;:::-;;:::i;50427:142::-;;;;;;;;;;-1:-1:-1;50427:142:0;;;;;:::i;:::-;;:::i;48633:129::-;;;;;;;;;;-1:-1:-1;48633:129:0;;;;;:::i;:::-;;:::i;119624:261::-;;;:::i;64145:53::-;;;;;;;;;;-1:-1:-1;64145:53:0;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;64145:53:0;;;;;;;;;;;4920:6:1;4908:19;;;4890:38;;-1:-1:-1;;;;;4964:32:1;;;4959:2;4944:18;;4937:60;5013:18;;;5006:34;5083:14;5076:22;5071:2;5056:18;;5049:50;4877:3;4862:19;64145:53:0;4667:438:1;104358:301:0;;;;;;;;;;-1:-1:-1;104358:301:0;;;;;:::i;:::-;;:::i;64700:320::-;;;;;;;;;;-1:-1:-1;64700:320:0;;;;;:::i;:::-;;:::i;:::-;;;;7795:25:1;;;7851:2;7836:18;;7829:34;;;;7768:18;64700:320:0;7621:248:1;120909:192:0;;;:::i;50667:250::-;;;;;;;;;;-1:-1:-1;50667:250:0;;;;;:::i;:::-;;:::i;44746:53::-;;;;;;;;;;-1:-1:-1;44746:53:0;;;;;:::i;:::-;;;;;;;;;;;;;;;;;8567:25:1;;;8555:2;8540:18;44746:53:0;8421:177:1;104730:151:0;;;;;;;;;;-1:-1:-1;104730:151:0;;;;;:::i;:::-;;:::i;48770:178::-;;;;;;;;;;-1:-1:-1;48770:178:0;;;;;:::i;:::-;;:::i;63835:39::-;;;;;;;;;;;;;;;;119306:310;;;;;;;;;;-1:-1:-1;119306:310:0;;;;;:::i;:::-;;:::i;63951:56::-;;;;;;;;;;-1:-1:-1;63951:56:0;;;;;:::i;:::-;;;;;;;;;;;;;;120230:359;;;;;;:::i;:::-;;:::i;65424:351::-;;;;;;:::i;:::-;;:::i;56897:85::-;;;;;;;;;;-1:-1:-1;56897:85:0;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;101856:223;;;;;;;;;;-1:-1:-1;101856:223:0;;;;;:::i;:::-;;:::i;58119:346::-;;;;;;;;;;-1:-1:-1;58119:346:0;;;;;:::i;:::-;;:::i;121109:75::-;;;;;;;;;;-1:-1:-1;121109:75:0;;;;;:::i;:::-;;:::i;118574:22::-;;;;;;;;;;;;;;;;101587:207;;;;;;;;;;-1:-1:-1;101587:207:0;;;;;:::i;:::-;;:::i;16956:103::-;;;;;;;;;;;;;:::i;44616:51::-;;;;;;;;;;-1:-1:-1;44616:51:0;;;;;:::i;:::-;;:::i;44674:65::-;;;;;;;;;;-1:-1:-1;44674:65:0;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;16315:87;;;;;;;;;;-1:-1:-1;16361:7:0;16388:6;-1:-1:-1;;;;;16388:6:0;16315:87;;68242:1009;;;;;;;;;;-1:-1:-1;68242:1009:0;;;;;:::i;:::-;;:::i;44806:23::-;;;;;;;;;;-1:-1:-1;44806:23:0;;;;-1:-1:-1;;;;;44806:23:0;;;102315:104;;;;;;;;;;;;;:::i;70877:351::-;;;;;;;;;;-1:-1:-1;70877:351:0;;;;;:::i;:::-;;:::i;49599:330::-;;;;;;;;;;-1:-1:-1;49599:330:0;;;;;:::i;:::-;;:::i;103901:155::-;;;;;;;;;;-1:-1:-1;103901:155:0;;;;;:::i;:::-;;:::i;49310:281::-;;;;;;;;;;-1:-1:-1;49310:281:0;;;;;:::i;:::-;;:::i;65783:348::-;;;;;;:::i;:::-;;:::i;63598:45::-;;;;;;;;;;;;63642:1;63598:45;;;;;15227:6:1;15215:19;;;15197:38;;15185:2;15170:18;63598:45:0;15053:188:1;44563:46:0;;;;;;;;;;;;;;;104952:279;;;;;;;;;;-1:-1:-1;104952:279:0;;;;;:::i;:::-;;:::i;49937:136::-;;;;;;;;;;-1:-1:-1;49937:136:0;;;;;:::i;:::-;;:::i;44499:55::-;;;;;;;;;;;;44549:5;44499:55;;120597:166;;;;;;;;;;-1:-1:-1;120597:166:0;;;;;:::i;:::-;;:::i;48290:204::-;;;;;;;;;;-1:-1:-1;48290:204:0;;;;;:::i;:::-;;:::i;70454:359::-;;;;;;;;;;-1:-1:-1;70454:359:0;;;;;:::i;:::-;;:::i;58651:767::-;;;;;;:::i;:::-;;:::i;119893:329::-;;;;;;;;;;-1:-1:-1;119893:329:0;;;;;:::i;:::-;;:::i;118535:30::-;;;;;;;;;;;;;;;;50081:284;;;;;;;;;;-1:-1:-1;50081:284:0;;;;;:::i;:::-;;:::i;118603:21::-;;;;;;;;;;;;;;;;104127:164;;;;;;;;;;-1:-1:-1;104127:164:0;;;;;:::i;:::-;;:::i;49095:207::-;;;;;;;;;;-1:-1:-1;49095:207:0;;;;;:::i;:::-;;:::i;65028:388::-;;;;;;;;;;-1:-1:-1;65028:388:0;;;;;:::i;:::-;;:::i;17214:201::-;;;;;;;;;;-1:-1:-1;17214:201:0;;;;;:::i;:::-;;:::i;48017:211::-;;;;;;;;;;-1:-1:-1;48017:211:0;;;;;:::i;:::-;;:::i;64014:57::-;;;;;;;;;;-1:-1:-1;64014:57:0;;;;;:::i;:::-;;;;;;;;;;;;;;45204:762;15104:10;45444;-1:-1:-1;;;;;45420:35:0;;45412:78;;;;-1:-1:-1;;;45412:78:0;;20055:2:1;45412:78:0;;;20037:21:1;20094:2;20074:18;;;20067:30;20133:32;20113:18;;;20106:60;20183:18;;45412:78:0;;;;;;;;;45532:32;;;45503:26;45532:32;;;:19;:32;;;;;45503:61;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;45738:13;:20;45716:11;;:18;;:42;:70;;;;;45785:1;45762:13;:20;:24;45716:70;:124;;;;-1:-1:-1;45816:24:0;;;;;;45790:22;;;;45800:11;;;;45790:22;:::i;:::-;;;;;;;;:50;45716:124;45708:175;;;;-1:-1:-1;;;45708:175:0;;21075:2:1;45708:175:0;;;21057:21:1;21114:2;21094:18;;;21087:30;21153:34;21133:18;;;21126:62;-1:-1:-1;;;21204:18:1;;;21197:36;21250:19;;45708:175:0;20873:402:1;45708:175:0;45896:62;45915:11;45928;;45896:62;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;45896:62:0;;;;;;;;;;;;;;;;;;;;;;45941:6;;-1:-1:-1;45896:62:0;-1:-1:-1;45949:8:0;;;;;;45896:62;;45949:8;;;;45896:62;;;;;;;;;-1:-1:-1;45896:18:0;;-1:-1:-1;;;45896:62:0:i;:::-;45335:631;45204:762;;;;;;:::o;117426:228::-;117541:4;-1:-1:-1;;;;;;117565:41:0;;;;:81;;;117610:36;117634:11;117610:23;:36::i;:::-;117558:88;117426:228;-1:-1:-1;;117426:228:0:o;102146:100::-;102200:13;102233:5;102226:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;102146:100;:::o;48502:123::-;16201:13;:11;:13::i;:::-;48582:35:::1;::::0;-1:-1:-1;;;48582:35:0;;15227:6:1;15215:19;;48582:35:0::1;::::0;::::1;15197:38:1::0;48582:10:0::1;-1:-1:-1::0;;;;;48582:25:0::1;::::0;::::1;::::0;15170:18:1;;48582:35:0::1;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;48502:123:::0;:::o;103658:171::-;103734:7;103754:23;103769:7;103754:14;:23::i;:::-;-1:-1:-1;103797:24:0;;;;:15;:24;;;;;;-1:-1:-1;;;;;103797:24:0;;103658:171::o;103176:416::-;103257:13;103273:23;103288:7;103273:14;:23::i;:::-;103257:39;;103321:5;-1:-1:-1;;;;;103315:11:0;:2;-1:-1:-1;;;;;103315:11:0;;103307:57;;;;-1:-1:-1;;;103307:57:0;;21482:2:1;103307:57:0;;;21464:21:1;21521:2;21501:18;;;21494:30;21560:34;21540:18;;;21533:62;-1:-1:-1;;;21611:18:1;;;21604:31;21652:19;;103307:57:0;21280:397:1;103307:57:0;15104:10;-1:-1:-1;;;;;103399:21:0;;;;:62;;-1:-1:-1;103424:37:0;103441:5;15104:10;104127:164;:::i;103424:37::-;103377:173;;;;-1:-1:-1;;;103377:173:0;;21884:2:1;103377:173:0;;;21866:21:1;21923:2;21903:18;;;21896:30;21962:34;21942:18;;;21935:62;22033:31;22013:18;;;22006:59;22082:19;;103377:173:0;21682:425:1;103377:173:0;103563:21;103572:2;103576:7;103563:8;:21::i;:::-;103246:346;103176:416;;:::o;70032:321::-;16201:13;:11;:13::i;:::-;70170:1:::1;70142:25;:29;70134:78;;;::::0;-1:-1:-1;;;70134:78:0;;22314:2:1;70134:78:0::1;::::0;::::1;22296:21:1::0;22353:2;22333:18;;;22326:30;22392:34;22372:18;;;22365:62;-1:-1:-1;;;22443:18:1;;;22436:34;22487:19;;70134:78:0::1;22112:400:1::0;70134:78:0::1;70223:24;:52:::0;;;70291:54:::1;::::0;8567:25:1;;;70291:54:0::1;::::0;8555:2:1;8540:18;70291:54:0::1;;;;;;;;70032:321:::0;:::o;50427:142::-;16201:13;:11;:13::i;:::-;50518:35:::1;::::0;;::::1;;::::0;;;:22:::1;:35;::::0;;;;:43;50427:142::o;48633:129::-;16201:13;:11;:13::i;:::-;48716:38:::1;::::0;-1:-1:-1;;;48716:38:0;;15227:6:1;15215:19;;48716:38:0::1;::::0;::::1;15197::1::0;48716:10:0::1;-1:-1:-1::0;;;;;48716:28:0::1;::::0;::::1;::::0;15170:18:1;;48716:38:0::1;15053:188:1::0;119624:261:0;119689:3;;119676:9;:16;;119668:50;;;;-1:-1:-1;;;119668:50:0;;22719:2:1;119668:50:0;;;22701:21:1;22758:2;22738:18;;;22731:30;-1:-1:-1;;;22777:18:1;;;22770:51;22838:18;;119668:50:0;22517:345:1;119668:50:0;119751:9;;119737:10;;:23;;119729:50;;;;-1:-1:-1;;;119729:50:0;;23069:2:1;119729:50:0;;;23051:21:1;23108:2;23088:18;;;23081:30;-1:-1:-1;;;23127:18:1;;;23120:44;23181:18;;119729:50:0;22867:338:1;119729:50:0;119803:10;;;;;;119790;119824:12;119803:10;119824:12;:::i;:::-;;;;;;119849:28;119859:10;119871:5;119849:9;:28::i;:::-;119657:228;119624:261::o;104358:301::-;104519:41;15104:10;104538:12;104552:7;104519:18;:41::i;:::-;104511:99;;;;-1:-1:-1;;;104511:99:0;;;;;;;:::i;:::-;104623:28;104633:4;104639:2;104643:7;104623:9;:28::i;64700:320::-;64866:14;64882:11;64913:99;64934:11;64947:10;64959:27;64977:8;64959:17;:27::i;:::-;64988:7;64997:14;64913:20;:99::i;:::-;64906:106;;;;64700:320;;;;;;;;:::o;120909:192::-;16201:13;:11;:13::i;:::-;120984:82:::1;::::0;120966:12:::1;::::0;120992:10:::1;::::0;121030:21:::1;::::0;120966:12;120984:82;120966:12;120984:82;121030:21;120992:10;120984:82:::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;120965:101;;;121085:7;121077:16;;;::::0;::::1;50667:250:::0;50809:32;;;50763:4;50809:32;;;:19;:32;;;;;50780:61;;50763:4;;50809:32;50780:61;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;50897:11;;50887:22;;;;;;;:::i;:::-;;;;;;;;50869:13;50859:24;;;;;;:50;50852:57;;;50667:250;;;;;:::o;104730:151::-;104834:39;104851:4;104857:2;104861:7;104834:39;;;;;;;;;;;;:16;:39::i;48770:178::-;16201:13;:11;:13::i;:::-;48885:55:::1;::::0;-1:-1:-1;;;48885:55:0;;-1:-1:-1;;;;;48885:10:0::1;:29;::::0;::::1;::::0;:55:::1;::::0;48915:11;;48928;;;;48885:55:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;119306:310:::0;16201:13;:11;:13::i;:::-;119466:40:::1;::::0;-1:-1:-1;;;119466:40:0;;119500:4:::1;119466:40;::::0;::::1;3507:51:1::0;119419:1:0::1;::::0;119431:10:::1;-1:-1:-1::0;;;;;119431:20:0::1;::::0;::::1;::::0;;;119466:25:::1;::::0;3480:18:1;;119466:40:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;119572:25;::::0;;-1:-1:-1;;;;;3525:32:1;;119572:25:0::1;::::0;::::1;3507:51:1::0;119521:10:0;;119546:11;;3480:18:1;119572:25:0::1;;;;;;;;;;;;119431:177;;;;;;;;;;;;;;;;;;:::i;120230:359::-:0;120416:36;;;;;;;:23;:36;;;;;;120352:101;;120367:11;;63642:1;;120400:14;;120352;:101::i;:::-;120485:24;;;120496:10;120485:24;;;25619:51:1;120507:1:0;25686:18:1;;;25679:45;120485:24:0;;;;;;;;;25592:18:1;;;;120485:24:0;;;120464:117;;120472:11;;120527:4;120535:18;120555:14;120571:9;120464:7;:117::i;65424:351::-;65649:118;65655:5;65662:11;65675:10;65687:27;65705:8;65687:17;:27::i;:::-;65716:14;65732:18;65752:14;65649:5;:118::i;101856:223::-;101928:7;106589:16;;;:7;:16;;;;;;-1:-1:-1;;;;;106589:16:0;;101992:56;;;;-1:-1:-1;;;101992:56:0;;25937:2:1;101992:56:0;;;25919:21:1;25976:2;25956:18;;;25949:30;-1:-1:-1;;;25995:18:1;;;25988:54;26059:18;;101992:56:0;25735:348:1;58119:346:0;15104:10;58333:4;58309:29;58301:80;;;;-1:-1:-1;;;58301:80:0;;26290:2:1;58301:80:0;;;26272:21:1;26329:2;26309:18;;;26302:30;26368:34;26348:18;;;26341:62;-1:-1:-1;;;26419:18:1;;;26412:36;26465:19;;58301:80:0;26088:402:1;58301:80:0;58392:65;58414:11;58427;;58392:65;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;58392:65:0;;;;;;;;;;;;;;;;;;;;;;58440:6;;-1:-1:-1;58392:65:0;-1:-1:-1;58448:8:0;;;;;;58392:65;;58448:8;;;;58392:65;;;;;;;;;-1:-1:-1;58392:21:0;;-1:-1:-1;;;58392:65:0:i;:::-;58119:346;;;;;;:::o;121109:75::-;16201:13;:11;:13::i;:::-;121166:3:::1;:10:::0;121109:75::o;101587:207::-;101659:7;-1:-1:-1;;;;;101687:19:0;;101679:73;;;;-1:-1:-1;;;101679:73:0;;26697:2:1;101679:73:0;;;26679:21:1;26736:2;26716:18;;;26709:30;26775:34;26755:18;;;26748:62;-1:-1:-1;;;26826:18:1;;;26819:39;26875:19;;101679:73:0;26495:405:1;101679:73:0;-1:-1:-1;;;;;;101770:16:0;;;;;:9;:16;;;;;;;101587:207::o;16956:103::-;16201:13;:11;:13::i;:::-;17021:30:::1;17048:1;17021:18;:30::i;:::-;16956:103::o:0;44616:51::-;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;68242:1009::-;62607:21;:19;:21::i;:::-;68352:19;;::::1;::::0;;::::1;::::0;;;;68328:21:::1;68390:28:::0;;;:13:::1;:28:::0;;;;;;;:42:::1;;::::0;::::1;;68382:72;;;::::0;-1:-1:-1;;;68382:72:0;;27107:2:1;68382:72:0::1;::::0;::::1;27089:21:1::0;27146:2;27126:18;;;27119:30;-1:-1:-1;;;27165:18:1;;;27158:47;27222:18;;68382:72:0::1;26905:341:1::0;68382:72:0::1;68470:22;68507:8;68496:37;;;;;;;;;;;;:::i;:::-;68546:14;68575:28:::0;;;:13:::1;:28;::::0;;;;:39;;;68656:34;;::::1;::::0;68467:66;;-1:-1:-1;68546:14:0;;-1:-1:-1;68563:138:0::1;::::0;68575:39:::1;::::0;::::1;::::0;68616:38;;::::1;-1:-1:-1::0;;;;;68616:38:0::1;::::0;68467:66;68563:11:::1;:138::i;:::-;68732:28;::::0;;;:13:::1;:28;::::0;;;;:34:::1;;::::0;68546:155;;-1:-1:-1;68720:46:0;::::1;68712:100;;;::::0;-1:-1:-1;;;68712:100:0;;29008:2:1;68712:100:0::1;::::0;::::1;28990:21:1::0;29047:2;29027:18;;;29020:30;29086:34;29066:18;;;29059:62;-1:-1:-1;;;29137:18:1;;;29130:39;29186:19;;68712:100:0::1;28806:405:1::0;68712:100:0::1;68842:8;:15;68829:9;:28:::0;68825:419:::1;;68937:28;::::0;;;:13:::1;:28;::::0;;;;;68930:35;;-1:-1:-1;;;;;;68930:35:0;;;;;::::1;::::0;;;;::::1;::::0;;::::1;::::0;;-1:-1:-1;;68930:35:0::1;::::0;;68985:28;::::1;::::0;::::1;::::0;68951:13;8567:25:1;;8555:2;8540:18;;8421:177;68985:28:0::1;;;;;;;;68825:419;;;69122:110;::::0;;::::1;::::0;::::1;::::0;;-1:-1:-1;69135:28:0;;;:13:::1;:28;::::0;;;;;;:39;;::::1;::::0;;::::1;69122:110:::0;;-1:-1:-1;;;;;69176:38:0;;;::::1;::::0;::::1;69122:110:::0;;::::1;::::0;;;;;;;;;69135:39;69122:110;;;;;;69091:28;;;;;;;;:141;;;;::::1;::::0;;::::1;-1:-1:-1::0;;;;;;69091:141:0;;;;;;::::1;::::0;;;;;;;::::1;::::0;;;;;;::::1;::::0;;;;;69176:38:::1;69091:141:::0;;::::1;::::0;;;::::1;;-1:-1:-1::0;;69091:141:0;;::::1;::::0;;;::::1;::::0;;68825:419:::1;68317:934;;;62651:20:::0;62045:1;63171:7;:22;62988:213;102315:104;102371:13;102404:7;102397:14;;;;;:::i;70877:351::-;16201:13;:11;:13::i;:::-;71029:1:::1;71003:23;:27;70995:74;;;::::0;-1:-1:-1;;;70995:74:0;;29418:2:1;70995:74:0::1;::::0;::::1;29400:21:1::0;29457:2;29437:18;;;29430:30;29496:34;29476:18;;;29469:62;-1:-1:-1;;;29547:18:1;;;29540:32;29589:19;;70995:74:0::1;29216:398:1::0;70995:74:0::1;71080:35;::::0;::::1;;::::0;;;:22:::1;:35;::::0;;;;;;;;:61;;;71157:63;;29791:38:1;;;29845:18;;29838:34;;;71157:63:0::1;::::0;29764:18:1;71157:63:0::1;;;;;;;;70877:351:::0;;:::o;49599:330::-;49723:35;;;49703:17;49723:35;;;:19;:35;;;;;49703:55;;49678:12;;49703:17;49723:35;49703:55;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;49777:4;:11;49792:1;49777:16;49769:58;;;;-1:-1:-1;;;49769:58:0;;30085:2:1;49769:58:0;;;30067:21:1;30124:2;30104:18;;;30097:30;30163:31;30143:18;;;30136:59;30212:18;;49769:58:0;29883:353:1;49769:58:0;49845:31;49856:1;49873:2;49859:4;:11;:16;;;;:::i;:::-;49845:4;;:31;:10;:31::i;:::-;49838:38;49599:330;-1:-1:-1;;;49599:330:0:o;103901:155::-;103996:52;15104:10;104029:8;104039;103996:18;:52::i;:::-;103901:155;;:::o;49310:281::-;16201:13;:11;:13::i;:::-;49482:14:::1;;49506:4;49465:47;;;;;;;;;;:::i;:::-;;::::0;;-1:-1:-1;;49465:47:0;;::::1;::::0;;;;;;49427:35:::1;::::0;::::1;;::::0;;;:19:::1;49465:47;49427:35:::0;;;:85:::1;::::0;:35;:85:::1;:::i;:::-;;49528:55;49552:14;49568;;49528:55;;;;;;;;:::i;:::-;;;;;;;;49310:281:::0;;;:::o;65783:348::-;66023:100;66029:5;66036:11;66049:10;66061:9;66072:14;66088:18;66108:14;66023:5;:100::i;104952:279::-;105083:41;15104:10;105116:7;105083:18;:41::i;:::-;105075:99;;;;-1:-1:-1;;;105075:99:0;;;;;;;:::i;:::-;105185:38;105199:4;105205:2;105209:7;105218:4;105185:13;:38::i;:::-;104952:279;;;;:::o;49937:136::-;16201:13;:11;:13::i;:::-;50007:8:::1;:20:::0;;-1:-1:-1;;;;;;50007:20:0::1;-1:-1:-1::0;;;;;50007:20:0;::::1;::::0;;::::1;::::0;;;50043:22:::1;::::0;3507:51:1;;;50043:22:0::1;::::0;3495:2:1;3480:18;50043:22:0::1;3361:203:1::0;120597:166:0;120665:13;120721:10;:8;:10::i;:::-;120733:20;120750:2;120733:16;:20::i;:::-;120704:50;;;;;;;;;:::i;:::-;;;;;;;;;;;;;120690:65;;120597:166;;;:::o;48290:204::-;16201:13;:11;:13::i;:::-;48424:62:::1;::::0;-1:-1:-1;;;48424:62:0;;-1:-1:-1;;;;;48424:10:0::1;:20;::::0;::::1;::::0;:62:::1;::::0;48445:8;;48455;;48465:11;;48478:7;;;;48424:62:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;48290:204:::0;;;;;:::o;70454:359::-;16201:13;:11;:13::i;:::-;70609:1:::1;70582:24;:28;70574:76;;;::::0;-1:-1:-1;;;70574:76:0;;34143:2:1;70574:76:0::1;::::0;::::1;34125:21:1::0;34182:2;34162:18;;;34155:30;34221:34;34201:18;;;34194:62;-1:-1:-1;;;34272:18:1;;;34265:33;34315:19;;70574:76:0::1;33941:399:1::0;70574:76:0::1;70661:36;::::0;::::1;;::::0;;;:23:::1;:36;::::0;;;;;;;;:63;;;70740:65;;29791:38:1;;;29845:18;;29838:34;;;70740:65:0::1;::::0;29764:18:1;70740:65:0::1;29619:259:1::0;58651:767:0;58862:27;;;58840:19;58862:27;;;:14;:27;;;;;;:40;;;;58890:11;;;;58862:40;:::i;:::-;;;;;;;;;;;;;;;;-1:-1:-1;;;;;58862:48:0;;;;;;;;;;;;-1:-1:-1;58862:48:0;58921:73;;;;-1:-1:-1;;;58921:73:0;;34547:2:1;58921:73:0;;;34529:21:1;34586:2;34566:18;;;34559:30;34625:34;34605:18;;;34598:62;-1:-1:-1;;;34676:18:1;;;34669:33;34719:19;;58921:73:0;34345:399:1;58921:73:0;59036:11;59023:8;;59013:19;;;;;;;:::i;:::-;;;;;;;;:34;59005:80;;;;-1:-1:-1;;;59005:80:0;;34951:2:1;59005:80:0;;;34933:21:1;34990:2;34970:18;;;34963:30;35029:34;35009:18;;;35002:62;-1:-1:-1;;;35080:18:1;;;35073:31;35121:19;;59005:80:0;34749:397:1;59005:80:0;59133:27;;;59192:1;59133:27;;;:14;:27;;;;;;:40;;;;59161:11;;;;59133:40;:::i;:::-;;;;;;;;;;;;;;;;-1:-1:-1;;;;;59133:48:0;;;;;;;;;;;;:61;;;;59263:65;;;;;;;;;;;;;;;;;;;59285:11;;59298;;59263:65;;;;;;59298:11;59263:65;;59298:11;59263:65;;;;;;;;;-1:-1:-1;;59263:65:0;;;;;;;;;;;;;;;;;;;;;;59311:6;;-1:-1:-1;59263:65:0;-1:-1:-1;59319:8:0;;;;;;59263:65;;59319:8;;;;59263:65;;;;;;;;;-1:-1:-1;59263:21:0;;-1:-1:-1;;;59263:65:0:i;:::-;59344:66;59364:11;59377;;59390:6;59398:11;59344:66;;;;;;;;;;:::i;:::-;;;;;;;;58784:634;58651:767;;;;;;:::o;119893:329::-;120078:24;;;120089:10;120078:24;;;25619:51:1;120015:14:0;25686:18:1;;;25679:45;;;120078:24:0;;;;;;;;;25592:18:1;;;120078:24:0;;;;-1:-1:-1;;;120120:94:0;;;120015:14;;;120120:10;-1:-1:-1;;;;;120120:23:0;;;;:94;;120144:11;;120173:4;;120078:24;;120190:7;;120199:14;;120120:94;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;120113:101;;;;;119893:329;;;;;;:::o;50081:284::-;16201:13;:11;:13::i;:::-;50205:1:::1;50195:7;:11;50187:45;;;::::0;-1:-1:-1;;;50187:45:0;;36756:2:1;50187:45:0::1;::::0;::::1;36738:21:1::0;36795:2;36775:18;;;36768:30;-1:-1:-1;;;36814:18:1;;;36807:51;36875:18;;50187:45:0::1;36554:345:1::0;50187:45:0::1;50243:28;::::0;;::::1;;::::0;;;:15:::1;:28;::::0;;;;;;;:41;;::::1;::::0;;;;;;;;;;:51;;;50310:47;;37127:34:1;;;37177:18;;37170:43;;;;37229:18;;;37222:34;;;50310:47:0::1;::::0;37090:2:1;37075:18;50310:47:0::1;36904:358:1::0;104127:164:0;-1:-1:-1;;;;;104248:25:0;;;104224:4;104248:25;;;:18;:25;;;;;;;;:35;;;;;;;;;;;;;;;104127:164::o;49095:207::-;16201:13;:11;:13::i;:::-;49196:35:::1;::::0;::::1;;::::0;;;:19:::1;:35;::::0;;;;:43:::1;49234:5:::0;;49196:35;:43:::1;:::i;:::-;;49255:39;49272:14;49288:5;;49255:39;;;;;;;;:::i;65028:388::-:0;65209:14;65225:11;65249:20;65283:10;65295:9;65272:33;;;;;;;;;:::i;:::-;;;;-1:-1:-1;;65272:33:0;;;;;;;;;;-1:-1:-1;;;65323:85:0;;65272:33;-1:-1:-1;;;;;;65323:10:0;:23;;;;:85;;65347:11;;65368:4;;65272:33;;65384:7;;65393:14;;65323:85;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;65316:92;;;;;65028:388;;;;;;;;:::o;17214:201::-;16201:13;:11;:13::i;:::-;-1:-1:-1;;;;;17303:22:0;::::1;17295:73;;;::::0;-1:-1:-1;;;17295:73:0;;40190:2:1;17295:73:0::1;::::0;::::1;40172:21:1::0;40229:2;40209:18;;;40202:30;40268:34;40248:18;;;40241:62;-1:-1:-1;;;40319:18:1;;;40312:36;40365:19;;17295:73:0::1;39988:402:1::0;17295:73:0::1;17379:28;17398:8;17379:18;:28::i;48017:211::-:0;48152:68;;-1:-1:-1;;;48152:68:0;;40632:6:1;40665:15;;;48152:68:0;;;40647:34:1;40717:15;;40697:18;;;40690:43;48201:4:0;40749:18:1;;;40742:60;40818:18;;;40811:34;;;48120:12:0;;48152:10;-1:-1:-1;;;;;48152:20:0;;;;40594:19:1;;48152:68:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;48152:68:0;;;;;;;;;;;;:::i;:::-;48145:75;;48017:211;;;;;;;:::o;57266:514::-;57416:12;57430:19;57453:153;57487:9;57498:3;57526:34;;;57562:11;57575;57588:6;57596:8;57503:102;;;;;;;;;;;:::i;:::-;;;;-1:-1:-1;;57503:102:0;;;;;;;;;;;;;;-1:-1:-1;;;;;57503:102:0;-1:-1:-1;;;;;;57503:102:0;;;;;;;;;;57461:4;;57453:153;;:33;:153::i;:::-;57415:191;;;;57666:7;57661:112;;57690:71;57710:11;57723;57736:6;57744:8;57754:6;57690:19;:71::i;101218:305::-;101320:4;-1:-1:-1;;;;;;101357:40:0;;-1:-1:-1;;;101357:40:0;;:105;;-1:-1:-1;;;;;;;101414:48:0;;-1:-1:-1;;;101414:48:0;101357:105;:158;;;;101479:36;101503:11;101479:23;:36::i;16480:132::-;16361:7;16388:6;-1:-1:-1;;;;;16388:6:0;15104:10;16544:23;16536:68;;;;-1:-1:-1;;;16536:68:0;;41960:2:1;16536:68:0;;;41942:21:1;;;41979:18;;;41972:30;42038:34;42018:18;;;42011:62;42090:18;;16536:68:0;41758:356:1;113221:135:0;113303:16;113311:7;113303;:16::i;:::-;113295:53;;;;-1:-1:-1;;;113295:53:0;;25937:2:1;113295:53:0;;;25919:21:1;25976:2;25956:18;;;25949:30;-1:-1:-1;;;25995:18:1;;;25988:54;26059:18;;113295:53:0;25735:348:1;112534:174:0;112609:24;;;;:15;:24;;;;;:29;;-1:-1:-1;;;;;;112609:29:0;-1:-1:-1;;;;;112609:29:0;;;;;;;;:24;;112663:23;112609:24;112663:14;:23::i;:::-;-1:-1:-1;;;;;112654:46:0;;;;;;;;;;;112534:174;;:::o;107827:110::-;107903:26;107913:2;107917:7;107903:26;;;;;;;;;;;;:9;:26::i;107221:264::-;107314:4;107331:13;107347:23;107362:7;107347:14;:23::i;:::-;107331:39;;107400:5;-1:-1:-1;;;;;107389:16:0;:7;-1:-1:-1;;;;;107389:16:0;;:52;;;;107409:32;107426:5;107433:7;107409:16;:32::i;:::-;107389:87;;;;107469:7;-1:-1:-1;;;;;107445:31:0;:20;107457:7;107445:11;:20::i;:::-;-1:-1:-1;;;;;107445:31:0;;107381:96;107221:264;-1:-1:-1;;;;107221:264:0:o;111186:1229::-;111311:4;-1:-1:-1;;;;;111284:31:0;:23;111299:7;111284:14;:23::i;:::-;-1:-1:-1;;;;;111284:31:0;;111276:81;;;;-1:-1:-1;;;111276:81:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;111376:16:0;;111368:65;;;;-1:-1:-1;;;111368:65:0;;42727:2:1;111368:65:0;;;42709:21:1;42766:2;42746:18;;;42739:30;42805:34;42785:18;;;42778:62;-1:-1:-1;;;42856:18:1;;;42849:34;42900:19;;111368:65:0;42525:400:1;111368:65:0;111618:4;-1:-1:-1;;;;;111591:31:0;:23;111606:7;111591:14;:23::i;:::-;-1:-1:-1;;;;;111591:31:0;;111583:81;;;;-1:-1:-1;;;111583:81:0;;;;;;;:::i;:::-;111736:24;;;;:15;:24;;;;;;;;111729:31;;-1:-1:-1;;;;;;111729:31:0;;;;;;-1:-1:-1;;;;;112212:15:0;;;;;;:9;:15;;;;;:20;;-1:-1:-1;;112212:20:0;;;112247:13;;;;;;;;;:18;;111729:31;112247:18;;;112287:16;;;:7;:16;;;;;;:21;;;;;;;;;;112326:27;;111752:7;;112326:27;;;103246:346;103176:416;;:::o;71455:185::-;71567:13;;;71578:1;71567:13;;;;;;;;;71519;;71545:19;;71567:13;;;;;;;;;;;;-1:-1:-1;71567:13:0;71545:35;;71602:7;71591:5;71597:1;71591:8;;;;;;;;:::i;:::-;;;;;;;;;;:18;71627:5;71455:185;-1:-1:-1;;71455:185:0:o;46816:420::-;46952:21;46976:28;46989:14;46976:12;:28::i;:::-;47034;;;;47015:16;47034:28;;;:15;:28;;;;;;;;:35;;;;;;;;;;;;46952:52;;-1:-1:-1;47015:16:0;47034:47;;47072:9;;47034:47;:::i;:::-;47015:66;;47114:1;47100:11;:15;47092:54;;;;-1:-1:-1;;;47092:54:0;;43394:2:1;47092:54:0;;;43376:21:1;43433:2;43413:18;;;43406:30;43472:28;43452:18;;;43445:56;43518:18;;47092:54:0;43192:350:1;47092:54:0;47185:11;47165:16;:31;;47157:71;;;;-1:-1:-1;;;47157:71:0;;43749:2:1;47157:71:0;;;43731:21:1;43788:2;43768:18;;;43761:30;43827:29;43807:18;;;43800:57;43874:18;;47157:71:0;43547:351:1;46255:553:0;46478:32;;;46449:26;46478:32;;;:19;:32;;;;;46449:61;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;46529:13;:20;46553:1;46529:25;46521:86;;;;-1:-1:-1;;;46521:86:0;;44105:2:1;46521:86:0;;;44087:21:1;44144:2;44124:18;;;44117:30;44183:34;44163:18;;;44156:62;-1:-1:-1;;;44234:18:1;;;44227:46;44290:19;;46521:86:0;43903:412:1;46521:86:0;46618:47;46636:11;46649:8;:15;46618:17;:47::i;:::-;46676:124;;-1:-1:-1;;;46676:124:0;;-1:-1:-1;;;;;46676:10:0;:15;;;;46699:10;;46676:124;;46711:11;;46724:13;;46739:8;;46749:14;;46765:18;;46785:14;;46676:124;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;46438:370;46255:553;;;;;;:::o;66139:960::-;66414:1;66395:9;:16;:20;66387:52;;;;-1:-1:-1;;;66387:52:0;;45367:2:1;66387:52:0;;;45349:21:1;45406:2;45386:18;;;45379:30;-1:-1:-1;;;45425:18:1;;;45418:49;45484:18;;66387:52:0;45165:343:1;66387:52:0;66458:9;:16;66478:1;66458:21;:80;;;-1:-1:-1;66503:35:0;;;;;;;:22;:35;;;;;;66483:16;;:55;;66458:80;66450:127;;;;-1:-1:-1;;;66450:127:0;;45715:2:1;66450:127:0;;;45697:21:1;45754:2;45734:18;;;45727:30;45793:34;45773:18;;;45766:62;-1:-1:-1;;;45844:18:1;;;45837:32;45886:19;;66450:127:0;45513:398:1;66450:127:0;66595:6;66590:127;66611:9;:16;66607:1;:20;66590:127;;;66649:56;66660:5;66667:11;66680:10;66692:9;66702:1;66692:12;;;;;;;;:::i;:::-;;;;;;;66649:10;:56::i;:::-;66629:3;;;;:::i;:::-;;;;66590:127;;;;66729:20;66763:10;66775:9;66752:33;;;;;;;;;:::i;:::-;;;;;;;;;;;;;66729:56;;66798:120;66813:11;63642:1;66846:14;66901:9;:16;66862:23;:36;66886:11;66862:36;;;;;;;;;;;;;;;;:55;;;;:::i;:::-;66798:14;:120::i;:::-;66929:92;66937:11;66950:7;66959:14;66975:18;66995:14;67011:9;66929:7;:92::i;:::-;67069:10;67037:54;;;;;;:::i;:::-;;;;;;;;67062:5;-1:-1:-1;;;;;67037:54:0;67049:11;67037:54;;;67081:9;67037:54;;;;;;:::i;:::-;;;;;;;;66345:754;66139:960;;;;;;;:::o;67107:1037::-;67349:27;67378:22;67415:8;67404:37;;;;;;;;;;;;:::i;:::-;67348:93;;;;67457:8;67466:1;67457:11;;;;;;;;:::i;:::-;;;;;;;67470:1;67457:14;67454:51;;67487:7;;;;67454:51;67606:2;67586:23;;67580:30;67515:17;67650:48;67662:11;67580:30;67515:17;67689:8;67650:11;:48::i;:::-;67633:65;;67725:8;:15;67713:9;:27;67709:347;;;67869:19;;;;;;;;;;67934:53;;;;;;;;;;;;;;-1:-1:-1;;;;;67934:53:0;;;;;;;;;;;;;;;67982:4;67934:53;;;;;;67845:21;67903:28;;;:13;:28;;;;;;;:84;;;;;;;;;;;-1:-1:-1;;;;;;67903:84:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;67903:84:0;;;;;;;;;;68007:37;;;;;;67869:19;;67879:8;;68007:37;:::i;:::-;;;;;;;;67742:314;67709:347;68116:9;-1:-1:-1;;;;;68073:63:0;68103:11;68073:63;;;;;;:::i;:::-;;;;;;;;68090:11;68073:63;;;68127:8;68073:63;;;;;;:::i;17575:191::-;17649:16;17668:6;;-1:-1:-1;;;;;17685:17:0;;;-1:-1:-1;;;;;;17685:17:0;;;;;;17718:40;;17668:6;;;;;;;17718:40;;17649:16;17718:40;17638:128;17575:191;:::o;62687:293::-;62089:1;62821:7;;:19;62813:63;;;;-1:-1:-1;;;62813:63:0;;47143:2:1;62813:63:0;;;47125:21:1;47182:2;47162:18;;;47155:30;47221:33;47201:18;;;47194:61;47272:18;;62813:63:0;46941:355:1;62813:63:0;62089:1;62954:7;:18;62687:293::o;69450:574::-;69572:7;69600:11;69622:263;69633:9;:16;69629:1;:20;69622:263;;;69759:24;;69747:9;:36;69785:5;69743:47;69807:48;69817:11;69830:10;69842:9;69852:1;69842:12;;;;;;;;:::i;:::-;;;;;;;69807:9;:48::i;:::-;69870:3;;;;:::i;:::-;;;;69622:263;;34324:2779;34465:12;34519:7;34503:12;34519:7;34513:2;34503:12;:::i;:::-;:23;;34495:50;;;;-1:-1:-1;;;34495:50:0;;47503:2:1;34495:50:0;;;47485:21:1;47542:2;47522:18;;;47515:30;-1:-1:-1;;;47561:18:1;;;47554:44;47615:18;;34495:50:0;47301:338:1;34495:50:0;34581:16;34590:7;34581:6;:16;:::i;:::-;34564:6;:13;:33;;34556:63;;;;-1:-1:-1;;;34556:63:0;;47846:2:1;34556:63:0;;;47828:21:1;47885:2;47865:18;;;47858:30;-1:-1:-1;;;47904:18:1;;;47897:47;47961:18;;34556:63:0;47644:341:1;34556:63:0;34632:22;34698:15;;34727:1933;;;;36804:4;36798:11;36785:24;;36985:1;36974:9;36967:20;37035:4;37024:9;37020:20;37014:4;37007:34;34691:2365;;34727:1933;34904:4;34898:11;34885:24;;35541:2;35532:7;35528:16;35913:9;35906:17;35900:4;35896:28;35884:9;35873;35869:25;35865:60;35962:7;35958:2;35954:16;36211:6;36197:9;36190:17;36184:4;36180:28;36168:9;36160:6;36156:22;36152:57;36148:70;35990:426;36245:3;36241:2;36238:11;35990:426;;;36387:9;;36376:21;;36287:4;36279:13;;;;36320;35990:426;;;-1:-1:-1;;36436:26:0;;;36640:2;36623:11;-1:-1:-1;;36619:25:0;36613:4;36606:39;-1:-1:-1;34691:2365:0;-1:-1:-1;37086:9:0;34324:2779;-1:-1:-1;;;;34324:2779:0:o;112851:281::-;112972:8;-1:-1:-1;;;;;112963:17:0;:5;-1:-1:-1;;;;;112963:17:0;;112955:55;;;;-1:-1:-1;;;112955:55:0;;48192:2:1;112955:55:0;;;48174:21:1;48231:2;48211:18;;;48204:30;48270:27;48250:18;;;48243:55;48315:18;;112955:55:0;47990:349:1;112955:55:0;-1:-1:-1;;;;;113021:25:0;;;;;;;:18;:25;;;;;;;;:35;;;;;;;;;;;;;:46;;-1:-1:-1;;113021:46:0;;;;;;;;;;113083:41;;2118::1;;;113083::0;;2091:18:1;113083:41:0;;;;;;;112851:281;;;:::o;106112:270::-;106225:28;106235:4;106241:2;106245:7;106225:9;:28::i;:::-;106272:47;106295:4;106301:2;106305:7;106314:4;106272:22;:47::i;:::-;106264:110;;;;-1:-1:-1;;;106264:110:0;;;;;;;:::i;120771:130::-;120823:13;120849:44;;;;;;;;;;;;;;;;;;;120771:130;:::o;97589:716::-;97645:13;97696:14;97713:17;97724:5;97713:10;:17::i;:::-;97733:1;97713:21;97696:38;;97749:20;97783:6;-1:-1:-1;;;;;97772:18:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;97772:18:0;-1:-1:-1;97749:41:0;-1:-1:-1;97914:28:0;;;97930:2;97914:28;97971:288;-1:-1:-1;;98003:5:0;-1:-1:-1;;;98140:2:0;98129:14;;98124:30;98003:5;98111:44;98201:2;98192:11;;;-1:-1:-1;98222:21:0;97971:288;98222:21;-1:-1:-1;98280:6:0;97589:716;-1:-1:-1;;;97589:716:0:o;51989:1275::-;52151:4;52157:12;52219:15;52245:13;52269:24;52306:8;52296:19;;-1:-1:-1;;;;;52296:19:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;52296:19:0;;52269:46;;52797:1;52771;52737:9;52731:16;52702:4;52691:9;52687:20;52656:1;52621:7;52595:4;52576:247;52564:259;;52888:16;52877:27;;52933:8;52924:7;52921:21;52918:78;;;52973:8;52962:19;;52918:78;53079:7;53066:11;53059:28;53197:7;53194:1;53187:4;53174:11;53170:22;53155:50;53234:8;;;;-1:-1:-1;51989:1275:0;-1:-1:-1;;;;;;51989:1275:0:o;57788:323::-;58012:8;58002:19;;;;;;57951:14;:27;57966:11;57951:27;;;;;;;;;;;;;;;57979:11;57951:40;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;57951:48:0;;;;;;;;;:70;;;;58037:66;;;;58051:11;;58064;;57992:6;;58085:8;;58095:7;;58037:66;:::i;:::-;;;;;;;;57788:323;;;;;:::o;64473:219::-;64575:4;-1:-1:-1;;;;;;64599:45:0;;-1:-1:-1;;;64599:45:0;;:85;;-1:-1:-1;;;;;;;;;;60301:40:0;;;64648:36;60192:157;106926:128;106991:4;106589:16;;;:7;:16;;;;;;-1:-1:-1;;;;;106589:16:0;107015:31;;;106926:128::o;108164:285::-;108259:18;108265:2;108269:7;108259:5;:18::i;:::-;108310:53;108341:1;108345:2;108349:7;108358:4;108310:22;:53::i;:::-;108288:153;;;;-1:-1:-1;;;108288:153:0;;;;;;;:::i;47244:271::-;47326:13;47385:2;47360:14;:21;:27;;47352:68;;;;-1:-1:-1;;;47352:68:0;;49821:2:1;47352:68:0;;;49803:21:1;49860:2;49840:18;;;49833:30;49899;49879:18;;;49872:58;49947:18;;47352:68:0;49619:352:1;47352:68:0;-1:-1:-1;47493:2:0;47473:23;47467:30;;47244:271::o;47523:389::-;47646:35;;;47622:21;47646:35;;;:22;:35;;;;;;;47696:21;;;47692:125;;-1:-1:-1;44549:5:0;47692:125;47851:16;47835:12;:32;;47827:77;;;;-1:-1:-1;;;47827:77:0;;50178:2:1;47827:77:0;;;50160:21:1;;;50197:18;;;50190:30;50256:34;50236:18;;;50229:62;50308:18;;47827:77:0;49976:356:1;117662:361:0;117779:42;15104:10;117798:12;15024:98;117779:42;117771:101;;;;-1:-1:-1;;;117771:101:0;;50539:2:1;117771:101:0;;;50521:21:1;50578:2;50558:18;;;50551:30;50617:34;50597:18;;;50590:62;-1:-1:-1;;;50668:18:1;;;50661:44;50722:19;;117771:101:0;50337:410:1;117771:101:0;117919:5;-1:-1:-1;;;;;117891:33:0;:24;117906:8;117891:14;:24::i;:::-;-1:-1:-1;;;;;117891:33:0;;117883:80;;;;-1:-1:-1;;;117883:80:0;;50954:2:1;117883:80:0;;;50936:21:1;50993:2;50973:18;;;50966:30;51032:34;51012:18;;;51005:62;-1:-1:-1;;;51083:18:1;;;51076:32;51125:19;;117883:80:0;50752:398:1;117883:80:0;117974:41;117984:5;117999:4;118006:8;117974:9;:41::i;118031:373::-;118139:17;118147:8;118139:7;:17::i;:::-;118138:18;:86;;;;118161:17;118169:8;118161:7;:17::i;:::-;:62;;;;-1:-1:-1;118218:4:0;118182:24;118197:8;118182:14;:24::i;:::-;-1:-1:-1;;;;;118182:41:0;;118161:62;118130:95;;;;;;118241:17;118249:8;118241:7;:17::i;:::-;118236:161;;118275:31;118285:10;118297:8;118275:9;:31::i;118236:161::-;118339:46;118357:4;118364:10;118376:8;118339:9;:46::i;113920:853::-;114074:4;-1:-1:-1;;;;;114095:13:0;;75068:19;:23;114091:675;;114131:71;;-1:-1:-1;;;114131:71:0;;-1:-1:-1;;;;;114131:36:0;;;;;:71;;15104:10;;114182:4;;114188:7;;114197:4;;114131:71;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;-1:-1:-1;114131:71:0;;;;;;;;-1:-1:-1;;114131:71:0;;;;;;;;;;;;:::i;:::-;;;114127:584;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;114372:6;:13;114389:1;114372:18;114368:328;;114415:60;;-1:-1:-1;;;114415:60:0;;;;;;;:::i;114368:328::-;114646:6;114640:13;114631:6;114627:2;114623:15;114616:38;114127:584;-1:-1:-1;;;;;;114253:51:0;-1:-1:-1;;;114253:51:0;;-1:-1:-1;114246:58:0;;114091:675;-1:-1:-1;114750:4:0;114743:11;;93333:948;93386:7;;-1:-1:-1;;;93464:17:0;;93460:106;;-1:-1:-1;;;93502:17:0;;;-1:-1:-1;93548:2:0;93538:12;93460:106;93593:8;93584:5;:17;93580:106;;93631:8;93622:17;;;-1:-1:-1;93668:2:0;93658:12;93580:106;93713:8;93704:5;:17;93700:106;;93751:8;93742:17;;;-1:-1:-1;93788:2:0;93778:12;93700:106;93833:7;93824:5;:16;93820:103;;93870:7;93861:16;;;-1:-1:-1;93906:1:0;93896:11;93820:103;93950:7;93941:5;:16;93937:103;;93987:7;93978:16;;;-1:-1:-1;94023:1:0;94013:11;93937:103;94067:7;94058:5;:16;94054:103;;94104:7;94095:16;;;-1:-1:-1;94140:1:0;94130:11;94054:103;94184:7;94175:5;:16;94171:68;;94222:1;94212:11;94267:6;93333:948;-1:-1:-1;;93333:948:0:o;108785:942::-;-1:-1:-1;;;;;108865:16:0;;108857:61;;;;-1:-1:-1;;;108857:61:0;;52105:2:1;108857:61:0;;;52087:21:1;;;52124:18;;;52117:30;52183:34;52163:18;;;52156:62;52235:18;;108857:61:0;51903:356:1;108857:61:0;108938:16;108946:7;108938;:16::i;:::-;108937:17;108929:58;;;;-1:-1:-1;;;108929:58:0;;52466:2:1;108929:58:0;;;52448:21:1;52505:2;52485:18;;;52478:30;52544;52524:18;;;52517:58;52592:18;;108929:58:0;52264:352:1;108929:58:0;109147:16;109155:7;109147;:16::i;:::-;109146:17;109138:58;;;;-1:-1:-1;;;109138:58:0;;52466:2:1;109138:58:0;;;52448:21:1;52505:2;52485:18;;;52478:30;52544;52524:18;;;52517:58;52592:18;;109138:58:0;52264:352:1;109138:58:0;-1:-1:-1;;;;;109545:13:0;;;;;;:9;:13;;;;;;;;:18;;109562:1;109545:18;;;109587:16;;;:7;:16;;;;;;:21;;-1:-1:-1;;;;;;109587:21:0;;;;;109626:33;109595:7;;109545:13;;109626:33;;109545:13;;109626:33;103901:155;;:::o;14:117:1:-;99:6;92:5;88:18;81:5;78:29;68:57;;121:1;118;111:12;136:347;187:8;197:6;251:3;244:4;236:6;232:17;228:27;218:55;;269:1;266;259:12;218:55;-1:-1:-1;292:20:1;;-1:-1:-1;;;;;324:30:1;;321:50;;;367:1;364;357:12;321:50;404:4;396:6;392:17;380:29;;456:3;449:4;440:6;432;428:19;424:30;421:39;418:59;;;473:1;470;463:12;418:59;136:347;;;;;:::o;488:171::-;555:20;;-1:-1:-1;;;;;604:30:1;;594:41;;584:69;;649:1;646;639:12;584:69;488:171;;;:::o;664:923::-;770:6;778;786;794;802;810;863:3;851:9;842:7;838:23;834:33;831:53;;;880:1;877;870:12;831:53;919:9;906:23;938:30;962:5;938:30;:::i;:::-;987:5;-1:-1:-1;1043:2:1;1028:18;;1015:32;-1:-1:-1;;;;;1096:14:1;;;1093:34;;;1123:1;1120;1113:12;1093:34;1162:58;1212:7;1203:6;1192:9;1188:22;1162:58;:::i;:::-;1239:8;;-1:-1:-1;1136:84:1;-1:-1:-1;1136:84:1;;-1:-1:-1;1293:37:1;1326:2;1311:18;;1293:37;:::i;:::-;1283:47;;1383:2;1372:9;1368:18;1355:32;1339:48;;1412:2;1402:8;1399:16;1396:36;;;1428:1;1425;1418:12;1396:36;;1467:60;1519:7;1508:8;1497:9;1493:24;1467:60;:::i;:::-;664:923;;;;-1:-1:-1;664:923:1;;-1:-1:-1;664:923:1;;1546:8;;664:923;-1:-1:-1;;;664:923:1:o;1592:131::-;-1:-1:-1;;;;;;1666:32:1;;1656:43;;1646:71;;1713:1;1710;1703:12;1728:245;1786:6;1839:2;1827:9;1818:7;1814:23;1810:32;1807:52;;;1855:1;1852;1845:12;1807:52;1894:9;1881:23;1913:30;1937:5;1913:30;:::i;2170:250::-;2255:1;2265:113;2279:6;2276:1;2273:13;2265:113;;;2355:11;;;2349:18;2336:11;;;2329:39;2301:2;2294:10;2265:113;;;-1:-1:-1;;2412:1:1;2394:16;;2387:27;2170:250::o;2425:271::-;2467:3;2505:5;2499:12;2532:6;2527:3;2520:19;2548:76;2617:6;2610:4;2605:3;2601:14;2594:4;2587:5;2583:16;2548:76;:::i;:::-;2678:2;2657:15;-1:-1:-1;;2653:29:1;2644:39;;;;2685:4;2640:50;;2425:271;-1:-1:-1;;2425:271:1:o;2701:220::-;2850:2;2839:9;2832:21;2813:4;2870:45;2911:2;2900:9;2896:18;2888:6;2870:45;:::i;2926:245::-;2984:6;3037:2;3025:9;3016:7;3012:23;3008:32;3005:52;;;3053:1;3050;3043:12;3005:52;3092:9;3079:23;3111:30;3135:5;3111:30;:::i;3176:180::-;3235:6;3288:2;3276:9;3267:7;3263:23;3259:32;3256:52;;;3304:1;3301;3294:12;3256:52;-1:-1:-1;3327:23:1;;3176:180;-1:-1:-1;3176:180:1:o;3569:131::-;-1:-1:-1;;;;;3644:31:1;;3634:42;;3624:70;;3690:1;3687;3680:12;3705:134;3773:20;;3802:31;3773:20;3802:31;:::i;3844:315::-;3912:6;3920;3973:2;3961:9;3952:7;3948:23;3944:32;3941:52;;;3989:1;3986;3979:12;3941:52;4028:9;4015:23;4047:31;4072:5;4047:31;:::i;:::-;4097:5;4149:2;4134:18;;;;4121:32;;-1:-1:-1;;;3844:315:1:o;4164:313::-;4231:6;4239;4292:2;4280:9;4271:7;4267:23;4263:32;4260:52;;;4308:1;4305;4298:12;4260:52;4347:9;4334:23;4366:30;4390:5;4366:30;:::i;5110:456::-;5187:6;5195;5203;5256:2;5244:9;5235:7;5231:23;5227:32;5224:52;;;5272:1;5269;5262:12;5224:52;5311:9;5298:23;5330:31;5355:5;5330:31;:::i;:::-;5380:5;-1:-1:-1;5437:2:1;5422:18;;5409:32;5450:33;5409:32;5450:33;:::i;:::-;5110:456;;5502:7;;-1:-1:-1;;;5556:2:1;5541:18;;;;5528:32;;5110:456::o;5571:127::-;5632:10;5627:3;5623:20;5620:1;5613:31;5663:4;5660:1;5653:15;5687:4;5684:1;5677:15;5703:275;5774:2;5768:9;5839:2;5820:13;;-1:-1:-1;;5816:27:1;5804:40;;-1:-1:-1;;;;;5859:34:1;;5895:22;;;5856:62;5853:88;;;5921:18;;:::i;:::-;5957:2;5950:22;5703:275;;-1:-1:-1;5703:275:1:o;5983:186::-;6031:4;-1:-1:-1;;;;;6056:6:1;6053:30;6050:56;;;6086:18;;:::i;:::-;-1:-1:-1;6152:2:1;6131:15;-1:-1:-1;;6127:29:1;6158:4;6123:40;;5983:186::o;6174:462::-;6216:5;6269:3;6262:4;6254:6;6250:17;6246:27;6236:55;;6287:1;6284;6277:12;6236:55;6323:6;6310:20;6354:48;6370:31;6398:2;6370:31;:::i;:::-;6354:48;:::i;:::-;6427:2;6418:7;6411:19;6473:3;6466:4;6461:2;6453:6;6449:15;6445:26;6442:35;6439:55;;;6490:1;6487;6480:12;6439:55;6555:2;6548:4;6540:6;6536:17;6529:4;6520:7;6516:18;6503:55;6603:1;6578:16;;;6596:4;6574:27;6567:38;;;;6582:7;6174:462;-1:-1:-1;;;6174:462:1:o;6641:160::-;6706:20;;6762:13;;6755:21;6745:32;;6735:60;;6791:1;6788;6781:12;6806:810;6915:6;6923;6931;6939;6947;7000:3;6988:9;6979:7;6975:23;6971:33;6968:53;;;7017:1;7014;7007:12;6968:53;7056:9;7043:23;7075:30;7099:5;7075:30;:::i;:::-;7124:5;-1:-1:-1;7180:2:1;7165:18;;7152:32;-1:-1:-1;;;;;7233:14:1;;;7230:34;;;7260:1;7257;7250:12;7230:34;7283:49;7324:7;7315:6;7304:9;7300:22;7283:49;:::i;:::-;7273:59;;7379:2;7368:9;7364:18;7351:32;7341:42;;7402:35;7433:2;7422:9;7418:18;7402:35;:::i;:::-;7392:45;;7490:3;7479:9;7475:19;7462:33;7446:49;;7520:2;7510:8;7507:16;7504:36;;;7536:1;7533;7526:12;7504:36;;7559:51;7602:7;7591:8;7580:9;7576:24;7559:51;:::i;:::-;7549:61;;;6806:810;;;;;;;;:::o;7874:542::-;7952:6;7960;7968;8021:2;8009:9;8000:7;7996:23;7992:32;7989:52;;;8037:1;8034;8027:12;7989:52;8076:9;8063:23;8095:30;8119:5;8095:30;:::i;:::-;8144:5;-1:-1:-1;8200:2:1;8185:18;;8172:32;-1:-1:-1;;;;;8216:30:1;;8213:50;;;8259:1;8256;8249:12;8213:50;8298:58;8348:7;8339:6;8328:9;8324:22;8298:58;:::i;:::-;7874:542;;8375:8;;-1:-1:-1;8272:84:1;;-1:-1:-1;;;;7874:542:1:o;8603:386::-;8670:6;8678;8731:2;8719:9;8710:7;8706:23;8702:32;8699:52;;;8747:1;8744;8737:12;8699:52;8786:9;8773:23;8805:30;8829:5;8805:30;:::i;:::-;8854:5;-1:-1:-1;8911:2:1;8896:18;;8883:32;8924:33;8883:32;8924:33;:::i;:::-;8976:7;8966:17;;;8603:386;;;;;:::o;8994:594::-;9079:6;9087;9095;9148:2;9136:9;9127:7;9123:23;9119:32;9116:52;;;9164:1;9161;9154:12;9116:52;9203:9;9190:23;9222:30;9246:5;9222:30;:::i;:::-;9271:5;-1:-1:-1;9328:2:1;9313:18;;9300:32;9341:33;9300:32;9341:33;:::i;:::-;9393:7;-1:-1:-1;9451:2:1;9436:18;;9423:32;-1:-1:-1;;;;;9467:30:1;;9464:50;;;9510:1;9507;9500:12;9464:50;9533:49;9574:7;9565:6;9554:9;9550:22;9533:49;:::i;:::-;9523:59;;;8994:594;;;;;:::o;9593:1175::-;9731:6;9739;9747;9755;9763;9771;9779;9832:3;9820:9;9811:7;9807:23;9803:33;9800:53;;;9849:1;9846;9839:12;9800:53;9888:9;9875:23;9907:31;9932:5;9907:31;:::i;:::-;9957:5;-1:-1:-1;10014:2:1;9999:18;;9986:32;10027;9986;10027;:::i;:::-;10078:7;-1:-1:-1;10136:2:1;10121:18;;10108:32;-1:-1:-1;;;;;10189:14:1;;;10186:34;;;10216:1;10213;10206:12;10186:34;10239:49;10280:7;10271:6;10260:9;10256:22;10239:49;:::i;:::-;10229:59;;10335:2;10324:9;10320:18;10307:32;10297:42;;10391:3;10380:9;10376:19;10363:33;10348:48;;10405:33;10430:7;10405:33;:::i;:::-;10457:7;;-1:-1:-1;10516:3:1;10501:19;;10488:33;;10530;10488;10530;:::i;:::-;10582:7;;-1:-1:-1;10642:3:1;10627:19;;10614:33;;10659:16;;;10656:36;;;10688:1;10685;10678:12;10656:36;;10711:51;10754:7;10743:8;10732:9;10728:24;10711:51;:::i;:::-;10701:61;;;9593:1175;;;;;;;;;;:::o;10773:525::-;10857:6;10865;10873;10926:2;10914:9;10905:7;10901:23;10897:32;10894:52;;;10942:1;10939;10932:12;10894:52;10981:9;10968:23;11000:30;11024:5;11000:30;:::i;:::-;11049:5;-1:-1:-1;11105:2:1;11090:18;;11077:32;-1:-1:-1;;;;;11121:30:1;;11118:50;;;11164:1;11161;11154:12;11118:50;11187:49;11228:7;11219:6;11208:9;11204:22;11187:49;:::i;:::-;11177:59;;;11255:37;11288:2;11277:9;11273:18;11255:37;:::i;:::-;11245:47;;10773:525;;;;;:::o;11485:247::-;11544:6;11597:2;11585:9;11576:7;11572:23;11568:32;11565:52;;;11613:1;11610;11603:12;11565:52;11652:9;11639:23;11671:31;11696:5;11671:31;:::i;11960:384::-;12026:6;12034;12087:2;12075:9;12066:7;12062:23;12058:32;12055:52;;;12103:1;12100;12093:12;12055:52;12142:9;12129:23;12161:30;12185:5;12161:30;:::i;:::-;12210:5;-1:-1:-1;12267:2:1;12252:18;;12239:32;12280;12239;12280;:::i;12349:320::-;12417:6;12470:2;12458:9;12449:7;12445:23;12441:32;12438:52;;;12486:1;12483;12476:12;12438:52;12526:9;12513:23;-1:-1:-1;;;;;12551:6:1;12548:30;12545:50;;;12591:1;12588;12581:12;12545:50;12614:49;12655:7;12646:6;12635:9;12631:22;12614:49;:::i;12674:315::-;12739:6;12747;12800:2;12788:9;12779:7;12775:23;12771:32;12768:52;;;12816:1;12813;12806:12;12768:52;12855:9;12842:23;12874:31;12899:5;12874:31;:::i;:::-;12924:5;-1:-1:-1;12948:35:1;12979:2;12964:18;;12948:35;:::i;:::-;12938:45;;12674:315;;;;;:::o;12994:183::-;13054:4;-1:-1:-1;;;;;13079:6:1;13076:30;13073:56;;;13109:18;;:::i;:::-;-1:-1:-1;13154:1:1;13150:14;13166:4;13146:25;;12994:183::o;13182:662::-;13236:5;13289:3;13282:4;13274:6;13270:17;13266:27;13256:55;;13307:1;13304;13297:12;13256:55;13343:6;13330:20;13369:4;13393:60;13409:43;13449:2;13409:43;:::i;13393:60::-;13487:15;;;13573:1;13569:10;;;;13557:23;;13553:32;;;13518:12;;;;13597:15;;;13594:35;;;13625:1;13622;13615:12;13594:35;13661:2;13653:6;13649:15;13673:142;13689:6;13684:3;13681:15;13673:142;;;13755:17;;13743:30;;13793:12;;;;13706;;13673:142;;;-1:-1:-1;13833:5:1;13182:662;-1:-1:-1;;;;;;13182:662:1:o;13849:1199::-;14012:6;14020;14028;14036;14044;14052;14060;14113:3;14101:9;14092:7;14088:23;14084:33;14081:53;;;14130:1;14127;14120:12;14081:53;14169:9;14156:23;14188:31;14213:5;14188:31;:::i;:::-;14238:5;-1:-1:-1;14295:2:1;14280:18;;14267:32;14308;14267;14308;:::i;:::-;14359:7;-1:-1:-1;14417:2:1;14402:18;;14389:32;-1:-1:-1;;;;;14470:14:1;;;14467:34;;;14497:1;14494;14487:12;14467:34;14520:49;14561:7;14552:6;14541:9;14537:22;14520:49;:::i;:::-;14510:59;;14622:2;14611:9;14607:18;14594:32;14578:48;;14651:2;14641:8;14638:16;14635:36;;;14667:1;14664;14657:12;14635:36;14690:63;14745:7;14734:8;14723:9;14719:24;14690:63;:::i;:::-;14680:73;;14772:39;14806:3;14795:9;14791:19;14772:39;:::i;:::-;14762:49;;14830:39;14864:3;14853:9;14849:19;14830:39;:::i;:::-;14820:49;;14922:3;14911:9;14907:19;14894:33;14878:49;;14952:2;14942:8;14939:16;14936:36;;;14968:1;14965;14958:12;15480:665;15575:6;15583;15591;15599;15652:3;15640:9;15631:7;15627:23;15623:33;15620:53;;;15669:1;15666;15659:12;15620:53;15708:9;15695:23;15727:31;15752:5;15727:31;:::i;:::-;15777:5;-1:-1:-1;15834:2:1;15819:18;;15806:32;15847:33;15806:32;15847:33;:::i;:::-;15899:7;-1:-1:-1;15953:2:1;15938:18;;15925:32;;-1:-1:-1;16008:2:1;15993:18;;15980:32;-1:-1:-1;;;;;16024:30:1;;16021:50;;;16067:1;16064;16057:12;16021:50;16090:49;16131:7;16122:6;16111:9;16107:22;16090:49;:::i;:::-;16080:59;;;15480:665;;;;;;;:::o;16150:750::-;16245:6;16253;16261;16269;16277;16330:3;16318:9;16309:7;16305:23;16301:33;16298:53;;;16347:1;16344;16337:12;16298:53;16386:9;16373:23;16405:30;16429:5;16405:30;:::i;:::-;16454:5;-1:-1:-1;16511:2:1;16496:18;;16483:32;16524;16483;16524;:::i;:::-;16575:7;-1:-1:-1;16629:2:1;16614:18;;16601:32;;-1:-1:-1;16684:2:1;16669:18;;16656:32;-1:-1:-1;;;;;16700:30:1;;16697:50;;;16743:1;16740;16733:12;16697:50;16782:58;16832:7;16823:6;16812:9;16808:22;16782:58;:::i;:::-;16150:750;;;;-1:-1:-1;16150:750:1;;-1:-1:-1;16859:8:1;;16756:84;16150:750;-1:-1:-1;;;16150:750:1:o;16905:521::-;16987:6;16995;17003;17056:2;17044:9;17035:7;17031:23;17027:32;17024:52;;;17072:1;17069;17062:12;17024:52;17111:9;17098:23;17130:30;17154:5;17130:30;:::i;:::-;17179:5;-1:-1:-1;17203:35:1;17234:2;17219:18;;17203:35;:::i;17431:452::-;17506:6;17514;17522;17575:2;17563:9;17554:7;17550:23;17546:32;17543:52;;;17591:1;17588;17581:12;17543:52;17630:9;17617:23;17649:30;17673:5;17649:30;:::i;:::-;17698:5;-1:-1:-1;17755:2:1;17740:18;;17727:32;17768;17727;17768;:::i;17888:388::-;17956:6;17964;18017:2;18005:9;17996:7;17992:23;17988:32;17985:52;;;18033:1;18030;18023:12;17985:52;18072:9;18059:23;18091:31;18116:5;18091:31;:::i;18281:968::-;18415:6;18423;18431;18439;18447;18500:3;18488:9;18479:7;18475:23;18471:33;18468:53;;;18517:1;18514;18507:12;18468:53;18556:9;18543:23;18575:30;18599:5;18575:30;:::i;:::-;18624:5;-1:-1:-1;18680:2:1;18665:18;;18652:32;-1:-1:-1;;;;;18733:14:1;;;18730:34;;;18760:1;18757;18750:12;18730:34;18783:49;18824:7;18815:6;18804:9;18800:22;18783:49;:::i;:::-;18773:59;;18885:2;18874:9;18870:18;18857:32;18841:48;;18914:2;18904:8;18901:16;18898:36;;;18930:1;18927;18920:12;18898:36;18953:63;19008:7;18997:8;18986:9;18982:24;18953:63;:::i;:::-;18943:73;;19035:35;19066:2;19055:9;19051:18;19035:35;:::i;19254:594::-;19338:6;19346;19354;19362;19415:3;19403:9;19394:7;19390:23;19386:33;19383:53;;;19432:1;19429;19422:12;19383:53;19471:9;19458:23;19490:30;19514:5;19490:30;:::i;:::-;19539:5;-1:-1:-1;19596:2:1;19581:18;;19568:32;19609;19568;19609;:::i;:::-;19660:7;-1:-1:-1;19719:2:1;19704:18;;19691:32;19732:33;19691:32;19732:33;:::i;:::-;19254:594;;;;-1:-1:-1;19784:7:1;;19838:2;19823:18;19810:32;;-1:-1:-1;;19254:594:1:o;20212:380::-;20291:1;20287:12;;;;20334;;;20355:61;;20409:4;20401:6;20397:17;20387:27;;20355:61;20462:2;20454:6;20451:14;20431:18;20428:38;20425:161;;20508:10;20503:3;20499:20;20496:1;20489:31;20543:4;20540:1;20533:15;20571:4;20568:1;20561:15;20425:161;;20212:380;;;:::o;20597:271::-;20780:6;20772;20767:3;20754:33;20736:3;20806:16;;20831:13;;;20806:16;20597:271;-1:-1:-1;20597:271:1:o;23210:127::-;23271:10;23266:3;23262:20;23259:1;23252:31;23302:4;23299:1;23292:15;23326:4;23323:1;23316:15;23342:135;23381:3;23402:17;;;23399:43;;23422:18;;:::i;:::-;-1:-1:-1;23469:1:1;23458:13;;23342:135::o;23482:409::-;23684:2;23666:21;;;23723:2;23703:18;;;23696:30;23762:34;23757:2;23742:18;;23735:62;-1:-1:-1;;;23828:2:1;23813:18;;23806:43;23881:3;23866:19;;23482:409::o;24106:266::-;24194:6;24189:3;24182:19;24246:6;24239:5;24232:4;24227:3;24223:14;24210:43;-1:-1:-1;24298:1:1;24273:16;;;24291:4;24269:27;;;24262:38;;;;24354:2;24333:15;;;-1:-1:-1;;24329:29:1;24320:39;;;24316:50;;24106:266::o;24377:326::-;24572:6;24564;24560:19;24549:9;24542:38;24616:2;24611;24600:9;24596:18;24589:30;24523:4;24636:61;24693:2;24682:9;24678:18;24670:6;24662;24636:61;:::i;24708:249::-;24777:6;24830:2;24818:9;24809:7;24805:23;24801:32;24798:52;;;24846:1;24843;24836:12;24798:52;24878:9;24872:16;24897:30;24921:5;24897:30;:::i;24962:472::-;25152:4;25181:6;25226:2;25218:6;25214:15;25203:9;25196:34;25278:2;25270:6;25266:15;25261:2;25250:9;25246:18;25239:43;;25318:6;25313:2;25302:9;25298:18;25291:34;25361:3;25356:2;25345:9;25341:18;25334:31;25382:46;25423:3;25412:9;25408:19;25400:6;25382:46;:::i;:::-;25374:54;24962:472;-1:-1:-1;;;;;;24962:472:1:o;27251:441::-;27304:5;27357:3;27350:4;27342:6;27338:17;27334:27;27324:55;;27375:1;27372;27365:12;27324:55;27404:6;27398:13;27435:48;27451:31;27479:2;27451:31;:::i;27435:48::-;27508:2;27499:7;27492:19;27554:3;27547:4;27542:2;27534:6;27530:15;27526:26;27523:35;27520:55;;;27571:1;27568;27561:12;27520:55;27584:77;27658:2;27651:4;27642:7;27638:18;27631:4;27623:6;27619:17;27584:77;:::i;27697:1104::-;27810:6;27818;27871:2;27859:9;27850:7;27846:23;27842:32;27839:52;;;27887:1;27884;27877:12;27839:52;27920:9;27914:16;-1:-1:-1;;;;;27990:2:1;27982:6;27979:14;27976:34;;;28006:1;28003;27996:12;27976:34;28029:60;28081:7;28072:6;28061:9;28057:22;28029:60;:::i;:::-;28019:70;;28108:2;28098:12;;28156:2;28145:9;28141:18;28135:25;28185:2;28175:8;28172:16;28169:36;;;28201:1;28198;28191:12;28169:36;28224:24;;;-1:-1:-1;28279:4:1;28271:13;;28267:27;-1:-1:-1;28257:55:1;;28308:1;28305;28298:12;28257:55;28337:2;28331:9;28360:60;28376:43;28416:2;28376:43;:::i;28360:60::-;28454:15;;;28536:1;28532:10;;;;28524:19;;28520:28;;;28485:12;;;;28560:19;;;28557:39;;;28592:1;28589;28582:12;28557:39;28616:11;;;;28636:135;28652:6;28647:3;28644:15;28636:135;;;28718:10;;28706:23;;28669:12;;;;28749;;;;28636:135;;;28790:5;28780:15;;;;;;;27697:1104;;;;;:::o;30241:128::-;30308:9;;;30329:11;;;30326:37;;;30343:18;;:::i;30374:360::-;30585:6;30577;30572:3;30559:33;30655:2;30651:15;;;;-1:-1:-1;;30647:53:1;30611:16;;30636:65;;;30725:2;30717:11;;30374:360;-1:-1:-1;30374:360:1:o;30864:544::-;30965:2;30960:3;30957:11;30954:448;;;31001:1;31026:5;31022:2;31015:17;31071:4;31067:2;31057:19;31141:2;31129:10;31125:19;31122:1;31118:27;31112:4;31108:38;31177:4;31165:10;31162:20;31159:47;;;-1:-1:-1;31200:4:1;31159:47;31255:2;31250:3;31246:12;31243:1;31239:20;31233:4;31229:31;31219:41;;31310:82;31328:2;31321:5;31318:13;31310:82;;;31373:17;;;31354:1;31343:13;31310:82;;31584:1348;31708:3;31702:10;-1:-1:-1;;;;;31727:6:1;31724:30;31721:56;;;31757:18;;:::i;:::-;31786:96;31875:6;31835:38;31867:4;31861:11;31835:38;:::i;:::-;31829:4;31786:96;:::i;:::-;31937:4;;32001:2;31990:14;;32018:1;32013:662;;;;32719:1;32736:6;32733:89;;;-1:-1:-1;32788:19:1;;;32782:26;32733:89;-1:-1:-1;;31541:1:1;31537:11;;;31533:24;31529:29;31519:40;31565:1;31561:11;;;31516:57;32835:81;;31983:943;;32013:662;30811:1;30804:14;;;30848:4;30835:18;;-1:-1:-1;;32049:20:1;;;32166:236;32180:7;32177:1;32174:14;32166:236;;;32269:19;;;32263:26;32248:42;;32361:27;;;;32329:1;32317:14;;;;32196:19;;32166:236;;;32170:3;32430:6;32421:7;32418:19;32415:201;;;32491:19;;;32485:26;-1:-1:-1;;32574:1:1;32570:14;;;32586:3;32566:24;32562:37;32558:42;32543:58;32528:74;;32415:201;-1:-1:-1;;;;;32662:1:1;32646:14;;;32642:22;32629:36;;-1:-1:-1;31584:1348:1:o;32937:496::-;33116:3;33154:6;33148:13;33170:66;33229:6;33224:3;33217:4;33209:6;33205:17;33170:66;:::i;:::-;33299:13;;33258:16;;;;33321:70;33299:13;33258:16;33368:4;33356:17;;33321:70;:::i;:::-;33407:20;;32937:496;-1:-1:-1;;;;32937:496:1:o;33438:498::-;33638:4;33667:6;33712:2;33704:6;33700:15;33689:9;33682:34;33764:2;33756:6;33752:15;33747:2;33736:9;33732:18;33725:43;;33804:6;33799:2;33788:9;33784:18;33777:34;33847:3;33842:2;33831:9;33827:18;33820:31;33868:62;33925:3;33914:9;33910:19;33902:6;33894;33868:62;:::i;:::-;33860:70;33438:498;-1:-1:-1;;;;;;;33438:498:1:o;35151:493::-;35400:6;35392;35388:19;35377:9;35370:38;35444:3;35439:2;35428:9;35424:18;35417:31;35351:4;35465:62;35522:3;35511:9;35507:19;35499:6;35491;35465:62;:::i;:::-;-1:-1:-1;;;;;35563:31:1;;;;35558:2;35543:18;;35536:59;-1:-1:-1;35626:2:1;35611:18;35604:34;35457:70;35151:493;-1:-1:-1;;;35151:493:1:o;35649:650::-;35938:6;35926:19;;35908:38;;-1:-1:-1;;;;;35982:32:1;;35977:2;35962:18;;35955:60;36002:3;36046:2;36031:18;;36024:31;;;-1:-1:-1;;36078:46:1;;36104:19;;36096:6;36078:46;:::i;:::-;36174:6;36167:14;36160:22;36155:2;36144:9;36140:18;36133:50;36232:9;36224:6;36220:22;36214:3;36203:9;36199:19;36192:51;36260:33;36286:6;36278;36260:33;:::i;:::-;36252:41;35649:650;-1:-1:-1;;;;;;;;35649:650:1:o;36304:245::-;36383:6;36391;36444:2;36432:9;36423:7;36419:23;36415:32;36412:52;;;36460:1;36457;36450:12;36412:52;-1:-1:-1;;36483:16:1;;36539:2;36524:18;;;36518:25;36483:16;;36518:25;;-1:-1:-1;36304:245:1:o;37267:1202::-;-1:-1:-1;;;;;37384:3:1;37381:27;37378:53;;;37411:18;;:::i;:::-;37440:93;37529:3;37489:38;37521:4;37515:11;37489:38;:::i;:::-;37483:4;37440:93;:::i;:::-;37559:1;37584:2;37579:3;37576:11;37601:1;37596:615;;;;38255:1;38272:3;38269:93;;;-1:-1:-1;38328:19:1;;;38315:33;38269:93;-1:-1:-1;;31541:1:1;31537:11;;;31533:24;31529:29;31519:40;31565:1;31561:11;;;31516:57;38375:78;;37569:894;;37596:615;30811:1;30804:14;;;30848:4;30835:18;;-1:-1:-1;;37632:17:1;;;37732:9;37754:229;37768:7;37765:1;37762:14;37754:229;;;37857:19;;;37844:33;37829:49;;37964:4;37949:20;;;;37917:1;37905:14;;;;37784:12;37754:229;;;37758:3;38011;38002:7;37999:16;37996:159;;;38135:1;38131:6;38125:3;38119;38116:1;38112:11;38108:21;38104:34;38100:39;38087:9;38082:3;38078:19;38065:33;38061:79;38053:6;38046:95;37996:159;;;38198:1;38192:3;38189:1;38185:11;38181:19;38175:4;38168:33;37569:894;;37267:1202;;;:::o;38474:435::-;38527:3;38565:5;38559:12;38592:6;38587:3;38580:19;38618:4;38647:2;38642:3;38638:12;38631:19;;38684:2;38677:5;38673:14;38705:1;38715:169;38729:6;38726:1;38723:13;38715:169;;;38790:13;;38778:26;;38824:12;;;;38859:15;;;;38751:1;38744:9;38715:169;;;-1:-1:-1;38900:3:1;;38474:435;-1:-1:-1;;;;;38474:435:1:o;38914:422::-;39139:2;39128:9;39121:21;39102:4;39165:45;39206:2;39195:9;39191:18;39183:6;39165:45;:::i;:::-;39258:9;39250:6;39246:22;39241:2;39230:9;39226:18;39219:50;39286:44;39323:6;39315;39286:44;:::i;:::-;39278:52;38914:422;-1:-1:-1;;;;;38914:422:1:o;40856:335::-;40935:6;40988:2;40976:9;40967:7;40963:23;40959:32;40956:52;;;41004:1;41001;40994:12;40956:52;41037:9;41031:16;-1:-1:-1;;;;;41062:6:1;41059:30;41056:50;;;41102:1;41099;41092:12;41056:50;41125:60;41177:7;41168:6;41157:9;41153:22;41125:60;:::i;41196:557::-;41453:6;41445;41441:19;41430:9;41423:38;41497:3;41492:2;41481:9;41477:18;41470:31;41404:4;41524:46;41565:3;41554:9;41550:19;41542:6;41524:46;:::i;:::-;-1:-1:-1;;;;;41610:6:1;41606:31;41601:2;41590:9;41586:18;41579:59;41686:9;41678:6;41674:22;41669:2;41658:9;41654:18;41647:50;41714:33;41740:6;41732;41714:33;:::i;42119:401::-;42321:2;42303:21;;;42360:2;42340:18;;;42333:30;42399:34;42394:2;42379:18;;42372:62;-1:-1:-1;;;42465:2:1;42450:18;;42443:35;42510:3;42495:19;;42119:401::o;42930:127::-;42991:10;42986:3;42982:20;42979:1;42972:31;43022:4;43019:1;43012:15;43046:4;43043:1;43036:15;43062:125;43127:9;;;43148:10;;;43145:36;;;43161:18;;:::i;44320:840::-;44669:6;44661;44657:19;44646:9;44639:38;44713:3;44708:2;44697:9;44693:18;44686:31;44620:4;44740:46;44781:3;44770:9;44766:19;44758:6;44740:46;:::i;:::-;44834:9;44826:6;44822:22;44817:2;44806:9;44802:18;44795:50;44868:33;44894:6;44886;44868:33;:::i;:::-;-1:-1:-1;;;;;44975:15:1;;;44970:2;44955:18;;44948:43;45028:15;;45022:3;45007:19;;45000:44;45081:22;;;44928:3;45060:19;;45053:51;44854:47;-1:-1:-1;45121:33:1;44854:47;45139:6;45121:33;:::i;:::-;45113:41;44320:840;-1:-1:-1;;;;;;;;;44320:840:1:o;45916:168::-;45989:9;;;46020;;46037:15;;;46031:22;;46017:37;46007:71;;46058:18;;:::i;46089:287::-;46218:3;46256:6;46250:13;46272:66;46331:6;46326:3;46319:4;46311:6;46307:17;46272:66;:::i;:::-;46354:16;;;;;46089:287;-1:-1:-1;;46089:287:1:o;46381:261::-;46560:2;46549:9;46542:21;46523:4;46580:56;46632:2;46621:9;46617:18;46609:6;46580:56;:::i;46647:289::-;46822:6;46811:9;46804:25;46865:2;46860;46849:9;46845:18;46838:30;46785:4;46885:45;46926:2;46915:9;46911:18;46903:6;46885:45;:::i;48344:414::-;48546:2;48528:21;;;48585:2;48565:18;;;48558:30;48624:34;48619:2;48604:18;;48597:62;-1:-1:-1;;;48690:2:1;48675:18;;48668:48;48748:3;48733:19;;48344:414::o;48895:719::-;49198:6;49190;49186:19;49175:9;49168:38;49242:3;49237:2;49226:9;49222:18;49215:31;49149:4;49269:46;49310:3;49299:9;49295:19;49287:6;49269:46;:::i;:::-;-1:-1:-1;;;;;49355:6:1;49351:31;49346:2;49335:9;49331:18;49324:59;49431:9;49423:6;49419:22;49414:2;49403:9;49399:18;49392:50;49465:33;49491:6;49483;49465:33;:::i;:::-;49451:47;;49547:9;49539:6;49535:22;49529:3;49518:9;49514:19;49507:51;49575:33;49601:6;49593;49575:33;:::i;51155:489::-;-1:-1:-1;;;;;51424:15:1;;;51406:34;;51476:15;;51471:2;51456:18;;51449:43;51523:2;51508:18;;51501:34;;;51571:3;51566:2;51551:18;;51544:31;;;51349:4;;51592:46;;51618:19;;51610:6;51592:46;:::i;51649:249::-;51718:6;51771:2;51759:9;51750:7;51746:23;51742:32;51739:52;;;51787:1;51784;51777:12;51739:52;51819:9;51813:16;51838:30;51862:5;51838:30;:::i

Swarm Source

ipfs://f76858e4b7bb5fab3ae912ee6c6d5fe87cfc482499e6fc998b4ef12a250eb1cf
[ Download: CSV Export  ]
[ Download: CSV Export  ]

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