ETH Price: $3,595.70 (-2.67%)

Token

ERC-20: L2Marathon (MarathonRunner)
 

Overview

Max Total Supply

0 MarathonRunner

Holders

2,119

Market

Volume (24H)

N/A

Min Price (24H)

N/A

Max Price (24H)

N/A

Other Info

Filtered by Token Holder
Null: 0x000...000
Balance
0 MarathonRunner
0x0000000000000000000000000000000000000000
Loading...
Loading
Loading...
Loading
Loading...
Loading

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

Contract Source Code Verified (Exact Match)

Contract Name:
L2Marathon

Compiler Version
v0.8.12+commit.f00d7308

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, None license

Contract Source Code (Solidity)

/**
 *Submitted for verification at Etherscan.io on 2023-07-15
*/

// 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[]));

        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 the UniversalONFT standard
contract UniversalONFT721 is ONFT721 {
    uint public nextMintId;
    uint public maxMintId;
    uint public fee;

    /// @notice Constructor for the UniversalONFT
    /// @param _name the name of the token
    /// @param _symbol the token symbol
    /// @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(
    string memory _name,
    string memory _symbol,
    uint256 _minGasToTransfer,
    address _layerZeroEndpoint,
    uint _startMintId,
    uint _endMintId) ONFT721(_name, _symbol, _minGasToTransfer, _layerZeroEndpoint) {
        nextMintId = _startMintId;
        maxMintId = _endMintId;
        fee = 0.00031 ether; // half a buck
    }

    /// @notice Mint your ONFT
    function mint() external payable {
        require(nextMintId <= maxMintId, "L2Marathon: max mint limit reached");
        require(msg.value >= fee, "Not enough ETH sent: check fee.");
        uint newId = nextMintId;
        nextMintId++;

        _safeMint(msg.sender, newId);
    }

    function withdrawETH() external onlyOwner returns(bool) {
        (bool success,)= payable(msg.sender).call{value: address(this).balance}("");
        return success;
    }

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

/// @title A LayerZero UniversalONFT example
/// @notice You can use this to mint ONFT and send nftIds across chain.
///  Each contract deployed to a chain should carefully set a `_startMintIndex` and a `_maxMint`
///  value to set a range of allowed mintable nftIds (so that no two chains can mint the same id!)
contract L2Marathon is UniversalONFT721 {
    constructor(uint256 _minGasToStore, address _layerZeroEndpoint, uint _startMintId, uint _endMintId) UniversalONFT721("L2Marathon", "MarathonRunner", _minGasToStore, _layerZeroEndpoint, _startMintId, _endMintId) {}
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"uint256","name":"_minGasToStore","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":"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":"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":"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":"tokenId","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":"withdrawETH","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"}]

60a06040523480156200001157600080fd5b5060405162004bb838038062004bb8833981016040819052620000349162000269565b6040518060400160405280600a815260200169261926b0b930ba3437b760b11b8152506040518060400160405280600e81526020016d26b0b930ba3437b7293ab73732b960911b8152508585858585858585838383838080620000a6620000a06200016f60201b60201c565b62000173565b6001600160a01b031660805250600160065581620001165760405162461bcd60e51b8152602060048201526024808201527f6d696e476173546f5472616e73666572416e6453746f7265206d7573742062656044820152630203e20360e41b606482015260840160405180910390fd5b5060075581516200012f90600b906020850190620001c3565b5080516200014590600c906020840190620001c3565b5050506011959095555050506012555050660119f17fe1600060135550620002f395505050505050565b3390565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b828054620001d190620002b6565b90600052602060002090601f016020900481019282620001f5576000855562000240565b82601f106200021057805160ff191683800117855562000240565b8280016001018555821562000240579182015b828111156200024057825182559160200191906001019062000223565b506200024e92915062000252565b5090565b5b808211156200024e576000815560010162000253565b600080600080608085870312156200028057600080fd5b845160208601519094506001600160a01b0381168114620002a057600080fd5b6040860151606090960151949790965092505050565b600181811c90821680620002cb57607f821691505b60208210811415620002ed57634e487b7160e01b600052602260045260246000fd5b50919050565b608051614871620003476000396000818161092e01528181610b7301528181610e77015281816110fc0152818161136601528181611c58015281816121390152818161226c015261327801526148716000f3fe6080604052600436106103755760003560e01c80638cfd8f5c116101d1578063c446183411610102578063e086e5ec116100a0578063f23536411161006f578063f235364114610ae3578063f2fde38b14610b03578063f5ecbdbc14610b23578063fa25f9b614610b4357600080fd5b8063e086e5ec14610a4f578063e1d4c87014610a64578063e985e9c514610a7a578063eb8d72b714610ac357600080fd5b8063d12473a5116100dc578063d12473a5146109e6578063d1deba1f14610a06578063ddca3f4314610a19578063df2a5b3b14610a2f57600080fd5b8063c446183414610990578063c87b56dd146109a6578063cbed8b9c146109c657600080fd5b8063a22cb4651161016f578063af3fb21c11610149578063af3fb21c146108f4578063b353aaa71461091c578063b88d4fde14610950578063baf3292d1461097057600080fd5b8063a22cb465146108a1578063a6c3d165146108c1578063ab3ffb93146108e157600080fd5b8063950c8a74116101ab578063950c8a741461082c57806395d89b411461084c5780639ea5d6b1146108615780639f38369a1461088157600080fd5b80638cfd8f5c146107b65780638da5cb5b146107ee5780638ffa1f2a1461080c57600080fd5b80633f1f4fa4116102ab5780636352211e116102495780636aa99da3116102235780636aa99da31461074b57806370a0823114610761578063715018a6146107815780637533d7881461079657600080fd5b80636352211e146106eb57806366ad5c8a1461070b57806369fe0e2d1461072b57600080fd5b8063482881901161028557806348288190146106465780634ac3f4ff1461065c57806351905636146106895780635b8c41e61461069c57600080fd5b80633f1f4fa4146105cb57806342842e0e1461060657806342d65a8d1461062657600080fd5b80630df374831161031857806322a3ecf9116102f257806322a3ecf9146104d357806323b872dd146105565780632a205e3d146105765780633d8b38f6146105ab57600080fd5b80630df374831461048b57806310ddb137146104ab5780631249c58b146104cb57600080fd5b806307e0db171161035457806307e0db17146103f3578063081812fc14610413578063095ea7b31461044b5780630b4cad4c1461046b57600080fd5b80621d35671461037a57806301ffc9a71461039c57806306fdde03146103d1575b600080fd5b34801561038657600080fd5b5061039a6103953660046138e1565b610b70565b005b3480156103a857600080fd5b506103bc6103b736600461398a565b610da1565b60405190151581526020015b60405180910390f35b3480156103dd57600080fd5b506103e6610dc4565b6040516103c891906139ff565b3480156103ff57600080fd5b5061039a61040e366004613a12565b610e56565b34801561041f57600080fd5b5061043361042e366004613a2d565b610edf565b6040516001600160a01b0390911681526020016103c8565b34801561045757600080fd5b5061039a610466366004613a66565b610f06565b34801561047757600080fd5b5061039a610486366004613a2d565b61101c565b34801561049757600080fd5b5061039a6104a6366004613a92565b6110bc565b3480156104b757600080fd5b5061039a6104c6366004613a12565b6110db565b61039a611133565b3480156104df57600080fd5b506105276104ee366004613a2d565b600a6020526000908152604090208054600182015460029092015461ffff821692620100009092046001600160a01b0316919060ff1684565b6040805161ffff90951685526001600160a01b03909316602085015291830152151560608201526080016103c8565b34801561056257600080fd5b5061039a610571366004613aae565b611208565b34801561058257600080fd5b50610596610591366004613bc2565b61123a565b604080519283526020830191909152016103c8565b3480156105b757600080fd5b506103bc6105c6366004613c50565b611260565b3480156105d757600080fd5b506105f86105e6366004613a12565b60036020526000908152604090205481565b6040519081526020016103c8565b34801561061257600080fd5b5061039a610621366004613aae565b61132c565b34801561063257600080fd5b5061039a610641366004613c50565b611347565b34801561065257600080fd5b506105f860075481565b34801561066857600080fd5b506105f8610677366004613a12565b60086020526000908152604090205481565b61039a610697366004613ca2565b6113cd565b3480156106a857600080fd5b506105f86106b7366004613d5b565b6005602090815260009384526040808520845180860184018051928152908401958401959095209452929052825290205481565b3480156106f757600080fd5b50610433610706366004613a2d565b6113e4565b34801561071757600080fd5b5061039a6107263660046138e1565b611444565b34801561073757600080fd5b5061039a610746366004613a2d565b611520565b34801561075757600080fd5b506105f860115481565b34801561076d57600080fd5b506105f861077c366004613db8565b61152d565b34801561078d57600080fd5b5061039a6115b3565b3480156107a257600080fd5b506103e66107b1366004613a12565b6115c7565b3480156107c257600080fd5b506105f86107d1366004613dd5565b600260209081526000928352604080842090915290825290205481565b3480156107fa57600080fd5b506000546001600160a01b0316610433565b34801561081857600080fd5b5061039a610827366004613e08565b611661565b34801561083857600080fd5b50600454610433906001600160a01b031681565b34801561085857600080fd5b506103e66118aa565b34801561086d57600080fd5b5061039a61087c366004613a92565b6118b9565b34801561088d57600080fd5b506103e661089c366004613a12565b611970565b3480156108ad57600080fd5b5061039a6108bc366004613e3c565b611a87565b3480156108cd57600080fd5b5061039a6108dc366004613c50565b611a96565b61039a6108ef366004613ef1565b611b29565b34801561090057600080fd5b50610909600181565b60405161ffff90911681526020016103c8565b34801561092857600080fd5b506104337f000000000000000000000000000000000000000000000000000000000000000081565b34801561095c57600080fd5b5061039a61096b366004613fa6565b611b38565b34801561097c57600080fd5b5061039a61098b366004613db8565b611b70565b34801561099c57600080fd5b506105f861271081565b3480156109b257600080fd5b506103e66109c1366004613a2d565b611bc6565b3480156109d257600080fd5b5061039a6109e1366004614011565b611c39565b3480156109f257600080fd5b5061039a610a01366004613a92565b611cce565b61039a610a143660046138e1565b611d7e565b348015610a2557600080fd5b506105f860135481565b348015610a3b57600080fd5b5061039a610a4a36600461407f565b611f94565b348015610a5b57600080fd5b506103bc612046565b348015610a7057600080fd5b506105f860125481565b348015610a8657600080fd5b506103bc610a953660046140bb565b6001600160a01b03918216600090815260106020908152604080832093909416825291909152205460ff1690565b348015610acf57600080fd5b5061039a610ade366004613c50565b6120a0565b348015610aef57600080fd5b50610596610afe3660046140f4565b6120fa565b348015610b0f57600080fd5b5061039a610b1e366004613db8565b6121c5565b348015610b2f57600080fd5b506103e6610b3e36600461416d565b61223b565b348015610b4f57600080fd5b506105f8610b5e366004613a12565b60096020526000908152604090205481565b337f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031614610bed5760405162461bcd60e51b815260206004820152601e60248201527f4c7a4170703a20696e76616c696420656e64706f696e742063616c6c6572000060448201526064015b60405180910390fd5b61ffff861660009081526001602052604081208054610c0b906141ba565b80601f0160208091040260200160405190810160405280929190818152602001828054610c37906141ba565b8015610c845780601f10610c5957610100808354040283529160200191610c84565b820191906000526020600020905b815481529060010190602001808311610c6757829003601f168201915b50505050509050805186869050148015610c9f575060008151115b8015610cc7575080516020820120604051610cbd90889088906141f5565b6040518091039020145b610d225760405162461bcd60e51b815260206004820152602660248201527f4c7a4170703a20696e76616c696420736f757263652073656e64696e6720636f6044820152651b9d1c9858dd60d21b6064820152608401610be4565b610d988787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f8a018190048102820181019092528881528a9350915088908890819084018382808284376000920191909152506122ee92505050565b50505050505050565b60006001600160e01b031982161580610dbe5750610dbe82612367565b92915050565b6060600b8054610dd3906141ba565b80601f0160208091040260200160405190810160405280929190818152602001828054610dff906141ba565b8015610e4c5780601f10610e2157610100808354040283529160200191610e4c565b820191906000526020600020905b815481529060010190602001808311610e2f57829003601f168201915b5050505050905090565b610e5e6123a7565b6040516307e0db1760e01b815261ffff821660048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906307e0db17906024015b600060405180830381600087803b158015610ec457600080fd5b505af1158015610ed8573d6000803e3d6000fd5b5050505050565b6000610eea82612401565b506000908152600f60205260409020546001600160a01b031690565b6000610f11826113e4565b9050806001600160a01b0316836001600160a01b03161415610f7f5760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e656044820152603960f91b6064820152608401610be4565b336001600160a01b0382161480610f9b5750610f9b8133610a95565b61100d5760405162461bcd60e51b815260206004820152603d60248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f7420746f60448201527f6b656e206f776e6572206f7220617070726f76656420666f7220616c6c0000006064820152608401610be4565b6110178383612451565b505050565b6110246123a7565b600081116110805760405162461bcd60e51b8152602060048201526024808201527f6d696e476173546f5472616e73666572416e6453746f7265206d7573742062656044820152630203e20360e41b6064820152608401610be4565b60078190556040518181527ffebbc4f8bb9ec2313950c718d43123124b15778efda4c1f1d529de2995b4f34d906020015b60405180910390a150565b6110c46123a7565b61ffff909116600090815260036020526040902055565b6110e36123a7565b6040516310ddb13760e01b815261ffff821660048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906310ddb13790602401610eaa565b60125460115411156111925760405162461bcd60e51b815260206004820152602260248201527f4c324d61726174686f6e3a206d6178206d696e74206c696d6974207265616368604482015261195960f21b6064820152608401610be4565b6013543410156111e45760405162461bcd60e51b815260206004820152601f60248201527f4e6f7420656e6f756768204554482073656e743a20636865636b206665652e006044820152606401610be4565b6011805490819060006111f68361421b565b919050555061120533826124bf565b50565b611213335b826124d9565b61122f5760405162461bcd60e51b8152600401610be490614236565b611017838383612557565b600080611252878761124b886126bb565b87876120fa565b915091509550959350505050565b61ffff831660009081526001602052604081208054829190611281906141ba565b80601f01602080910402602001604051908101604052809291908181526020018280546112ad906141ba565b80156112fa5780601f106112cf576101008083540402835291602001916112fa565b820191906000526020600020905b8154815290600101906020018083116112dd57829003601f168201915b5050505050905083836040516113119291906141f5565b60405180910390208180519060200120149150509392505050565b61101783838360405180602001604052806000815250611b38565b61134f6123a7565b6040516342d65a8d60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906342d65a8d9061139f908690869086906004016142ac565b600060405180830381600087803b1580156113b957600080fd5b505af1158015610d98573d6000803e3d6000fd5b610d988787876113dc886126bb565b878787612706565b6000818152600d60205260408120546001600160a01b031680610dbe5760405162461bcd60e51b8152602060048201526018602482015277115490cdcc8c4e881a5b9d985b1a59081d1bdad95b88125160421b6044820152606401610be4565b3330146114a25760405162461bcd60e51b815260206004820152602660248201527f4e6f6e626c6f636b696e674c7a4170703a2063616c6c6572206d7573742062656044820152650204c7a4170760d41b6064820152608401610be4565b6115188686868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f8901819004810282018101909252878152899350915087908790819084018382808284376000920191909152506128da92505050565b505050505050565b6115286123a7565b601355565b60006001600160a01b0382166115975760405162461bcd60e51b815260206004820152602960248201527f4552433732313a2061646472657373207a65726f206973206e6f7420612076616044820152683634b21037bbb732b960b91b6064820152608401610be4565b506001600160a01b03166000908152600e602052604090205490565b6115bb6123a7565b6115c56000612a31565b565b600160205260009081526040902080546115e0906141ba565b80601f016020809104026020016040519081016040528092919081815260200182805461160c906141ba565b80156116595780601f1061162e57610100808354040283529160200191611659565b820191906000526020600020905b81548152906001019060200180831161163c57829003601f168201915b505050505081565b611669612a81565b80516020808301919091206000818152600a90925260409091206002015460ff166116ca5760405162461bcd60e51b81526020600482015260116024820152701b9bc818dc99591a5d1cc81cdd1bdc9959607a1b6044820152606401610be4565b6000828060200190518101906116e0919061430f565b6000848152600a60205260408120805460019091015492945090925061171c9161ffff8216916201000090046001600160a01b03169085612adb565b6000848152600a602052604090206001015490915081116117915760405162461bcd60e51b815260206004820152602960248201527f6e6f7420656e6f7567682067617320746f2070726f6365737320637265646974604482015268103a3930b739b332b960b91b6064820152608401610be4565b8151811415611809576000838152600a602052604080822080546001600160b01b031916815560018101929092556002909101805460ff19169055517fd7be02b8dd0d27bd0517a9cb4d7469ce27df4313821ae5ec1ff69acc594ba233906117fc9085815260200190565b60405180910390a161189d565b604080516080810182526000858152600a6020818152848320805461ffff80821687526001600160a01b03620100008084048216868a019081529989018b8152600160608b01818152998f90529790965297519851169096026001600160b01b03199091169690951695909517939093178455915191830191909155516002909101805491151560ff199092169190911790555b5050506112056001600655565b6060600c8054610dd3906141ba565b6118c16123a7565b6000811161191c5760405162461bcd60e51b815260206004820152602260248201527f647374436861696e4964546f42617463684c696d6974206d757374206265203e604482015261020360f41b6064820152608401610be4565b61ffff8216600081815260086020908152604091829020849055815192835282018390527f7315f7654d594ead24a30160ed9ba2d23247f543016b918343591e93d7afdb6d91015b60405180910390a15050565b61ffff8116600090815260016020526040812080546060929190611993906141ba565b80601f01602080910402602001604051908101604052809291908181526020018280546119bf906141ba565b8015611a0c5780601f106119e157610100808354040283529160200191611a0c565b820191906000526020600020905b8154815290600101906020018083116119ef57829003601f168201915b50505050509050805160001415611a655760405162461bcd60e51b815260206004820152601d60248201527f4c7a4170703a206e6f20747275737465642070617468207265636f72640000006044820152606401610be4565b611a80600060148351611a7891906143c9565b839190612b2d565b9392505050565b611a92338383612c3a565b5050565b611a9e6123a7565b818130604051602001611ab3939291906143e0565b60408051601f1981840301815291815261ffff85166000908152600160209081529190208251611ae89391929091019061375e565b507f8c0400cfe2d1199b1a725c78960bcc2a344d869b80590d0f2bd005db15a572ce838383604051611b1c939291906142ac565b60405180910390a1505050565b610d9887878787878787612706565b611b4233836124d9565b611b5e5760405162461bcd60e51b8152600401610be490614236565b611b6a84848484612d09565b50505050565b611b786123a7565b600480546001600160a01b0319166001600160a01b0383169081179091556040519081527f5db758e995a17ec1ad84bdef7e8c3293a0bd6179bcce400dff5d4c3d87db726b906020016110b1565b6060611bd182612401565b6000611be860408051602081019091526000815290565b90506000815111611c085760405180602001604052806000815250611a80565b80611c1284612d3c565b604051602001611c23929190614406565b6040516020818303038152906040529392505050565b611c416123a7565b6040516332fb62e760e21b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063cbed8b9c90611c959088908890889088908890600401614435565b600060405180830381600087803b158015611caf57600080fd5b505af1158015611cc3573d6000803e3d6000fd5b505050505050505050565b611cd66123a7565b60008111611d325760405162461bcd60e51b815260206004820152602360248201527f647374436861696e4964546f5472616e73666572476173206d7573742062652060448201526203e20360ec1b6064820152608401610be4565b61ffff8216600081815260096020908152604091829020849055815192835282018390527fc46df2983228ac2d9754e94a0d565e6671665dc8ad38602bc8e544f0685a29fb9101611964565b61ffff86166000908152600560205260408082209051611da190889088906141f5565b90815260408051602092819003830190206001600160401b03871660009081529252902054905080611e215760405162461bcd60e51b815260206004820152602360248201527f4e6f6e626c6f636b696e674c7a4170703a206e6f2073746f726564206d65737360448201526261676560e81b6064820152608401610be4565b808383604051611e329291906141f5565b604051809103902014611e915760405162461bcd60e51b815260206004820152602160248201527f4e6f6e626c6f636b696e674c7a4170703a20696e76616c6964207061796c6f616044820152601960fa1b6064820152608401610be4565b61ffff87166000908152600560205260408082209051611eb490899089906141f5565b90815260408051602092819003830181206001600160401b038916600090815290845282902093909355601f88018290048202830182019052868252611f4c918991899089908190840183828082843760009201919091525050604080516020601f8a018190048102820181019092528881528a9350915088908890819084018382808284376000920191909152506128da92505050565b7fc264d91f3adc5588250e1551f547752ca0cfa8f6b530d243b9f9f4cab10ea8e58787878785604051611f8395949392919061446e565b60405180910390a150505050505050565b611f9c6123a7565b60008111611fe45760405162461bcd60e51b81526020600482015260156024820152744c7a4170703a20696e76616c6964206d696e47617360581b6044820152606401610be4565b61ffff83811660008181526002602090815260408083209487168084529482529182902085905581519283528201929092529081018290527f9d5c7c0b934da8fefa9c7760c98383778a12dfbfc0c3b3106518f43fb9508ac090606001611b1c565b60006120506123a7565b604051600090339047908381818185875af1925050503d8060008114612092576040519150601f19603f3d011682016040523d82523d6000602084013e612097565b606091505b50909250505090565b6120a86123a7565b61ffff831660009081526001602052604090206120c69083836137e2565b507ffa41487ad5d6728f0b19276fa1eddc16558578f5109fc39d2dc33c3230470dab838383604051611b1c939291906142ac565b600080600086866040516020016121129291906144e4565b60408051601f198184030181529082905263040a7bb160e41b825291506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906340a7bb1090612176908b90309086908b908b90600401614512565b6040805180830381865afa158015612192573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121b69190614566565b92509250509550959350505050565b6121cd6123a7565b6001600160a01b0381166122325760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610be4565b61120581612a31565b604051633d7b2f6f60e21b815261ffff808616600483015284166024820152306044820152606481018290526060907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063f5ecbdbc90608401600060405180830381865afa1580156122bb573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526122e3919081019061458a565b90505b949350505050565b6000806123515a60966366ad5c8a60e01b8989898960405160240161231694939291906145be565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915230929190612dd8565b9150915081611518576115188686868685612e62565b60006001600160e01b031982166380ac58cd60e01b148061239857506001600160e01b03198216635b5e139f60e01b145b80610dbe5750610dbe82612eff565b6000546001600160a01b031633146115c55760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610be4565b61240a81612f34565b6112055760405162461bcd60e51b8152602060048201526018602482015277115490cdcc8c4e881a5b9d985b1a59081d1bdad95b88125160421b6044820152606401610be4565b6000818152600f6020526040902080546001600160a01b0319166001600160a01b0384169081179091558190612486826113e4565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b611a92828260405180602001604052806000815250612f51565b6000806124e5836113e4565b9050806001600160a01b0316846001600160a01b0316148061252c57506001600160a01b0380821660009081526010602090815260408083209388168352929052205460ff165b806122e65750836001600160a01b031661254584610edf565b6001600160a01b031614949350505050565b826001600160a01b031661256a826113e4565b6001600160a01b0316146125905760405162461bcd60e51b8152600401610be4906145fc565b6001600160a01b0382166125f25760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f206164646044820152637265737360e01b6064820152608401610be4565b826001600160a01b0316612605826113e4565b6001600160a01b03161461262b5760405162461bcd60e51b8152600401610be4906145fc565b6000818152600f6020908152604080832080546001600160a01b03199081169091556001600160a01b03878116808652600e8552838620805460001901905590871680865283862080546001019055868652600d90945282852080549092168417909155905184937fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b604080516001808252818301909252606091600091906020808301908036833701905050905082816000815181106126f5576126f5614641565b602090810291909101015292915050565b600084511161274d5760405162461bcd60e51b8152602060048201526013602482015272746f6b656e4964735b5d20697320656d70747960681b6044820152606401610be4565b835160011480612771575061ffff8616600090815260086020526040902054845111155b6127c85760405162461bcd60e51b815260206004820152602260248201527f62617463682073697a65206578636565647320647374206261746368206c696d6044820152611a5d60f21b6064820152608401610be4565b60005b845181101561280b576127f98888888885815181106127ec576127ec614641565b6020026020010151612f84565b806128038161421b565b9150506127cb565b50600085856040516020016128219291906144e4565b6040516020818303038152906040529050612866876001848851600960008d61ffff1661ffff168152602001908152602001600020546128619190614657565b61306f565b61287487828686863461314e565b856040516128829190614676565b6040518091039020886001600160a01b03168861ffff167fe1b87c47fdeb4f9cbadbca9df3af7aba453bb6e501075d0440d88125b711522a886040516128c89190614692565b60405180910390a45050505050505050565b600080828060200190518101906128f1919061430f565b60148201519193509150600061290988838386612adb565b905082518110156129dd5784516020808701919091206040805160808101825261ffff808d1682526001600160a01b038088168387019081528385018881526001606086018181526000898152600a909a529887902095518654935190941662010000026001600160b01b03199093169390941692909217178355519082015592516002909301805493151560ff199094169390931790925590517f10e0b70d256bccc84b7027506978bd8b68984a870788b93b479def144c839ad7906129d390839089906146a5565b60405180910390a1505b816001600160a01b0316876040516129f59190614676565b60405180910390208961ffff167f5b821db8a46f8ecbe1941ba2f51cfeea9643268b56631f70d45e2a745d990265866040516128c89190614692565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60026006541415612ad45760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610be4565b6002600655565b6000825b82518110156122e3576007545a1015612af7576122e3565b612b1b8686858481518110612b0e57612b0e614641565b60200260200101516132f4565b80612b258161421b565b915050612adf565b606081612b3b81601f6146be565b1015612b7a5760405162461bcd60e51b815260206004820152600e60248201526d736c6963655f6f766572666c6f7760901b6044820152606401610be4565b612b8482846146be565b84511015612bc85760405162461bcd60e51b8152602060048201526011602482015270736c6963655f6f75744f66426f756e647360781b6044820152606401610be4565b606082158015612be75760405191506000825260208201604052612c31565b6040519150601f8416801560200281840101858101878315602002848b0101015b81831015612c20578051835260209283019201612c08565b5050858452601f01601f1916604052505b50949350505050565b816001600160a01b0316836001600160a01b03161415612c9c5760405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c6572000000000000006044820152606401610be4565b6001600160a01b03838116600081815260106020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b612d14848484612557565b612d2084848484613354565b611b6a5760405162461bcd60e51b8152600401610be4906146d6565b60606000612d498361344f565b60010190506000816001600160401b03811115612d6857612d68613aef565b6040519080825280601f01601f191660200182016040528015612d92576020820181803683370190505b5090508181016020015b600019016f181899199a1a9b1b9c1cb0b131b232b360811b600a86061a8153600a8504945084612dcb57612dd0565b612d9c565b509392505050565b6000606060008060008661ffff166001600160401b03811115612dfd57612dfd613aef565b6040519080825280601f01601f191660200182016040528015612e27576020820181803683370190505b50905060008087516020890160008d8df191503d925086831115612e49578692505b828152826000602083013e909890975095505050505050565b8180519060200120600560008761ffff1661ffff16815260200190815260200160002085604051612e939190614676565b9081526040805191829003602090810183206001600160401b0388166000908152915220919091557fe183f33de2837795525b4792ca4cd60535bd77c53b7e7030060bfcf5734d6b0c90612ef09087908790879087908790614728565b60405180910390a15050505050565b60006001600160e01b031982166322bac5d960e01b1480610dbe57506301ffc9a760e01b6001600160e01b0319831614610dbe565b6000908152600d60205260409020546001600160a01b0316151590565b612f5b8383613527565b612f686000848484613354565b6110175760405162461bcd60e51b8152600401610be4906146d6565b612f8d3361120d565b612ff05760405162461bcd60e51b815260206004820152602e60248201527f4f4e46543732313a2073656e642063616c6c6572206973206e6f74206f776e6560448201526d1c881b9bdc88185c1c1c9bdd995960921b6064820152608401610be4565b836001600160a01b0316613003826113e4565b6001600160a01b0316146130645760405162461bcd60e51b815260206004820152602260248201527f4f4e46543732313a2073656e642066726f6d20696e636f7272656374206f776e60448201526132b960f11b6064820152608401610be4565b611b6a843083612557565b600061307a83613694565b61ffff8087166000908152600260209081526040808320938916835292905290812054919250906130ac9084906146be565b9050600081116130fe5760405162461bcd60e51b815260206004820152601a60248201527f4c7a4170703a206d696e4761734c696d6974206e6f74207365740000000000006044820152606401610be4565b808210156115185760405162461bcd60e51b815260206004820152601b60248201527f4c7a4170703a20676173206c696d697420697320746f6f206c6f7700000000006044820152606401610be4565b61ffff86166000908152600160205260408120805461316c906141ba565b80601f0160208091040260200160405190810160405280929190818152602001828054613198906141ba565b80156131e55780601f106131ba576101008083540402835291602001916131e5565b820191906000526020600020905b8154815290600101906020018083116131c857829003601f168201915b505050505090508051600014156132575760405162461bcd60e51b815260206004820152603060248201527f4c7a4170703a2064657374696e6174696f6e20636861696e206973206e6f742060448201526f61207472757374656420736f7572636560801b6064820152608401610be4565b6132628787516136f0565b60405162c5803160e81b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063c58031009084906132b9908b9086908c908c908c908c9060040161477a565b6000604051808303818588803b1580156132d257600080fd5b505af11580156132e6573d6000803e3d6000fd5b505050505050505050505050565b6132fd81612f34565b1580613329575061330d81612f34565b801561332957503061331e826113e4565b6001600160a01b0316145b61333257600080fd5b61333b81612f34565b6133495761101782826124bf565b611017308383612557565b60006001600160a01b0384163b1561344757604051630a85bd0160e11b81526001600160a01b0385169063150b7a02906133989033908990889088906004016147e1565b6020604051808303816000875af19250505080156133d3575060408051601f3d908101601f191682019092526133d09181019061481e565b60015b61342d573d808015613401576040519150601f19603f3d011682016040523d82523d6000602084013e613406565b606091505b5080516134255760405162461bcd60e51b8152600401610be4906146d6565b805181602001fd5b6001600160e01b031916630a85bd0160e11b1490506122e6565b5060016122e6565b60008072184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b831061348e5772184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b830492506040015b6d04ee2d6d415b85acef810000000083106134ba576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc1000083106134d857662386f26fc10000830492506010015b6305f5e10083106134f0576305f5e100830492506008015b612710831061350457612710830492506004015b60648310613516576064830492506002015b600a8310610dbe5760010192915050565b6001600160a01b03821661357d5760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f20616464726573736044820152606401610be4565b61358681612f34565b156135d35760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e746564000000006044820152606401610be4565b6135dc81612f34565b156136295760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e746564000000006044820152606401610be4565b6001600160a01b0382166000818152600e6020908152604080832080546001019055848352600d90915280822080546001600160a01b0319168417905551839291907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b60006022825110156136e85760405162461bcd60e51b815260206004820152601c60248201527f4c7a4170703a20696e76616c69642061646170746572506172616d73000000006044820152606401610be4565b506022015190565b61ffff82166000908152600360205260409020548061370e57506127105b808211156110175760405162461bcd60e51b815260206004820181905260248201527f4c7a4170703a207061796c6f61642073697a6520697320746f6f206c617267656044820152606401610be4565b82805461376a906141ba565b90600052602060002090601f01602090048101928261378c57600085556137d2565b82601f106137a557805160ff19168380011785556137d2565b828001600101855582156137d2579182015b828111156137d25782518255916020019190600101906137b7565b506137de929150613856565b5090565b8280546137ee906141ba565b90600052602060002090601f01602090048101928261381057600085556137d2565b82601f106138295782800160ff198235161785556137d2565b828001600101855582156137d2579182015b828111156137d257823582559160200191906001019061383b565b5b808211156137de5760008155600101613857565b803561ffff8116811461387d57600080fd5b919050565b60008083601f84011261389457600080fd5b5081356001600160401b038111156138ab57600080fd5b6020830191508360208285010111156138c357600080fd5b9250929050565b80356001600160401b038116811461387d57600080fd5b600080600080600080608087890312156138fa57600080fd5b6139038761386b565b955060208701356001600160401b038082111561391f57600080fd5b61392b8a838b01613882565b909750955085915061393f60408a016138ca565b9450606089013591508082111561395557600080fd5b5061396289828a01613882565b979a9699509497509295939492505050565b6001600160e01b03198116811461120557600080fd5b60006020828403121561399c57600080fd5b8135611a8081613974565b60005b838110156139c25781810151838201526020016139aa565b83811115611b6a5750506000910152565b600081518084526139eb8160208601602086016139a7565b601f01601f19169290920160200192915050565b602081526000611a8060208301846139d3565b600060208284031215613a2457600080fd5b611a808261386b565b600060208284031215613a3f57600080fd5b5035919050565b6001600160a01b038116811461120557600080fd5b803561387d81613a46565b60008060408385031215613a7957600080fd5b8235613a8481613a46565b946020939093013593505050565b60008060408385031215613aa557600080fd5b613a848361386b565b600080600060608486031215613ac357600080fd5b8335613ace81613a46565b92506020840135613ade81613a46565b929592945050506040919091013590565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b0381118282101715613b2d57613b2d613aef565b604052919050565b60006001600160401b03821115613b4e57613b4e613aef565b50601f01601f191660200190565b600082601f830112613b6d57600080fd5b8135613b80613b7b82613b35565b613b05565b818152846020838601011115613b9557600080fd5b816020850160208301376000918101602001919091529392505050565b8035801515811461387d57600080fd5b600080600080600060a08688031215613bda57600080fd5b613be38661386b565b945060208601356001600160401b0380821115613bff57600080fd5b613c0b89838a01613b5c565b955060408801359450613c2060608901613bb2565b93506080880135915080821115613c3657600080fd5b50613c4388828901613b5c565b9150509295509295909350565b600080600060408486031215613c6557600080fd5b613c6e8461386b565b925060208401356001600160401b03811115613c8957600080fd5b613c9586828701613882565b9497909650939450505050565b600080600080600080600060e0888a031215613cbd57600080fd5b8735613cc881613a46565b9650613cd66020890161386b565b955060408801356001600160401b0380821115613cf257600080fd5b613cfe8b838c01613b5c565b965060608a0135955060808a01359150613d1782613a46565b90935060a089013590613d2982613a46565b90925060c08901359080821115613d3f57600080fd5b50613d4c8a828b01613b5c565b91505092959891949750929550565b600080600060608486031215613d7057600080fd5b613d798461386b565b925060208401356001600160401b03811115613d9457600080fd5b613da086828701613b5c565b925050613daf604085016138ca565b90509250925092565b600060208284031215613dca57600080fd5b8135611a8081613a46565b60008060408385031215613de857600080fd5b613df18361386b565b9150613dff6020840161386b565b90509250929050565b600060208284031215613e1a57600080fd5b81356001600160401b03811115613e3057600080fd5b6122e684828501613b5c565b60008060408385031215613e4f57600080fd5b8235613e5a81613a46565b9150613dff60208401613bb2565b60006001600160401b03821115613e8157613e81613aef565b5060051b60200190565b600082601f830112613e9c57600080fd5b81356020613eac613b7b83613e68565b82815260059290921b84018101918181019086841115613ecb57600080fd5b8286015b84811015613ee65780358352918301918301613ecf565b509695505050505050565b600080600080600080600060e0888a031215613f0c57600080fd5b8735613f1781613a46565b9650613f256020890161386b565b955060408801356001600160401b0380821115613f4157600080fd5b613f4d8b838c01613b5c565b965060608a0135915080821115613f6357600080fd5b613f6f8b838c01613e8b565b955060808a01359150613f8182613a46565b819450613f9060a08b01613a5b565b935060c08a0135915080821115613d3f57600080fd5b60008060008060808587031215613fbc57600080fd5b8435613fc781613a46565b93506020850135613fd781613a46565b92506040850135915060608501356001600160401b03811115613ff957600080fd5b61400587828801613b5c565b91505092959194509250565b60008060008060006080868803121561402957600080fd5b6140328661386b565b94506140406020870161386b565b93506040860135925060608601356001600160401b0381111561406257600080fd5b61406e88828901613882565b969995985093965092949392505050565b60008060006060848603121561409457600080fd5b61409d8461386b565b92506140ab6020850161386b565b9150604084013590509250925092565b600080604083850312156140ce57600080fd5b82356140d981613a46565b915060208301356140e981613a46565b809150509250929050565b600080600080600060a0868803121561410c57600080fd5b6141158661386b565b945060208601356001600160401b038082111561413157600080fd5b61413d89838a01613b5c565b9550604088013591508082111561415357600080fd5b61415f89838a01613e8b565b9450613c2060608901613bb2565b6000806000806080858703121561418357600080fd5b61418c8561386b565b935061419a6020860161386b565b925060408501356141aa81613a46565b9396929550929360600135925050565b600181811c908216806141ce57607f821691505b602082108114156141ef57634e487b7160e01b600052602260045260246000fd5b50919050565b8183823760009101908152919050565b634e487b7160e01b600052601160045260246000fd5b600060001982141561422f5761422f614205565b5060010190565b6020808252602d908201527f4552433732313a2063616c6c6572206973206e6f7420746f6b656e206f776e6560408201526c1c881bdc88185c1c1c9bdd9959609a1b606082015260800190565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b61ffff841681526040602082015260006122e3604083018486614283565b600082601f8301126142db57600080fd5b81516142e9613b7b82613b35565b8181528460208386010111156142fe57600080fd5b6122e68260208301602087016139a7565b6000806040838503121561432257600080fd5b82516001600160401b038082111561433957600080fd5b614345868387016142ca565b935060209150818501518181111561435c57600080fd5b85019050601f8101861361436f57600080fd5b805161437d613b7b82613e68565b81815260059190911b8201830190838101908883111561439c57600080fd5b928401925b828410156143ba578351825292840192908401906143a1565b80955050505050509250929050565b6000828210156143db576143db614205565b500390565b8284823760609190911b6bffffffffffffffffffffffff19169101908152601401919050565b600083516144188184602088016139a7565b83519083019061442c8183602088016139a7565b01949350505050565b600061ffff808816835280871660208401525084604083015260806060830152614463608083018486614283565b979650505050505050565b61ffff8616815260806020820152600061448c608083018688614283565b6001600160401b0394909416604083015250606001529392505050565b600081518084526020808501945080840160005b838110156144d9578151875295820195908201906001016144bd565b509495945050505050565b6040815260006144f760408301856139d3565b828103602084015261450981856144a9565b95945050505050565b61ffff861681526001600160a01b038516602082015260a060408201819052600090614540908301866139d3565b8415156060840152828103608084015261455a81856139d3565b98975050505050505050565b6000806040838503121561457957600080fd5b505080516020909101519092909150565b60006020828403121561459c57600080fd5b81516001600160401b038111156145b257600080fd5b6122e6848285016142ca565b61ffff851681526080602082015260006145db60808301866139d3565b6001600160401b0385166040840152828103606084015261446381856139d3565b60208082526025908201527f4552433732313a207472616e736665722066726f6d20696e636f72726563742060408201526437bbb732b960d91b606082015260800190565b634e487b7160e01b600052603260045260246000fd5b600081600019048311821515161561467157614671614205565b500290565b600082516146888184602087016139a7565b9190910192915050565b602081526000611a8060208301846144a9565b8281526040602082015260006122e660408301846139d3565b600082198211156146d1576146d1614205565b500190565b60208082526032908201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b606082015260800190565b61ffff8616815260a06020820152600061474560a08301876139d3565b6001600160401b0386166040840152828103606084015261476681866139d3565b9050828103608084015261455a81856139d3565b61ffff8716815260c06020820152600061479760c08301886139d3565b82810360408401526147a981886139d3565b6001600160a01b0387811660608601528616608085015283810360a085015290506147d481856139d3565b9998505050505050505050565b6001600160a01b0385811682528416602082015260408101839052608060608201819052600090614814908301846139d3565b9695505050505050565b60006020828403121561483057600080fd5b8151611a808161397456fea26469706673582212209d1f2077e2ec613c51f889ee55d33f6b9af56585183e8ce48e2b810c616ee6cb64736f6c634300080c00330000000000000000000000000000000000000000000000000000000000030d4000000000000000000000000066a71dcef29a0ffbdbe3c6a460a3b5bc225cd675000000000000000000000000000000000000000000000000000000000121eac10000000000000000000000000000000000000000000000000000000001312d00

Deployed Bytecode

0x6080604052600436106103755760003560e01c80638cfd8f5c116101d1578063c446183411610102578063e086e5ec116100a0578063f23536411161006f578063f235364114610ae3578063f2fde38b14610b03578063f5ecbdbc14610b23578063fa25f9b614610b4357600080fd5b8063e086e5ec14610a4f578063e1d4c87014610a64578063e985e9c514610a7a578063eb8d72b714610ac357600080fd5b8063d12473a5116100dc578063d12473a5146109e6578063d1deba1f14610a06578063ddca3f4314610a19578063df2a5b3b14610a2f57600080fd5b8063c446183414610990578063c87b56dd146109a6578063cbed8b9c146109c657600080fd5b8063a22cb4651161016f578063af3fb21c11610149578063af3fb21c146108f4578063b353aaa71461091c578063b88d4fde14610950578063baf3292d1461097057600080fd5b8063a22cb465146108a1578063a6c3d165146108c1578063ab3ffb93146108e157600080fd5b8063950c8a74116101ab578063950c8a741461082c57806395d89b411461084c5780639ea5d6b1146108615780639f38369a1461088157600080fd5b80638cfd8f5c146107b65780638da5cb5b146107ee5780638ffa1f2a1461080c57600080fd5b80633f1f4fa4116102ab5780636352211e116102495780636aa99da3116102235780636aa99da31461074b57806370a0823114610761578063715018a6146107815780637533d7881461079657600080fd5b80636352211e146106eb57806366ad5c8a1461070b57806369fe0e2d1461072b57600080fd5b8063482881901161028557806348288190146106465780634ac3f4ff1461065c57806351905636146106895780635b8c41e61461069c57600080fd5b80633f1f4fa4146105cb57806342842e0e1461060657806342d65a8d1461062657600080fd5b80630df374831161031857806322a3ecf9116102f257806322a3ecf9146104d357806323b872dd146105565780632a205e3d146105765780633d8b38f6146105ab57600080fd5b80630df374831461048b57806310ddb137146104ab5780631249c58b146104cb57600080fd5b806307e0db171161035457806307e0db17146103f3578063081812fc14610413578063095ea7b31461044b5780630b4cad4c1461046b57600080fd5b80621d35671461037a57806301ffc9a71461039c57806306fdde03146103d1575b600080fd5b34801561038657600080fd5b5061039a6103953660046138e1565b610b70565b005b3480156103a857600080fd5b506103bc6103b736600461398a565b610da1565b60405190151581526020015b60405180910390f35b3480156103dd57600080fd5b506103e6610dc4565b6040516103c891906139ff565b3480156103ff57600080fd5b5061039a61040e366004613a12565b610e56565b34801561041f57600080fd5b5061043361042e366004613a2d565b610edf565b6040516001600160a01b0390911681526020016103c8565b34801561045757600080fd5b5061039a610466366004613a66565b610f06565b34801561047757600080fd5b5061039a610486366004613a2d565b61101c565b34801561049757600080fd5b5061039a6104a6366004613a92565b6110bc565b3480156104b757600080fd5b5061039a6104c6366004613a12565b6110db565b61039a611133565b3480156104df57600080fd5b506105276104ee366004613a2d565b600a6020526000908152604090208054600182015460029092015461ffff821692620100009092046001600160a01b0316919060ff1684565b6040805161ffff90951685526001600160a01b03909316602085015291830152151560608201526080016103c8565b34801561056257600080fd5b5061039a610571366004613aae565b611208565b34801561058257600080fd5b50610596610591366004613bc2565b61123a565b604080519283526020830191909152016103c8565b3480156105b757600080fd5b506103bc6105c6366004613c50565b611260565b3480156105d757600080fd5b506105f86105e6366004613a12565b60036020526000908152604090205481565b6040519081526020016103c8565b34801561061257600080fd5b5061039a610621366004613aae565b61132c565b34801561063257600080fd5b5061039a610641366004613c50565b611347565b34801561065257600080fd5b506105f860075481565b34801561066857600080fd5b506105f8610677366004613a12565b60086020526000908152604090205481565b61039a610697366004613ca2565b6113cd565b3480156106a857600080fd5b506105f86106b7366004613d5b565b6005602090815260009384526040808520845180860184018051928152908401958401959095209452929052825290205481565b3480156106f757600080fd5b50610433610706366004613a2d565b6113e4565b34801561071757600080fd5b5061039a6107263660046138e1565b611444565b34801561073757600080fd5b5061039a610746366004613a2d565b611520565b34801561075757600080fd5b506105f860115481565b34801561076d57600080fd5b506105f861077c366004613db8565b61152d565b34801561078d57600080fd5b5061039a6115b3565b3480156107a257600080fd5b506103e66107b1366004613a12565b6115c7565b3480156107c257600080fd5b506105f86107d1366004613dd5565b600260209081526000928352604080842090915290825290205481565b3480156107fa57600080fd5b506000546001600160a01b0316610433565b34801561081857600080fd5b5061039a610827366004613e08565b611661565b34801561083857600080fd5b50600454610433906001600160a01b031681565b34801561085857600080fd5b506103e66118aa565b34801561086d57600080fd5b5061039a61087c366004613a92565b6118b9565b34801561088d57600080fd5b506103e661089c366004613a12565b611970565b3480156108ad57600080fd5b5061039a6108bc366004613e3c565b611a87565b3480156108cd57600080fd5b5061039a6108dc366004613c50565b611a96565b61039a6108ef366004613ef1565b611b29565b34801561090057600080fd5b50610909600181565b60405161ffff90911681526020016103c8565b34801561092857600080fd5b506104337f00000000000000000000000066a71dcef29a0ffbdbe3c6a460a3b5bc225cd67581565b34801561095c57600080fd5b5061039a61096b366004613fa6565b611b38565b34801561097c57600080fd5b5061039a61098b366004613db8565b611b70565b34801561099c57600080fd5b506105f861271081565b3480156109b257600080fd5b506103e66109c1366004613a2d565b611bc6565b3480156109d257600080fd5b5061039a6109e1366004614011565b611c39565b3480156109f257600080fd5b5061039a610a01366004613a92565b611cce565b61039a610a143660046138e1565b611d7e565b348015610a2557600080fd5b506105f860135481565b348015610a3b57600080fd5b5061039a610a4a36600461407f565b611f94565b348015610a5b57600080fd5b506103bc612046565b348015610a7057600080fd5b506105f860125481565b348015610a8657600080fd5b506103bc610a953660046140bb565b6001600160a01b03918216600090815260106020908152604080832093909416825291909152205460ff1690565b348015610acf57600080fd5b5061039a610ade366004613c50565b6120a0565b348015610aef57600080fd5b50610596610afe3660046140f4565b6120fa565b348015610b0f57600080fd5b5061039a610b1e366004613db8565b6121c5565b348015610b2f57600080fd5b506103e6610b3e36600461416d565b61223b565b348015610b4f57600080fd5b506105f8610b5e366004613a12565b60096020526000908152604090205481565b337f00000000000000000000000066a71dcef29a0ffbdbe3c6a460a3b5bc225cd6756001600160a01b031614610bed5760405162461bcd60e51b815260206004820152601e60248201527f4c7a4170703a20696e76616c696420656e64706f696e742063616c6c6572000060448201526064015b60405180910390fd5b61ffff861660009081526001602052604081208054610c0b906141ba565b80601f0160208091040260200160405190810160405280929190818152602001828054610c37906141ba565b8015610c845780601f10610c5957610100808354040283529160200191610c84565b820191906000526020600020905b815481529060010190602001808311610c6757829003601f168201915b50505050509050805186869050148015610c9f575060008151115b8015610cc7575080516020820120604051610cbd90889088906141f5565b6040518091039020145b610d225760405162461bcd60e51b815260206004820152602660248201527f4c7a4170703a20696e76616c696420736f757263652073656e64696e6720636f6044820152651b9d1c9858dd60d21b6064820152608401610be4565b610d988787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f8a018190048102820181019092528881528a9350915088908890819084018382808284376000920191909152506122ee92505050565b50505050505050565b60006001600160e01b031982161580610dbe5750610dbe82612367565b92915050565b6060600b8054610dd3906141ba565b80601f0160208091040260200160405190810160405280929190818152602001828054610dff906141ba565b8015610e4c5780601f10610e2157610100808354040283529160200191610e4c565b820191906000526020600020905b815481529060010190602001808311610e2f57829003601f168201915b5050505050905090565b610e5e6123a7565b6040516307e0db1760e01b815261ffff821660048201527f00000000000000000000000066a71dcef29a0ffbdbe3c6a460a3b5bc225cd6756001600160a01b0316906307e0db17906024015b600060405180830381600087803b158015610ec457600080fd5b505af1158015610ed8573d6000803e3d6000fd5b5050505050565b6000610eea82612401565b506000908152600f60205260409020546001600160a01b031690565b6000610f11826113e4565b9050806001600160a01b0316836001600160a01b03161415610f7f5760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e656044820152603960f91b6064820152608401610be4565b336001600160a01b0382161480610f9b5750610f9b8133610a95565b61100d5760405162461bcd60e51b815260206004820152603d60248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f7420746f60448201527f6b656e206f776e6572206f7220617070726f76656420666f7220616c6c0000006064820152608401610be4565b6110178383612451565b505050565b6110246123a7565b600081116110805760405162461bcd60e51b8152602060048201526024808201527f6d696e476173546f5472616e73666572416e6453746f7265206d7573742062656044820152630203e20360e41b6064820152608401610be4565b60078190556040518181527ffebbc4f8bb9ec2313950c718d43123124b15778efda4c1f1d529de2995b4f34d906020015b60405180910390a150565b6110c46123a7565b61ffff909116600090815260036020526040902055565b6110e36123a7565b6040516310ddb13760e01b815261ffff821660048201527f00000000000000000000000066a71dcef29a0ffbdbe3c6a460a3b5bc225cd6756001600160a01b0316906310ddb13790602401610eaa565b60125460115411156111925760405162461bcd60e51b815260206004820152602260248201527f4c324d61726174686f6e3a206d6178206d696e74206c696d6974207265616368604482015261195960f21b6064820152608401610be4565b6013543410156111e45760405162461bcd60e51b815260206004820152601f60248201527f4e6f7420656e6f756768204554482073656e743a20636865636b206665652e006044820152606401610be4565b6011805490819060006111f68361421b565b919050555061120533826124bf565b50565b611213335b826124d9565b61122f5760405162461bcd60e51b8152600401610be490614236565b611017838383612557565b600080611252878761124b886126bb565b87876120fa565b915091509550959350505050565b61ffff831660009081526001602052604081208054829190611281906141ba565b80601f01602080910402602001604051908101604052809291908181526020018280546112ad906141ba565b80156112fa5780601f106112cf576101008083540402835291602001916112fa565b820191906000526020600020905b8154815290600101906020018083116112dd57829003601f168201915b5050505050905083836040516113119291906141f5565b60405180910390208180519060200120149150509392505050565b61101783838360405180602001604052806000815250611b38565b61134f6123a7565b6040516342d65a8d60e01b81526001600160a01b037f00000000000000000000000066a71dcef29a0ffbdbe3c6a460a3b5bc225cd67516906342d65a8d9061139f908690869086906004016142ac565b600060405180830381600087803b1580156113b957600080fd5b505af1158015610d98573d6000803e3d6000fd5b610d988787876113dc886126bb565b878787612706565b6000818152600d60205260408120546001600160a01b031680610dbe5760405162461bcd60e51b8152602060048201526018602482015277115490cdcc8c4e881a5b9d985b1a59081d1bdad95b88125160421b6044820152606401610be4565b3330146114a25760405162461bcd60e51b815260206004820152602660248201527f4e6f6e626c6f636b696e674c7a4170703a2063616c6c6572206d7573742062656044820152650204c7a4170760d41b6064820152608401610be4565b6115188686868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f8901819004810282018101909252878152899350915087908790819084018382808284376000920191909152506128da92505050565b505050505050565b6115286123a7565b601355565b60006001600160a01b0382166115975760405162461bcd60e51b815260206004820152602960248201527f4552433732313a2061646472657373207a65726f206973206e6f7420612076616044820152683634b21037bbb732b960b91b6064820152608401610be4565b506001600160a01b03166000908152600e602052604090205490565b6115bb6123a7565b6115c56000612a31565b565b600160205260009081526040902080546115e0906141ba565b80601f016020809104026020016040519081016040528092919081815260200182805461160c906141ba565b80156116595780601f1061162e57610100808354040283529160200191611659565b820191906000526020600020905b81548152906001019060200180831161163c57829003601f168201915b505050505081565b611669612a81565b80516020808301919091206000818152600a90925260409091206002015460ff166116ca5760405162461bcd60e51b81526020600482015260116024820152701b9bc818dc99591a5d1cc81cdd1bdc9959607a1b6044820152606401610be4565b6000828060200190518101906116e0919061430f565b6000848152600a60205260408120805460019091015492945090925061171c9161ffff8216916201000090046001600160a01b03169085612adb565b6000848152600a602052604090206001015490915081116117915760405162461bcd60e51b815260206004820152602960248201527f6e6f7420656e6f7567682067617320746f2070726f6365737320637265646974604482015268103a3930b739b332b960b91b6064820152608401610be4565b8151811415611809576000838152600a602052604080822080546001600160b01b031916815560018101929092556002909101805460ff19169055517fd7be02b8dd0d27bd0517a9cb4d7469ce27df4313821ae5ec1ff69acc594ba233906117fc9085815260200190565b60405180910390a161189d565b604080516080810182526000858152600a6020818152848320805461ffff80821687526001600160a01b03620100008084048216868a019081529989018b8152600160608b01818152998f90529790965297519851169096026001600160b01b03199091169690951695909517939093178455915191830191909155516002909101805491151560ff199092169190911790555b5050506112056001600655565b6060600c8054610dd3906141ba565b6118c16123a7565b6000811161191c5760405162461bcd60e51b815260206004820152602260248201527f647374436861696e4964546f42617463684c696d6974206d757374206265203e604482015261020360f41b6064820152608401610be4565b61ffff8216600081815260086020908152604091829020849055815192835282018390527f7315f7654d594ead24a30160ed9ba2d23247f543016b918343591e93d7afdb6d91015b60405180910390a15050565b61ffff8116600090815260016020526040812080546060929190611993906141ba565b80601f01602080910402602001604051908101604052809291908181526020018280546119bf906141ba565b8015611a0c5780601f106119e157610100808354040283529160200191611a0c565b820191906000526020600020905b8154815290600101906020018083116119ef57829003601f168201915b50505050509050805160001415611a655760405162461bcd60e51b815260206004820152601d60248201527f4c7a4170703a206e6f20747275737465642070617468207265636f72640000006044820152606401610be4565b611a80600060148351611a7891906143c9565b839190612b2d565b9392505050565b611a92338383612c3a565b5050565b611a9e6123a7565b818130604051602001611ab3939291906143e0565b60408051601f1981840301815291815261ffff85166000908152600160209081529190208251611ae89391929091019061375e565b507f8c0400cfe2d1199b1a725c78960bcc2a344d869b80590d0f2bd005db15a572ce838383604051611b1c939291906142ac565b60405180910390a1505050565b610d9887878787878787612706565b611b4233836124d9565b611b5e5760405162461bcd60e51b8152600401610be490614236565b611b6a84848484612d09565b50505050565b611b786123a7565b600480546001600160a01b0319166001600160a01b0383169081179091556040519081527f5db758e995a17ec1ad84bdef7e8c3293a0bd6179bcce400dff5d4c3d87db726b906020016110b1565b6060611bd182612401565b6000611be860408051602081019091526000815290565b90506000815111611c085760405180602001604052806000815250611a80565b80611c1284612d3c565b604051602001611c23929190614406565b6040516020818303038152906040529392505050565b611c416123a7565b6040516332fb62e760e21b81526001600160a01b037f00000000000000000000000066a71dcef29a0ffbdbe3c6a460a3b5bc225cd675169063cbed8b9c90611c959088908890889088908890600401614435565b600060405180830381600087803b158015611caf57600080fd5b505af1158015611cc3573d6000803e3d6000fd5b505050505050505050565b611cd66123a7565b60008111611d325760405162461bcd60e51b815260206004820152602360248201527f647374436861696e4964546f5472616e73666572476173206d7573742062652060448201526203e20360ec1b6064820152608401610be4565b61ffff8216600081815260096020908152604091829020849055815192835282018390527fc46df2983228ac2d9754e94a0d565e6671665dc8ad38602bc8e544f0685a29fb9101611964565b61ffff86166000908152600560205260408082209051611da190889088906141f5565b90815260408051602092819003830190206001600160401b03871660009081529252902054905080611e215760405162461bcd60e51b815260206004820152602360248201527f4e6f6e626c6f636b696e674c7a4170703a206e6f2073746f726564206d65737360448201526261676560e81b6064820152608401610be4565b808383604051611e329291906141f5565b604051809103902014611e915760405162461bcd60e51b815260206004820152602160248201527f4e6f6e626c6f636b696e674c7a4170703a20696e76616c6964207061796c6f616044820152601960fa1b6064820152608401610be4565b61ffff87166000908152600560205260408082209051611eb490899089906141f5565b90815260408051602092819003830181206001600160401b038916600090815290845282902093909355601f88018290048202830182019052868252611f4c918991899089908190840183828082843760009201919091525050604080516020601f8a018190048102820181019092528881528a9350915088908890819084018382808284376000920191909152506128da92505050565b7fc264d91f3adc5588250e1551f547752ca0cfa8f6b530d243b9f9f4cab10ea8e58787878785604051611f8395949392919061446e565b60405180910390a150505050505050565b611f9c6123a7565b60008111611fe45760405162461bcd60e51b81526020600482015260156024820152744c7a4170703a20696e76616c6964206d696e47617360581b6044820152606401610be4565b61ffff83811660008181526002602090815260408083209487168084529482529182902085905581519283528201929092529081018290527f9d5c7c0b934da8fefa9c7760c98383778a12dfbfc0c3b3106518f43fb9508ac090606001611b1c565b60006120506123a7565b604051600090339047908381818185875af1925050503d8060008114612092576040519150601f19603f3d011682016040523d82523d6000602084013e612097565b606091505b50909250505090565b6120a86123a7565b61ffff831660009081526001602052604090206120c69083836137e2565b507ffa41487ad5d6728f0b19276fa1eddc16558578f5109fc39d2dc33c3230470dab838383604051611b1c939291906142ac565b600080600086866040516020016121129291906144e4565b60408051601f198184030181529082905263040a7bb160e41b825291506001600160a01b037f00000000000000000000000066a71dcef29a0ffbdbe3c6a460a3b5bc225cd67516906340a7bb1090612176908b90309086908b908b90600401614512565b6040805180830381865afa158015612192573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121b69190614566565b92509250509550959350505050565b6121cd6123a7565b6001600160a01b0381166122325760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610be4565b61120581612a31565b604051633d7b2f6f60e21b815261ffff808616600483015284166024820152306044820152606481018290526060907f00000000000000000000000066a71dcef29a0ffbdbe3c6a460a3b5bc225cd6756001600160a01b03169063f5ecbdbc90608401600060405180830381865afa1580156122bb573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526122e3919081019061458a565b90505b949350505050565b6000806123515a60966366ad5c8a60e01b8989898960405160240161231694939291906145be565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915230929190612dd8565b9150915081611518576115188686868685612e62565b60006001600160e01b031982166380ac58cd60e01b148061239857506001600160e01b03198216635b5e139f60e01b145b80610dbe5750610dbe82612eff565b6000546001600160a01b031633146115c55760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610be4565b61240a81612f34565b6112055760405162461bcd60e51b8152602060048201526018602482015277115490cdcc8c4e881a5b9d985b1a59081d1bdad95b88125160421b6044820152606401610be4565b6000818152600f6020526040902080546001600160a01b0319166001600160a01b0384169081179091558190612486826113e4565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b611a92828260405180602001604052806000815250612f51565b6000806124e5836113e4565b9050806001600160a01b0316846001600160a01b0316148061252c57506001600160a01b0380821660009081526010602090815260408083209388168352929052205460ff165b806122e65750836001600160a01b031661254584610edf565b6001600160a01b031614949350505050565b826001600160a01b031661256a826113e4565b6001600160a01b0316146125905760405162461bcd60e51b8152600401610be4906145fc565b6001600160a01b0382166125f25760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f206164646044820152637265737360e01b6064820152608401610be4565b826001600160a01b0316612605826113e4565b6001600160a01b03161461262b5760405162461bcd60e51b8152600401610be4906145fc565b6000818152600f6020908152604080832080546001600160a01b03199081169091556001600160a01b03878116808652600e8552838620805460001901905590871680865283862080546001019055868652600d90945282852080549092168417909155905184937fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b604080516001808252818301909252606091600091906020808301908036833701905050905082816000815181106126f5576126f5614641565b602090810291909101015292915050565b600084511161274d5760405162461bcd60e51b8152602060048201526013602482015272746f6b656e4964735b5d20697320656d70747960681b6044820152606401610be4565b835160011480612771575061ffff8616600090815260086020526040902054845111155b6127c85760405162461bcd60e51b815260206004820152602260248201527f62617463682073697a65206578636565647320647374206261746368206c696d6044820152611a5d60f21b6064820152608401610be4565b60005b845181101561280b576127f98888888885815181106127ec576127ec614641565b6020026020010151612f84565b806128038161421b565b9150506127cb565b50600085856040516020016128219291906144e4565b6040516020818303038152906040529050612866876001848851600960008d61ffff1661ffff168152602001908152602001600020546128619190614657565b61306f565b61287487828686863461314e565b856040516128829190614676565b6040518091039020886001600160a01b03168861ffff167fe1b87c47fdeb4f9cbadbca9df3af7aba453bb6e501075d0440d88125b711522a886040516128c89190614692565b60405180910390a45050505050505050565b600080828060200190518101906128f1919061430f565b60148201519193509150600061290988838386612adb565b905082518110156129dd5784516020808701919091206040805160808101825261ffff808d1682526001600160a01b038088168387019081528385018881526001606086018181526000898152600a909a529887902095518654935190941662010000026001600160b01b03199093169390941692909217178355519082015592516002909301805493151560ff199094169390931790925590517f10e0b70d256bccc84b7027506978bd8b68984a870788b93b479def144c839ad7906129d390839089906146a5565b60405180910390a1505b816001600160a01b0316876040516129f59190614676565b60405180910390208961ffff167f5b821db8a46f8ecbe1941ba2f51cfeea9643268b56631f70d45e2a745d990265866040516128c89190614692565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60026006541415612ad45760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610be4565b6002600655565b6000825b82518110156122e3576007545a1015612af7576122e3565b612b1b8686858481518110612b0e57612b0e614641565b60200260200101516132f4565b80612b258161421b565b915050612adf565b606081612b3b81601f6146be565b1015612b7a5760405162461bcd60e51b815260206004820152600e60248201526d736c6963655f6f766572666c6f7760901b6044820152606401610be4565b612b8482846146be565b84511015612bc85760405162461bcd60e51b8152602060048201526011602482015270736c6963655f6f75744f66426f756e647360781b6044820152606401610be4565b606082158015612be75760405191506000825260208201604052612c31565b6040519150601f8416801560200281840101858101878315602002848b0101015b81831015612c20578051835260209283019201612c08565b5050858452601f01601f1916604052505b50949350505050565b816001600160a01b0316836001600160a01b03161415612c9c5760405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c6572000000000000006044820152606401610be4565b6001600160a01b03838116600081815260106020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b612d14848484612557565b612d2084848484613354565b611b6a5760405162461bcd60e51b8152600401610be4906146d6565b60606000612d498361344f565b60010190506000816001600160401b03811115612d6857612d68613aef565b6040519080825280601f01601f191660200182016040528015612d92576020820181803683370190505b5090508181016020015b600019016f181899199a1a9b1b9c1cb0b131b232b360811b600a86061a8153600a8504945084612dcb57612dd0565b612d9c565b509392505050565b6000606060008060008661ffff166001600160401b03811115612dfd57612dfd613aef565b6040519080825280601f01601f191660200182016040528015612e27576020820181803683370190505b50905060008087516020890160008d8df191503d925086831115612e49578692505b828152826000602083013e909890975095505050505050565b8180519060200120600560008761ffff1661ffff16815260200190815260200160002085604051612e939190614676565b9081526040805191829003602090810183206001600160401b0388166000908152915220919091557fe183f33de2837795525b4792ca4cd60535bd77c53b7e7030060bfcf5734d6b0c90612ef09087908790879087908790614728565b60405180910390a15050505050565b60006001600160e01b031982166322bac5d960e01b1480610dbe57506301ffc9a760e01b6001600160e01b0319831614610dbe565b6000908152600d60205260409020546001600160a01b0316151590565b612f5b8383613527565b612f686000848484613354565b6110175760405162461bcd60e51b8152600401610be4906146d6565b612f8d3361120d565b612ff05760405162461bcd60e51b815260206004820152602e60248201527f4f4e46543732313a2073656e642063616c6c6572206973206e6f74206f776e6560448201526d1c881b9bdc88185c1c1c9bdd995960921b6064820152608401610be4565b836001600160a01b0316613003826113e4565b6001600160a01b0316146130645760405162461bcd60e51b815260206004820152602260248201527f4f4e46543732313a2073656e642066726f6d20696e636f7272656374206f776e60448201526132b960f11b6064820152608401610be4565b611b6a843083612557565b600061307a83613694565b61ffff8087166000908152600260209081526040808320938916835292905290812054919250906130ac9084906146be565b9050600081116130fe5760405162461bcd60e51b815260206004820152601a60248201527f4c7a4170703a206d696e4761734c696d6974206e6f74207365740000000000006044820152606401610be4565b808210156115185760405162461bcd60e51b815260206004820152601b60248201527f4c7a4170703a20676173206c696d697420697320746f6f206c6f7700000000006044820152606401610be4565b61ffff86166000908152600160205260408120805461316c906141ba565b80601f0160208091040260200160405190810160405280929190818152602001828054613198906141ba565b80156131e55780601f106131ba576101008083540402835291602001916131e5565b820191906000526020600020905b8154815290600101906020018083116131c857829003601f168201915b505050505090508051600014156132575760405162461bcd60e51b815260206004820152603060248201527f4c7a4170703a2064657374696e6174696f6e20636861696e206973206e6f742060448201526f61207472757374656420736f7572636560801b6064820152608401610be4565b6132628787516136f0565b60405162c5803160e81b81526001600160a01b037f00000000000000000000000066a71dcef29a0ffbdbe3c6a460a3b5bc225cd675169063c58031009084906132b9908b9086908c908c908c908c9060040161477a565b6000604051808303818588803b1580156132d257600080fd5b505af11580156132e6573d6000803e3d6000fd5b505050505050505050505050565b6132fd81612f34565b1580613329575061330d81612f34565b801561332957503061331e826113e4565b6001600160a01b0316145b61333257600080fd5b61333b81612f34565b6133495761101782826124bf565b611017308383612557565b60006001600160a01b0384163b1561344757604051630a85bd0160e11b81526001600160a01b0385169063150b7a02906133989033908990889088906004016147e1565b6020604051808303816000875af19250505080156133d3575060408051601f3d908101601f191682019092526133d09181019061481e565b60015b61342d573d808015613401576040519150601f19603f3d011682016040523d82523d6000602084013e613406565b606091505b5080516134255760405162461bcd60e51b8152600401610be4906146d6565b805181602001fd5b6001600160e01b031916630a85bd0160e11b1490506122e6565b5060016122e6565b60008072184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b831061348e5772184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b830492506040015b6d04ee2d6d415b85acef810000000083106134ba576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc1000083106134d857662386f26fc10000830492506010015b6305f5e10083106134f0576305f5e100830492506008015b612710831061350457612710830492506004015b60648310613516576064830492506002015b600a8310610dbe5760010192915050565b6001600160a01b03821661357d5760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f20616464726573736044820152606401610be4565b61358681612f34565b156135d35760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e746564000000006044820152606401610be4565b6135dc81612f34565b156136295760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e746564000000006044820152606401610be4565b6001600160a01b0382166000818152600e6020908152604080832080546001019055848352600d90915280822080546001600160a01b0319168417905551839291907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b60006022825110156136e85760405162461bcd60e51b815260206004820152601c60248201527f4c7a4170703a20696e76616c69642061646170746572506172616d73000000006044820152606401610be4565b506022015190565b61ffff82166000908152600360205260409020548061370e57506127105b808211156110175760405162461bcd60e51b815260206004820181905260248201527f4c7a4170703a207061796c6f61642073697a6520697320746f6f206c617267656044820152606401610be4565b82805461376a906141ba565b90600052602060002090601f01602090048101928261378c57600085556137d2565b82601f106137a557805160ff19168380011785556137d2565b828001600101855582156137d2579182015b828111156137d25782518255916020019190600101906137b7565b506137de929150613856565b5090565b8280546137ee906141ba565b90600052602060002090601f01602090048101928261381057600085556137d2565b82601f106138295782800160ff198235161785556137d2565b828001600101855582156137d2579182015b828111156137d257823582559160200191906001019061383b565b5b808211156137de5760008155600101613857565b803561ffff8116811461387d57600080fd5b919050565b60008083601f84011261389457600080fd5b5081356001600160401b038111156138ab57600080fd5b6020830191508360208285010111156138c357600080fd5b9250929050565b80356001600160401b038116811461387d57600080fd5b600080600080600080608087890312156138fa57600080fd5b6139038761386b565b955060208701356001600160401b038082111561391f57600080fd5b61392b8a838b01613882565b909750955085915061393f60408a016138ca565b9450606089013591508082111561395557600080fd5b5061396289828a01613882565b979a9699509497509295939492505050565b6001600160e01b03198116811461120557600080fd5b60006020828403121561399c57600080fd5b8135611a8081613974565b60005b838110156139c25781810151838201526020016139aa565b83811115611b6a5750506000910152565b600081518084526139eb8160208601602086016139a7565b601f01601f19169290920160200192915050565b602081526000611a8060208301846139d3565b600060208284031215613a2457600080fd5b611a808261386b565b600060208284031215613a3f57600080fd5b5035919050565b6001600160a01b038116811461120557600080fd5b803561387d81613a46565b60008060408385031215613a7957600080fd5b8235613a8481613a46565b946020939093013593505050565b60008060408385031215613aa557600080fd5b613a848361386b565b600080600060608486031215613ac357600080fd5b8335613ace81613a46565b92506020840135613ade81613a46565b929592945050506040919091013590565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b0381118282101715613b2d57613b2d613aef565b604052919050565b60006001600160401b03821115613b4e57613b4e613aef565b50601f01601f191660200190565b600082601f830112613b6d57600080fd5b8135613b80613b7b82613b35565b613b05565b818152846020838601011115613b9557600080fd5b816020850160208301376000918101602001919091529392505050565b8035801515811461387d57600080fd5b600080600080600060a08688031215613bda57600080fd5b613be38661386b565b945060208601356001600160401b0380821115613bff57600080fd5b613c0b89838a01613b5c565b955060408801359450613c2060608901613bb2565b93506080880135915080821115613c3657600080fd5b50613c4388828901613b5c565b9150509295509295909350565b600080600060408486031215613c6557600080fd5b613c6e8461386b565b925060208401356001600160401b03811115613c8957600080fd5b613c9586828701613882565b9497909650939450505050565b600080600080600080600060e0888a031215613cbd57600080fd5b8735613cc881613a46565b9650613cd66020890161386b565b955060408801356001600160401b0380821115613cf257600080fd5b613cfe8b838c01613b5c565b965060608a0135955060808a01359150613d1782613a46565b90935060a089013590613d2982613a46565b90925060c08901359080821115613d3f57600080fd5b50613d4c8a828b01613b5c565b91505092959891949750929550565b600080600060608486031215613d7057600080fd5b613d798461386b565b925060208401356001600160401b03811115613d9457600080fd5b613da086828701613b5c565b925050613daf604085016138ca565b90509250925092565b600060208284031215613dca57600080fd5b8135611a8081613a46565b60008060408385031215613de857600080fd5b613df18361386b565b9150613dff6020840161386b565b90509250929050565b600060208284031215613e1a57600080fd5b81356001600160401b03811115613e3057600080fd5b6122e684828501613b5c565b60008060408385031215613e4f57600080fd5b8235613e5a81613a46565b9150613dff60208401613bb2565b60006001600160401b03821115613e8157613e81613aef565b5060051b60200190565b600082601f830112613e9c57600080fd5b81356020613eac613b7b83613e68565b82815260059290921b84018101918181019086841115613ecb57600080fd5b8286015b84811015613ee65780358352918301918301613ecf565b509695505050505050565b600080600080600080600060e0888a031215613f0c57600080fd5b8735613f1781613a46565b9650613f256020890161386b565b955060408801356001600160401b0380821115613f4157600080fd5b613f4d8b838c01613b5c565b965060608a0135915080821115613f6357600080fd5b613f6f8b838c01613e8b565b955060808a01359150613f8182613a46565b819450613f9060a08b01613a5b565b935060c08a0135915080821115613d3f57600080fd5b60008060008060808587031215613fbc57600080fd5b8435613fc781613a46565b93506020850135613fd781613a46565b92506040850135915060608501356001600160401b03811115613ff957600080fd5b61400587828801613b5c565b91505092959194509250565b60008060008060006080868803121561402957600080fd5b6140328661386b565b94506140406020870161386b565b93506040860135925060608601356001600160401b0381111561406257600080fd5b61406e88828901613882565b969995985093965092949392505050565b60008060006060848603121561409457600080fd5b61409d8461386b565b92506140ab6020850161386b565b9150604084013590509250925092565b600080604083850312156140ce57600080fd5b82356140d981613a46565b915060208301356140e981613a46565b809150509250929050565b600080600080600060a0868803121561410c57600080fd5b6141158661386b565b945060208601356001600160401b038082111561413157600080fd5b61413d89838a01613b5c565b9550604088013591508082111561415357600080fd5b61415f89838a01613e8b565b9450613c2060608901613bb2565b6000806000806080858703121561418357600080fd5b61418c8561386b565b935061419a6020860161386b565b925060408501356141aa81613a46565b9396929550929360600135925050565b600181811c908216806141ce57607f821691505b602082108114156141ef57634e487b7160e01b600052602260045260246000fd5b50919050565b8183823760009101908152919050565b634e487b7160e01b600052601160045260246000fd5b600060001982141561422f5761422f614205565b5060010190565b6020808252602d908201527f4552433732313a2063616c6c6572206973206e6f7420746f6b656e206f776e6560408201526c1c881bdc88185c1c1c9bdd9959609a1b606082015260800190565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b61ffff841681526040602082015260006122e3604083018486614283565b600082601f8301126142db57600080fd5b81516142e9613b7b82613b35565b8181528460208386010111156142fe57600080fd5b6122e68260208301602087016139a7565b6000806040838503121561432257600080fd5b82516001600160401b038082111561433957600080fd5b614345868387016142ca565b935060209150818501518181111561435c57600080fd5b85019050601f8101861361436f57600080fd5b805161437d613b7b82613e68565b81815260059190911b8201830190838101908883111561439c57600080fd5b928401925b828410156143ba578351825292840192908401906143a1565b80955050505050509250929050565b6000828210156143db576143db614205565b500390565b8284823760609190911b6bffffffffffffffffffffffff19169101908152601401919050565b600083516144188184602088016139a7565b83519083019061442c8183602088016139a7565b01949350505050565b600061ffff808816835280871660208401525084604083015260806060830152614463608083018486614283565b979650505050505050565b61ffff8616815260806020820152600061448c608083018688614283565b6001600160401b0394909416604083015250606001529392505050565b600081518084526020808501945080840160005b838110156144d9578151875295820195908201906001016144bd565b509495945050505050565b6040815260006144f760408301856139d3565b828103602084015261450981856144a9565b95945050505050565b61ffff861681526001600160a01b038516602082015260a060408201819052600090614540908301866139d3565b8415156060840152828103608084015261455a81856139d3565b98975050505050505050565b6000806040838503121561457957600080fd5b505080516020909101519092909150565b60006020828403121561459c57600080fd5b81516001600160401b038111156145b257600080fd5b6122e6848285016142ca565b61ffff851681526080602082015260006145db60808301866139d3565b6001600160401b0385166040840152828103606084015261446381856139d3565b60208082526025908201527f4552433732313a207472616e736665722066726f6d20696e636f72726563742060408201526437bbb732b960d91b606082015260800190565b634e487b7160e01b600052603260045260246000fd5b600081600019048311821515161561467157614671614205565b500290565b600082516146888184602087016139a7565b9190910192915050565b602081526000611a8060208301846144a9565b8281526040602082015260006122e660408301846139d3565b600082198211156146d1576146d1614205565b500190565b60208082526032908201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b606082015260800190565b61ffff8616815260a06020820152600061474560a08301876139d3565b6001600160401b0386166040840152828103606084015261476681866139d3565b9050828103608084015261455a81856139d3565b61ffff8716815260c06020820152600061479760c08301886139d3565b82810360408401526147a981886139d3565b6001600160a01b0387811660608601528616608085015283810360a085015290506147d481856139d3565b9998505050505050505050565b6001600160a01b0385811682528416602082015260408101839052608060608201819052600090614814908301846139d3565b9695505050505050565b60006020828403121561483057600080fd5b8151611a808161397456fea26469706673582212209d1f2077e2ec613c51f889ee55d33f6b9af56585183e8ce48e2b810c616ee6cb64736f6c634300080c0033

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

0000000000000000000000000000000000000000000000000000000000030d4000000000000000000000000066a71dcef29a0ffbdbe3c6a460a3b5bc225cd675000000000000000000000000000000000000000000000000000000000121eac10000000000000000000000000000000000000000000000000000000001312d00

-----Decoded View---------------
Arg [0] : _minGasToStore (uint256): 200000
Arg [1] : _layerZeroEndpoint (address): 0x66A71Dcef29A0fFBDBE3c6a460a3B5BC225Cd675
Arg [2] : _startMintId (uint256): 19000001
Arg [3] : _endMintId (uint256): 20000000

-----Encoded View---------------
4 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000030d40
Arg [1] : 00000000000000000000000066a71dcef29a0ffbdbe3c6a460a3b5bc225cd675
Arg [2] : 000000000000000000000000000000000000000000000000000000000121eac1
Arg [3] : 0000000000000000000000000000000000000000000000000000000001312d00


Deployed Bytecode Sourcemap

120084:263:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;45130:762;;;;;;;;;;-1:-1:-1;45130:762:0;;;;;:::i;:::-;;:::i;:::-;;117291:228;;;;;;;;;;-1:-1:-1;117291:228:0;;;;;:::i;:::-;;:::i;:::-;;;2124:14:1;;2117:22;2099:41;;2087:2;2072:18;117291:228:0;;;;;;;;102011:100;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;48428:123::-;;;;;;;;;;-1:-1:-1;48428:123:0;;;;;:::i;:::-;;:::i;103523:171::-;;;;;;;;;;-1:-1:-1;103523:171:0;;;;;:::i;:::-;;:::i;:::-;;;-1:-1:-1;;;;;3440:32:1;;;3422:51;;3410:2;3395:18;103523:171:0;3276:203:1;103041:416:0;;;;;;;;;;-1:-1:-1;103041:416:0;;;;;:::i;:::-;;:::i;69897:321::-;;;;;;;;;;-1:-1:-1;69897:321:0;;;;;:::i;:::-;;:::i;50353:142::-;;;;;;;;;;-1:-1:-1;50353:142:0;;;;;:::i;:::-;;:::i;48559:129::-;;;;;;;;;;-1:-1:-1;48559:129:0;;;;;:::i;:::-;;:::i;119203:291::-;;;:::i;64071:53::-;;;;;;;;;;-1:-1:-1;64071:53:0;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;64071:53:0;;;;;;;;;;;4774:6:1;4762:19;;;4744:38;;-1:-1:-1;;;;;4818:32:1;;;4813:2;4798:18;;4791:60;4867:18;;;4860:34;4937:14;4930:22;4925:2;4910:18;;4903:50;4731:3;4716:19;64071:53:0;4521:438:1;104223:301:0;;;;;;;;;;-1:-1:-1;104223:301:0;;;;;:::i;:::-;;:::i;64626:320::-;;;;;;;;;;-1:-1:-1;64626:320:0;;;;;:::i;:::-;;:::i;:::-;;;;7588:25:1;;;7644:2;7629:18;;7622:34;;;;7561:18;64626:320:0;7414:248:1;50593:250:0;;;;;;;;;;-1:-1:-1;50593:250:0;;;;;:::i;:::-;;:::i;44672:53::-;;;;;;;;;;-1:-1:-1;44672:53:0;;;;;:::i;:::-;;;;;;;;;;;;;;;;;8299:25:1;;;8287:2;8272:18;44672:53:0;8153:177:1;104595:151:0;;;;;;;;;;-1:-1:-1;104595:151:0;;;;;:::i;:::-;;:::i;48696:178::-;;;;;;;;;;-1:-1:-1;48696:178:0;;;;;:::i;:::-;;:::i;63761:39::-;;;;;;;;;;;;;;;;63877:56;;;;;;;;;;-1:-1:-1;63877:56:0;;;;;:::i;:::-;;;;;;;;;;;;;;65350:351;;;;;;:::i;:::-;;:::i;56823:85::-;;;;;;;;;;-1:-1:-1;56823:85:0;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;101721:223;;;;;;;;;;-1:-1:-1;101721:223:0;;;;;:::i;:::-;;:::i;58045:346::-;;;;;;;;;;-1:-1:-1;58045:346:0;;;;;:::i;:::-;;:::i;119685:75::-;;;;;;;;;;-1:-1:-1;119685:75:0;;;;;:::i;:::-;;:::i;118372:22::-;;;;;;;;;;;;;;;;101452:207;;;;;;;;;;-1:-1:-1;101452:207:0;;;;;:::i;:::-;;:::i;16882:103::-;;;;;;;;;;;;;:::i;44542:51::-;;;;;;;;;;-1:-1:-1;44542:51:0;;;;;:::i;:::-;;:::i;44600:65::-;;;;;;;;;;-1:-1:-1;44600:65:0;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;16241:87;;;;;;;;;;-1:-1:-1;16287:7:0;16314:6;-1:-1:-1;;;;;16314:6:0;16241:87;;68107:1009;;;;;;;;;;-1:-1:-1;68107:1009:0;;;;;:::i;:::-;;:::i;44732:23::-;;;;;;;;;;-1:-1:-1;44732:23:0;;;;-1:-1:-1;;;;;44732:23:0;;;102180:104;;;;;;;;;;;;;:::i;70742:351::-;;;;;;;;;;-1:-1:-1;70742:351:0;;;;;:::i;:::-;;:::i;49525:330::-;;;;;;;;;;-1:-1:-1;49525:330:0;;;;;:::i;:::-;;:::i;103766:155::-;;;;;;;;;;-1:-1:-1;103766:155:0;;;;;:::i;:::-;;:::i;49236:281::-;;;;;;;;;;-1:-1:-1;49236:281:0;;;;;:::i;:::-;;:::i;65709:348::-;;;;;;:::i;:::-;;:::i;63524:45::-;;;;;;;;;;;;63568:1;63524:45;;;;;13713:6:1;13701:19;;;13683:38;;13671:2;13656:18;63524:45:0;13539:188:1;44489:46:0;;;;;;;;;;;;;;;104817:279;;;;;;;;;;-1:-1:-1;104817:279:0;;;;;:::i;:::-;;:::i;49863:136::-;;;;;;;;;;-1:-1:-1;49863:136:0;;;;;:::i;:::-;;:::i;44425:55::-;;;;;;;;;;;;44475:5;44425:55;;102355:281;;;;;;;;;;-1:-1:-1;102355:281:0;;;;;:::i;:::-;;:::i;48216:204::-;;;;;;;;;;-1:-1:-1;48216:204:0;;;;;:::i;:::-;;:::i;70319:359::-;;;;;;;;;;-1:-1:-1;70319:359:0;;;;;:::i;:::-;;:::i;58577:767::-;;;;;;:::i;:::-;;:::i;118429:15::-;;;;;;;;;;;;;;;;50007:284;;;;;;;;;;-1:-1:-1;50007:284:0;;;;;:::i;:::-;;:::i;119502:175::-;;;;;;;;;;;;;:::i;118401:21::-;;;;;;;;;;;;;;;;103992:164;;;;;;;;;;-1:-1:-1;103992:164:0;;;;;:::i;:::-;-1:-1:-1;;;;;104113:25:0;;;104089:4;104113:25;;;:18;:25;;;;;;;;:35;;;;;;;;;;;;;;;103992:164;49021:207;;;;;;;;;;-1:-1:-1;49021:207:0;;;;;:::i;:::-;;:::i;64954:388::-;;;;;;;;;;-1:-1:-1;64954:388:0;;;;;:::i;:::-;;:::i;17140:201::-;;;;;;;;;;-1:-1:-1;17140:201:0;;;;;:::i;:::-;;:::i;47943:211::-;;;;;;;;;;-1:-1:-1;47943:211:0;;;;;:::i;:::-;;:::i;63940:57::-;;;;;;;;;;-1:-1:-1;63940:57:0;;;;;:::i;:::-;;;;;;;;;;;;;;45130:762;15030:10;45370;-1:-1:-1;;;;;45346:35:0;;45338:78;;;;-1:-1:-1;;;45338:78:0;;17564:2:1;45338:78:0;;;17546:21:1;17603:2;17583:18;;;17576:30;17642:32;17622:18;;;17615:60;17692:18;;45338:78:0;;;;;;;;;45458:32;;;45429:26;45458:32;;;:19;:32;;;;;45429:61;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;45664:13;:20;45642:11;;:18;;:42;:70;;;;;45711:1;45688:13;:20;:24;45642:70;:124;;;;-1:-1:-1;45742:24:0;;;;;;45716:22;;;;45726:11;;;;45716:22;:::i;:::-;;;;;;;;:50;45642:124;45634:175;;;;-1:-1:-1;;;45634:175:0;;18584:2:1;45634:175:0;;;18566:21:1;18623:2;18603:18;;;18596:30;18662:34;18642:18;;;18635:62;-1:-1:-1;;;18713:18:1;;;18706:36;18759:19;;45634:175:0;18382:402:1;45634:175:0;45822:62;45841:11;45854;;45822:62;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;45822:62:0;;;;;;;;;;;;;;;;;;;;;;45867:6;;-1:-1:-1;45822:62:0;-1:-1:-1;45875:8:0;;;;;;45822:62;;45875:8;;;;45822:62;;;;;;;;;-1:-1:-1;45822:18:0;;-1:-1:-1;;;45822:62:0:i;:::-;45261:631;45130:762;;;;;;:::o;117291:228::-;117406:4;-1:-1:-1;;;;;;117430:41:0;;;;:81;;;117475:36;117499:11;117475:23;:36::i;:::-;117423:88;117291:228;-1:-1:-1;;117291:228:0:o;102011:100::-;102065:13;102098:5;102091:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;102011:100;:::o;48428:123::-;16127:13;:11;:13::i;:::-;48508:35:::1;::::0;-1:-1:-1;;;48508:35:0;;13713:6:1;13701:19;;48508:35:0::1;::::0;::::1;13683:38:1::0;48508:10:0::1;-1:-1:-1::0;;;;;48508:25:0::1;::::0;::::1;::::0;13656:18:1;;48508:35:0::1;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;48428:123:::0;:::o;103523:171::-;103599:7;103619:23;103634:7;103619:14;:23::i;:::-;-1:-1:-1;103662:24:0;;;;:15;:24;;;;;;-1:-1:-1;;;;;103662:24:0;;103523:171::o;103041:416::-;103122:13;103138:23;103153:7;103138:14;:23::i;:::-;103122:39;;103186:5;-1:-1:-1;;;;;103180:11:0;:2;-1:-1:-1;;;;;103180:11:0;;;103172:57;;;;-1:-1:-1;;;103172:57:0;;18991:2:1;103172:57:0;;;18973:21:1;19030:2;19010:18;;;19003:30;19069:34;19049:18;;;19042:62;-1:-1:-1;;;19120:18:1;;;19113:31;19161:19;;103172:57:0;18789:397:1;103172:57:0;15030:10;-1:-1:-1;;;;;103264:21:0;;;;:62;;-1:-1:-1;103289:37:0;103306:5;15030:10;103992:164;:::i;103289:37::-;103242:173;;;;-1:-1:-1;;;103242:173:0;;19393:2:1;103242:173:0;;;19375:21:1;19432:2;19412:18;;;19405:30;19471:34;19451:18;;;19444:62;19542:31;19522:18;;;19515:59;19591:19;;103242:173:0;19191:425:1;103242:173:0;103428:21;103437:2;103441:7;103428:8;:21::i;:::-;103111:346;103041:416;;:::o;69897:321::-;16127:13;:11;:13::i;:::-;70035:1:::1;70007:25;:29;69999:78;;;::::0;-1:-1:-1;;;69999:78:0;;19823:2:1;69999:78:0::1;::::0;::::1;19805:21:1::0;19862:2;19842:18;;;19835:30;19901:34;19881:18;;;19874:62;-1:-1:-1;;;19952:18:1;;;19945:34;19996:19;;69999:78:0::1;19621:400:1::0;69999:78:0::1;70088:24;:52:::0;;;70156:54:::1;::::0;8299:25:1;;;70156:54:0::1;::::0;8287:2:1;8272:18;70156:54:0::1;;;;;;;;69897:321:::0;:::o;50353:142::-;16127:13;:11;:13::i;:::-;50444:35:::1;::::0;;::::1;;::::0;;;:22:::1;:35;::::0;;;;:43;50353:142::o;48559:129::-;16127:13;:11;:13::i;:::-;48642:38:::1;::::0;-1:-1:-1;;;48642:38:0;;13713:6:1;13701:19;;48642:38:0::1;::::0;::::1;13683::1::0;48642:10:0::1;-1:-1:-1::0;;;;;48642:28:0::1;::::0;::::1;::::0;13656:18:1;;48642:38:0::1;13539:188:1::0;119203:291:0;119269:9;;119255:10;;:23;;119247:70;;;;-1:-1:-1;;;119247:70:0;;20228:2:1;119247:70:0;;;20210:21:1;20267:2;20247:18;;;20240:30;20306:34;20286:18;;;20279:62;-1:-1:-1;;;20357:18:1;;;20350:32;20399:19;;119247:70:0;20026:398:1;119247:70:0;119349:3;;119336:9;:16;;119328:60;;;;-1:-1:-1;;;119328:60:0;;20631:2:1;119328:60:0;;;20613:21:1;20670:2;20650:18;;;20643:30;20709:33;20689:18;;;20682:61;20760:18;;119328:60:0;20429:355:1;119328:60:0;119412:10;;;;;;119399;119433:12;119412:10;119433:12;:::i;:::-;;;;;;119458:28;119468:10;119480:5;119458:9;:28::i;:::-;119236:258;119203:291::o;104223:301::-;104384:41;15030:10;104403:12;104417:7;104384:18;:41::i;:::-;104376:99;;;;-1:-1:-1;;;104376:99:0;;;;;;;:::i;:::-;104488:28;104498:4;104504:2;104508:7;104488:9;:28::i;64626:320::-;64792:14;64808:11;64839:99;64860:11;64873:10;64885:27;64903:8;64885:17;:27::i;:::-;64914:7;64923:14;64839:20;:99::i;:::-;64832:106;;;;64626:320;;;;;;;;:::o;50593:250::-;50735:32;;;50689:4;50735:32;;;:19;:32;;;;;50706:61;;50689:4;;50735:32;50706:61;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;50823:11;;50813:22;;;;;;;:::i;:::-;;;;;;;;50795:13;50785:24;;;;;;:50;50778:57;;;50593:250;;;;;:::o;104595:151::-;104699:39;104716:4;104722:2;104726:7;104699:39;;;;;;;;;;;;:16;:39::i;48696:178::-;16127:13;:11;:13::i;:::-;48811:55:::1;::::0;-1:-1:-1;;;48811:55:0;;-1:-1:-1;;;;;48811:10:0::1;:29;::::0;::::1;::::0;:55:::1;::::0;48841:11;;48854;;;;48811:55:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;65350:351:::0;65575:118;65581:5;65588:11;65601:10;65613:27;65631:8;65613:17;:27::i;:::-;65642:14;65658:18;65678:14;65575:5;:118::i;101721:223::-;101793:7;106454:16;;;:7;:16;;;;;;-1:-1:-1;;;;;106454:16:0;;101857:56;;;;-1:-1:-1;;;101857:56:0;;22279:2:1;101857:56:0;;;22261:21:1;22318:2;22298:18;;;22291:30;-1:-1:-1;;;22337:18:1;;;22330:54;22401:18;;101857:56:0;22077:348:1;58045:346:0;15030:10;58259:4;58235:29;58227:80;;;;-1:-1:-1;;;58227:80:0;;22632:2:1;58227:80:0;;;22614:21:1;22671:2;22651:18;;;22644:30;22710:34;22690:18;;;22683:62;-1:-1:-1;;;22761:18:1;;;22754:36;22807:19;;58227:80:0;22430:402:1;58227:80:0;58318:65;58340:11;58353;;58318:65;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;58318:65:0;;;;;;;;;;;;;;;;;;;;;;58366:6;;-1:-1:-1;58318:65:0;-1:-1:-1;58374:8:0;;;;;;58318:65;;58374:8;;;;58318:65;;;;;;;;;-1:-1:-1;58318:21:0;;-1:-1:-1;;;58318:65:0:i;:::-;58045:346;;;;;;:::o;119685:75::-;16127:13;:11;:13::i;:::-;119742:3:::1;:10:::0;119685:75::o;101452:207::-;101524:7;-1:-1:-1;;;;;101552:19:0;;101544:73;;;;-1:-1:-1;;;101544:73:0;;23039:2:1;101544:73:0;;;23021:21:1;23078:2;23058:18;;;23051:30;23117:34;23097:18;;;23090:62;-1:-1:-1;;;23168:18:1;;;23161:39;23217:19;;101544:73:0;22837:405:1;101544:73:0;-1:-1:-1;;;;;;101635:16:0;;;;;:9;:16;;;;;;;101452:207::o;16882:103::-;16127:13;:11;:13::i;:::-;16947:30:::1;16974:1;16947:18;:30::i;:::-;16882:103::o:0;44542:51::-;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;68107:1009::-;62533:21;:19;:21::i;:::-;68217:19;;::::1;::::0;;::::1;::::0;;;;68193:21:::1;68255:28:::0;;;:13:::1;:28:::0;;;;;;;:42:::1;;::::0;::::1;;68247:72;;;::::0;-1:-1:-1;;;68247:72:0;;23449:2:1;68247:72:0::1;::::0;::::1;23431:21:1::0;23488:2;23468:18;;;23461:30;-1:-1:-1;;;23507:18:1;;;23500:47;23564:18;;68247:72:0::1;23247:341:1::0;68247:72:0::1;68335:22;68372:8;68361:37;;;;;;;;;;;;:::i;:::-;68411:14;68440:28:::0;;;:13:::1;:28;::::0;;;;:39;;;68521:34;;::::1;::::0;68332:66;;-1:-1:-1;68411:14:0;;-1:-1:-1;68428:138:0::1;::::0;68440:39:::1;::::0;::::1;::::0;68481:38;;::::1;-1:-1:-1::0;;;;;68481:38:0::1;::::0;68332:66;68428:11:::1;:138::i;:::-;68597:28;::::0;;;:13:::1;:28;::::0;;;;:34:::1;;::::0;68411:155;;-1:-1:-1;68585:46:0;::::1;68577:100;;;::::0;-1:-1:-1;;;68577:100:0;;25337:2:1;68577:100:0::1;::::0;::::1;25319:21:1::0;25376:2;25356:18;;;25349:30;25415:34;25395:18;;;25388:62;-1:-1:-1;;;25466:18:1;;;25459:39;25515:19;;68577:100:0::1;25135:405:1::0;68577:100:0::1;68707:8;:15;68694:9;:28;68690:419;;;68802:28;::::0;;;:13:::1;:28;::::0;;;;;68795:35;;-1:-1:-1;;;;;;68795:35:0;;;;;::::1;::::0;;;;::::1;::::0;;::::1;::::0;;-1:-1:-1;;68795:35:0::1;::::0;;68850:28;::::1;::::0;::::1;::::0;68816:13;8299:25:1;;8287:2;8272:18;;8153:177;68850:28:0::1;;;;;;;;68690:419;;;68987:110;::::0;;::::1;::::0;::::1;::::0;;-1:-1:-1;69000:28:0;;;:13:::1;:28;::::0;;;;;;:39;;::::1;::::0;;::::1;68987:110:::0;;-1:-1:-1;;;;;69041:38:0;;;::::1;::::0;::::1;68987:110:::0;;::::1;::::0;;;;;;;;;69000:39;68987:110;;;;;;68956:28;;;;;;;;:141;;;;::::1;::::0;;::::1;-1:-1:-1::0;;;;;;68956:141:0;;;;;;::::1;::::0;;;;;;;::::1;::::0;;;;;;::::1;::::0;;;;;69041:38:::1;68956:141:::0;;::::1;::::0;;;::::1;;-1:-1:-1::0;;68956:141:0;;::::1;::::0;;;::::1;::::0;;68690:419:::1;68182:934;;;62577:20:::0;61971:1;63097:7;:22;62914:213;102180:104;102236:13;102269:7;102262:14;;;;;:::i;70742:351::-;16127:13;:11;:13::i;:::-;70894:1:::1;70868:23;:27;70860:74;;;::::0;-1:-1:-1;;;70860:74:0;;25747:2:1;70860:74:0::1;::::0;::::1;25729:21:1::0;25786:2;25766:18;;;25759:30;25825:34;25805:18;;;25798:62;-1:-1:-1;;;25876:18:1;;;25869:32;25918:19;;70860:74:0::1;25545:398:1::0;70860:74:0::1;70945:35;::::0;::::1;;::::0;;;:22:::1;:35;::::0;;;;;;;;:61;;;71022:63;;26120:38:1;;;26174:18;;26167:34;;;71022:63:0::1;::::0;26093:18:1;71022:63:0::1;;;;;;;;70742:351:::0;;:::o;49525:330::-;49649:35;;;49629:17;49649:35;;;:19;:35;;;;;49629:55;;49604:12;;49629:17;49649:35;49629:55;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;49703:4;:11;49718:1;49703:16;;49695:58;;;;-1:-1:-1;;;49695:58:0;;26414:2:1;49695:58:0;;;26396:21:1;26453:2;26433:18;;;26426:30;26492:31;26472:18;;;26465:59;26541:18;;49695:58:0;26212:353:1;49695:58:0;49771:31;49782:1;49799:2;49785:4;:11;:16;;;;:::i;:::-;49771:4;;:31;:10;:31::i;:::-;49764:38;49525:330;-1:-1:-1;;;49525:330:0:o;103766:155::-;103861:52;15030:10;103894:8;103904;103861:18;:52::i;:::-;103766:155;;:::o;49236:281::-;16127:13;:11;:13::i;:::-;49408:14:::1;;49432:4;49391:47;;;;;;;;;;:::i;:::-;;::::0;;-1:-1:-1;;49391:47:0;;::::1;::::0;;;;;;49353:35:::1;::::0;::::1;;::::0;;;:19:::1;49391:47;49353:35:::0;;;;;;:85;;::::1;::::0;:35;;:85;;::::1;::::0;::::1;:::i;:::-;;49454:55;49478:14;49494;;49454:55;;;;;;;;:::i;:::-;;;;;;;;49236:281:::0;;;:::o;65709:348::-;65949:100;65955:5;65962:11;65975:10;65987:9;65998:14;66014:18;66034:14;65949:5;:100::i;104817:279::-;104948:41;15030:10;104981:7;104948:18;:41::i;:::-;104940:99;;;;-1:-1:-1;;;104940:99:0;;;;;;;:::i;:::-;105050:38;105064:4;105070:2;105074:7;105083:4;105050:13;:38::i;:::-;104817:279;;;;:::o;49863:136::-;16127:13;:11;:13::i;:::-;49933:8:::1;:20:::0;;-1:-1:-1;;;;;;49933:20:0::1;-1:-1:-1::0;;;;;49933:20:0;::::1;::::0;;::::1;::::0;;;49969:22:::1;::::0;3422:51:1;;;49969:22:0::1;::::0;3410:2:1;3395:18;49969:22:0::1;3276:203:1::0;102355:281:0;102428:13;102454:23;102469:7;102454:14;:23::i;:::-;102490:21;102514:10;102962:9;;;;;;;;;-1:-1:-1;102962:9:0;;;102885:94;102514:10;102490:34;;102566:1;102548:7;102542:21;:25;:86;;;;;;;;;;;;;;;;;102594:7;102603:18;:7;:16;:18::i;:::-;102577:45;;;;;;;;;:::i;:::-;;;;;;;;;;;;;102535:93;102355:281;-1:-1:-1;;;102355:281:0:o;48216:204::-;16127:13;:11;:13::i;:::-;48350:62:::1;::::0;-1:-1:-1;;;48350:62:0;;-1:-1:-1;;;;;48350:10:0::1;:20;::::0;::::1;::::0;:62:::1;::::0;48371:8;;48381;;48391:11;;48404:7;;;;48350:62:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;48216:204:::0;;;;;:::o;70319:359::-;16127:13;:11;:13::i;:::-;70474:1:::1;70447:24;:28;70439:76;;;::::0;-1:-1:-1;;;70439:76:0;;28267:2:1;70439:76:0::1;::::0;::::1;28249:21:1::0;28306:2;28286:18;;;28279:30;28345:34;28325:18;;;28318:62;-1:-1:-1;;;28396:18:1;;;28389:33;28439:19;;70439:76:0::1;28065:399:1::0;70439:76:0::1;70526:36;::::0;::::1;;::::0;;;:23:::1;:36;::::0;;;;;;;;:63;;;70605:65;;26120:38:1;;;26174:18;;26167:34;;;70605:65:0::1;::::0;26093:18:1;70605:65:0::1;25948:259:1::0;58577:767:0;58788:27;;;58766:19;58788:27;;;:14;:27;;;;;;:40;;;;58816:11;;;;58788:40;:::i;:::-;;;;;;;;;;;;;;;;-1:-1:-1;;;;;58788:48:0;;;;;;;;;;;;-1:-1:-1;58788:48:0;58847:73;;;;-1:-1:-1;;;58847:73:0;;28671:2:1;58847:73:0;;;28653:21:1;28710:2;28690:18;;;28683:30;28749:34;28729:18;;;28722:62;-1:-1:-1;;;28800:18:1;;;28793:33;28843:19;;58847:73:0;28469:399:1;58847:73:0;58962:11;58949:8;;58939:19;;;;;;;:::i;:::-;;;;;;;;:34;58931:80;;;;-1:-1:-1;;;58931:80:0;;29075:2:1;58931:80:0;;;29057:21:1;29114:2;29094:18;;;29087:30;29153:34;29133:18;;;29126:62;-1:-1:-1;;;29204:18:1;;;29197:31;29245:19;;58931:80:0;28873:397:1;58931:80:0;59059:27;;;59118:1;59059:27;;;:14;:27;;;;;;:40;;;;59087:11;;;;59059:40;:::i;:::-;;;;;;;;;;;;;;;;-1:-1:-1;;;;;59059:48:0;;;;;;;;;;;;:61;;;;59189:65;;;;;;;;;;;;;;;;;;;59211:11;;59224;;59189:65;;;;;;59224:11;59189:65;;59224:11;59189:65;;;;;;;;;-1:-1:-1;;59189:65:0;;;;;;;;;;;;;;;;;;;;;;59237:6;;-1:-1:-1;59189:65:0;-1:-1:-1;59245:8:0;;;;;;59189:65;;59245:8;;;;59189:65;;;;;;;;;-1:-1:-1;59189:21:0;;-1:-1:-1;;;59189:65:0:i;:::-;59270:66;59290:11;59303;;59316:6;59324:11;59270:66;;;;;;;;;;:::i;:::-;;;;;;;;58710:634;58577:767;;;;;;:::o;50007:284::-;16127:13;:11;:13::i;:::-;50131:1:::1;50121:7;:11;50113:45;;;::::0;-1:-1:-1;;;50113:45:0;;29975:2:1;50113:45:0::1;::::0;::::1;29957:21:1::0;30014:2;29994:18;;;29987:30;-1:-1:-1;;;30033:18:1;;;30026:51;30094:18;;50113:45:0::1;29773:345:1::0;50113:45:0::1;50169:28;::::0;;::::1;;::::0;;;:15:::1;:28;::::0;;;;;;;:41;;::::1;::::0;;;;;;;;;;:51;;;50236:47;;30346:34:1;;;30396:18;;30389:43;;;;30448:18;;;30441:34;;;50236:47:0::1;::::0;30309:2:1;30294:18;50236:47:0::1;30123:358:1::0;119502:175:0;119552:4;16127:13;:11;:13::i;:::-;119586:58:::1;::::0;119570:12:::1;::::0;119594:10:::1;::::0;119618:21:::1;::::0;119570:12;119586:58;119570:12;119586:58;119618:21;119594:10;119586:58:::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1::0;119569:75:0;;-1:-1:-1;;;119502:175:0;:::o;49021:207::-;16127:13;:11;:13::i;:::-;49122:35:::1;::::0;::::1;;::::0;;;:19:::1;:35;::::0;;;;:43:::1;::::0;49160:5;;49122:43:::1;:::i;:::-;;49181:39;49198:14;49214:5;;49181:39;;;;;;;;:::i;64954:388::-:0;65135:14;65151:11;65175:20;65209:10;65221:9;65198:33;;;;;;;;;:::i;:::-;;;;-1:-1:-1;;65198:33:0;;;;;;;;;;-1:-1:-1;;;65249:85:0;;65198:33;-1:-1:-1;;;;;;65249:10:0;:23;;;;:85;;65273:11;;65294:4;;65198:33;;65310:7;;65319:14;;65249:85;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;65242:92;;;;;64954:388;;;;;;;;:::o;17140:201::-;16127:13;:11;:13::i;:::-;-1:-1:-1;;;;;17229:22:0;::::1;17221:73;;;::::0;-1:-1:-1;;;17221:73:0;;32662:2:1;17221:73:0::1;::::0;::::1;32644:21:1::0;32701:2;32681:18;;;32674:30;32740:34;32720:18;;;32713:62;-1:-1:-1;;;32791:18:1;;;32784:36;32837:19;;17221:73:0::1;32460:402:1::0;17221:73:0::1;17305:28;17324:8;17305:18;:28::i;47943:211::-:0;48078:68;;-1:-1:-1;;;48078:68:0;;33104:6:1;33137:15;;;48078:68:0;;;33119:34:1;33189:15;;33169:18;;;33162:43;48127:4:0;33221:18:1;;;33214:60;33290:18;;;33283:34;;;48046:12:0;;48078:10;-1:-1:-1;;;;;48078:20:0;;;;33066:19:1;;48078:68:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;48078:68:0;;;;;;;;;;;;:::i;:::-;48071:75;;47943:211;;;;;;;:::o;57192:514::-;57342:12;57356:19;57379:153;57413:9;57424:3;57452:34;;;57488:11;57501;57514:6;57522:8;57429:102;;;;;;;;;;;:::i;:::-;;;;-1:-1:-1;;57429:102:0;;;;;;;;;;;;;;-1:-1:-1;;;;;57429:102:0;-1:-1:-1;;;;;;57429:102:0;;;;;;;;;;57387:4;;57379:153;;:33;:153::i;:::-;57341:191;;;;57592:7;57587:112;;57616:71;57636:11;57649;57662:6;57670:8;57680:6;57616:19;:71::i;101083:305::-;101185:4;-1:-1:-1;;;;;;101222:40:0;;-1:-1:-1;;;101222:40:0;;:105;;-1:-1:-1;;;;;;;101279:48:0;;-1:-1:-1;;;101279:48:0;101222:105;:158;;;;101344:36;101368:11;101344:23;:36::i;16406:132::-;16287:7;16314:6;-1:-1:-1;;;;;16314:6:0;15030:10;16470:23;16462:68;;;;-1:-1:-1;;;16462:68:0;;34432:2:1;16462:68:0;;;34414:21:1;;;34451:18;;;34444:30;34510:34;34490:18;;;34483:62;34562:18;;16462:68:0;34230:356:1;113086:135:0;113168:16;113176:7;113168;:16::i;:::-;113160:53;;;;-1:-1:-1;;;113160:53:0;;22279:2:1;113160:53:0;;;22261:21:1;22318:2;22298:18;;;22291:30;-1:-1:-1;;;22337:18:1;;;22330:54;22401:18;;113160:53:0;22077:348:1;112399:174:0;112474:24;;;;:15;:24;;;;;:29;;-1:-1:-1;;;;;;112474:29:0;-1:-1:-1;;;;;112474:29:0;;;;;;;;:24;;112528:23;112474:24;112528:14;:23::i;:::-;-1:-1:-1;;;;;112519:46:0;;;;;;;;;;;112399:174;;:::o;107692:110::-;107768:26;107778:2;107782:7;107768:26;;;;;;;;;;;;:9;:26::i;107086:264::-;107179:4;107196:13;107212:23;107227:7;107212:14;:23::i;:::-;107196:39;;107265:5;-1:-1:-1;;;;;107254:16:0;:7;-1:-1:-1;;;;;107254:16:0;;:52;;;-1:-1:-1;;;;;;104113:25:0;;;104089:4;104113:25;;;:18;:25;;;;;;;;:35;;;;;;;;;;;;107274:32;107254:87;;;;107334:7;-1:-1:-1;;;;;107310:31:0;:20;107322:7;107310:11;:20::i;:::-;-1:-1:-1;;;;;107310:31:0;;107246:96;107086:264;-1:-1:-1;;;;107086:264:0:o;111051:1229::-;111176:4;-1:-1:-1;;;;;111149:31:0;:23;111164:7;111149:14;:23::i;:::-;-1:-1:-1;;;;;111149:31:0;;111141:81;;;;-1:-1:-1;;;111141:81:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;111241:16:0;;111233:65;;;;-1:-1:-1;;;111233:65:0;;35199:2:1;111233:65:0;;;35181:21:1;35238:2;35218:18;;;35211:30;35277:34;35257:18;;;35250:62;-1:-1:-1;;;35328:18:1;;;35321:34;35372:19;;111233:65:0;34997:400:1;111233:65:0;111483:4;-1:-1:-1;;;;;111456:31:0;:23;111471:7;111456:14;:23::i;:::-;-1:-1:-1;;;;;111456:31:0;;111448:81;;;;-1:-1:-1;;;111448:81:0;;;;;;;:::i;:::-;111601:24;;;;:15;:24;;;;;;;;111594:31;;-1:-1:-1;;;;;;111594:31:0;;;;;;-1:-1:-1;;;;;112077:15:0;;;;;;:9;:15;;;;;:20;;-1:-1:-1;;112077:20:0;;;112112:13;;;;;;;;;:18;;111594:31;112112:18;;;112152:16;;;:7;:16;;;;;;:21;;;;;;;;;;112191:27;;111617:7;;112191:27;;;103111:346;103041:416;;:::o;71320:185::-;71432:13;;;71443:1;71432:13;;;;;;;;;71384;;71410:19;;71432:13;;;;;;;;;;;;-1:-1:-1;71432:13:0;71410:35;;71467:7;71456:5;71462:1;71456:8;;;;;;;;:::i;:::-;;;;;;;;;;:18;71492:5;71320:185;-1:-1:-1;;71320:185:0:o;66065:960::-;66340:1;66321:9;:16;:20;66313:52;;;;-1:-1:-1;;;66313:52:0;;35736:2:1;66313:52:0;;;35718:21:1;35775:2;35755:18;;;35748:30;-1:-1:-1;;;35794:18:1;;;35787:49;35853:18;;66313:52:0;35534:343:1;66313:52:0;66384:9;:16;66404:1;66384:21;:80;;;-1:-1:-1;66429:35:0;;;;;;;:22;:35;;;;;;66409:16;;:55;;66384:80;66376:127;;;;-1:-1:-1;;;66376:127:0;;36084:2:1;66376:127:0;;;36066:21:1;36123:2;36103:18;;;36096:30;36162:34;36142:18;;;36135:62;-1:-1:-1;;;36213:18:1;;;36206:32;36255:19;;66376:127:0;35882:398:1;66376:127:0;66521:6;66516:127;66537:9;:16;66533:1;:20;66516:127;;;66575:56;66586:5;66593:11;66606:10;66618:9;66628:1;66618:12;;;;;;;;:::i;:::-;;;;;;;66575:10;:56::i;:::-;66555:3;;;;:::i;:::-;;;;66516:127;;;;66655:20;66689:10;66701:9;66678:33;;;;;;;;;:::i;:::-;;;;;;;;;;;;;66655:56;;66724:120;66739:11;63568:1;66772:14;66827:9;:16;66788:23;:36;66812:11;66788:36;;;;;;;;;;;;;;;;:55;;;;:::i;:::-;66724:14;:120::i;:::-;66855:92;66863:11;66876:7;66885:14;66901:18;66921:14;66937:9;66855:7;:92::i;:::-;66995:10;66963:54;;;;;;:::i;:::-;;;;;;;;66988:5;-1:-1:-1;;;;;66963:54:0;66975:11;66963:54;;;67007:9;66963:54;;;;;;:::i;:::-;;;;;;;;66271:754;66065:960;;;;;;;:::o;67033:976::-;67275:27;67304:22;67341:8;67330:37;;;;;;;;;;;;:::i;:::-;67471:2;67451:23;;67445:30;67274:93;;-1:-1:-1;67274:93:0;-1:-1:-1;67380:17:0;67515:48;67527:11;67445:30;67380:17;67274:93;67515:11;:48::i;:::-;67498:65;;67590:8;:15;67578:9;:27;67574:347;;;67734:19;;;;;;;;;;67799:53;;;;;;;;;;;;;;-1:-1:-1;;;;;67799:53:0;;;;;;;;;;;;;;;67847:4;67799:53;;;;;;67710:21;67768:28;;;:13;:28;;;;;;;:84;;;;;;;;;;;-1:-1:-1;;;;;;67768:84:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;67768:84:0;;;;;;;;;;67872:37;;;;;;67734:19;;67744:8;;67872:37;:::i;:::-;;;;;;;;67607:314;67574:347;67981:9;-1:-1:-1;;;;;67938:63:0;67968:11;67938:63;;;;;;:::i;:::-;;;;;;;;67955:11;67938:63;;;67992:8;67938:63;;;;;;:::i;17501:191::-;17575:16;17594:6;;-1:-1:-1;;;;;17611:17:0;;;-1:-1:-1;;;;;;17611:17:0;;;;;;17644:40;;17594:6;;;;;;;17644:40;;17575:16;17644:40;17564:128;17501:191;:::o;62613:293::-;62015:1;62747:7;;:19;;62739:63;;;;-1:-1:-1;;;62739:63:0;;37499:2:1;62739:63:0;;;37481:21:1;37538:2;37518:18;;;37511:30;37577:33;37557:18;;;37550:61;37628:18;;62739:63:0;37297:355:1;62739:63:0;62015:1;62880:7;:18;62613:293::o;69315:574::-;69437:7;69465:11;69487:263;69498:9;:16;69494:1;:20;69487:263;;;69624:24;;69612:9;:36;69608:47;;;69650:5;;69608:47;69672:48;69682:11;69695:10;69707:9;69717:1;69707:12;;;;;;;;:::i;:::-;;;;;;;69672:9;:48::i;:::-;69735:3;;;;:::i;:::-;;;;69487:263;;34250:2779;34391:12;34445:7;34429:12;34445:7;34439:2;34429:12;:::i;:::-;:23;;34421:50;;;;-1:-1:-1;;;34421:50:0;;37992:2:1;34421:50:0;;;37974:21:1;38031:2;38011:18;;;38004:30;-1:-1:-1;;;38050:18:1;;;38043:44;38104:18;;34421:50:0;37790:338:1;34421:50:0;34507:16;34516:7;34507:6;:16;:::i;:::-;34490:6;:13;:33;;34482:63;;;;-1:-1:-1;;;34482:63:0;;38335:2:1;34482:63:0;;;38317:21:1;38374:2;38354:18;;;38347:30;-1:-1:-1;;;38393:18:1;;;38386:47;38450:18;;34482:63:0;38133:341:1;34482:63:0;34558:22;34624:15;;34653:1933;;;;36730:4;36724:11;36711:24;;36911:1;36900:9;36893:20;36961:4;36950:9;36946:20;36940:4;36933:34;34617:2365;;34653:1933;34830:4;34824:11;34811:24;;35467:2;35458:7;35454:16;35839:9;35832:17;35826:4;35822:28;35810:9;35799;35795:25;35791:60;35888:7;35884:2;35880:16;36137:6;36123:9;36116:17;36110:4;36106:28;36094:9;36086:6;36082:22;36078:57;36074:70;35916:426;36171:3;36167:2;36164:11;35916:426;;;36313:9;;36302:21;;36213:4;36205:13;;;;36246;35916:426;;;-1:-1:-1;;36362:26:0;;;36566:2;36549:11;-1:-1:-1;;36545:25:0;36539:4;36532:39;-1:-1:-1;34617:2365:0;-1:-1:-1;37012:9:0;34250:2779;-1:-1:-1;;;;34250:2779:0:o;112716:281::-;112837:8;-1:-1:-1;;;;;112828:17:0;:5;-1:-1:-1;;;;;112828:17:0;;;112820:55;;;;-1:-1:-1;;;112820:55:0;;38681:2:1;112820:55:0;;;38663:21:1;38720:2;38700:18;;;38693:30;38759:27;38739:18;;;38732:55;38804:18;;112820:55:0;38479:349:1;112820:55:0;-1:-1:-1;;;;;112886:25:0;;;;;;;:18;:25;;;;;;;;:35;;;;;;;;;;;;;:46;;-1:-1:-1;;112886:46:0;;;;;;;;;;112948:41;;2099::1;;;112948::0;;2072:18:1;112948:41:0;;;;;;;112716:281;;;:::o;105977:270::-;106090:28;106100:4;106106:2;106110:7;106090:9;:28::i;:::-;106137:47;106160:4;106166:2;106170:7;106179:4;106137:22;:47::i;:::-;106129:110;;;;-1:-1:-1;;;106129:110:0;;;;;;;:::i;97454:716::-;97510:13;97561:14;97578:17;97589:5;97578:10;:17::i;:::-;97598:1;97578:21;97561:38;;97614:20;97648:6;-1:-1:-1;;;;;97637:18:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;97637:18:0;-1:-1:-1;97614:41:0;-1:-1:-1;97779:28:0;;;97795:2;97779:28;97836:288;-1:-1:-1;;97868:5:0;-1:-1:-1;;;98005:2:0;97994:14;;97989:30;97868:5;97976:44;98066:2;98057:11;;;-1:-1:-1;98091:10:0;98087:21;;98103:5;;98087:21;97836:288;;;-1:-1:-1;98145:6:0;97454:716;-1:-1:-1;;;97454:716:0:o;51915:1275::-;52077:4;52083:12;52145:15;52171:13;52195:24;52232:8;52222:19;;-1:-1:-1;;;;;52222:19:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;52222:19:0;;52195:46;;52723:1;52697;52663:9;52657:16;52628:4;52617:9;52613:20;52582:1;52547:7;52521:4;52502:247;52490:259;;52814:16;52803:27;;52859:8;52850:7;52847:21;52844:78;;;52899:8;52888:19;;52844:78;53005:7;52992:11;52985:28;53123:7;53120:1;53113:4;53100:11;53096:22;53081:50;53160:8;;;;-1:-1:-1;51915:1275:0;-1:-1:-1;;;;;;51915:1275:0:o;57714:323::-;57938:8;57928:19;;;;;;57877:14;:27;57892:11;57877:27;;;;;;;;;;;;;;;57905:11;57877:40;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;57877:48:0;;;;;;;;;:70;;;;57963:66;;;;57977:11;;57990;;57918:6;;58011:8;;58021:7;;57963:66;:::i;:::-;;;;;;;;57714:323;;;;;:::o;64399:219::-;64501:4;-1:-1:-1;;;;;;64525:45:0;;-1:-1:-1;;;64525:45:0;;:85;;-1:-1:-1;;;;;;;;;;60227:40:0;;;64574:36;60118:157;106791:128;106856:4;106454:16;;;:7;:16;;;;;;-1:-1:-1;;;;;106454:16:0;106880:31;;;106791:128::o;108029:285::-;108124:18;108130:2;108134:7;108124:5;:18::i;:::-;108175:53;108206:1;108210:2;108214:7;108223:4;108175:22;:53::i;:::-;108153:153;;;;-1:-1:-1;;;108153:153:0;;;;;;;:::i;117527:361::-;117644:42;15030:10;117663:12;14950:98;117644:42;117636:101;;;;-1:-1:-1;;;117636:101:0;;40310:2:1;117636:101:0;;;40292:21:1;40349:2;40329:18;;;40322:30;40388:34;40368:18;;;40361:62;-1:-1:-1;;;40439:18:1;;;40432:44;40493:19;;117636:101:0;40108:410:1;117636:101:0;117784:5;-1:-1:-1;;;;;117756:33:0;:24;117771:8;117756:14;:24::i;:::-;-1:-1:-1;;;;;117756:33:0;;117748:80;;;;-1:-1:-1;;;117748:80:0;;40725:2:1;117748:80:0;;;40707:21:1;40764:2;40744:18;;;40737:30;40803:34;40783:18;;;40776:62;-1:-1:-1;;;40854:18:1;;;40847:32;40896:19;;117748:80:0;40523:398:1;117748:80:0;117839:41;117849:5;117864:4;117871:8;117839:9;:41::i;46742:420::-;46878:21;46902:28;46915:14;46902:12;:28::i;:::-;46960;;;;46941:16;46960:28;;;:15;:28;;;;;;;;:35;;;;;;;;;;;;46878:52;;-1:-1:-1;46941:16:0;46960:47;;46998:9;;46960:47;:::i;:::-;46941:66;;47040:1;47026:11;:15;47018:54;;;;-1:-1:-1;;;47018:54:0;;41128:2:1;47018:54:0;;;41110:21:1;41167:2;41147:18;;;41140:30;41206:28;41186:18;;;41179:56;41252:18;;47018:54:0;40926:350:1;47018:54:0;47111:11;47091:16;:31;;47083:71;;;;-1:-1:-1;;;47083:71:0;;41483:2:1;47083:71:0;;;41465:21:1;41522:2;41502:18;;;41495:30;41561:29;41541:18;;;41534:57;41608:18;;47083:71:0;41281:351:1;46181:553:0;46404:32;;;46375:26;46404:32;;;:19;:32;;;;;46375:61;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;46455:13;:20;46479:1;46455:25;;46447:86;;;;-1:-1:-1;;;46447:86:0;;41839:2:1;46447:86:0;;;41821:21:1;41878:2;41858:18;;;41851:30;41917:34;41897:18;;;41890:62;-1:-1:-1;;;41968:18:1;;;41961:46;42024:19;;46447:86:0;41637:412:1;46447:86:0;46544:47;46562:11;46575:8;:15;46544:17;:47::i;:::-;46602:124;;-1:-1:-1;;;46602:124:0;;-1:-1:-1;;;;;46602:10:0;:15;;;;46625:10;;46602:124;;46637:11;;46650:13;;46665:8;;46675:14;;46691:18;;46711:14;;46602:124;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;46364:370;46181:553;;;;;;:::o;117896:373::-;118004:17;118012:8;118004:7;:17::i;:::-;118003:18;:86;;;;118026:17;118034:8;118026:7;:17::i;:::-;:62;;;;-1:-1:-1;118083:4:0;118047:24;118062:8;118047:14;:24::i;:::-;-1:-1:-1;;;;;118047:41:0;;118026:62;117995:95;;;;;;118106:17;118114:8;118106:7;:17::i;:::-;118101:161;;118140:31;118150:10;118162:8;118140:9;:31::i;118101:161::-;118204:46;118222:4;118229:10;118241:8;118204:9;:46::i;113785:853::-;113939:4;-1:-1:-1;;;;;113960:13:0;;74933:19;:23;113956:675;;113996:71;;-1:-1:-1;;;113996:71:0;;-1:-1:-1;;;;;113996:36:0;;;;;:71;;15030:10;;114047:4;;114053:7;;114062:4;;113996:71;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;-1:-1:-1;113996:71:0;;;;;;;;-1:-1:-1;;113996:71:0;;;;;;;;;;;;:::i;:::-;;;113992:584;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;114237:13:0;;114233:328;;114280:60;;-1:-1:-1;;;114280:60:0;;;;;;;:::i;114233:328::-;114511:6;114505:13;114496:6;114492:2;114488:15;114481:38;113992:584;-1:-1:-1;;;;;;114118:51:0;-1:-1:-1;;;114118:51:0;;-1:-1:-1;114111:58:0;;113956:675;-1:-1:-1;114615:4:0;114608:11;;93198:948;93251:7;;-1:-1:-1;;;93329:17:0;;93325:106;;-1:-1:-1;;;93367:17:0;;;-1:-1:-1;93413:2:0;93403:12;93325:106;93458:8;93449:5;:17;93445:106;;93496:8;93487:17;;;-1:-1:-1;93533:2:0;93523:12;93445:106;93578:8;93569:5;:17;93565:106;;93616:8;93607:17;;;-1:-1:-1;93653:2:0;93643:12;93565:106;93698:7;93689:5;:16;93685:103;;93735:7;93726:16;;;-1:-1:-1;93771:1:0;93761:11;93685:103;93815:7;93806:5;:16;93802:103;;93852:7;93843:16;;;-1:-1:-1;93888:1:0;93878:11;93802:103;93932:7;93923:5;:16;93919:103;;93969:7;93960:16;;;-1:-1:-1;94005:1:0;93995:11;93919:103;94049:7;94040:5;:16;94036:68;;94087:1;94077:11;94132:6;93198:948;-1:-1:-1;;93198:948:0:o;108650:942::-;-1:-1:-1;;;;;108730:16:0;;108722:61;;;;-1:-1:-1;;;108722:61:0;;43849:2:1;108722:61:0;;;43831:21:1;;;43868:18;;;43861:30;43927:34;43907:18;;;43900:62;43979:18;;108722:61:0;43647:356:1;108722:61:0;108803:16;108811:7;108803;:16::i;:::-;108802:17;108794:58;;;;-1:-1:-1;;;108794:58:0;;44210:2:1;108794:58:0;;;44192:21:1;44249:2;44229:18;;;44222:30;44288;44268:18;;;44261:58;44336:18;;108794:58:0;44008:352:1;108794:58:0;109012:16;109020:7;109012;:16::i;:::-;109011:17;109003:58;;;;-1:-1:-1;;;109003:58:0;;44210:2:1;109003:58:0;;;44192:21:1;44249:2;44229:18;;;44222:30;44288;44268:18;;;44261:58;44336:18;;109003:58:0;44008:352:1;109003:58:0;-1:-1:-1;;;;;109410:13:0;;;;;;:9;:13;;;;;;;;:18;;109427:1;109410:18;;;109452:16;;;:7;:16;;;;;;:21;;-1:-1:-1;;;;;;109452:21:0;;;;;109491:33;109460:7;;109410:13;;109491:33;;109410:13;;109491:33;103766:155;;:::o;47170:271::-;47252:13;47311:2;47286:14;:21;:27;;47278:68;;;;-1:-1:-1;;;47278:68:0;;44567:2:1;47278:68:0;;;44549:21:1;44606:2;44586:18;;;44579:30;44645;44625:18;;;44618:58;44693:18;;47278:68:0;44365:352:1;47278:68:0;-1:-1:-1;47419:2:0;47399:23;47393:30;;47170:271::o;47449:389::-;47572:35;;;47548:21;47572:35;;;:22;:35;;;;;;47622:21;47618:125;;-1:-1:-1;44475:5:0;47618:125;47777:16;47761:12;:32;;47753:77;;;;-1:-1:-1;;;47753:77:0;;44924:2:1;47753:77:0;;;44906:21:1;;;44943:18;;;44936:30;45002:34;44982:18;;;44975:62;45054:18;;47753:77:0;44722:356:1;-1:-1:-1;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;14:159:1;81:20;;141:6;130:18;;120:29;;110:57;;163:1;160;153:12;110:57;14:159;;;:::o;178:347::-;229:8;239:6;293:3;286:4;278:6;274:17;270:27;260:55;;311:1;308;301:12;260:55;-1:-1:-1;334:20:1;;-1:-1:-1;;;;;366:30:1;;363:50;;;409:1;406;399:12;363:50;446:4;438:6;434:17;422:29;;498:3;491:4;482:6;474;470:19;466:30;463:39;460:59;;;515:1;512;505:12;460:59;178:347;;;;;:::o;530:171::-;597:20;;-1:-1:-1;;;;;646:30:1;;636:41;;626:69;;691:1;688;681:12;706:862;812:6;820;828;836;844;852;905:3;893:9;884:7;880:23;876:33;873:53;;;922:1;919;912:12;873:53;945:28;963:9;945:28;:::i;:::-;935:38;;1024:2;1013:9;1009:18;996:32;-1:-1:-1;;;;;1088:2:1;1080:6;1077:14;1074:34;;;1104:1;1101;1094:12;1074:34;1143:58;1193:7;1184:6;1173:9;1169:22;1143:58;:::i;:::-;1220:8;;-1:-1:-1;1117:84:1;-1:-1:-1;1117:84:1;;-1:-1:-1;1274:37:1;1307:2;1292:18;;1274:37;:::i;:::-;1264:47;;1364:2;1353:9;1349:18;1336:32;1320:48;;1393:2;1383:8;1380:16;1377:36;;;1409:1;1406;1399:12;1377:36;;1448:60;1500:7;1489:8;1478:9;1474:24;1448:60;:::i;:::-;706:862;;;;-1:-1:-1;706:862:1;;-1:-1:-1;706:862:1;;1527:8;;706:862;-1:-1:-1;;;706:862:1:o;1573:131::-;-1:-1:-1;;;;;;1647:32:1;;1637:43;;1627:71;;1694:1;1691;1684:12;1709:245;1767:6;1820:2;1808:9;1799:7;1795:23;1791:32;1788:52;;;1836:1;1833;1826:12;1788:52;1875:9;1862:23;1894:30;1918:5;1894:30;:::i;2151:258::-;2223:1;2233:113;2247:6;2244:1;2241:13;2233:113;;;2323:11;;;2317:18;2304:11;;;2297:39;2269:2;2262:10;2233:113;;;2364:6;2361:1;2358:13;2355:48;;;-1:-1:-1;;2399:1:1;2381:16;;2374:27;2151:258::o;2414:::-;2456:3;2494:5;2488:12;2521:6;2516:3;2509:19;2537:63;2593:6;2586:4;2581:3;2577:14;2570:4;2563:5;2559:16;2537:63;:::i;:::-;2654:2;2633:15;-1:-1:-1;;2629:29:1;2620:39;;;;2661:4;2616:50;;2414:258;-1:-1:-1;;2414:258:1:o;2677:220::-;2826:2;2815:9;2808:21;2789:4;2846:45;2887:2;2876:9;2872:18;2864:6;2846:45;:::i;2902:184::-;2960:6;3013:2;3001:9;2992:7;2988:23;2984:32;2981:52;;;3029:1;3026;3019:12;2981:52;3052:28;3070:9;3052:28;:::i;3091:180::-;3150:6;3203:2;3191:9;3182:7;3178:23;3174:32;3171:52;;;3219:1;3216;3209:12;3171:52;-1:-1:-1;3242:23:1;;3091:180;-1:-1:-1;3091:180:1:o;3484:131::-;-1:-1:-1;;;;;3559:31:1;;3549:42;;3539:70;;3605:1;3602;3595:12;3620:134;3688:20;;3717:31;3688:20;3717:31;:::i;3759:315::-;3827:6;3835;3888:2;3876:9;3867:7;3863:23;3859:32;3856:52;;;3904:1;3901;3894:12;3856:52;3943:9;3930:23;3962:31;3987:5;3962:31;:::i;:::-;4012:5;4064:2;4049:18;;;;4036:32;;-1:-1:-1;;;3759:315:1:o;4079:252::-;4146:6;4154;4207:2;4195:9;4186:7;4182:23;4178:32;4175:52;;;4223:1;4220;4213:12;4175:52;4246:28;4264:9;4246:28;:::i;4964:456::-;5041:6;5049;5057;5110:2;5098:9;5089:7;5085:23;5081:32;5078:52;;;5126:1;5123;5116:12;5078:52;5165:9;5152:23;5184:31;5209:5;5184:31;:::i;:::-;5234:5;-1:-1:-1;5291:2:1;5276:18;;5263:32;5304:33;5263:32;5304:33;:::i;:::-;4964:456;;5356:7;;-1:-1:-1;;;5410:2:1;5395:18;;;;5382:32;;4964:456::o;5425:127::-;5486:10;5481:3;5477:20;5474:1;5467:31;5517:4;5514:1;5507:15;5541:4;5538:1;5531:15;5557:275;5628:2;5622:9;5693:2;5674:13;;-1:-1:-1;;5670:27:1;5658:40;;-1:-1:-1;;;;;5713:34:1;;5749:22;;;5710:62;5707:88;;;5775:18;;:::i;:::-;5811:2;5804:22;5557:275;;-1:-1:-1;5557:275:1:o;5837:186::-;5885:4;-1:-1:-1;;;;;5910:6:1;5907:30;5904:56;;;5940:18;;:::i;:::-;-1:-1:-1;6006:2:1;5985:15;-1:-1:-1;;5981:29:1;6012:4;5977:40;;5837:186::o;6028:462::-;6070:5;6123:3;6116:4;6108:6;6104:17;6100:27;6090:55;;6141:1;6138;6131:12;6090:55;6177:6;6164:20;6208:48;6224:31;6252:2;6224:31;:::i;:::-;6208:48;:::i;:::-;6281:2;6272:7;6265:19;6327:3;6320:4;6315:2;6307:6;6303:15;6299:26;6296:35;6293:55;;;6344:1;6341;6334:12;6293:55;6409:2;6402:4;6394:6;6390:17;6383:4;6374:7;6370:18;6357:55;6457:1;6432:16;;;6450:4;6428:27;6421:38;;;;6436:7;6028:462;-1:-1:-1;;;6028:462:1:o;6495:160::-;6560:20;;6616:13;;6609:21;6599:32;;6589:60;;6645:1;6642;6635:12;6660:749;6769:6;6777;6785;6793;6801;6854:3;6842:9;6833:7;6829:23;6825:33;6822:53;;;6871:1;6868;6861:12;6822:53;6894:28;6912:9;6894:28;:::i;:::-;6884:38;;6973:2;6962:9;6958:18;6945:32;-1:-1:-1;;;;;7037:2:1;7029:6;7026:14;7023:34;;;7053:1;7050;7043:12;7023:34;7076:49;7117:7;7108:6;7097:9;7093:22;7076:49;:::i;:::-;7066:59;;7172:2;7161:9;7157:18;7144:32;7134:42;;7195:35;7226:2;7215:9;7211:18;7195:35;:::i;:::-;7185:45;;7283:3;7272:9;7268:19;7255:33;7239:49;;7313:2;7303:8;7300:16;7297:36;;;7329:1;7326;7319:12;7297:36;;7352:51;7395:7;7384:8;7373:9;7369:24;7352:51;:::i;:::-;7342:61;;;6660:749;;;;;;;;:::o;7667:481::-;7745:6;7753;7761;7814:2;7802:9;7793:7;7789:23;7785:32;7782:52;;;7830:1;7827;7820:12;7782:52;7853:28;7871:9;7853:28;:::i;:::-;7843:38;;7932:2;7921:9;7917:18;7904:32;-1:-1:-1;;;;;7951:6:1;7948:30;7945:50;;;7991:1;7988;7981:12;7945:50;8030:58;8080:7;8071:6;8060:9;8056:22;8030:58;:::i;:::-;7667:481;;8107:8;;-1:-1:-1;8004:84:1;;-1:-1:-1;;;;7667:481:1:o;8335:1108::-;8473:6;8481;8489;8497;8505;8513;8521;8574:3;8562:9;8553:7;8549:23;8545:33;8542:53;;;8591:1;8588;8581:12;8542:53;8630:9;8617:23;8649:31;8674:5;8649:31;:::i;:::-;8699:5;-1:-1:-1;8723:37:1;8756:2;8741:18;;8723:37;:::i;:::-;8713:47;;8811:2;8800:9;8796:18;8783:32;-1:-1:-1;;;;;8875:2:1;8867:6;8864:14;8861:34;;;8891:1;8888;8881:12;8861:34;8914:49;8955:7;8946:6;8935:9;8931:22;8914:49;:::i;:::-;8904:59;;9010:2;8999:9;8995:18;8982:32;8972:42;;9066:3;9055:9;9051:19;9038:33;9023:48;;9080:33;9105:7;9080:33;:::i;:::-;9132:7;;-1:-1:-1;9191:3:1;9176:19;;9163:33;;9205;9163;9205;:::i;:::-;9257:7;;-1:-1:-1;9317:3:1;9302:19;;9289:33;;9334:16;;;9331:36;;;9363:1;9360;9353:12;9331:36;;9386:51;9429:7;9418:8;9407:9;9403:24;9386:51;:::i;:::-;9376:61;;;8335:1108;;;;;;;;;;:::o;9448:464::-;9532:6;9540;9548;9601:2;9589:9;9580:7;9576:23;9572:32;9569:52;;;9617:1;9614;9607:12;9569:52;9640:28;9658:9;9640:28;:::i;:::-;9630:38;;9719:2;9708:9;9704:18;9691:32;-1:-1:-1;;;;;9738:6:1;9735:30;9732:50;;;9778:1;9775;9768:12;9732:50;9801:49;9842:7;9833:6;9822:9;9818:22;9801:49;:::i;:::-;9791:59;;;9869:37;9902:2;9891:9;9887:18;9869:37;:::i;:::-;9859:47;;9448:464;;;;;:::o;10099:247::-;10158:6;10211:2;10199:9;10190:7;10186:23;10182:32;10179:52;;;10227:1;10224;10217:12;10179:52;10266:9;10253:23;10285:31;10310:5;10285:31;:::i;10574:256::-;10640:6;10648;10701:2;10689:9;10680:7;10676:23;10672:32;10669:52;;;10717:1;10714;10707:12;10669:52;10740:28;10758:9;10740:28;:::i;:::-;10730:38;;10787:37;10820:2;10809:9;10805:18;10787:37;:::i;:::-;10777:47;;10574:256;;;;;:::o;10835:320::-;10903:6;10956:2;10944:9;10935:7;10931:23;10927:32;10924:52;;;10972:1;10969;10962:12;10924:52;11012:9;10999:23;-1:-1:-1;;;;;11037:6:1;11034:30;11031:50;;;11077:1;11074;11067:12;11031:50;11100:49;11141:7;11132:6;11121:9;11117:22;11100:49;:::i;11160:315::-;11225:6;11233;11286:2;11274:9;11265:7;11261:23;11257:32;11254:52;;;11302:1;11299;11292:12;11254:52;11341:9;11328:23;11360:31;11385:5;11360:31;:::i;:::-;11410:5;-1:-1:-1;11434:35:1;11465:2;11450:18;;11434:35;:::i;11480:183::-;11540:4;-1:-1:-1;;;;;11565:6:1;11562:30;11559:56;;;11595:18;;:::i;:::-;-1:-1:-1;11640:1:1;11636:14;11652:4;11632:25;;11480:183::o;11668:662::-;11722:5;11775:3;11768:4;11760:6;11756:17;11752:27;11742:55;;11793:1;11790;11783:12;11742:55;11829:6;11816:20;11855:4;11879:60;11895:43;11935:2;11895:43;:::i;11879:60::-;11973:15;;;12059:1;12055:10;;;;12043:23;;12039:32;;;12004:12;;;;12083:15;;;12080:35;;;12111:1;12108;12101:12;12080:35;12147:2;12139:6;12135:15;12159:142;12175:6;12170:3;12167:15;12159:142;;;12241:17;;12229:30;;12279:12;;;;12192;;12159:142;;;-1:-1:-1;12319:5:1;11668:662;-1:-1:-1;;;;;;11668:662:1:o;12335:1199::-;12498:6;12506;12514;12522;12530;12538;12546;12599:3;12587:9;12578:7;12574:23;12570:33;12567:53;;;12616:1;12613;12606:12;12567:53;12655:9;12642:23;12674:31;12699:5;12674:31;:::i;:::-;12724:5;-1:-1:-1;12748:37:1;12781:2;12766:18;;12748:37;:::i;:::-;12738:47;;12836:2;12825:9;12821:18;12808:32;-1:-1:-1;;;;;12900:2:1;12892:6;12889:14;12886:34;;;12916:1;12913;12906:12;12886:34;12939:49;12980:7;12971:6;12960:9;12956:22;12939:49;:::i;:::-;12929:59;;13041:2;13030:9;13026:18;13013:32;12997:48;;13070:2;13060:8;13057:16;13054:36;;;13086:1;13083;13076:12;13054:36;13109:63;13164:7;13153:8;13142:9;13138:24;13109:63;:::i;:::-;13099:73;;13224:3;13213:9;13209:19;13196:33;13181:48;;13238:33;13263:7;13238:33;:::i;:::-;13290:7;13280:17;;13316:39;13350:3;13339:9;13335:19;13316:39;:::i;:::-;13306:49;;13408:3;13397:9;13393:19;13380:33;13364:49;;13438:2;13428:8;13425:16;13422:36;;;13454:1;13451;13444:12;13966:665;14061:6;14069;14077;14085;14138:3;14126:9;14117:7;14113:23;14109:33;14106:53;;;14155:1;14152;14145:12;14106:53;14194:9;14181:23;14213:31;14238:5;14213:31;:::i;:::-;14263:5;-1:-1:-1;14320:2:1;14305:18;;14292:32;14333:33;14292:32;14333:33;:::i;:::-;14385:7;-1:-1:-1;14439:2:1;14424:18;;14411:32;;-1:-1:-1;14494:2:1;14479:18;;14466:32;-1:-1:-1;;;;;14510:30:1;;14507:50;;;14553:1;14550;14543:12;14507:50;14576:49;14617:7;14608:6;14597:9;14593:22;14576:49;:::i;:::-;14566:59;;;13966:665;;;;;;;:::o;14636:622::-;14731:6;14739;14747;14755;14763;14816:3;14804:9;14795:7;14791:23;14787:33;14784:53;;;14833:1;14830;14823:12;14784:53;14856:28;14874:9;14856:28;:::i;:::-;14846:38;;14903:37;14936:2;14925:9;14921:18;14903:37;:::i;:::-;14893:47;;14987:2;14976:9;14972:18;14959:32;14949:42;;15042:2;15031:9;15027:18;15014:32;-1:-1:-1;;;;;15061:6:1;15058:30;15055:50;;;15101:1;15098;15091:12;15055:50;15140:58;15190:7;15181:6;15170:9;15166:22;15140:58;:::i;:::-;14636:622;;;;-1:-1:-1;14636:622:1;;-1:-1:-1;15217:8:1;;15114:84;14636:622;-1:-1:-1;;;14636:622:1:o;15263:324::-;15338:6;15346;15354;15407:2;15395:9;15386:7;15382:23;15378:32;15375:52;;;15423:1;15420;15413:12;15375:52;15446:28;15464:9;15446:28;:::i;:::-;15436:38;;15493:37;15526:2;15515:9;15511:18;15493:37;:::i;:::-;15483:47;;15577:2;15566:9;15562:18;15549:32;15539:42;;15263:324;;;;;:::o;15592:388::-;15660:6;15668;15721:2;15709:9;15700:7;15696:23;15692:32;15689:52;;;15737:1;15734;15727:12;15689:52;15776:9;15763:23;15795:31;15820:5;15795:31;:::i;:::-;15845:5;-1:-1:-1;15902:2:1;15887:18;;15874:32;15915:33;15874:32;15915:33;:::i;:::-;15967:7;15957:17;;;15592:388;;;;;:::o;15985:907::-;16119:6;16127;16135;16143;16151;16204:3;16192:9;16183:7;16179:23;16175:33;16172:53;;;16221:1;16218;16211:12;16172:53;16244:28;16262:9;16244:28;:::i;:::-;16234:38;;16323:2;16312:9;16308:18;16295:32;-1:-1:-1;;;;;16387:2:1;16379:6;16376:14;16373:34;;;16403:1;16400;16393:12;16373:34;16426:49;16467:7;16458:6;16447:9;16443:22;16426:49;:::i;:::-;16416:59;;16528:2;16517:9;16513:18;16500:32;16484:48;;16557:2;16547:8;16544:16;16541:36;;;16573:1;16570;16563:12;16541:36;16596:63;16651:7;16640:8;16629:9;16625:24;16596:63;:::i;:::-;16586:73;;16678:35;16709:2;16698:9;16694:18;16678:35;:::i;16897:460::-;16981:6;16989;16997;17005;17058:3;17046:9;17037:7;17033:23;17029:33;17026:53;;;17075:1;17072;17065:12;17026:53;17098:28;17116:9;17098:28;:::i;:::-;17088:38;;17145:37;17178:2;17167:9;17163:18;17145:37;:::i;:::-;17135:47;;17232:2;17221:9;17217:18;17204:32;17245:31;17270:5;17245:31;:::i;:::-;16897:460;;;;-1:-1:-1;17295:5:1;;17347:2;17332:18;17319:32;;-1:-1:-1;;16897:460:1:o;17721:380::-;17800:1;17796:12;;;;17843;;;17864:61;;17918:4;17910:6;17906:17;17896:27;;17864:61;17971:2;17963:6;17960:14;17940:18;17937:38;17934:161;;;18017:10;18012:3;18008:20;18005:1;17998:31;18052:4;18049:1;18042:15;18080:4;18077:1;18070:15;17934:161;;17721:380;;;:::o;18106:271::-;18289:6;18281;18276:3;18263:33;18245:3;18315:16;;18340:13;;;18315:16;18106:271;-1:-1:-1;18106:271:1:o;20789:127::-;20850:10;20845:3;20841:20;20838:1;20831:31;20881:4;20878:1;20871:15;20905:4;20902:1;20895:15;20921:135;20960:3;-1:-1:-1;;20981:17:1;;20978:43;;;21001:18;;:::i;:::-;-1:-1:-1;21048:1:1;21037:13;;20921:135::o;21061:409::-;21263:2;21245:21;;;21302:2;21282:18;;;21275:30;21341:34;21336:2;21321:18;;21314:62;-1:-1:-1;;;21407:2:1;21392:18;;21385:43;21460:3;21445:19;;21061:409::o;21475:266::-;21563:6;21558:3;21551:19;21615:6;21608:5;21601:4;21596:3;21592:14;21579:43;-1:-1:-1;21667:1:1;21642:16;;;21660:4;21638:27;;;21631:38;;;;21723:2;21702:15;;;-1:-1:-1;;21698:29:1;21689:39;;;21685:50;;21475:266::o;21746:326::-;21941:6;21933;21929:19;21918:9;21911:38;21985:2;21980;21969:9;21965:18;21958:30;21892:4;22005:61;22062:2;22051:9;22047:18;22039:6;22031;22005:61;:::i;23593:428::-;23646:5;23699:3;23692:4;23684:6;23680:17;23676:27;23666:55;;23717:1;23714;23707:12;23666:55;23746:6;23740:13;23777:48;23793:31;23821:2;23793:31;:::i;23777:48::-;23850:2;23841:7;23834:19;23896:3;23889:4;23884:2;23876:6;23872:15;23868:26;23865:35;23862:55;;;23913:1;23910;23903:12;23862:55;23926:64;23987:2;23980:4;23971:7;23967:18;23960:4;23952:6;23948:17;23926:64;:::i;24026:1104::-;24139:6;24147;24200:2;24188:9;24179:7;24175:23;24171:32;24168:52;;;24216:1;24213;24206:12;24168:52;24249:9;24243:16;-1:-1:-1;;;;;24319:2:1;24311:6;24308:14;24305:34;;;24335:1;24332;24325:12;24305:34;24358:60;24410:7;24401:6;24390:9;24386:22;24358:60;:::i;:::-;24348:70;;24437:2;24427:12;;24485:2;24474:9;24470:18;24464:25;24514:2;24504:8;24501:16;24498:36;;;24530:1;24527;24520:12;24498:36;24553:24;;;-1:-1:-1;24608:4:1;24600:13;;24596:27;-1:-1:-1;24586:55:1;;24637:1;24634;24627:12;24586:55;24666:2;24660:9;24689:60;24705:43;24745:2;24705:43;:::i;24689:60::-;24783:15;;;24865:1;24861:10;;;;24853:19;;24849:28;;;24814:12;;;;24889:19;;;24886:39;;;24921:1;24918;24911:12;24886:39;24945:11;;;;24965:135;24981:6;24976:3;24973:15;24965:135;;;25047:10;;25035:23;;24998:12;;;;25078;;;;24965:135;;;25119:5;25109:15;;;;;;;24026:1104;;;;;:::o;26570:125::-;26610:4;26638:1;26635;26632:8;26629:34;;;26643:18;;:::i;:::-;-1:-1:-1;26680:9:1;;26570:125::o;26700:382::-;26911:6;26903;26898:3;26885:33;27003:2;26999:15;;;;-1:-1:-1;;26995:53:1;26937:16;;26984:65;;;27073:2;27065:11;;26700:382;-1:-1:-1;26700:382:1:o;27087:470::-;27266:3;27304:6;27298:13;27320:53;27366:6;27361:3;27354:4;27346:6;27342:17;27320:53;:::i;:::-;27436:13;;27395:16;;;;27458:57;27436:13;27395:16;27492:4;27480:17;;27458:57;:::i;:::-;27531:20;;27087:470;-1:-1:-1;;;;27087:470:1:o;27562:498::-;27762:4;27791:6;27836:2;27828:6;27824:15;27813:9;27806:34;27888:2;27880:6;27876:15;27871:2;27860:9;27856:18;27849:43;;27928:6;27923:2;27912:9;27908:18;27901:34;27971:3;27966:2;27955:9;27951:18;27944:31;27992:62;28049:3;28038:9;28034:19;28026:6;28018;27992:62;:::i;:::-;27984:70;27562:498;-1:-1:-1;;;;;;;27562:498:1:o;29275:493::-;29524:6;29516;29512:19;29501:9;29494:38;29568:3;29563:2;29552:9;29548:18;29541:31;29475:4;29589:62;29646:3;29635:9;29631:19;29623:6;29615;29589:62;:::i;:::-;-1:-1:-1;;;;;29687:31:1;;;;29682:2;29667:18;;29660:59;-1:-1:-1;29750:2:1;29735:18;29728:34;29581:70;29275:493;-1:-1:-1;;;29275:493:1:o;30696:435::-;30749:3;30787:5;30781:12;30814:6;30809:3;30802:19;30840:4;30869:2;30864:3;30860:12;30853:19;;30906:2;30899:5;30895:14;30927:1;30937:169;30951:6;30948:1;30945:13;30937:169;;;31012:13;;31000:26;;31046:12;;;;31081:15;;;;30973:1;30966:9;30937:169;;;-1:-1:-1;31122:3:1;;30696:435;-1:-1:-1;;;;;30696:435:1:o;31136:422::-;31361:2;31350:9;31343:21;31324:4;31387:45;31428:2;31417:9;31413:18;31405:6;31387:45;:::i;:::-;31480:9;31472:6;31468:22;31463:2;31452:9;31448:18;31441:50;31508:44;31545:6;31537;31508:44;:::i;:::-;31500:52;31136:422;-1:-1:-1;;;;;31136:422:1:o;31563:642::-;31844:6;31832:19;;31814:38;;-1:-1:-1;;;;;31888:32:1;;31883:2;31868:18;;31861:60;31908:3;31952:2;31937:18;;31930:31;;;-1:-1:-1;;31984:46:1;;32010:19;;32002:6;31984:46;:::i;:::-;32080:6;32073:14;32066:22;32061:2;32050:9;32046:18;32039:50;32138:9;32130:6;32126:22;32120:3;32109:9;32105:19;32098:51;32166:33;32192:6;32184;32166:33;:::i;:::-;32158:41;31563:642;-1:-1:-1;;;;;;;;31563:642:1:o;32210:245::-;32289:6;32297;32350:2;32338:9;32329:7;32325:23;32321:32;32318:52;;;32366:1;32363;32356:12;32318:52;-1:-1:-1;;32389:16:1;;32445:2;32430:18;;;32424:25;32389:16;;32424:25;;-1:-1:-1;32210:245:1:o;33328:335::-;33407:6;33460:2;33448:9;33439:7;33435:23;33431:32;33428:52;;;33476:1;33473;33466:12;33428:52;33509:9;33503:16;-1:-1:-1;;;;;33534:6:1;33531:30;33528:50;;;33574:1;33571;33564:12;33528:50;33597:60;33649:7;33640:6;33629:9;33625:22;33597:60;:::i;33668:557::-;33925:6;33917;33913:19;33902:9;33895:38;33969:3;33964:2;33953:9;33949:18;33942:31;33876:4;33996:46;34037:3;34026:9;34022:19;34014:6;33996:46;:::i;:::-;-1:-1:-1;;;;;34082:6:1;34078:31;34073:2;34062:9;34058:18;34051:59;34158:9;34150:6;34146:22;34141:2;34130:9;34126:18;34119:50;34186:33;34212:6;34204;34186:33;:::i;34591:401::-;34793:2;34775:21;;;34832:2;34812:18;;;34805:30;34871:34;34866:2;34851:18;;34844:62;-1:-1:-1;;;34937:2:1;34922:18;;34915:35;34982:3;34967:19;;34591:401::o;35402:127::-;35463:10;35458:3;35454:20;35451:1;35444:31;35494:4;35491:1;35484:15;35518:4;35515:1;35508:15;36285:168;36325:7;36391:1;36387;36383:6;36379:14;36376:1;36373:21;36368:1;36361:9;36354:17;36350:45;36347:71;;;36398:18;;:::i;:::-;-1:-1:-1;36438:9:1;;36285:168::o;36458:274::-;36587:3;36625:6;36619:13;36641:53;36687:6;36682:3;36675:4;36667:6;36663:17;36641:53;:::i;:::-;36710:16;;;;;36458:274;-1:-1:-1;;36458:274:1:o;36737:261::-;36916:2;36905:9;36898:21;36879:4;36936:56;36988:2;36977:9;36973:18;36965:6;36936:56;:::i;37003:289::-;37178:6;37167:9;37160:25;37221:2;37216;37205:9;37201:18;37194:30;37141:4;37241:45;37282:2;37271:9;37267:18;37259:6;37241:45;:::i;37657:128::-;37697:3;37728:1;37724:6;37721:1;37718:13;37715:39;;;37734:18;;:::i;:::-;-1:-1:-1;37770:9:1;;37657:128::o;38833:414::-;39035:2;39017:21;;;39074:2;39054:18;;;39047:30;39113:34;39108:2;39093:18;;39086:62;-1:-1:-1;;;39179:2:1;39164:18;;39157:48;39237:3;39222:19;;38833:414::o;39384:719::-;39687:6;39679;39675:19;39664:9;39657:38;39731:3;39726:2;39715:9;39711:18;39704:31;39638:4;39758:46;39799:3;39788:9;39784:19;39776:6;39758:46;:::i;:::-;-1:-1:-1;;;;;39844:6:1;39840:31;39835:2;39824:9;39820:18;39813:59;39920:9;39912:6;39908:22;39903:2;39892:9;39888:18;39881:50;39954:33;39980:6;39972;39954:33;:::i;:::-;39940:47;;40036:9;40028:6;40024:22;40018:3;40007:9;40003:19;39996:51;40064:33;40090:6;40082;40064:33;:::i;42054:840::-;42403:6;42395;42391:19;42380:9;42373:38;42447:3;42442:2;42431:9;42427:18;42420:31;42354:4;42474:46;42515:3;42504:9;42500:19;42492:6;42474:46;:::i;:::-;42568:9;42560:6;42556:22;42551:2;42540:9;42536:18;42529:50;42602:33;42628:6;42620;42602:33;:::i;:::-;-1:-1:-1;;;;;42709:15:1;;;42704:2;42689:18;;42682:43;42762:15;;42756:3;42741:19;;42734:44;42815:22;;;42662:3;42794:19;;42787:51;42588:47;-1:-1:-1;42855:33:1;42588:47;42873:6;42855:33;:::i;:::-;42847:41;42054:840;-1:-1:-1;;;;;;;;;42054:840:1:o;42899:489::-;-1:-1:-1;;;;;43168:15:1;;;43150:34;;43220:15;;43215:2;43200:18;;43193:43;43267:2;43252:18;;43245:34;;;43315:3;43310:2;43295:18;;43288:31;;;43093:4;;43336:46;;43362:19;;43354:6;43336:46;:::i;:::-;43328:54;42899:489;-1:-1:-1;;;;;;42899:489:1:o;43393:249::-;43462:6;43515:2;43503:9;43494:7;43490:23;43486:32;43483:52;;;43531:1;43528;43521:12;43483:52;43563:9;43557:16;43582:30;43606:5;43582:30;:::i

Swarm Source

ipfs://9d1f2077e2ec613c51f889ee55d33f6b9af56585183e8ce48e2b810c616ee6cb
Loading...
Loading
Loading...
Loading
[ Download: CSV Export  ]
[ Download: CSV Export  ]

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