ETH Price: $3,551.61 (+0.63%)

Token

UltraMarathon (UltraRunner)
 

Overview

Max Total Supply

0 UltraRunner

Holders

4,921

Market

Onchain Market Cap

$0.00

Circulating Supply Market Cap

-
Balance
1 UltraRunner
0x94cbfd9caf353df0d83c109010f8a4a9da5a1990
Loading...
Loading
Loading...
Loading
Loading...
Loading

Click here to update the token information / general information

Contract Source Code Verified (Exact Match)

Contract Name:
UltraMarathon

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 optimistic.etherscan.io on 2023-07-29
*/

// SPDX-License-Identifier: BUSL-1.1

pragma solidity ^0.8.0;

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

/// @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 UltraMarathon is UniversalONFT721 {
    uint public fee;
    string internal baseUriStr;

    constructor(uint256 _minGasToStore, address _layerZeroEndpoint, uint _startMintId, uint _endMintId) UniversalONFT721("UltraMarathon", "UltraRunner", _minGasToStore, _layerZeroEndpoint, _startMintId, _endMintId) {
        fee = 0.00031 ether;
        baseUriStr = "";
    }

    /// @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 ultraMint(uint256 times) public payable {
        require(msg.value >= times * fee, "Not enough ETH sent");
        for (uint i = 0; i < times; ++i) {
            uint newId = nextMintId;
            nextMintId++;
            _safeMint(msg.sender, newId);
        }
    }

    function ultraRun(address _from, uint16[] memory _dstChainIds, bytes memory _toAddress, uint[] memory _tokenIds, address payable _refundAddress, address _zroPaymentAddress, bytes[] memory _adapterParams, uint[] memory _nativeFees) public payable {
        require(_tokenIds.length == _dstChainIds.length, "UltraMarathon: tokenIds and dstChainIds length mismatch");
        require(_tokenIds.length == _adapterParams.length, "UltraMarathon: tokenIds and adapterParams length mismatch");
        require(_tokenIds.length == _nativeFees.length, "UltraMarathon: tokenIds and nativeFees length mismatch");
        require(_nativeFees.length == _dstChainIds.length, "UltraMarathon: nativeFees and dstChainIds length mismatch");
        require(_adapterParams.length == _dstChainIds.length, "UltraMarathon: nativeFees and dstChainIds length mismatch");
        require(_adapterParams.length == _nativeFees.length, "UltraMarathon: nativeFees and adapterParams length mismatch");

        for (uint i = 0; i < _dstChainIds.length; i++) {
            uint16 _dstChainId = _dstChainIds[i];
            bytes memory _adapterParam = _adapterParams[i];
            uint _tokenId = _tokenIds[i];
            uint _nativeFee = _nativeFees[i];

            _ultraSend(_from, _dstChainId, _toAddress, _toSingletonArray(_tokenId), _refundAddress, _zroPaymentAddress, _adapterParam, _nativeFee);
        }
    }

    function _ultraSend(address _from, uint16 _dstChainId, bytes memory _toAddress, uint[] memory _tokenIds, address payable _refundAddress, address _zroPaymentAddress, bytes memory _adapterParams, uint _nativeFee) internal virtual {
        // allow 1 by default
        require(_nativeFee > 0, "nativeFee must be > 0");
        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, _nativeFee);
        emit SendToChain(_dstChainId, _from, _toAddress, _tokenIds);
    }

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

    function _baseURI() internal view override returns (string memory) {
        return baseUriStr;
    }

    function setBaseUri(string memory _baseUri) external onlyOwner {
        baseUriStr = _baseUri;
    }
}

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":"string","name":"_baseUri","type":"string"}],"name":"setBaseUri","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":[{"internalType":"uint256","name":"times","type":"uint256"}],"name":"ultraMint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"uint16[]","name":"_dstChainIds","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[]"},{"internalType":"uint256[]","name":"_nativeFees","type":"uint256[]"}],"name":"ultraRun","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"withdrawETH","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"}]

60a06040523480156200001157600080fd5b506040516200541e3803806200541e83398101604081905262000034916200028a565b6040518060400160405280600d81526020016c2ab63a3930a6b0b930ba3437b760991b8152506040518060400160405280600b81526020016a2ab63a3930a93ab73732b960a91b8152508585858585858585838383838080620000a6620000a06200019060201b60201c565b62000194565b6001600160a01b031660805250600160065581620001165760405162461bcd60e51b8152602060048201526024808201527f6d696e476173546f5472616e73666572416e6453746f7265206d7573742062656044820152630203e20360e41b606482015260840160405180910390fd5b5060075581516200012f90600b906020850190620001e4565b5080516200014590600c906020840190620001e4565b5050506011959095555050506012555050660119f17fe16000601355505060408051602081019182905260009081905262000185925060149190620001e4565b505050505062000314565b3390565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b828054620001f290620002d7565b90600052602060002090601f01602090048101928262000216576000855562000261565b82601f106200023157805160ff191683800117855562000261565b8280016001018555821562000261579182015b828111156200026157825182559160200191906001019062000244565b506200026f92915062000273565b5090565b5b808211156200026f576000815560010162000274565b60008060008060808587031215620002a157600080fd5b845160208601519094506001600160a01b0381168114620002c157600080fd5b6040860151606090960151949790965092505050565b600181811c90821680620002ec57607f821691505b602082108114156200030e57634e487b7160e01b600052602260045260246000fd5b50919050565b6080516150b6620003686000396000818161098201528181610bda01528181610ede015281816111630152818161146001528181611d5c0152818161223d0152818161237001526137ea01526150b66000f3fe6080604052600436106103965760003560e01c80638da5cb5b116101dc578063c87b56dd11610102578063e1d4c870116100a0578063f2fde38b1161006f578063f2fde38b14610b57578063f5ecbdbc14610b77578063f7f3f2fd14610b97578063fa25f9b614610baa57600080fd5b8063e1d4c87014610ab8578063e985e9c514610ace578063eb8d72b714610b17578063f235364114610b3757600080fd5b8063d1deba1f116100dc578063d1deba1f14610a5a578063ddca3f4314610a6d578063df2a5b3b14610a83578063e086e5ec14610aa357600080fd5b8063c87b56dd146109fa578063cbed8b9c14610a1a578063d12473a514610a3a57600080fd5b8063a22cb4651161017a578063b353aaa711610149578063b353aaa714610970578063b88d4fde146109a4578063baf3292d146109c4578063c4461834146109e457600080fd5b8063a22cb465146108f5578063a6c3d16514610915578063ab3ffb9314610935578063af3fb21c1461094857600080fd5b806395d89b41116101b657806395d89b41146108805780639ea5d6b1146108955780639f38369a146108b5578063a0bcfc7f146108d557600080fd5b80638da5cb5b146108225780638ffa1f2a14610840578063950c8a741461086057600080fd5b80633f6dc453116102c15780636352211e1161025f57806370a082311161022e57806370a0823114610795578063715018a6146107b55780637533d788146107ca5780638cfd8f5c146107ea57600080fd5b80636352211e1461071f57806366ad5c8a1461073f57806369fe0e2d1461075f5780636aa99da31461077f57600080fd5b8063482881901161029b578063482881901461067a5780634ac3f4ff1461069057806351905636146106bd5780635b8c41e6146106d057600080fd5b80633f6dc4531461062757806342842e0e1461063a57806342d65a8d1461065a57600080fd5b80630df374831161033957806323b872dd1161030857806323b872dd146105775780632a205e3d146105975780633d8b38f6146105cc5780633f1f4fa4146105ec57600080fd5b80630df37483146104ac57806310ddb137146104cc5780631249c58b146104ec57806322a3ecf9146104f457600080fd5b806307e0db171161037557806307e0db1714610414578063081812fc14610434578063095ea7b31461046c5780630b4cad4c1461048c57600080fd5b80621d35671461039b57806301ffc9a7146103bd57806306fdde03146103f2575b600080fd5b3480156103a757600080fd5b506103bb6103b6366004613e53565b610bd7565b005b3480156103c957600080fd5b506103dd6103d8366004613efc565b610e08565b60405190151581526020015b60405180910390f35b3480156103fe57600080fd5b50610407610e2b565b6040516103e99190613f71565b34801561042057600080fd5b506103bb61042f366004613f84565b610ebd565b34801561044057600080fd5b5061045461044f366004613f9f565b610f46565b6040516001600160a01b0390911681526020016103e9565b34801561047857600080fd5b506103bb610487366004613fd8565b610f6d565b34801561049857600080fd5b506103bb6104a7366004613f9f565b611083565b3480156104b857600080fd5b506103bb6104c7366004614004565b611123565b3480156104d857600080fd5b506103bb6104e7366004613f84565b611142565b6103bb61119a565b34801561050057600080fd5b5061054861050f366004613f9f565b600a6020526000908152604090208054600182015460029092015461ffff821692620100009092046001600160a01b0316919060ff1684565b6040805161ffff90951685526001600160a01b03909316602085015291830152151560608201526080016103e9565b34801561058357600080fd5b506103bb610592366004614020565b61126f565b3480156105a357600080fd5b506105b76105b236600461413c565b6112a1565b604080519283526020830191909152016103e9565b3480156105d857600080fd5b506103dd6105e73660046141ca565b6112c7565b3480156105f857600080fd5b50610619610607366004613f84565b60036020526000908152604090205481565b6040519081526020016103e9565b6103bb610635366004613f9f565b611393565b34801561064657600080fd5b506103bb610655366004614020565b611426565b34801561066657600080fd5b506103bb6106753660046141ca565b611441565b34801561068657600080fd5b5061061960075481565b34801561069c57600080fd5b506106196106ab366004613f84565b60086020526000908152604090205481565b6103bb6106cb36600461421c565b6114c7565b3480156106dc57600080fd5b506106196106eb3660046142d5565b6005602090815260009384526040808520845180860184018051928152908401958401959095209452929052825290205481565b34801561072b57600080fd5b5061045461073a366004613f9f565b6114de565b34801561074b57600080fd5b506103bb61075a366004613e53565b61153e565b34801561076b57600080fd5b506103bb61077a366004613f9f565b61161a565b34801561078b57600080fd5b5061061960115481565b3480156107a157600080fd5b506106196107b0366004614332565b611627565b3480156107c157600080fd5b506103bb6116ad565b3480156107d657600080fd5b506104076107e5366004613f84565b6116c1565b3480156107f657600080fd5b5061061961080536600461434f565b600260209081526000928352604080842090915290825290205481565b34801561082e57600080fd5b506000546001600160a01b0316610454565b34801561084c57600080fd5b506103bb61085b366004614382565b61175b565b34801561086c57600080fd5b50600454610454906001600160a01b031681565b34801561088c57600080fd5b506104076119a4565b3480156108a157600080fd5b506103bb6108b0366004614004565b6119b3565b3480156108c157600080fd5b506104076108d0366004613f84565b611a6a565b3480156108e157600080fd5b506103bb6108f03660046143b6565b611b81565b34801561090157600080fd5b506103bb6109103660046143fe565b611b9c565b34801561092157600080fd5b506103bb6109303660046141ca565b611ba7565b6103bb6109433660046144b3565b611c3a565b34801561095457600080fd5b5061095d600181565b60405161ffff90911681526020016103e9565b34801561097c57600080fd5b506104547f000000000000000000000000000000000000000000000000000000000000000081565b3480156109b057600080fd5b506103bb6109bf366004614568565b611c49565b3480156109d057600080fd5b506103bb6109df366004614332565b611c81565b3480156109f057600080fd5b5061061961271081565b348015610a0657600080fd5b50610407610a15366004613f9f565b611cd7565b348015610a2657600080fd5b506103bb610a353660046145d3565b611d3d565b348015610a4657600080fd5b506103bb610a55366004614004565b611dd2565b6103bb610a68366004613e53565b611e82565b348015610a7957600080fd5b5061061960135481565b348015610a8f57600080fd5b506103bb610a9e366004614641565b612098565b348015610aaf57600080fd5b506103dd61214a565b348015610ac457600080fd5b5061061960125481565b348015610ada57600080fd5b506103dd610ae936600461467d565b6001600160a01b03918216600090815260106020908152604080832093909416825291909152205460ff1690565b348015610b2357600080fd5b506103bb610b323660046141ca565b6121a4565b348015610b4357600080fd5b506105b7610b523660046146b6565b6121fe565b348015610b6357600080fd5b506103bb610b72366004614332565b6122c9565b348015610b8357600080fd5b50610407610b9236600461472f565b61233f565b6103bb610ba536600461485d565b6123f2565b348015610bb657600080fd5b50610619610bc5366004613f84565b60096020526000908152604090205481565b337f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031614610c545760405162461bcd60e51b815260206004820152601e60248201527f4c7a4170703a20696e76616c696420656e64706f696e742063616c6c6572000060448201526064015b60405180910390fd5b61ffff861660009081526001602052604081208054610c7290614960565b80601f0160208091040260200160405190810160405280929190818152602001828054610c9e90614960565b8015610ceb5780601f10610cc057610100808354040283529160200191610ceb565b820191906000526020600020905b815481529060010190602001808311610cce57829003601f168201915b50505050509050805186869050148015610d06575060008151115b8015610d2e575080516020820120604051610d24908890889061499b565b6040518091039020145b610d895760405162461bcd60e51b815260206004820152602660248201527f4c7a4170703a20696e76616c696420736f757263652073656e64696e6720636f6044820152651b9d1c9858dd60d21b6064820152608401610c4b565b610dff8787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f8a018190048102820181019092528881528a9350915088908890819084018382808284376000920191909152506126bc92505050565b50505050505050565b60006001600160e01b031982161580610e255750610e2582612735565b92915050565b6060600b8054610e3a90614960565b80601f0160208091040260200160405190810160405280929190818152602001828054610e6690614960565b8015610eb35780601f10610e8857610100808354040283529160200191610eb3565b820191906000526020600020905b815481529060010190602001808311610e9657829003601f168201915b5050505050905090565b610ec5612775565b6040516307e0db1760e01b815261ffff821660048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906307e0db17906024015b600060405180830381600087803b158015610f2b57600080fd5b505af1158015610f3f573d6000803e3d6000fd5b5050505050565b6000610f51826127cf565b506000908152600f60205260409020546001600160a01b031690565b6000610f78826114de565b9050806001600160a01b0316836001600160a01b03161415610fe65760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e656044820152603960f91b6064820152608401610c4b565b336001600160a01b038216148061100257506110028133610ae9565b6110745760405162461bcd60e51b815260206004820152603d60248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f7420746f60448201527f6b656e206f776e6572206f7220617070726f76656420666f7220616c6c0000006064820152608401610c4b565b61107e838361281f565b505050565b61108b612775565b600081116110e75760405162461bcd60e51b8152602060048201526024808201527f6d696e476173546f5472616e73666572416e6453746f7265206d7573742062656044820152630203e20360e41b6064820152608401610c4b565b60078190556040518181527ffebbc4f8bb9ec2313950c718d43123124b15778efda4c1f1d529de2995b4f34d906020015b60405180910390a150565b61112b612775565b61ffff909116600090815260036020526040902055565b61114a612775565b6040516310ddb13760e01b815261ffff821660048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906310ddb13790602401610f11565b60125460115411156111f95760405162461bcd60e51b815260206004820152602260248201527f4c324d61726174686f6e3a206d6178206d696e74206c696d6974207265616368604482015261195960f21b6064820152608401610c4b565b60135434101561124b5760405162461bcd60e51b815260206004820152601f60248201527f4e6f7420656e6f756768204554482073656e743a20636865636b206665652e006044820152606401610c4b565b60118054908190600061125d836149c1565b919050555061126c338261288d565b50565b61127a335b826128a7565b6112965760405162461bcd60e51b8152600401610c4b906149dc565b61107e838383612925565b6000806112b987876112b288612a89565b87876121fe565b915091509550959350505050565b61ffff8316600090815260016020526040812080548291906112e890614960565b80601f016020809104026020016040519081016040528092919081815260200182805461131490614960565b80156113615780601f1061133657610100808354040283529160200191611361565b820191906000526020600020905b81548152906001019060200180831161134457829003601f168201915b50505050509050838360405161137892919061499b565b60405180910390208180519060200120149150509392505050565b6013546113a09082614a29565b3410156113e55760405162461bcd60e51b8152602060048201526013602482015272139bdd08195b9bdd59da08115512081cd95b9d606a1b6044820152606401610c4b565b60005b8181101561142257601180549081906000611402836149c1565b9190505550611411338261288d565b5061141b816149c1565b90506113e8565b5050565b61107e83838360405180602001604052806000815250611c49565b611449612775565b6040516342d65a8d60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906342d65a8d9061149990869086908690600401614a71565b600060405180830381600087803b1580156114b357600080fd5b505af1158015610dff573d6000803e3d6000fd5b610dff8787876114d688612a89565b878787612ad4565b6000818152600d60205260408120546001600160a01b031680610e255760405162461bcd60e51b8152602060048201526018602482015277115490cdcc8c4e881a5b9d985b1a59081d1bdad95b88125160421b6044820152606401610c4b565b33301461159c5760405162461bcd60e51b815260206004820152602660248201527f4e6f6e626c6f636b696e674c7a4170703a2063616c6c6572206d7573742062656044820152650204c7a4170760d41b6064820152608401610c4b565b6116128686868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f890181900481028201810190925287815289935091508790879081908401838280828437600092019190915250612c6d92505050565b505050505050565b611622612775565b601355565b60006001600160a01b0382166116915760405162461bcd60e51b815260206004820152602960248201527f4552433732313a2061646472657373207a65726f206973206e6f7420612076616044820152683634b21037bbb732b960b91b6064820152608401610c4b565b506001600160a01b03166000908152600e602052604090205490565b6116b5612775565b6116bf6000612dc4565b565b600160205260009081526040902080546116da90614960565b80601f016020809104026020016040519081016040528092919081815260200182805461170690614960565b80156117535780601f1061172857610100808354040283529160200191611753565b820191906000526020600020905b81548152906001019060200180831161173657829003601f168201915b505050505081565b611763612e14565b80516020808301919091206000818152600a90925260409091206002015460ff166117c45760405162461bcd60e51b81526020600482015260116024820152701b9bc818dc99591a5d1cc81cdd1bdc9959607a1b6044820152606401610c4b565b6000828060200190518101906117da9190614ad4565b6000848152600a6020526040812080546001909101549294509092506118169161ffff8216916201000090046001600160a01b03169085612e6e565b6000848152600a6020526040902060010154909150811161188b5760405162461bcd60e51b815260206004820152602960248201527f6e6f7420656e6f7567682067617320746f2070726f6365737320637265646974604482015268103a3930b739b332b960b91b6064820152608401610c4b565b8151811415611903576000838152600a602052604080822080546001600160b01b031916815560018101929092556002909101805460ff19169055517fd7be02b8dd0d27bd0517a9cb4d7469ce27df4313821ae5ec1ff69acc594ba233906118f69085815260200190565b60405180910390a1611997565b604080516080810182526000858152600a6020818152848320805461ffff80821687526001600160a01b03620100008084048216868a019081529989018b8152600160608b01818152998f90529790965297519851169096026001600160b01b03199091169690951695909517939093178455915191830191909155516002909101805491151560ff199092169190911790555b50505061126c6001600655565b6060600c8054610e3a90614960565b6119bb612775565b60008111611a165760405162461bcd60e51b815260206004820152602260248201527f647374436861696e4964546f42617463684c696d6974206d757374206265203e604482015261020360f41b6064820152608401610c4b565b61ffff8216600081815260086020908152604091829020849055815192835282018390527f7315f7654d594ead24a30160ed9ba2d23247f543016b918343591e93d7afdb6d91015b60405180910390a15050565b61ffff8116600090815260016020526040812080546060929190611a8d90614960565b80601f0160208091040260200160405190810160405280929190818152602001828054611ab990614960565b8015611b065780601f10611adb57610100808354040283529160200191611b06565b820191906000526020600020905b815481529060010190602001808311611ae957829003601f168201915b50505050509050805160001415611b5f5760405162461bcd60e51b815260206004820152601d60248201527f4c7a4170703a206e6f20747275737465642070617468207265636f72640000006044820152606401610c4b565b611b7a600060148351611b729190614b8e565b839190612ec0565b9392505050565b611b89612775565b8051611422906014906020840190613cd0565b611422338383612fcd565b611baf612775565b818130604051602001611bc493929190614ba5565b60408051601f1981840301815291815261ffff85166000908152600160209081529190208251611bf993919290910190613cd0565b507f8c0400cfe2d1199b1a725c78960bcc2a344d869b80590d0f2bd005db15a572ce838383604051611c2d93929190614a71565b60405180910390a1505050565b610dff87878787878787612ad4565b611c5333836128a7565b611c6f5760405162461bcd60e51b8152600401610c4b906149dc565b611c7b8484848461309c565b50505050565b611c89612775565b600480546001600160a01b0319166001600160a01b0383169081179091556040519081527f5db758e995a17ec1ad84bdef7e8c3293a0bd6179bcce400dff5d4c3d87db726b90602001611118565b6060611ce2826127cf565b6000611cec6130cf565b90506000815111611d0c5760405180602001604052806000815250611b7a565b80611d16846130de565b604051602001611d27929190614bcb565b6040516020818303038152906040529392505050565b611d45612775565b6040516332fb62e760e21b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063cbed8b9c90611d999088908890889088908890600401614bfa565b600060405180830381600087803b158015611db357600080fd5b505af1158015611dc7573d6000803e3d6000fd5b505050505050505050565b611dda612775565b60008111611e365760405162461bcd60e51b815260206004820152602360248201527f647374436861696e4964546f5472616e73666572476173206d7573742062652060448201526203e20360ec1b6064820152608401610c4b565b61ffff8216600081815260096020908152604091829020849055815192835282018390527fc46df2983228ac2d9754e94a0d565e6671665dc8ad38602bc8e544f0685a29fb9101611a5e565b61ffff86166000908152600560205260408082209051611ea5908890889061499b565b90815260408051602092819003830190206001600160401b03871660009081529252902054905080611f255760405162461bcd60e51b815260206004820152602360248201527f4e6f6e626c6f636b696e674c7a4170703a206e6f2073746f726564206d65737360448201526261676560e81b6064820152608401610c4b565b808383604051611f3692919061499b565b604051809103902014611f955760405162461bcd60e51b815260206004820152602160248201527f4e6f6e626c6f636b696e674c7a4170703a20696e76616c6964207061796c6f616044820152601960fa1b6064820152608401610c4b565b61ffff87166000908152600560205260408082209051611fb8908990899061499b565b90815260408051602092819003830181206001600160401b038916600090815290845282902093909355601f88018290048202830182019052868252612050918991899089908190840183828082843760009201919091525050604080516020601f8a018190048102820181019092528881528a935091508890889081908401838280828437600092019190915250612c6d92505050565b7fc264d91f3adc5588250e1551f547752ca0cfa8f6b530d243b9f9f4cab10ea8e58787878785604051612087959493929190614c33565b60405180910390a150505050505050565b6120a0612775565b600081116120e85760405162461bcd60e51b81526020600482015260156024820152744c7a4170703a20696e76616c6964206d696e47617360581b6044820152606401610c4b565b61ffff83811660008181526002602090815260408083209487168084529482529182902085905581519283528201929092529081018290527f9d5c7c0b934da8fefa9c7760c98383778a12dfbfc0c3b3106518f43fb9508ac090606001611c2d565b6000612154612775565b604051600090339047908381818185875af1925050503d8060008114612196576040519150601f19603f3d011682016040523d82523d6000602084013e61219b565b606091505b50909250505090565b6121ac612775565b61ffff831660009081526001602052604090206121ca908383613d54565b507ffa41487ad5d6728f0b19276fa1eddc16558578f5109fc39d2dc33c3230470dab838383604051611c2d93929190614a71565b60008060008686604051602001612216929190614ca9565b60408051601f198184030181529082905263040a7bb160e41b825291506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906340a7bb109061227a908b90309086908b908b90600401614cd7565b6040805180830381865afa158015612296573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122ba9190614d2b565b92509250509550959350505050565b6122d1612775565b6001600160a01b0381166123365760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610c4b565b61126c81612dc4565b604051633d7b2f6f60e21b815261ffff808616600483015284166024820152306044820152606481018290526060907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063f5ecbdbc90608401600060405180830381865afa1580156123bf573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526123e79190810190614d4f565b90505b949350505050565b86518551146124695760405162461bcd60e51b815260206004820152603760248201527f556c7472614d61726174686f6e3a20746f6b656e49647320616e64206473744360448201527f6861696e496473206c656e677468206d69736d617463680000000000000000006064820152608401610c4b565b81518551146124e05760405162461bcd60e51b815260206004820152603960248201527f556c7472614d61726174686f6e3a20746f6b656e49647320616e64206164617060448201527f746572506172616d73206c656e677468206d69736d61746368000000000000006064820152608401610c4b565b80518551146125505760405162461bcd60e51b815260206004820152603660248201527f556c7472614d61726174686f6e3a20746f6b656e49647320616e64206e6174696044820152750ecca8ccacae640d8cadccee8d040dad2e6dac2e8c6d60531b6064820152608401610c4b565b86518151146125715760405162461bcd60e51b8152600401610c4b90614d83565b86518251146125925760405162461bcd60e51b8152600401610c4b90614d83565b80518251146126095760405162461bcd60e51b815260206004820152603b60248201527f556c7472614d61726174686f6e3a206e61746976654665657320616e6420616460448201527f6170746572506172616d73206c656e677468206d69736d6174636800000000006064820152608401610c4b565b60005b8751811015611dc757600088828151811061262957612629614de0565b60200260200101519050600084838151811061264757612647614de0565b60200260200101519050600088848151811061266557612665614de0565b60200260200101519050600085858151811061268357612683614de0565b602002602001015190506126a58d858d61269c86612a89565b8d8d898861317a565b5050505080806126b4906149c1565b91505061260c565b60008061271f5a60966366ad5c8a60e01b898989896040516024016126e49493929190614df6565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091523092919061334a565b91509150816116125761161286868686856133d4565b60006001600160e01b031982166380ac58cd60e01b148061276657506001600160e01b03198216635b5e139f60e01b145b80610e255750610e2582613471565b6000546001600160a01b031633146116bf5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610c4b565b6127d8816134a6565b61126c5760405162461bcd60e51b8152602060048201526018602482015277115490cdcc8c4e881a5b9d985b1a59081d1bdad95b88125160421b6044820152606401610c4b565b6000818152600f6020526040902080546001600160a01b0319166001600160a01b0384169081179091558190612854826114de565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b6114228282604051806020016040528060008152506134c3565b6000806128b3836114de565b9050806001600160a01b0316846001600160a01b031614806128fa57506001600160a01b0380821660009081526010602090815260408083209388168352929052205460ff165b806123ea5750836001600160a01b031661291384610f46565b6001600160a01b031614949350505050565b826001600160a01b0316612938826114de565b6001600160a01b03161461295e5760405162461bcd60e51b8152600401610c4b90614e34565b6001600160a01b0382166129c05760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f206164646044820152637265737360e01b6064820152608401610c4b565b826001600160a01b03166129d3826114de565b6001600160a01b0316146129f95760405162461bcd60e51b8152600401610c4b90614e34565b6000818152600f6020908152604080832080546001600160a01b03199081169091556001600160a01b03878116808652600e8552838620805460001901905590871680865283862080546001019055868652600d90945282852080549092168417909155905184937fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b60408051600180825281830190925260609160009190602080830190803683370190505090508281600081518110612ac357612ac3614de0565b602090810291909101015292915050565b6000845111612b1b5760405162461bcd60e51b8152602060048201526013602482015272746f6b656e4964735b5d20697320656d70747960681b6044820152606401610c4b565b835160011480612b3f575061ffff8616600090815260086020526040902054845111155b612b5b5760405162461bcd60e51b8152600401610c4b90614e79565b60005b8451811015612b9e57612b8c888888888581518110612b7f57612b7f614de0565b60200260200101516134f6565b80612b96816149c1565b915050612b5e565b5060008585604051602001612bb4929190614ca9565b6040516020818303038152906040529050612bf9876001848851600960008d61ffff1661ffff16815260200190815260200160002054612bf49190614a29565b6135e1565b612c078782868686346136c0565b85604051612c159190614ebb565b6040518091039020886001600160a01b03168861ffff167fe1b87c47fdeb4f9cbadbca9df3af7aba453bb6e501075d0440d88125b711522a88604051612c5b9190614ed7565b60405180910390a45050505050505050565b60008082806020019051810190612c849190614ad4565b601482015191935091506000612c9c88838386612e6e565b90508251811015612d705784516020808701919091206040805160808101825261ffff808d1682526001600160a01b038088168387019081528385018881526001606086018181526000898152600a909a529887902095518654935190941662010000026001600160b01b03199093169390941692909217178355519082015592516002909301805493151560ff199094169390931790925590517f10e0b70d256bccc84b7027506978bd8b68984a870788b93b479def144c839ad790612d669083908990614eea565b60405180910390a1505b816001600160a01b031687604051612d889190614ebb565b60405180910390208961ffff167f5b821db8a46f8ecbe1941ba2f51cfeea9643268b56631f70d45e2a745d99026586604051612c5b9190614ed7565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60026006541415612e675760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610c4b565b6002600655565b6000825b82518110156123e7576007545a1015612e8a576123e7565b612eae8686858481518110612ea157612ea1614de0565b6020026020010151613866565b80612eb8816149c1565b915050612e72565b606081612ece81601f614f03565b1015612f0d5760405162461bcd60e51b815260206004820152600e60248201526d736c6963655f6f766572666c6f7760901b6044820152606401610c4b565b612f178284614f03565b84511015612f5b5760405162461bcd60e51b8152602060048201526011602482015270736c6963655f6f75744f66426f756e647360781b6044820152606401610c4b565b606082158015612f7a5760405191506000825260208201604052612fc4565b6040519150601f8416801560200281840101858101878315602002848b0101015b81831015612fb3578051835260209283019201612f9b565b5050858452601f01601f1916604052505b50949350505050565b816001600160a01b0316836001600160a01b0316141561302f5760405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c6572000000000000006044820152606401610c4b565b6001600160a01b03838116600081815260106020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b6130a7848484612925565b6130b3848484846138c6565b611c7b5760405162461bcd60e51b8152600401610c4b90614f1b565b606060148054610e3a90614960565b606060006130eb836139c1565b60010190506000816001600160401b0381111561310a5761310a614061565b6040519080825280601f01601f191660200182016040528015613134576020820181803683370190505b5090508181016020015b600019016f181899199a1a9b1b9c1cb0b131b232b360811b600a86061a8153600a850494508461316d57613172565b61313e565b509392505050565b600081116131c25760405162461bcd60e51b815260206004820152601560248201527406e6174697665466565206d757374206265203e203605c1b6044820152606401610c4b565b60008551116132095760405162461bcd60e51b8152602060048201526013602482015272746f6b656e4964735b5d20697320656d70747960681b6044820152606401610c4b565b84516001148061322d575061ffff8716600090815260086020526040902054855111155b6132495760405162461bcd60e51b8152600401610c4b90614e79565b60005b855181101561327f5761326d898989898581518110612b7f57612b7f614de0565b80613277816149c1565b91505061324c565b5060008686604051602001613295929190614ca9565b60405160208183030381529060405290506132d5886001858951600960008e61ffff1661ffff16815260200190815260200160002054612bf49190614a29565b6132e38882878787876136c0565b866040516132f19190614ebb565b6040518091039020896001600160a01b03168961ffff167fe1b87c47fdeb4f9cbadbca9df3af7aba453bb6e501075d0440d88125b711522a896040516133379190614ed7565b60405180910390a4505050505050505050565b6000606060008060008661ffff166001600160401b0381111561336f5761336f614061565b6040519080825280601f01601f191660200182016040528015613399576020820181803683370190505b50905060008087516020890160008d8df191503d9250868311156133bb578692505b828152826000602083013e909890975095505050505050565b8180519060200120600560008761ffff1661ffff168152602001908152602001600020856040516134059190614ebb565b9081526040805191829003602090810183206001600160401b0388166000908152915220919091557fe183f33de2837795525b4792ca4cd60535bd77c53b7e7030060bfcf5734d6b0c906134629087908790879087908790614f6d565b60405180910390a15050505050565b60006001600160e01b031982166322bac5d960e01b1480610e2557506301ffc9a760e01b6001600160e01b0319831614610e25565b6000908152600d60205260409020546001600160a01b0316151590565b6134cd8383613a99565b6134da60008484846138c6565b61107e5760405162461bcd60e51b8152600401610c4b90614f1b565b6134ff33611274565b6135625760405162461bcd60e51b815260206004820152602e60248201527f4f4e46543732313a2073656e642063616c6c6572206973206e6f74206f776e6560448201526d1c881b9bdc88185c1c1c9bdd995960921b6064820152608401610c4b565b836001600160a01b0316613575826114de565b6001600160a01b0316146135d65760405162461bcd60e51b815260206004820152602260248201527f4f4e46543732313a2073656e642066726f6d20696e636f7272656374206f776e60448201526132b960f11b6064820152608401610c4b565b611c7b843083612925565b60006135ec83613c06565b61ffff80871660009081526002602090815260408083209389168352929052908120549192509061361e908490614f03565b9050600081116136705760405162461bcd60e51b815260206004820152601a60248201527f4c7a4170703a206d696e4761734c696d6974206e6f74207365740000000000006044820152606401610c4b565b808210156116125760405162461bcd60e51b815260206004820152601b60248201527f4c7a4170703a20676173206c696d697420697320746f6f206c6f7700000000006044820152606401610c4b565b61ffff8616600090815260016020526040812080546136de90614960565b80601f016020809104026020016040519081016040528092919081815260200182805461370a90614960565b80156137575780601f1061372c57610100808354040283529160200191613757565b820191906000526020600020905b81548152906001019060200180831161373a57829003601f168201915b505050505090508051600014156137c95760405162461bcd60e51b815260206004820152603060248201527f4c7a4170703a2064657374696e6174696f6e20636861696e206973206e6f742060448201526f61207472757374656420736f7572636560801b6064820152608401610c4b565b6137d4878751613c62565b60405162c5803160e81b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063c580310090849061382b908b9086908c908c908c908c90600401614fbf565b6000604051808303818588803b15801561384457600080fd5b505af1158015613858573d6000803e3d6000fd5b505050505050505050505050565b61386f816134a6565b158061389b575061387f816134a6565b801561389b575030613890826114de565b6001600160a01b0316145b6138a457600080fd5b6138ad816134a6565b6138bb5761107e828261288d565b61107e308383612925565b60006001600160a01b0384163b156139b957604051630a85bd0160e11b81526001600160a01b0385169063150b7a029061390a903390899088908890600401615026565b6020604051808303816000875af1925050508015613945575060408051601f3d908101601f1916820190925261394291810190615063565b60015b61399f573d808015613973576040519150601f19603f3d011682016040523d82523d6000602084013e613978565b606091505b5080516139975760405162461bcd60e51b8152600401610c4b90614f1b565b805181602001fd5b6001600160e01b031916630a85bd0160e11b1490506123ea565b5060016123ea565b60008072184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b8310613a005772184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b830492506040015b6d04ee2d6d415b85acef81000000008310613a2c576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc100008310613a4a57662386f26fc10000830492506010015b6305f5e1008310613a62576305f5e100830492506008015b6127108310613a7657612710830492506004015b60648310613a88576064830492506002015b600a8310610e255760010192915050565b6001600160a01b038216613aef5760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f20616464726573736044820152606401610c4b565b613af8816134a6565b15613b455760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e746564000000006044820152606401610c4b565b613b4e816134a6565b15613b9b5760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e746564000000006044820152606401610c4b565b6001600160a01b0382166000818152600e6020908152604080832080546001019055848352600d90915280822080546001600160a01b0319168417905551839291907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b6000602282511015613c5a5760405162461bcd60e51b815260206004820152601c60248201527f4c7a4170703a20696e76616c69642061646170746572506172616d73000000006044820152606401610c4b565b506022015190565b61ffff821660009081526003602052604090205480613c8057506127105b8082111561107e5760405162461bcd60e51b815260206004820181905260248201527f4c7a4170703a207061796c6f61642073697a6520697320746f6f206c617267656044820152606401610c4b565b828054613cdc90614960565b90600052602060002090601f016020900481019282613cfe5760008555613d44565b82601f10613d1757805160ff1916838001178555613d44565b82800160010185558215613d44579182015b82811115613d44578251825591602001919060010190613d29565b50613d50929150613dc8565b5090565b828054613d6090614960565b90600052602060002090601f016020900481019282613d825760008555613d44565b82601f10613d9b5782800160ff19823516178555613d44565b82800160010185558215613d44579182015b82811115613d44578235825591602001919060010190613dad565b5b80821115613d505760008155600101613dc9565b803561ffff81168114613def57600080fd5b919050565b60008083601f840112613e0657600080fd5b5081356001600160401b03811115613e1d57600080fd5b602083019150836020828501011115613e3557600080fd5b9250929050565b80356001600160401b0381168114613def57600080fd5b60008060008060008060808789031215613e6c57600080fd5b613e7587613ddd565b955060208701356001600160401b0380821115613e9157600080fd5b613e9d8a838b01613df4565b9097509550859150613eb160408a01613e3c565b94506060890135915080821115613ec757600080fd5b50613ed489828a01613df4565b979a9699509497509295939492505050565b6001600160e01b03198116811461126c57600080fd5b600060208284031215613f0e57600080fd5b8135611b7a81613ee6565b60005b83811015613f34578181015183820152602001613f1c565b83811115611c7b5750506000910152565b60008151808452613f5d816020860160208601613f19565b601f01601f19169290920160200192915050565b602081526000611b7a6020830184613f45565b600060208284031215613f9657600080fd5b611b7a82613ddd565b600060208284031215613fb157600080fd5b5035919050565b6001600160a01b038116811461126c57600080fd5b8035613def81613fb8565b60008060408385031215613feb57600080fd5b8235613ff681613fb8565b946020939093013593505050565b6000806040838503121561401757600080fd5b613ff683613ddd565b60008060006060848603121561403557600080fd5b833561404081613fb8565b9250602084013561405081613fb8565b929592945050506040919091013590565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b038111828210171561409f5761409f614061565b604052919050565b60006001600160401b038211156140c0576140c0614061565b50601f01601f191660200190565b60006140e16140dc846140a7565b614077565b90508281528383830111156140f557600080fd5b828260208301376000602084830101529392505050565b600082601f83011261411d57600080fd5b611b7a838335602085016140ce565b80358015158114613def57600080fd5b600080600080600060a0868803121561415457600080fd5b61415d86613ddd565b945060208601356001600160401b038082111561417957600080fd5b61418589838a0161410c565b95506040880135945061419a6060890161412c565b935060808801359150808211156141b057600080fd5b506141bd8882890161410c565b9150509295509295909350565b6000806000604084860312156141df57600080fd5b6141e884613ddd565b925060208401356001600160401b0381111561420357600080fd5b61420f86828701613df4565b9497909650939450505050565b600080600080600080600060e0888a03121561423757600080fd5b873561424281613fb8565b965061425060208901613ddd565b955060408801356001600160401b038082111561426c57600080fd5b6142788b838c0161410c565b965060608a0135955060808a0135915061429182613fb8565b90935060a0890135906142a382613fb8565b90925060c089013590808211156142b957600080fd5b506142c68a828b0161410c565b91505092959891949750929550565b6000806000606084860312156142ea57600080fd5b6142f384613ddd565b925060208401356001600160401b0381111561430e57600080fd5b61431a8682870161410c565b92505061432960408501613e3c565b90509250925092565b60006020828403121561434457600080fd5b8135611b7a81613fb8565b6000806040838503121561436257600080fd5b61436b83613ddd565b915061437960208401613ddd565b90509250929050565b60006020828403121561439457600080fd5b81356001600160401b038111156143aa57600080fd5b6123ea8482850161410c565b6000602082840312156143c857600080fd5b81356001600160401b038111156143de57600080fd5b8201601f810184136143ef57600080fd5b6123ea848235602084016140ce565b6000806040838503121561441157600080fd5b823561441c81613fb8565b91506143796020840161412c565b60006001600160401b0382111561444357614443614061565b5060051b60200190565b600082601f83011261445e57600080fd5b8135602061446e6140dc8361442a565b82815260059290921b8401810191818101908684111561448d57600080fd5b8286015b848110156144a85780358352918301918301614491565b509695505050505050565b600080600080600080600060e0888a0312156144ce57600080fd5b87356144d981613fb8565b96506144e760208901613ddd565b955060408801356001600160401b038082111561450357600080fd5b61450f8b838c0161410c565b965060608a013591508082111561452557600080fd5b6145318b838c0161444d565b955060808a0135915061454382613fb8565b81945061455260a08b01613fcd565b935060c08a01359150808211156142b957600080fd5b6000806000806080858703121561457e57600080fd5b843561458981613fb8565b9350602085013561459981613fb8565b92506040850135915060608501356001600160401b038111156145bb57600080fd5b6145c78782880161410c565b91505092959194509250565b6000806000806000608086880312156145eb57600080fd5b6145f486613ddd565b945061460260208701613ddd565b93506040860135925060608601356001600160401b0381111561462457600080fd5b61463088828901613df4565b969995985093965092949392505050565b60008060006060848603121561465657600080fd5b61465f84613ddd565b925061466d60208501613ddd565b9150604084013590509250925092565b6000806040838503121561469057600080fd5b823561469b81613fb8565b915060208301356146ab81613fb8565b809150509250929050565b600080600080600060a086880312156146ce57600080fd5b6146d786613ddd565b945060208601356001600160401b03808211156146f357600080fd5b6146ff89838a0161410c565b9550604088013591508082111561471557600080fd5b61472189838a0161444d565b945061419a6060890161412c565b6000806000806080858703121561474557600080fd5b61474e85613ddd565b935061475c60208601613ddd565b9250604085013561476c81613fb8565b9396929550929360600135925050565b600082601f83011261478d57600080fd5b8135602061479d6140dc8361442a565b82815260059290921b840181019181810190868411156147bc57600080fd5b8286015b848110156144a8576147d181613ddd565b83529183019183016147c0565b600082601f8301126147ef57600080fd5b813560206147ff6140dc8361442a565b82815260059290921b8401810191818101908684111561481e57600080fd5b8286015b848110156144a85780356001600160401b038111156148415760008081fd5b61484f8986838b010161410c565b845250918301918301614822565b600080600080600080600080610100898b03121561487a57600080fd5b61488389613fcd565b975060208901356001600160401b038082111561489f57600080fd5b6148ab8c838d0161477c565b985060408b01359150808211156148c157600080fd5b6148cd8c838d0161410c565b975060608b01359150808211156148e357600080fd5b6148ef8c838d0161444d565b96506148fd60808c01613fcd565b955061490b60a08c01613fcd565b945060c08b013591508082111561492157600080fd5b61492d8c838d016147de565b935060e08b013591508082111561494357600080fd5b506149508b828c0161444d565b9150509295985092959890939650565b600181811c9082168061497457607f821691505b6020821081141561499557634e487b7160e01b600052602260045260246000fd5b50919050565b8183823760009101908152919050565b634e487b7160e01b600052601160045260246000fd5b60006000198214156149d5576149d56149ab565b5060010190565b6020808252602d908201527f4552433732313a2063616c6c6572206973206e6f7420746f6b656e206f776e6560408201526c1c881bdc88185c1c1c9bdd9959609a1b606082015260800190565b6000816000190483118215151615614a4357614a436149ab565b500290565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b61ffff841681526040602082015260006123e7604083018486614a48565b600082601f830112614aa057600080fd5b8151614aae6140dc826140a7565b818152846020838601011115614ac357600080fd5b6123ea826020830160208701613f19565b60008060408385031215614ae757600080fd5b82516001600160401b0380821115614afe57600080fd5b614b0a86838701614a8f565b9350602091508185015181811115614b2157600080fd5b85019050601f81018613614b3457600080fd5b8051614b426140dc8261442a565b81815260059190911b82018301908381019088831115614b6157600080fd5b928401925b82841015614b7f57835182529284019290840190614b66565b80955050505050509250929050565b600082821015614ba057614ba06149ab565b500390565b8284823760609190911b6bffffffffffffffffffffffff19169101908152601401919050565b60008351614bdd818460208801613f19565b835190830190614bf1818360208801613f19565b01949350505050565b600061ffff808816835280871660208401525084604083015260806060830152614c28608083018486614a48565b979650505050505050565b61ffff86168152608060208201526000614c51608083018688614a48565b6001600160401b0394909416604083015250606001529392505050565b600081518084526020808501945080840160005b83811015614c9e57815187529582019590820190600101614c82565b509495945050505050565b604081526000614cbc6040830185613f45565b8281036020840152614cce8185614c6e565b95945050505050565b61ffff861681526001600160a01b038516602082015260a060408201819052600090614d0590830186613f45565b84151560608401528281036080840152614d1f8185613f45565b98975050505050505050565b60008060408385031215614d3e57600080fd5b505080516020909101519092909150565b600060208284031215614d6157600080fd5b81516001600160401b03811115614d7757600080fd5b6123ea84828501614a8f565b60208082526039908201527f556c7472614d61726174686f6e3a206e61746976654665657320616e6420647360408201527f74436861696e496473206c656e677468206d69736d6174636800000000000000606082015260800190565b634e487b7160e01b600052603260045260246000fd5b61ffff85168152608060208201526000614e136080830186613f45565b6001600160401b03851660408401528281036060840152614c288185613f45565b60208082526025908201527f4552433732313a207472616e736665722066726f6d20696e636f72726563742060408201526437bbb732b960d91b606082015260800190565b60208082526022908201527f62617463682073697a65206578636565647320647374206261746368206c696d6040820152611a5d60f21b606082015260800190565b60008251614ecd818460208701613f19565b9190910192915050565b602081526000611b7a6020830184614c6e565b8281526040602082015260006123ea6040830184613f45565b60008219821115614f1657614f166149ab565b500190565b60208082526032908201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b606082015260800190565b61ffff8616815260a060208201526000614f8a60a0830187613f45565b6001600160401b03861660408401528281036060840152614fab8186613f45565b90508281036080840152614d1f8185613f45565b61ffff8716815260c060208201526000614fdc60c0830188613f45565b8281036040840152614fee8188613f45565b6001600160a01b0387811660608601528616608085015283810360a085015290506150198185613f45565b9998505050505050505050565b6001600160a01b038581168252841660208201526040810183905260806060820181905260009061505990830184613f45565b9695505050505050565b60006020828403121561507557600080fd5b8151611b7a81613ee656fea2646970667358221220df4283bee9755404704503999e3a7ac76220b0946be9a43f9fa9cc3daa3c99c764736f6c634300080c003300000000000000000000000000000000000000000000000000000000000186a00000000000000000000000003c2269811836af69497e5f486a85d7316753cf6200000000000000000000000000000000000000000000000000000000004c4b4100000000000000000000000000000000000000000000000000000000005b8d80

Deployed Bytecode

0x6080604052600436106103965760003560e01c80638da5cb5b116101dc578063c87b56dd11610102578063e1d4c870116100a0578063f2fde38b1161006f578063f2fde38b14610b57578063f5ecbdbc14610b77578063f7f3f2fd14610b97578063fa25f9b614610baa57600080fd5b8063e1d4c87014610ab8578063e985e9c514610ace578063eb8d72b714610b17578063f235364114610b3757600080fd5b8063d1deba1f116100dc578063d1deba1f14610a5a578063ddca3f4314610a6d578063df2a5b3b14610a83578063e086e5ec14610aa357600080fd5b8063c87b56dd146109fa578063cbed8b9c14610a1a578063d12473a514610a3a57600080fd5b8063a22cb4651161017a578063b353aaa711610149578063b353aaa714610970578063b88d4fde146109a4578063baf3292d146109c4578063c4461834146109e457600080fd5b8063a22cb465146108f5578063a6c3d16514610915578063ab3ffb9314610935578063af3fb21c1461094857600080fd5b806395d89b41116101b657806395d89b41146108805780639ea5d6b1146108955780639f38369a146108b5578063a0bcfc7f146108d557600080fd5b80638da5cb5b146108225780638ffa1f2a14610840578063950c8a741461086057600080fd5b80633f6dc453116102c15780636352211e1161025f57806370a082311161022e57806370a0823114610795578063715018a6146107b55780637533d788146107ca5780638cfd8f5c146107ea57600080fd5b80636352211e1461071f57806366ad5c8a1461073f57806369fe0e2d1461075f5780636aa99da31461077f57600080fd5b8063482881901161029b578063482881901461067a5780634ac3f4ff1461069057806351905636146106bd5780635b8c41e6146106d057600080fd5b80633f6dc4531461062757806342842e0e1461063a57806342d65a8d1461065a57600080fd5b80630df374831161033957806323b872dd1161030857806323b872dd146105775780632a205e3d146105975780633d8b38f6146105cc5780633f1f4fa4146105ec57600080fd5b80630df37483146104ac57806310ddb137146104cc5780631249c58b146104ec57806322a3ecf9146104f457600080fd5b806307e0db171161037557806307e0db1714610414578063081812fc14610434578063095ea7b31461046c5780630b4cad4c1461048c57600080fd5b80621d35671461039b57806301ffc9a7146103bd57806306fdde03146103f2575b600080fd5b3480156103a757600080fd5b506103bb6103b6366004613e53565b610bd7565b005b3480156103c957600080fd5b506103dd6103d8366004613efc565b610e08565b60405190151581526020015b60405180910390f35b3480156103fe57600080fd5b50610407610e2b565b6040516103e99190613f71565b34801561042057600080fd5b506103bb61042f366004613f84565b610ebd565b34801561044057600080fd5b5061045461044f366004613f9f565b610f46565b6040516001600160a01b0390911681526020016103e9565b34801561047857600080fd5b506103bb610487366004613fd8565b610f6d565b34801561049857600080fd5b506103bb6104a7366004613f9f565b611083565b3480156104b857600080fd5b506103bb6104c7366004614004565b611123565b3480156104d857600080fd5b506103bb6104e7366004613f84565b611142565b6103bb61119a565b34801561050057600080fd5b5061054861050f366004613f9f565b600a6020526000908152604090208054600182015460029092015461ffff821692620100009092046001600160a01b0316919060ff1684565b6040805161ffff90951685526001600160a01b03909316602085015291830152151560608201526080016103e9565b34801561058357600080fd5b506103bb610592366004614020565b61126f565b3480156105a357600080fd5b506105b76105b236600461413c565b6112a1565b604080519283526020830191909152016103e9565b3480156105d857600080fd5b506103dd6105e73660046141ca565b6112c7565b3480156105f857600080fd5b50610619610607366004613f84565b60036020526000908152604090205481565b6040519081526020016103e9565b6103bb610635366004613f9f565b611393565b34801561064657600080fd5b506103bb610655366004614020565b611426565b34801561066657600080fd5b506103bb6106753660046141ca565b611441565b34801561068657600080fd5b5061061960075481565b34801561069c57600080fd5b506106196106ab366004613f84565b60086020526000908152604090205481565b6103bb6106cb36600461421c565b6114c7565b3480156106dc57600080fd5b506106196106eb3660046142d5565b6005602090815260009384526040808520845180860184018051928152908401958401959095209452929052825290205481565b34801561072b57600080fd5b5061045461073a366004613f9f565b6114de565b34801561074b57600080fd5b506103bb61075a366004613e53565b61153e565b34801561076b57600080fd5b506103bb61077a366004613f9f565b61161a565b34801561078b57600080fd5b5061061960115481565b3480156107a157600080fd5b506106196107b0366004614332565b611627565b3480156107c157600080fd5b506103bb6116ad565b3480156107d657600080fd5b506104076107e5366004613f84565b6116c1565b3480156107f657600080fd5b5061061961080536600461434f565b600260209081526000928352604080842090915290825290205481565b34801561082e57600080fd5b506000546001600160a01b0316610454565b34801561084c57600080fd5b506103bb61085b366004614382565b61175b565b34801561086c57600080fd5b50600454610454906001600160a01b031681565b34801561088c57600080fd5b506104076119a4565b3480156108a157600080fd5b506103bb6108b0366004614004565b6119b3565b3480156108c157600080fd5b506104076108d0366004613f84565b611a6a565b3480156108e157600080fd5b506103bb6108f03660046143b6565b611b81565b34801561090157600080fd5b506103bb6109103660046143fe565b611b9c565b34801561092157600080fd5b506103bb6109303660046141ca565b611ba7565b6103bb6109433660046144b3565b611c3a565b34801561095457600080fd5b5061095d600181565b60405161ffff90911681526020016103e9565b34801561097c57600080fd5b506104547f0000000000000000000000003c2269811836af69497e5f486a85d7316753cf6281565b3480156109b057600080fd5b506103bb6109bf366004614568565b611c49565b3480156109d057600080fd5b506103bb6109df366004614332565b611c81565b3480156109f057600080fd5b5061061961271081565b348015610a0657600080fd5b50610407610a15366004613f9f565b611cd7565b348015610a2657600080fd5b506103bb610a353660046145d3565b611d3d565b348015610a4657600080fd5b506103bb610a55366004614004565b611dd2565b6103bb610a68366004613e53565b611e82565b348015610a7957600080fd5b5061061960135481565b348015610a8f57600080fd5b506103bb610a9e366004614641565b612098565b348015610aaf57600080fd5b506103dd61214a565b348015610ac457600080fd5b5061061960125481565b348015610ada57600080fd5b506103dd610ae936600461467d565b6001600160a01b03918216600090815260106020908152604080832093909416825291909152205460ff1690565b348015610b2357600080fd5b506103bb610b323660046141ca565b6121a4565b348015610b4357600080fd5b506105b7610b523660046146b6565b6121fe565b348015610b6357600080fd5b506103bb610b72366004614332565b6122c9565b348015610b8357600080fd5b50610407610b9236600461472f565b61233f565b6103bb610ba536600461485d565b6123f2565b348015610bb657600080fd5b50610619610bc5366004613f84565b60096020526000908152604090205481565b337f0000000000000000000000003c2269811836af69497e5f486a85d7316753cf626001600160a01b031614610c545760405162461bcd60e51b815260206004820152601e60248201527f4c7a4170703a20696e76616c696420656e64706f696e742063616c6c6572000060448201526064015b60405180910390fd5b61ffff861660009081526001602052604081208054610c7290614960565b80601f0160208091040260200160405190810160405280929190818152602001828054610c9e90614960565b8015610ceb5780601f10610cc057610100808354040283529160200191610ceb565b820191906000526020600020905b815481529060010190602001808311610cce57829003601f168201915b50505050509050805186869050148015610d06575060008151115b8015610d2e575080516020820120604051610d24908890889061499b565b6040518091039020145b610d895760405162461bcd60e51b815260206004820152602660248201527f4c7a4170703a20696e76616c696420736f757263652073656e64696e6720636f6044820152651b9d1c9858dd60d21b6064820152608401610c4b565b610dff8787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f8a018190048102820181019092528881528a9350915088908890819084018382808284376000920191909152506126bc92505050565b50505050505050565b60006001600160e01b031982161580610e255750610e2582612735565b92915050565b6060600b8054610e3a90614960565b80601f0160208091040260200160405190810160405280929190818152602001828054610e6690614960565b8015610eb35780601f10610e8857610100808354040283529160200191610eb3565b820191906000526020600020905b815481529060010190602001808311610e9657829003601f168201915b5050505050905090565b610ec5612775565b6040516307e0db1760e01b815261ffff821660048201527f0000000000000000000000003c2269811836af69497e5f486a85d7316753cf626001600160a01b0316906307e0db17906024015b600060405180830381600087803b158015610f2b57600080fd5b505af1158015610f3f573d6000803e3d6000fd5b5050505050565b6000610f51826127cf565b506000908152600f60205260409020546001600160a01b031690565b6000610f78826114de565b9050806001600160a01b0316836001600160a01b03161415610fe65760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e656044820152603960f91b6064820152608401610c4b565b336001600160a01b038216148061100257506110028133610ae9565b6110745760405162461bcd60e51b815260206004820152603d60248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f7420746f60448201527f6b656e206f776e6572206f7220617070726f76656420666f7220616c6c0000006064820152608401610c4b565b61107e838361281f565b505050565b61108b612775565b600081116110e75760405162461bcd60e51b8152602060048201526024808201527f6d696e476173546f5472616e73666572416e6453746f7265206d7573742062656044820152630203e20360e41b6064820152608401610c4b565b60078190556040518181527ffebbc4f8bb9ec2313950c718d43123124b15778efda4c1f1d529de2995b4f34d906020015b60405180910390a150565b61112b612775565b61ffff909116600090815260036020526040902055565b61114a612775565b6040516310ddb13760e01b815261ffff821660048201527f0000000000000000000000003c2269811836af69497e5f486a85d7316753cf626001600160a01b0316906310ddb13790602401610f11565b60125460115411156111f95760405162461bcd60e51b815260206004820152602260248201527f4c324d61726174686f6e3a206d6178206d696e74206c696d6974207265616368604482015261195960f21b6064820152608401610c4b565b60135434101561124b5760405162461bcd60e51b815260206004820152601f60248201527f4e6f7420656e6f756768204554482073656e743a20636865636b206665652e006044820152606401610c4b565b60118054908190600061125d836149c1565b919050555061126c338261288d565b50565b61127a335b826128a7565b6112965760405162461bcd60e51b8152600401610c4b906149dc565b61107e838383612925565b6000806112b987876112b288612a89565b87876121fe565b915091509550959350505050565b61ffff8316600090815260016020526040812080548291906112e890614960565b80601f016020809104026020016040519081016040528092919081815260200182805461131490614960565b80156113615780601f1061133657610100808354040283529160200191611361565b820191906000526020600020905b81548152906001019060200180831161134457829003601f168201915b50505050509050838360405161137892919061499b565b60405180910390208180519060200120149150509392505050565b6013546113a09082614a29565b3410156113e55760405162461bcd60e51b8152602060048201526013602482015272139bdd08195b9bdd59da08115512081cd95b9d606a1b6044820152606401610c4b565b60005b8181101561142257601180549081906000611402836149c1565b9190505550611411338261288d565b5061141b816149c1565b90506113e8565b5050565b61107e83838360405180602001604052806000815250611c49565b611449612775565b6040516342d65a8d60e01b81526001600160a01b037f0000000000000000000000003c2269811836af69497e5f486a85d7316753cf6216906342d65a8d9061149990869086908690600401614a71565b600060405180830381600087803b1580156114b357600080fd5b505af1158015610dff573d6000803e3d6000fd5b610dff8787876114d688612a89565b878787612ad4565b6000818152600d60205260408120546001600160a01b031680610e255760405162461bcd60e51b8152602060048201526018602482015277115490cdcc8c4e881a5b9d985b1a59081d1bdad95b88125160421b6044820152606401610c4b565b33301461159c5760405162461bcd60e51b815260206004820152602660248201527f4e6f6e626c6f636b696e674c7a4170703a2063616c6c6572206d7573742062656044820152650204c7a4170760d41b6064820152608401610c4b565b6116128686868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f890181900481028201810190925287815289935091508790879081908401838280828437600092019190915250612c6d92505050565b505050505050565b611622612775565b601355565b60006001600160a01b0382166116915760405162461bcd60e51b815260206004820152602960248201527f4552433732313a2061646472657373207a65726f206973206e6f7420612076616044820152683634b21037bbb732b960b91b6064820152608401610c4b565b506001600160a01b03166000908152600e602052604090205490565b6116b5612775565b6116bf6000612dc4565b565b600160205260009081526040902080546116da90614960565b80601f016020809104026020016040519081016040528092919081815260200182805461170690614960565b80156117535780601f1061172857610100808354040283529160200191611753565b820191906000526020600020905b81548152906001019060200180831161173657829003601f168201915b505050505081565b611763612e14565b80516020808301919091206000818152600a90925260409091206002015460ff166117c45760405162461bcd60e51b81526020600482015260116024820152701b9bc818dc99591a5d1cc81cdd1bdc9959607a1b6044820152606401610c4b565b6000828060200190518101906117da9190614ad4565b6000848152600a6020526040812080546001909101549294509092506118169161ffff8216916201000090046001600160a01b03169085612e6e565b6000848152600a6020526040902060010154909150811161188b5760405162461bcd60e51b815260206004820152602960248201527f6e6f7420656e6f7567682067617320746f2070726f6365737320637265646974604482015268103a3930b739b332b960b91b6064820152608401610c4b565b8151811415611903576000838152600a602052604080822080546001600160b01b031916815560018101929092556002909101805460ff19169055517fd7be02b8dd0d27bd0517a9cb4d7469ce27df4313821ae5ec1ff69acc594ba233906118f69085815260200190565b60405180910390a1611997565b604080516080810182526000858152600a6020818152848320805461ffff80821687526001600160a01b03620100008084048216868a019081529989018b8152600160608b01818152998f90529790965297519851169096026001600160b01b03199091169690951695909517939093178455915191830191909155516002909101805491151560ff199092169190911790555b50505061126c6001600655565b6060600c8054610e3a90614960565b6119bb612775565b60008111611a165760405162461bcd60e51b815260206004820152602260248201527f647374436861696e4964546f42617463684c696d6974206d757374206265203e604482015261020360f41b6064820152608401610c4b565b61ffff8216600081815260086020908152604091829020849055815192835282018390527f7315f7654d594ead24a30160ed9ba2d23247f543016b918343591e93d7afdb6d91015b60405180910390a15050565b61ffff8116600090815260016020526040812080546060929190611a8d90614960565b80601f0160208091040260200160405190810160405280929190818152602001828054611ab990614960565b8015611b065780601f10611adb57610100808354040283529160200191611b06565b820191906000526020600020905b815481529060010190602001808311611ae957829003601f168201915b50505050509050805160001415611b5f5760405162461bcd60e51b815260206004820152601d60248201527f4c7a4170703a206e6f20747275737465642070617468207265636f72640000006044820152606401610c4b565b611b7a600060148351611b729190614b8e565b839190612ec0565b9392505050565b611b89612775565b8051611422906014906020840190613cd0565b611422338383612fcd565b611baf612775565b818130604051602001611bc493929190614ba5565b60408051601f1981840301815291815261ffff85166000908152600160209081529190208251611bf993919290910190613cd0565b507f8c0400cfe2d1199b1a725c78960bcc2a344d869b80590d0f2bd005db15a572ce838383604051611c2d93929190614a71565b60405180910390a1505050565b610dff87878787878787612ad4565b611c5333836128a7565b611c6f5760405162461bcd60e51b8152600401610c4b906149dc565b611c7b8484848461309c565b50505050565b611c89612775565b600480546001600160a01b0319166001600160a01b0383169081179091556040519081527f5db758e995a17ec1ad84bdef7e8c3293a0bd6179bcce400dff5d4c3d87db726b90602001611118565b6060611ce2826127cf565b6000611cec6130cf565b90506000815111611d0c5760405180602001604052806000815250611b7a565b80611d16846130de565b604051602001611d27929190614bcb565b6040516020818303038152906040529392505050565b611d45612775565b6040516332fb62e760e21b81526001600160a01b037f0000000000000000000000003c2269811836af69497e5f486a85d7316753cf62169063cbed8b9c90611d999088908890889088908890600401614bfa565b600060405180830381600087803b158015611db357600080fd5b505af1158015611dc7573d6000803e3d6000fd5b505050505050505050565b611dda612775565b60008111611e365760405162461bcd60e51b815260206004820152602360248201527f647374436861696e4964546f5472616e73666572476173206d7573742062652060448201526203e20360ec1b6064820152608401610c4b565b61ffff8216600081815260096020908152604091829020849055815192835282018390527fc46df2983228ac2d9754e94a0d565e6671665dc8ad38602bc8e544f0685a29fb9101611a5e565b61ffff86166000908152600560205260408082209051611ea5908890889061499b565b90815260408051602092819003830190206001600160401b03871660009081529252902054905080611f255760405162461bcd60e51b815260206004820152602360248201527f4e6f6e626c6f636b696e674c7a4170703a206e6f2073746f726564206d65737360448201526261676560e81b6064820152608401610c4b565b808383604051611f3692919061499b565b604051809103902014611f955760405162461bcd60e51b815260206004820152602160248201527f4e6f6e626c6f636b696e674c7a4170703a20696e76616c6964207061796c6f616044820152601960fa1b6064820152608401610c4b565b61ffff87166000908152600560205260408082209051611fb8908990899061499b565b90815260408051602092819003830181206001600160401b038916600090815290845282902093909355601f88018290048202830182019052868252612050918991899089908190840183828082843760009201919091525050604080516020601f8a018190048102820181019092528881528a935091508890889081908401838280828437600092019190915250612c6d92505050565b7fc264d91f3adc5588250e1551f547752ca0cfa8f6b530d243b9f9f4cab10ea8e58787878785604051612087959493929190614c33565b60405180910390a150505050505050565b6120a0612775565b600081116120e85760405162461bcd60e51b81526020600482015260156024820152744c7a4170703a20696e76616c6964206d696e47617360581b6044820152606401610c4b565b61ffff83811660008181526002602090815260408083209487168084529482529182902085905581519283528201929092529081018290527f9d5c7c0b934da8fefa9c7760c98383778a12dfbfc0c3b3106518f43fb9508ac090606001611c2d565b6000612154612775565b604051600090339047908381818185875af1925050503d8060008114612196576040519150601f19603f3d011682016040523d82523d6000602084013e61219b565b606091505b50909250505090565b6121ac612775565b61ffff831660009081526001602052604090206121ca908383613d54565b507ffa41487ad5d6728f0b19276fa1eddc16558578f5109fc39d2dc33c3230470dab838383604051611c2d93929190614a71565b60008060008686604051602001612216929190614ca9565b60408051601f198184030181529082905263040a7bb160e41b825291506001600160a01b037f0000000000000000000000003c2269811836af69497e5f486a85d7316753cf6216906340a7bb109061227a908b90309086908b908b90600401614cd7565b6040805180830381865afa158015612296573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122ba9190614d2b565b92509250509550959350505050565b6122d1612775565b6001600160a01b0381166123365760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610c4b565b61126c81612dc4565b604051633d7b2f6f60e21b815261ffff808616600483015284166024820152306044820152606481018290526060907f0000000000000000000000003c2269811836af69497e5f486a85d7316753cf626001600160a01b03169063f5ecbdbc90608401600060405180830381865afa1580156123bf573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526123e79190810190614d4f565b90505b949350505050565b86518551146124695760405162461bcd60e51b815260206004820152603760248201527f556c7472614d61726174686f6e3a20746f6b656e49647320616e64206473744360448201527f6861696e496473206c656e677468206d69736d617463680000000000000000006064820152608401610c4b565b81518551146124e05760405162461bcd60e51b815260206004820152603960248201527f556c7472614d61726174686f6e3a20746f6b656e49647320616e64206164617060448201527f746572506172616d73206c656e677468206d69736d61746368000000000000006064820152608401610c4b565b80518551146125505760405162461bcd60e51b815260206004820152603660248201527f556c7472614d61726174686f6e3a20746f6b656e49647320616e64206e6174696044820152750ecca8ccacae640d8cadccee8d040dad2e6dac2e8c6d60531b6064820152608401610c4b565b86518151146125715760405162461bcd60e51b8152600401610c4b90614d83565b86518251146125925760405162461bcd60e51b8152600401610c4b90614d83565b80518251146126095760405162461bcd60e51b815260206004820152603b60248201527f556c7472614d61726174686f6e3a206e61746976654665657320616e6420616460448201527f6170746572506172616d73206c656e677468206d69736d6174636800000000006064820152608401610c4b565b60005b8751811015611dc757600088828151811061262957612629614de0565b60200260200101519050600084838151811061264757612647614de0565b60200260200101519050600088848151811061266557612665614de0565b60200260200101519050600085858151811061268357612683614de0565b602002602001015190506126a58d858d61269c86612a89565b8d8d898861317a565b5050505080806126b4906149c1565b91505061260c565b60008061271f5a60966366ad5c8a60e01b898989896040516024016126e49493929190614df6565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091523092919061334a565b91509150816116125761161286868686856133d4565b60006001600160e01b031982166380ac58cd60e01b148061276657506001600160e01b03198216635b5e139f60e01b145b80610e255750610e2582613471565b6000546001600160a01b031633146116bf5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610c4b565b6127d8816134a6565b61126c5760405162461bcd60e51b8152602060048201526018602482015277115490cdcc8c4e881a5b9d985b1a59081d1bdad95b88125160421b6044820152606401610c4b565b6000818152600f6020526040902080546001600160a01b0319166001600160a01b0384169081179091558190612854826114de565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b6114228282604051806020016040528060008152506134c3565b6000806128b3836114de565b9050806001600160a01b0316846001600160a01b031614806128fa57506001600160a01b0380821660009081526010602090815260408083209388168352929052205460ff165b806123ea5750836001600160a01b031661291384610f46565b6001600160a01b031614949350505050565b826001600160a01b0316612938826114de565b6001600160a01b03161461295e5760405162461bcd60e51b8152600401610c4b90614e34565b6001600160a01b0382166129c05760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f206164646044820152637265737360e01b6064820152608401610c4b565b826001600160a01b03166129d3826114de565b6001600160a01b0316146129f95760405162461bcd60e51b8152600401610c4b90614e34565b6000818152600f6020908152604080832080546001600160a01b03199081169091556001600160a01b03878116808652600e8552838620805460001901905590871680865283862080546001019055868652600d90945282852080549092168417909155905184937fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b60408051600180825281830190925260609160009190602080830190803683370190505090508281600081518110612ac357612ac3614de0565b602090810291909101015292915050565b6000845111612b1b5760405162461bcd60e51b8152602060048201526013602482015272746f6b656e4964735b5d20697320656d70747960681b6044820152606401610c4b565b835160011480612b3f575061ffff8616600090815260086020526040902054845111155b612b5b5760405162461bcd60e51b8152600401610c4b90614e79565b60005b8451811015612b9e57612b8c888888888581518110612b7f57612b7f614de0565b60200260200101516134f6565b80612b96816149c1565b915050612b5e565b5060008585604051602001612bb4929190614ca9565b6040516020818303038152906040529050612bf9876001848851600960008d61ffff1661ffff16815260200190815260200160002054612bf49190614a29565b6135e1565b612c078782868686346136c0565b85604051612c159190614ebb565b6040518091039020886001600160a01b03168861ffff167fe1b87c47fdeb4f9cbadbca9df3af7aba453bb6e501075d0440d88125b711522a88604051612c5b9190614ed7565b60405180910390a45050505050505050565b60008082806020019051810190612c849190614ad4565b601482015191935091506000612c9c88838386612e6e565b90508251811015612d705784516020808701919091206040805160808101825261ffff808d1682526001600160a01b038088168387019081528385018881526001606086018181526000898152600a909a529887902095518654935190941662010000026001600160b01b03199093169390941692909217178355519082015592516002909301805493151560ff199094169390931790925590517f10e0b70d256bccc84b7027506978bd8b68984a870788b93b479def144c839ad790612d669083908990614eea565b60405180910390a1505b816001600160a01b031687604051612d889190614ebb565b60405180910390208961ffff167f5b821db8a46f8ecbe1941ba2f51cfeea9643268b56631f70d45e2a745d99026586604051612c5b9190614ed7565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60026006541415612e675760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610c4b565b6002600655565b6000825b82518110156123e7576007545a1015612e8a576123e7565b612eae8686858481518110612ea157612ea1614de0565b6020026020010151613866565b80612eb8816149c1565b915050612e72565b606081612ece81601f614f03565b1015612f0d5760405162461bcd60e51b815260206004820152600e60248201526d736c6963655f6f766572666c6f7760901b6044820152606401610c4b565b612f178284614f03565b84511015612f5b5760405162461bcd60e51b8152602060048201526011602482015270736c6963655f6f75744f66426f756e647360781b6044820152606401610c4b565b606082158015612f7a5760405191506000825260208201604052612fc4565b6040519150601f8416801560200281840101858101878315602002848b0101015b81831015612fb3578051835260209283019201612f9b565b5050858452601f01601f1916604052505b50949350505050565b816001600160a01b0316836001600160a01b0316141561302f5760405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c6572000000000000006044820152606401610c4b565b6001600160a01b03838116600081815260106020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b6130a7848484612925565b6130b3848484846138c6565b611c7b5760405162461bcd60e51b8152600401610c4b90614f1b565b606060148054610e3a90614960565b606060006130eb836139c1565b60010190506000816001600160401b0381111561310a5761310a614061565b6040519080825280601f01601f191660200182016040528015613134576020820181803683370190505b5090508181016020015b600019016f181899199a1a9b1b9c1cb0b131b232b360811b600a86061a8153600a850494508461316d57613172565b61313e565b509392505050565b600081116131c25760405162461bcd60e51b815260206004820152601560248201527406e6174697665466565206d757374206265203e203605c1b6044820152606401610c4b565b60008551116132095760405162461bcd60e51b8152602060048201526013602482015272746f6b656e4964735b5d20697320656d70747960681b6044820152606401610c4b565b84516001148061322d575061ffff8716600090815260086020526040902054855111155b6132495760405162461bcd60e51b8152600401610c4b90614e79565b60005b855181101561327f5761326d898989898581518110612b7f57612b7f614de0565b80613277816149c1565b91505061324c565b5060008686604051602001613295929190614ca9565b60405160208183030381529060405290506132d5886001858951600960008e61ffff1661ffff16815260200190815260200160002054612bf49190614a29565b6132e38882878787876136c0565b866040516132f19190614ebb565b6040518091039020896001600160a01b03168961ffff167fe1b87c47fdeb4f9cbadbca9df3af7aba453bb6e501075d0440d88125b711522a896040516133379190614ed7565b60405180910390a4505050505050505050565b6000606060008060008661ffff166001600160401b0381111561336f5761336f614061565b6040519080825280601f01601f191660200182016040528015613399576020820181803683370190505b50905060008087516020890160008d8df191503d9250868311156133bb578692505b828152826000602083013e909890975095505050505050565b8180519060200120600560008761ffff1661ffff168152602001908152602001600020856040516134059190614ebb565b9081526040805191829003602090810183206001600160401b0388166000908152915220919091557fe183f33de2837795525b4792ca4cd60535bd77c53b7e7030060bfcf5734d6b0c906134629087908790879087908790614f6d565b60405180910390a15050505050565b60006001600160e01b031982166322bac5d960e01b1480610e2557506301ffc9a760e01b6001600160e01b0319831614610e25565b6000908152600d60205260409020546001600160a01b0316151590565b6134cd8383613a99565b6134da60008484846138c6565b61107e5760405162461bcd60e51b8152600401610c4b90614f1b565b6134ff33611274565b6135625760405162461bcd60e51b815260206004820152602e60248201527f4f4e46543732313a2073656e642063616c6c6572206973206e6f74206f776e6560448201526d1c881b9bdc88185c1c1c9bdd995960921b6064820152608401610c4b565b836001600160a01b0316613575826114de565b6001600160a01b0316146135d65760405162461bcd60e51b815260206004820152602260248201527f4f4e46543732313a2073656e642066726f6d20696e636f7272656374206f776e60448201526132b960f11b6064820152608401610c4b565b611c7b843083612925565b60006135ec83613c06565b61ffff80871660009081526002602090815260408083209389168352929052908120549192509061361e908490614f03565b9050600081116136705760405162461bcd60e51b815260206004820152601a60248201527f4c7a4170703a206d696e4761734c696d6974206e6f74207365740000000000006044820152606401610c4b565b808210156116125760405162461bcd60e51b815260206004820152601b60248201527f4c7a4170703a20676173206c696d697420697320746f6f206c6f7700000000006044820152606401610c4b565b61ffff8616600090815260016020526040812080546136de90614960565b80601f016020809104026020016040519081016040528092919081815260200182805461370a90614960565b80156137575780601f1061372c57610100808354040283529160200191613757565b820191906000526020600020905b81548152906001019060200180831161373a57829003601f168201915b505050505090508051600014156137c95760405162461bcd60e51b815260206004820152603060248201527f4c7a4170703a2064657374696e6174696f6e20636861696e206973206e6f742060448201526f61207472757374656420736f7572636560801b6064820152608401610c4b565b6137d4878751613c62565b60405162c5803160e81b81526001600160a01b037f0000000000000000000000003c2269811836af69497e5f486a85d7316753cf62169063c580310090849061382b908b9086908c908c908c908c90600401614fbf565b6000604051808303818588803b15801561384457600080fd5b505af1158015613858573d6000803e3d6000fd5b505050505050505050505050565b61386f816134a6565b158061389b575061387f816134a6565b801561389b575030613890826114de565b6001600160a01b0316145b6138a457600080fd5b6138ad816134a6565b6138bb5761107e828261288d565b61107e308383612925565b60006001600160a01b0384163b156139b957604051630a85bd0160e11b81526001600160a01b0385169063150b7a029061390a903390899088908890600401615026565b6020604051808303816000875af1925050508015613945575060408051601f3d908101601f1916820190925261394291810190615063565b60015b61399f573d808015613973576040519150601f19603f3d011682016040523d82523d6000602084013e613978565b606091505b5080516139975760405162461bcd60e51b8152600401610c4b90614f1b565b805181602001fd5b6001600160e01b031916630a85bd0160e11b1490506123ea565b5060016123ea565b60008072184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b8310613a005772184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b830492506040015b6d04ee2d6d415b85acef81000000008310613a2c576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc100008310613a4a57662386f26fc10000830492506010015b6305f5e1008310613a62576305f5e100830492506008015b6127108310613a7657612710830492506004015b60648310613a88576064830492506002015b600a8310610e255760010192915050565b6001600160a01b038216613aef5760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f20616464726573736044820152606401610c4b565b613af8816134a6565b15613b455760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e746564000000006044820152606401610c4b565b613b4e816134a6565b15613b9b5760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e746564000000006044820152606401610c4b565b6001600160a01b0382166000818152600e6020908152604080832080546001019055848352600d90915280822080546001600160a01b0319168417905551839291907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b6000602282511015613c5a5760405162461bcd60e51b815260206004820152601c60248201527f4c7a4170703a20696e76616c69642061646170746572506172616d73000000006044820152606401610c4b565b506022015190565b61ffff821660009081526003602052604090205480613c8057506127105b8082111561107e5760405162461bcd60e51b815260206004820181905260248201527f4c7a4170703a207061796c6f61642073697a6520697320746f6f206c617267656044820152606401610c4b565b828054613cdc90614960565b90600052602060002090601f016020900481019282613cfe5760008555613d44565b82601f10613d1757805160ff1916838001178555613d44565b82800160010185558215613d44579182015b82811115613d44578251825591602001919060010190613d29565b50613d50929150613dc8565b5090565b828054613d6090614960565b90600052602060002090601f016020900481019282613d825760008555613d44565b82601f10613d9b5782800160ff19823516178555613d44565b82800160010185558215613d44579182015b82811115613d44578235825591602001919060010190613dad565b5b80821115613d505760008155600101613dc9565b803561ffff81168114613def57600080fd5b919050565b60008083601f840112613e0657600080fd5b5081356001600160401b03811115613e1d57600080fd5b602083019150836020828501011115613e3557600080fd5b9250929050565b80356001600160401b0381168114613def57600080fd5b60008060008060008060808789031215613e6c57600080fd5b613e7587613ddd565b955060208701356001600160401b0380821115613e9157600080fd5b613e9d8a838b01613df4565b9097509550859150613eb160408a01613e3c565b94506060890135915080821115613ec757600080fd5b50613ed489828a01613df4565b979a9699509497509295939492505050565b6001600160e01b03198116811461126c57600080fd5b600060208284031215613f0e57600080fd5b8135611b7a81613ee6565b60005b83811015613f34578181015183820152602001613f1c565b83811115611c7b5750506000910152565b60008151808452613f5d816020860160208601613f19565b601f01601f19169290920160200192915050565b602081526000611b7a6020830184613f45565b600060208284031215613f9657600080fd5b611b7a82613ddd565b600060208284031215613fb157600080fd5b5035919050565b6001600160a01b038116811461126c57600080fd5b8035613def81613fb8565b60008060408385031215613feb57600080fd5b8235613ff681613fb8565b946020939093013593505050565b6000806040838503121561401757600080fd5b613ff683613ddd565b60008060006060848603121561403557600080fd5b833561404081613fb8565b9250602084013561405081613fb8565b929592945050506040919091013590565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b038111828210171561409f5761409f614061565b604052919050565b60006001600160401b038211156140c0576140c0614061565b50601f01601f191660200190565b60006140e16140dc846140a7565b614077565b90508281528383830111156140f557600080fd5b828260208301376000602084830101529392505050565b600082601f83011261411d57600080fd5b611b7a838335602085016140ce565b80358015158114613def57600080fd5b600080600080600060a0868803121561415457600080fd5b61415d86613ddd565b945060208601356001600160401b038082111561417957600080fd5b61418589838a0161410c565b95506040880135945061419a6060890161412c565b935060808801359150808211156141b057600080fd5b506141bd8882890161410c565b9150509295509295909350565b6000806000604084860312156141df57600080fd5b6141e884613ddd565b925060208401356001600160401b0381111561420357600080fd5b61420f86828701613df4565b9497909650939450505050565b600080600080600080600060e0888a03121561423757600080fd5b873561424281613fb8565b965061425060208901613ddd565b955060408801356001600160401b038082111561426c57600080fd5b6142788b838c0161410c565b965060608a0135955060808a0135915061429182613fb8565b90935060a0890135906142a382613fb8565b90925060c089013590808211156142b957600080fd5b506142c68a828b0161410c565b91505092959891949750929550565b6000806000606084860312156142ea57600080fd5b6142f384613ddd565b925060208401356001600160401b0381111561430e57600080fd5b61431a8682870161410c565b92505061432960408501613e3c565b90509250925092565b60006020828403121561434457600080fd5b8135611b7a81613fb8565b6000806040838503121561436257600080fd5b61436b83613ddd565b915061437960208401613ddd565b90509250929050565b60006020828403121561439457600080fd5b81356001600160401b038111156143aa57600080fd5b6123ea8482850161410c565b6000602082840312156143c857600080fd5b81356001600160401b038111156143de57600080fd5b8201601f810184136143ef57600080fd5b6123ea848235602084016140ce565b6000806040838503121561441157600080fd5b823561441c81613fb8565b91506143796020840161412c565b60006001600160401b0382111561444357614443614061565b5060051b60200190565b600082601f83011261445e57600080fd5b8135602061446e6140dc8361442a565b82815260059290921b8401810191818101908684111561448d57600080fd5b8286015b848110156144a85780358352918301918301614491565b509695505050505050565b600080600080600080600060e0888a0312156144ce57600080fd5b87356144d981613fb8565b96506144e760208901613ddd565b955060408801356001600160401b038082111561450357600080fd5b61450f8b838c0161410c565b965060608a013591508082111561452557600080fd5b6145318b838c0161444d565b955060808a0135915061454382613fb8565b81945061455260a08b01613fcd565b935060c08a01359150808211156142b957600080fd5b6000806000806080858703121561457e57600080fd5b843561458981613fb8565b9350602085013561459981613fb8565b92506040850135915060608501356001600160401b038111156145bb57600080fd5b6145c78782880161410c565b91505092959194509250565b6000806000806000608086880312156145eb57600080fd5b6145f486613ddd565b945061460260208701613ddd565b93506040860135925060608601356001600160401b0381111561462457600080fd5b61463088828901613df4565b969995985093965092949392505050565b60008060006060848603121561465657600080fd5b61465f84613ddd565b925061466d60208501613ddd565b9150604084013590509250925092565b6000806040838503121561469057600080fd5b823561469b81613fb8565b915060208301356146ab81613fb8565b809150509250929050565b600080600080600060a086880312156146ce57600080fd5b6146d786613ddd565b945060208601356001600160401b03808211156146f357600080fd5b6146ff89838a0161410c565b9550604088013591508082111561471557600080fd5b61472189838a0161444d565b945061419a6060890161412c565b6000806000806080858703121561474557600080fd5b61474e85613ddd565b935061475c60208601613ddd565b9250604085013561476c81613fb8565b9396929550929360600135925050565b600082601f83011261478d57600080fd5b8135602061479d6140dc8361442a565b82815260059290921b840181019181810190868411156147bc57600080fd5b8286015b848110156144a8576147d181613ddd565b83529183019183016147c0565b600082601f8301126147ef57600080fd5b813560206147ff6140dc8361442a565b82815260059290921b8401810191818101908684111561481e57600080fd5b8286015b848110156144a85780356001600160401b038111156148415760008081fd5b61484f8986838b010161410c565b845250918301918301614822565b600080600080600080600080610100898b03121561487a57600080fd5b61488389613fcd565b975060208901356001600160401b038082111561489f57600080fd5b6148ab8c838d0161477c565b985060408b01359150808211156148c157600080fd5b6148cd8c838d0161410c565b975060608b01359150808211156148e357600080fd5b6148ef8c838d0161444d565b96506148fd60808c01613fcd565b955061490b60a08c01613fcd565b945060c08b013591508082111561492157600080fd5b61492d8c838d016147de565b935060e08b013591508082111561494357600080fd5b506149508b828c0161444d565b9150509295985092959890939650565b600181811c9082168061497457607f821691505b6020821081141561499557634e487b7160e01b600052602260045260246000fd5b50919050565b8183823760009101908152919050565b634e487b7160e01b600052601160045260246000fd5b60006000198214156149d5576149d56149ab565b5060010190565b6020808252602d908201527f4552433732313a2063616c6c6572206973206e6f7420746f6b656e206f776e6560408201526c1c881bdc88185c1c1c9bdd9959609a1b606082015260800190565b6000816000190483118215151615614a4357614a436149ab565b500290565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b61ffff841681526040602082015260006123e7604083018486614a48565b600082601f830112614aa057600080fd5b8151614aae6140dc826140a7565b818152846020838601011115614ac357600080fd5b6123ea826020830160208701613f19565b60008060408385031215614ae757600080fd5b82516001600160401b0380821115614afe57600080fd5b614b0a86838701614a8f565b9350602091508185015181811115614b2157600080fd5b85019050601f81018613614b3457600080fd5b8051614b426140dc8261442a565b81815260059190911b82018301908381019088831115614b6157600080fd5b928401925b82841015614b7f57835182529284019290840190614b66565b80955050505050509250929050565b600082821015614ba057614ba06149ab565b500390565b8284823760609190911b6bffffffffffffffffffffffff19169101908152601401919050565b60008351614bdd818460208801613f19565b835190830190614bf1818360208801613f19565b01949350505050565b600061ffff808816835280871660208401525084604083015260806060830152614c28608083018486614a48565b979650505050505050565b61ffff86168152608060208201526000614c51608083018688614a48565b6001600160401b0394909416604083015250606001529392505050565b600081518084526020808501945080840160005b83811015614c9e57815187529582019590820190600101614c82565b509495945050505050565b604081526000614cbc6040830185613f45565b8281036020840152614cce8185614c6e565b95945050505050565b61ffff861681526001600160a01b038516602082015260a060408201819052600090614d0590830186613f45565b84151560608401528281036080840152614d1f8185613f45565b98975050505050505050565b60008060408385031215614d3e57600080fd5b505080516020909101519092909150565b600060208284031215614d6157600080fd5b81516001600160401b03811115614d7757600080fd5b6123ea84828501614a8f565b60208082526039908201527f556c7472614d61726174686f6e3a206e61746976654665657320616e6420647360408201527f74436861696e496473206c656e677468206d69736d6174636800000000000000606082015260800190565b634e487b7160e01b600052603260045260246000fd5b61ffff85168152608060208201526000614e136080830186613f45565b6001600160401b03851660408401528281036060840152614c288185613f45565b60208082526025908201527f4552433732313a207472616e736665722066726f6d20696e636f72726563742060408201526437bbb732b960d91b606082015260800190565b60208082526022908201527f62617463682073697a65206578636565647320647374206261746368206c696d6040820152611a5d60f21b606082015260800190565b60008251614ecd818460208701613f19565b9190910192915050565b602081526000611b7a6020830184614c6e565b8281526040602082015260006123ea6040830184613f45565b60008219821115614f1657614f166149ab565b500190565b60208082526032908201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b606082015260800190565b61ffff8616815260a060208201526000614f8a60a0830187613f45565b6001600160401b03861660408401528281036060840152614fab8186613f45565b90508281036080840152614d1f8185613f45565b61ffff8716815260c060208201526000614fdc60c0830188613f45565b8281036040840152614fee8188613f45565b6001600160a01b0387811660608601528616608085015283810360a085015290506150198185613f45565b9998505050505050505050565b6001600160a01b038581168252841660208201526040810183905260806060820181905260009061505990830184613f45565b9695505050505050565b60006020828403121561507557600080fd5b8151611b7a81613ee656fea2646970667358221220df4283bee9755404704503999e3a7ac76220b0946be9a43f9fa9cc3daa3c99c764736f6c634300080c0033

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

00000000000000000000000000000000000000000000000000000000000186a00000000000000000000000003c2269811836af69497e5f486a85d7316753cf6200000000000000000000000000000000000000000000000000000000004c4b4100000000000000000000000000000000000000000000000000000000005b8d80

-----Decoded View---------------
Arg [0] : _minGasToStore (uint256): 100000
Arg [1] : _layerZeroEndpoint (address): 0x3c2269811836af69497E5F486A85D7316753cf62
Arg [2] : _startMintId (uint256): 5000001
Arg [3] : _endMintId (uint256): 6000000

-----Encoded View---------------
4 Constructor Arguments found :
Arg [0] : 00000000000000000000000000000000000000000000000000000000000186a0
Arg [1] : 0000000000000000000000003c2269811836af69497e5f486a85d7316753cf62
Arg [2] : 00000000000000000000000000000000000000000000000000000000004c4b41
Arg [3] : 00000000000000000000000000000000000000000000000000000000005b8d80


Deployed Bytecode Sourcemap

114582:3967:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;40288:762;;;;;;;;;;-1:-1:-1;40288:762:0;;;;;:::i;:::-;;:::i;:::-;;112449:228;;;;;;;;;;-1:-1:-1;112449:228:0;;;;;:::i;:::-;;:::i;:::-;;;2124:14:1;;2117:22;2099:41;;2087:2;2072:18;112449:228:0;;;;;;;;97169:100;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;43586:123::-;;;;;;;;;;-1:-1:-1;43586:123:0;;;;;:::i;:::-;;:::i;98681:171::-;;;;;;;;;;-1:-1:-1;98681:171:0;;;;;:::i;:::-;;:::i;:::-;;;-1:-1:-1;;;;;3440:32:1;;;3422:51;;3410:2;3395:18;98681:171:0;3276:203:1;98199:416:0;;;;;;;;;;-1:-1:-1;98199:416:0;;;;;:::i;:::-;;:::i;65055:321::-;;;;;;;;;;-1:-1:-1;65055:321:0;;;;;:::i;:::-;;:::i;45511:142::-;;;;;;;;;;-1:-1:-1;45511:142:0;;;;;:::i;:::-;;:::i;43717:129::-;;;;;;;;;;-1:-1:-1;43717:129:0;;;;;:::i;:::-;;:::i;115004:291::-;;;:::i;59229:53::-;;;;;;;;;;-1:-1:-1;59229:53:0;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;59229: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;59229:53:0;4521:438:1;99381:301:0;;;;;;;;;;-1:-1:-1;99381:301:0;;;;;:::i;:::-;;:::i;59784:320::-;;;;;;;;;;-1:-1:-1;59784:320:0;;;;;:::i;:::-;;:::i;:::-;;;;7687:25:1;;;7743:2;7728:18;;7721:34;;;;7660:18;59784:320:0;7513:248:1;45751:250:0;;;;;;;;;;-1:-1:-1;45751:250:0;;;;;:::i;:::-;;:::i;39830:53::-;;;;;;;;;;-1:-1:-1;39830:53:0;;;;;:::i;:::-;;;;;;;;;;;;;;;;;8398:25:1;;;8386:2;8371:18;39830:53:0;8252:177:1;115303:287:0;;;;;;:::i;:::-;;:::i;99753:151::-;;;;;;;;;;-1:-1:-1;99753:151:0;;;;;:::i;:::-;;:::i;43854:178::-;;;;;;;;;;-1:-1:-1;43854:178:0;;;;;:::i;:::-;;:::i;58919:39::-;;;;;;;;;;;;;;;;59035:56;;;;;;;;;;-1:-1:-1;59035:56:0;;;;;:::i;:::-;;;;;;;;;;;;;;60508:351;;;;;;:::i;:::-;;:::i;51981:85::-;;;;;;;;;;-1:-1:-1;51981:85:0;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;96879:223;;;;;;;;;;-1:-1:-1;96879:223:0;;;;;:::i;:::-;;:::i;53203:346::-;;;;;;;;;;-1:-1:-1;53203:346:0;;;;;:::i;:::-;;:::i;118249:75::-;;;;;;;;;;-1:-1:-1;118249:75:0;;;;;:::i;:::-;;:::i;113530:22::-;;;;;;;;;;;;;;;;96610:207;;;;;;;;;;-1:-1:-1;96610:207:0;;;;;:::i;:::-;;:::i;12040:103::-;;;;;;;;;;;;;:::i;39700:51::-;;;;;;;;;;-1:-1:-1;39700:51:0;;;;;:::i;:::-;;:::i;39758:65::-;;;;;;;;;;-1:-1:-1;39758:65:0;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;11399:87;;;;;;;;;;-1:-1:-1;11445:7:0;11472:6;-1:-1:-1;;;;;11472:6:0;11399:87;;63265:1009;;;;;;;;;;-1:-1:-1;63265:1009:0;;;;;:::i;:::-;;:::i;39890:23::-;;;;;;;;;;-1:-1:-1;39890:23:0;;;;-1:-1:-1;;;;;39890:23:0;;;97338:104;;;;;;;;;;;;;:::i;65900:351::-;;;;;;;;;;-1:-1:-1;65900:351:0;;;;;:::i;:::-;;:::i;44683:330::-;;;;;;;;;;-1:-1:-1;44683:330:0;;;;;:::i;:::-;;:::i;118443:103::-;;;;;;;;;;-1:-1:-1;118443:103:0;;;;;:::i;:::-;;:::i;98924:155::-;;;;;;;;;;-1:-1:-1;98924:155:0;;;;;:::i;:::-;;:::i;44394:281::-;;;;;;;;;;-1:-1:-1;44394:281:0;;;;;:::i;:::-;;:::i;60867:348::-;;;;;;:::i;:::-;;:::i;58682:45::-;;;;;;;;;;;;58726:1;58682:45;;;;;14267:6:1;14255:19;;;14237:38;;14225:2;14210:18;58682:45:0;14093:188:1;39647:46:0;;;;;;;;;;;;;;;99975:279;;;;;;;;;;-1:-1:-1;99975:279:0;;;;;:::i;:::-;;:::i;45021:136::-;;;;;;;;;;-1:-1:-1;45021:136:0;;;;;:::i;:::-;;:::i;39583:55::-;;;;;;;;;;;;39633:5;39583:55;;97513:281;;;;;;;;;;-1:-1:-1;97513:281:0;;;;;:::i;:::-;;:::i;43374:204::-;;;;;;;;;;-1:-1:-1;43374:204:0;;;;;:::i;:::-;;:::i;65477:359::-;;;;;;;;;;-1:-1:-1;65477:359:0;;;;;:::i;:::-;;:::i;53735:767::-;;;;;;:::i;:::-;;:::i;114632:15::-;;;;;;;;;;;;;;;;45165:284;;;;;;;;;;-1:-1:-1;45165:284:0;;;;;:::i;:::-;;:::i;118063:178::-;;;;;;;;;;;;;:::i;113559:21::-;;;;;;;;;;;;;;;;99150:164;;;;;;;;;;-1:-1:-1;99150:164:0;;;;;:::i;:::-;-1:-1:-1;;;;;99271:25:0;;;99247:4;99271:25;;;:18;:25;;;;;;;;:35;;;;;;;;;;;;;;;99150:164;44179:207;;;;;;;;;;-1:-1:-1;44179:207:0;;;;;:::i;:::-;;:::i;60112:388::-;;;;;;;;;;-1:-1:-1;60112:388:0;;;;;:::i;:::-;;:::i;12298:201::-;;;;;;;;;;-1:-1:-1;12298:201:0;;;;;:::i;:::-;;:::i;43101:211::-;;;;;;;;;;-1:-1:-1;43101:211:0;;;;;:::i;:::-;;:::i;115598:1407::-;;;;;;:::i;:::-;;:::i;59098:57::-;;;;;;;;;;-1:-1:-1;59098:57:0;;;;;:::i;:::-;;;;;;;;;;;;;;40288:762;10188:10;40528;-1:-1:-1;;;;;40504:35:0;;40496:78;;;;-1:-1:-1;;;40496:78:0;;21170:2:1;40496:78:0;;;21152:21:1;21209:2;21189:18;;;21182:30;21248:32;21228:18;;;21221:60;21298:18;;40496:78:0;;;;;;;;;40616:32;;;40587:26;40616:32;;;:19;:32;;;;;40587:61;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;40822:13;:20;40800:11;;:18;;:42;:70;;;;;40869:1;40846:13;:20;:24;40800:70;:124;;;;-1:-1:-1;40900:24:0;;;;;;40874:22;;;;40884:11;;;;40874:22;:::i;:::-;;;;;;;;:50;40800:124;40792:175;;;;-1:-1:-1;;;40792:175:0;;22190:2:1;40792:175:0;;;22172:21:1;22229:2;22209:18;;;22202:30;22268:34;22248:18;;;22241:62;-1:-1:-1;;;22319:18:1;;;22312:36;22365:19;;40792:175:0;21988:402:1;40792:175:0;40980:62;40999:11;41012;;40980:62;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;40980:62:0;;;;;;;;;;;;;;;;;;;;;;41025:6;;-1:-1:-1;40980:62:0;-1:-1:-1;41033:8:0;;;;;;40980:62;;41033:8;;;;40980:62;;;;;;;;;-1:-1:-1;40980:18:0;;-1:-1:-1;;;40980:62:0:i;:::-;40419:631;40288:762;;;;;;:::o;112449:228::-;112564:4;-1:-1:-1;;;;;;112588:41:0;;;;:81;;;112633:36;112657:11;112633:23;:36::i;:::-;112581:88;112449:228;-1:-1:-1;;112449:228:0:o;97169:100::-;97223:13;97256:5;97249:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;97169:100;:::o;43586:123::-;11285:13;:11;:13::i;:::-;43666:35:::1;::::0;-1:-1:-1;;;43666:35:0;;14267:6:1;14255:19;;43666:35:0::1;::::0;::::1;14237:38:1::0;43666:10:0::1;-1:-1:-1::0;;;;;43666:25:0::1;::::0;::::1;::::0;14210:18:1;;43666:35:0::1;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;43586:123:::0;:::o;98681:171::-;98757:7;98777:23;98792:7;98777:14;:23::i;:::-;-1:-1:-1;98820:24:0;;;;:15;:24;;;;;;-1:-1:-1;;;;;98820:24:0;;98681:171::o;98199:416::-;98280:13;98296:23;98311:7;98296:14;:23::i;:::-;98280:39;;98344:5;-1:-1:-1;;;;;98338:11:0;:2;-1:-1:-1;;;;;98338:11:0;;;98330:57;;;;-1:-1:-1;;;98330:57:0;;22597:2:1;98330:57:0;;;22579:21:1;22636:2;22616:18;;;22609:30;22675:34;22655:18;;;22648:62;-1:-1:-1;;;22726:18:1;;;22719:31;22767:19;;98330:57:0;22395:397:1;98330:57:0;10188:10;-1:-1:-1;;;;;98422:21:0;;;;:62;;-1:-1:-1;98447:37:0;98464:5;10188:10;99150:164;:::i;98447:37::-;98400:173;;;;-1:-1:-1;;;98400:173:0;;22999:2:1;98400:173:0;;;22981:21:1;23038:2;23018:18;;;23011:30;23077:34;23057:18;;;23050:62;23148:31;23128:18;;;23121:59;23197:19;;98400:173:0;22797:425:1;98400:173:0;98586:21;98595:2;98599:7;98586:8;:21::i;:::-;98269:346;98199:416;;:::o;65055:321::-;11285:13;:11;:13::i;:::-;65193:1:::1;65165:25;:29;65157:78;;;::::0;-1:-1:-1;;;65157:78:0;;23429:2:1;65157:78:0::1;::::0;::::1;23411:21:1::0;23468:2;23448:18;;;23441:30;23507:34;23487:18;;;23480:62;-1:-1:-1;;;23558:18:1;;;23551:34;23602:19;;65157:78:0::1;23227:400:1::0;65157:78:0::1;65246:24;:52:::0;;;65314:54:::1;::::0;8398:25:1;;;65314:54:0::1;::::0;8386:2:1;8371:18;65314:54:0::1;;;;;;;;65055:321:::0;:::o;45511:142::-;11285:13;:11;:13::i;:::-;45602:35:::1;::::0;;::::1;;::::0;;;:22:::1;:35;::::0;;;;:43;45511:142::o;43717:129::-;11285:13;:11;:13::i;:::-;43800:38:::1;::::0;-1:-1:-1;;;43800:38:0;;14267:6:1;14255:19;;43800:38:0::1;::::0;::::1;14237::1::0;43800:10:0::1;-1:-1:-1::0;;;;;43800:28:0::1;::::0;::::1;::::0;14210:18:1;;43800:38:0::1;14093:188:1::0;115004:291:0;115070:9;;115056:10;;:23;;115048:70;;;;-1:-1:-1;;;115048:70:0;;23834:2:1;115048:70:0;;;23816:21:1;23873:2;23853:18;;;23846:30;23912:34;23892:18;;;23885:62;-1:-1:-1;;;23963:18:1;;;23956:32;24005:19;;115048:70:0;23632:398:1;115048:70:0;115150:3;;115137:9;:16;;115129:60;;;;-1:-1:-1;;;115129:60:0;;24237:2:1;115129:60:0;;;24219:21:1;24276:2;24256:18;;;24249:30;24315:33;24295:18;;;24288:61;24366:18;;115129:60:0;24035:355:1;115129:60:0;115213:10;;;;;;115200;115234:12;115213:10;115234:12;:::i;:::-;;;;;;115259:28;115269:10;115281:5;115259:9;:28::i;:::-;115037:258;115004:291::o;99381:301::-;99542:41;10188:10;99561:12;99575:7;99542:18;:41::i;:::-;99534:99;;;;-1:-1:-1;;;99534:99:0;;;;;;;:::i;:::-;99646:28;99656:4;99662:2;99666:7;99646:9;:28::i;59784:320::-;59950:14;59966:11;59997:99;60018:11;60031:10;60043:27;60061:8;60043:17;:27::i;:::-;60072:7;60081:14;59997:20;:99::i;:::-;59990:106;;;;59784:320;;;;;;;;:::o;45751:250::-;45893:32;;;45847:4;45893:32;;;:19;:32;;;;;45864:61;;45847:4;;45893:32;45864:61;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;45981:11;;45971:22;;;;;;;:::i;:::-;;;;;;;;45953:13;45943:24;;;;;;:50;45936:57;;;45751:250;;;;;:::o;115303:287::-;115392:3;;115384:11;;:5;:11;:::i;:::-;115371:9;:24;;115363:56;;;;-1:-1:-1;;;115363:56:0;;25456:2:1;115363:56:0;;;25438:21:1;25495:2;25475:18;;;25468:30;-1:-1:-1;;;25514:18:1;;;25507:49;25573:18;;115363:56:0;25254:343:1;115363:56:0;115435:6;115430:153;115451:5;115447:1;:9;115430:153;;;115491:10;;;;;;115478;115516:12;115491:10;115516:12;:::i;:::-;;;;;;115543:28;115553:10;115565:5;115543:9;:28::i;:::-;-1:-1:-1;115458:3:0;;;:::i;:::-;;;115430:153;;;;115303:287;:::o;99753:151::-;99857:39;99874:4;99880:2;99884:7;99857:39;;;;;;;;;;;;:16;:39::i;43854:178::-;11285:13;:11;:13::i;:::-;43969:55:::1;::::0;-1:-1:-1;;;43969:55:0;;-1:-1:-1;;;;;43969:10:0::1;:29;::::0;::::1;::::0;:55:::1;::::0;43999:11;;44012;;;;43969:55:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;60508:351:::0;60733:118;60739:5;60746:11;60759:10;60771:27;60789:8;60771:17;:27::i;:::-;60800:14;60816:18;60836:14;60733:5;:118::i;96879:223::-;96951:7;101612:16;;;:7;:16;;;;;;-1:-1:-1;;;;;101612:16:0;;97015:56;;;;-1:-1:-1;;;97015:56:0;;26406:2:1;97015:56:0;;;26388:21:1;26445:2;26425:18;;;26418:30;-1:-1:-1;;;26464:18:1;;;26457:54;26528:18;;97015:56:0;26204:348:1;53203:346:0;10188:10;53417:4;53393:29;53385:80;;;;-1:-1:-1;;;53385:80:0;;26759:2:1;53385:80:0;;;26741:21:1;26798:2;26778:18;;;26771:30;26837:34;26817:18;;;26810:62;-1:-1:-1;;;26888:18:1;;;26881:36;26934:19;;53385:80:0;26557:402:1;53385:80:0;53476:65;53498:11;53511;;53476:65;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;53476:65:0;;;;;;;;;;;;;;;;;;;;;;53524:6;;-1:-1:-1;53476:65:0;-1:-1:-1;53532:8:0;;;;;;53476:65;;53532:8;;;;53476:65;;;;;;;;;-1:-1:-1;53476:21:0;;-1:-1:-1;;;53476:65:0:i;:::-;53203:346;;;;;;:::o;118249:75::-;11285:13;:11;:13::i;:::-;118306:3:::1;:10:::0;118249:75::o;96610:207::-;96682:7;-1:-1:-1;;;;;96710:19:0;;96702:73;;;;-1:-1:-1;;;96702:73:0;;27166:2:1;96702:73:0;;;27148:21:1;27205:2;27185:18;;;27178:30;27244:34;27224:18;;;27217:62;-1:-1:-1;;;27295:18:1;;;27288:39;27344:19;;96702:73:0;26964:405:1;96702:73:0;-1:-1:-1;;;;;;96793:16:0;;;;;:9;:16;;;;;;;96610:207::o;12040:103::-;11285:13;:11;:13::i;:::-;12105:30:::1;12132:1;12105:18;:30::i;:::-;12040:103::o:0;39700:51::-;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;63265:1009::-;57691:21;:19;:21::i;:::-;63375:19;;::::1;::::0;;::::1;::::0;;;;63351:21:::1;63413:28:::0;;;:13:::1;:28:::0;;;;;;;:42:::1;;::::0;::::1;;63405:72;;;::::0;-1:-1:-1;;;63405:72:0;;27576:2:1;63405:72:0::1;::::0;::::1;27558:21:1::0;27615:2;27595:18;;;27588:30;-1:-1:-1;;;27634:18:1;;;27627:47;27691:18;;63405:72:0::1;27374:341:1::0;63405:72:0::1;63493:22;63530:8;63519:37;;;;;;;;;;;;:::i;:::-;63569:14;63598:28:::0;;;:13:::1;:28;::::0;;;;:39;;;63679:34;;::::1;::::0;63490:66;;-1:-1:-1;63569:14:0;;-1:-1:-1;63586:138:0::1;::::0;63598:39:::1;::::0;::::1;::::0;63639:38;;::::1;-1:-1:-1::0;;;;;63639:38:0::1;::::0;63490:66;63586:11:::1;:138::i;:::-;63755:28;::::0;;;:13:::1;:28;::::0;;;;:34:::1;;::::0;63569:155;;-1:-1:-1;63743:46:0;::::1;63735:100;;;::::0;-1:-1:-1;;;63735:100:0;;29464:2:1;63735:100:0::1;::::0;::::1;29446:21:1::0;29503:2;29483:18;;;29476:30;29542:34;29522:18;;;29515:62;-1:-1:-1;;;29593:18:1;;;29586:39;29642:19;;63735:100:0::1;29262:405:1::0;63735:100:0::1;63865:8;:15;63852:9;:28;63848:419;;;63960:28;::::0;;;:13:::1;:28;::::0;;;;;63953:35;;-1:-1:-1;;;;;;63953:35:0;;;;;::::1;::::0;;;;::::1;::::0;;::::1;::::0;;-1:-1:-1;;63953:35:0::1;::::0;;64008:28;::::1;::::0;::::1;::::0;63974:13;8398:25:1;;8386:2;8371:18;;8252:177;64008:28:0::1;;;;;;;;63848:419;;;64145:110;::::0;;::::1;::::0;::::1;::::0;;-1:-1:-1;64158:28:0;;;:13:::1;:28;::::0;;;;;;:39;;::::1;::::0;;::::1;64145:110:::0;;-1:-1:-1;;;;;64199:38:0;;;::::1;::::0;::::1;64145:110:::0;;::::1;::::0;;;;;;;;;64158:39;64145:110;;;;;;64114:28;;;;;;;;:141;;;;::::1;::::0;;::::1;-1:-1:-1::0;;;;;;64114:141:0;;;;;;::::1;::::0;;;;;;;::::1;::::0;;;;;;::::1;::::0;;;;;64199:38:::1;64114:141:::0;;::::1;::::0;;;::::1;;-1:-1:-1::0;;64114:141:0;;::::1;::::0;;;::::1;::::0;;63848:419:::1;63340:934;;;57735:20:::0;57129:1;58255:7;:22;58072:213;97338:104;97394:13;97427:7;97420:14;;;;;:::i;65900:351::-;11285:13;:11;:13::i;:::-;66052:1:::1;66026:23;:27;66018:74;;;::::0;-1:-1:-1;;;66018:74:0;;29874:2:1;66018:74:0::1;::::0;::::1;29856:21:1::0;29913:2;29893:18;;;29886:30;29952:34;29932:18;;;29925:62;-1:-1:-1;;;30003:18:1;;;29996:32;30045:19;;66018:74:0::1;29672:398:1::0;66018:74:0::1;66103:35;::::0;::::1;;::::0;;;:22:::1;:35;::::0;;;;;;;;:61;;;66180:63;;30247:38:1;;;30301:18;;30294:34;;;66180:63:0::1;::::0;30220:18:1;66180:63:0::1;;;;;;;;65900:351:::0;;:::o;44683:330::-;44807:35;;;44787:17;44807:35;;;:19;:35;;;;;44787:55;;44762:12;;44787:17;44807:35;44787:55;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;44861:4;:11;44876:1;44861:16;;44853:58;;;;-1:-1:-1;;;44853:58:0;;30541:2:1;44853:58:0;;;30523:21:1;30580:2;30560:18;;;30553:30;30619:31;30599:18;;;30592:59;30668:18;;44853:58:0;30339:353:1;44853:58:0;44929:31;44940:1;44957:2;44943:4;:11;:16;;;;:::i;:::-;44929:4;;:31;:10;:31::i;:::-;44922:38;44683:330;-1:-1:-1;;;44683:330:0:o;118443:103::-;11285:13;:11;:13::i;:::-;118517:21;;::::1;::::0;:10:::1;::::0;:21:::1;::::0;::::1;::::0;::::1;:::i;98924:155::-:0;99019:52;10188:10;99052:8;99062;99019:18;:52::i;44394:281::-;11285:13;:11;:13::i;:::-;44566:14:::1;;44590:4;44549:47;;;;;;;;;;:::i;:::-;;::::0;;-1:-1:-1;;44549:47:0;;::::1;::::0;;;;;;44511:35:::1;::::0;::::1;;::::0;;;:19:::1;44549:47;44511:35:::0;;;;;;:85;;::::1;::::0;:35;;:85;;::::1;::::0;::::1;:::i;:::-;;44612:55;44636:14;44652;;44612:55;;;;;;;;:::i;:::-;;;;;;;;44394:281:::0;;;:::o;60867:348::-;61107:100;61113:5;61120:11;61133:10;61145:9;61156:14;61172:18;61192:14;61107:5;:100::i;99975:279::-;100106:41;10188:10;100139:7;100106:18;:41::i;:::-;100098:99;;;;-1:-1:-1;;;100098:99:0;;;;;;;:::i;:::-;100208:38;100222:4;100228:2;100232:7;100241:4;100208:13;:38::i;:::-;99975:279;;;;:::o;45021:136::-;11285:13;:11;:13::i;:::-;45091:8:::1;:20:::0;;-1:-1:-1;;;;;;45091:20:0::1;-1:-1:-1::0;;;;;45091:20:0;::::1;::::0;;::::1;::::0;;;45127:22:::1;::::0;3422:51:1;;;45127:22:0::1;::::0;3410:2:1;3395:18;45127:22:0::1;3276:203:1::0;97513:281:0;97586:13;97612:23;97627:7;97612:14;:23::i;:::-;97648:21;97672:10;:8;:10::i;:::-;97648:34;;97724:1;97706:7;97700:21;:25;:86;;;;;;;;;;;;;;;;;97752:7;97761:18;:7;:16;:18::i;:::-;97735:45;;;;;;;;;:::i;:::-;;;;;;;;;;;;;97693:93;97513:281;-1:-1:-1;;;97513:281:0:o;43374:204::-;11285:13;:11;:13::i;:::-;43508:62:::1;::::0;-1:-1:-1;;;43508:62:0;;-1:-1:-1;;;;;43508:10:0::1;:20;::::0;::::1;::::0;:62:::1;::::0;43529:8;;43539;;43549:11;;43562:7;;;;43508:62:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;43374:204:::0;;;;;:::o;65477:359::-;11285:13;:11;:13::i;:::-;65632:1:::1;65605:24;:28;65597:76;;;::::0;-1:-1:-1;;;65597:76:0;;32394:2:1;65597:76:0::1;::::0;::::1;32376:21:1::0;32433:2;32413:18;;;32406:30;32472:34;32452:18;;;32445:62;-1:-1:-1;;;32523:18:1;;;32516:33;32566:19;;65597:76:0::1;32192:399:1::0;65597:76:0::1;65684:36;::::0;::::1;;::::0;;;:23:::1;:36;::::0;;;;;;;;:63;;;65763:65;;30247:38:1;;;30301:18;;30294:34;;;65763:65:0::1;::::0;30220:18:1;65763:65:0::1;30075:259:1::0;53735:767:0;53946:27;;;53924:19;53946:27;;;:14;:27;;;;;;:40;;;;53974:11;;;;53946:40;:::i;:::-;;;;;;;;;;;;;;;;-1:-1:-1;;;;;53946:48:0;;;;;;;;;;;;-1:-1:-1;53946:48:0;54005:73;;;;-1:-1:-1;;;54005:73:0;;32798:2:1;54005:73:0;;;32780:21:1;32837:2;32817:18;;;32810:30;32876:34;32856:18;;;32849:62;-1:-1:-1;;;32927:18:1;;;32920:33;32970:19;;54005:73:0;32596:399:1;54005:73:0;54120:11;54107:8;;54097:19;;;;;;;:::i;:::-;;;;;;;;:34;54089:80;;;;-1:-1:-1;;;54089:80:0;;33202:2:1;54089:80:0;;;33184:21:1;33241:2;33221:18;;;33214:30;33280:34;33260:18;;;33253:62;-1:-1:-1;;;33331:18:1;;;33324:31;33372:19;;54089:80:0;33000:397:1;54089:80:0;54217:27;;;54276:1;54217:27;;;:14;:27;;;;;;:40;;;;54245:11;;;;54217:40;:::i;:::-;;;;;;;;;;;;;;;;-1:-1:-1;;;;;54217:48:0;;;;;;;;;;;;:61;;;;54347:65;;;;;;;;;;;;;;;;;;;54369:11;;54382;;54347:65;;;;;;54382:11;54347:65;;54382:11;54347:65;;;;;;;;;-1:-1:-1;;54347:65:0;;;;;;;;;;;;;;;;;;;;;;54395:6;;-1:-1:-1;54347:65:0;-1:-1:-1;54403:8:0;;;;;;54347:65;;54403:8;;;;54347:65;;;;;;;;;-1:-1:-1;54347:21:0;;-1:-1:-1;;;54347:65:0:i;:::-;54428:66;54448:11;54461;;54474:6;54482:11;54428:66;;;;;;;;;;:::i;:::-;;;;;;;;53868:634;53735:767;;;;;;:::o;45165:284::-;11285:13;:11;:13::i;:::-;45289:1:::1;45279:7;:11;45271:45;;;::::0;-1:-1:-1;;;45271:45:0;;34102:2:1;45271:45:0::1;::::0;::::1;34084:21:1::0;34141:2;34121:18;;;34114:30;-1:-1:-1;;;34160:18:1;;;34153:51;34221:18;;45271:45:0::1;33900:345:1::0;45271:45:0::1;45327:28;::::0;;::::1;;::::0;;;:15:::1;:28;::::0;;;;;;;:41;;::::1;::::0;;;;;;;;;;:51;;;45394:47;;34473:34:1;;;34523:18;;34516:43;;;;34575:18;;;34568:34;;;45394:47:0::1;::::0;34436:2:1;34421:18;45394:47:0::1;34250:358:1::0;118063:178:0;118114:4;11285:13;:11;:13::i;:::-;118150:58:::1;::::0;118132:12:::1;::::0;118158:10:::1;::::0;118182:21:::1;::::0;118132:12;118150:58;118132:12;118150:58;118182:21;118158:10;118150:58:::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1::0;118131:77:0;;-1:-1:-1;;;118063:178:0;:::o;44179:207::-;11285:13;:11;:13::i;:::-;44280:35:::1;::::0;::::1;;::::0;;;:19:::1;:35;::::0;;;;:43:::1;::::0;44318:5;;44280:43:::1;:::i;:::-;;44339:39;44356:14;44372:5;;44339:39;;;;;;;;:::i;60112:388::-:0;60293:14;60309:11;60333:20;60367:10;60379:9;60356:33;;;;;;;;;:::i;:::-;;;;-1:-1:-1;;60356:33:0;;;;;;;;;;-1:-1:-1;;;60407:85:0;;60356:33;-1:-1:-1;;;;;;60407:10:0;:23;;;;:85;;60431:11;;60452:4;;60356:33;;60468:7;;60477:14;;60407:85;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;60400:92;;;;;60112:388;;;;;;;;:::o;12298:201::-;11285:13;:11;:13::i;:::-;-1:-1:-1;;;;;12387:22:0;::::1;12379:73;;;::::0;-1:-1:-1;;;12379:73:0;;36789:2:1;12379:73:0::1;::::0;::::1;36771:21:1::0;36828:2;36808:18;;;36801:30;36867:34;36847:18;;;36840:62;-1:-1:-1;;;36918:18:1;;;36911:36;36964:19;;12379:73:0::1;36587:402:1::0;12379:73:0::1;12463:28;12482:8;12463:18;:28::i;43101:211::-:0;43236:68;;-1:-1:-1;;;43236:68:0;;37231:6:1;37264:15;;;43236:68:0;;;37246:34:1;37316:15;;37296:18;;;37289:43;43285:4:0;37348:18:1;;;37341:60;37417:18;;;37410:34;;;43204:12:0;;43236:10;-1:-1:-1;;;;;43236:20:0;;;;37193:19:1;;43236:68:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;43236:68:0;;;;;;;;;;;;:::i;:::-;43229:75;;43101:211;;;;;;;:::o;115598:1407::-;115883:12;:19;115863:9;:16;:39;115855:107;;;;-1:-1:-1;;;115855:107:0;;37997:2:1;115855:107:0;;;37979:21:1;38036:2;38016:18;;;38009:30;38075:34;38055:18;;;38048:62;38146:25;38126:18;;;38119:53;38189:19;;115855:107:0;37795:419:1;115855:107:0;116001:14;:21;115981:9;:16;:41;115973:111;;;;-1:-1:-1;;;115973:111:0;;38421:2:1;115973:111:0;;;38403:21:1;38460:2;38440:18;;;38433:30;38499:34;38479:18;;;38472:62;38570:27;38550:18;;;38543:55;38615:19;;115973:111:0;38219:421:1;115973:111:0;116123:11;:18;116103:9;:16;:38;116095:105;;;;-1:-1:-1;;;116095:105:0;;38847:2:1;116095:105:0;;;38829:21:1;38886:2;38866:18;;;38859:30;38925:34;38905:18;;;38898:62;-1:-1:-1;;;38976:18:1;;;38969:52;39038:19;;116095:105:0;38645:418:1;116095:105:0;116241:12;:19;116219:11;:18;:41;116211:111;;;;-1:-1:-1;;;116211:111:0;;;;;;;:::i;:::-;116366:12;:19;116341:14;:21;:44;116333:114;;;;-1:-1:-1;;;116333:114:0;;;;;;;:::i;:::-;116491:11;:18;116466:14;:21;:43;116458:115;;;;-1:-1:-1;;;116458:115:0;;39696:2:1;116458:115:0;;;39678:21:1;39735:2;39715:18;;;39708:30;39774:34;39754:18;;;39747:62;39845:29;39825:18;;;39818:57;39892:19;;116458:115:0;39494:423:1;116458:115:0;116591:6;116586:412;116607:12;:19;116603:1;:23;116586:412;;;116648:18;116669:12;116682:1;116669:15;;;;;;;;:::i;:::-;;;;;;;116648:36;;116699:26;116728:14;116743:1;116728:17;;;;;;;;:::i;:::-;;;;;;;116699:46;;116760:13;116776:9;116786:1;116776:12;;;;;;;;:::i;:::-;;;;;;;116760:28;;116803:15;116821:11;116833:1;116821:14;;;;;;;;:::i;:::-;;;;;;;116803:32;;116852:134;116863:5;116870:11;116883:10;116895:27;116913:8;116895:17;:27::i;:::-;116924:14;116940:18;116960:13;116975:10;116852;:134::i;:::-;116633:365;;;;116628:3;;;;;:::i;:::-;;;;116586:412;;52350:514;52500:12;52514:19;52537:153;52571:9;52582:3;52610:34;;;52646:11;52659;52672:6;52680:8;52587:102;;;;;;;;;;;:::i;:::-;;;;-1:-1:-1;;52587:102:0;;;;;;;;;;;;;;-1:-1:-1;;;;;52587:102:0;-1:-1:-1;;;;;;52587:102:0;;;;;;;;;;52545:4;;52537:153;;:33;:153::i;:::-;52499:191;;;;52750:7;52745:112;;52774:71;52794:11;52807;52820:6;52828:8;52838:6;52774:19;:71::i;96241:305::-;96343:4;-1:-1:-1;;;;;;96380:40:0;;-1:-1:-1;;;96380:40:0;;:105;;-1:-1:-1;;;;;;;96437:48:0;;-1:-1:-1;;;96437:48:0;96380:105;:158;;;;96502:36;96526:11;96502:23;:36::i;11564:132::-;11445:7;11472:6;-1:-1:-1;;;;;11472:6:0;10188:10;11628:23;11620:68;;;;-1:-1:-1;;;11620:68:0;;40818:2:1;11620:68:0;;;40800:21:1;;;40837:18;;;40830:30;40896:34;40876:18;;;40869:62;40948:18;;11620:68:0;40616:356:1;108244:135:0;108326:16;108334:7;108326;:16::i;:::-;108318:53;;;;-1:-1:-1;;;108318:53:0;;26406:2:1;108318:53:0;;;26388:21:1;26445:2;26425:18;;;26418:30;-1:-1:-1;;;26464:18:1;;;26457:54;26528:18;;108318:53:0;26204:348:1;107557:174:0;107632:24;;;;:15;:24;;;;;:29;;-1:-1:-1;;;;;;107632:29:0;-1:-1:-1;;;;;107632:29:0;;;;;;;;:24;;107686:23;107632:24;107686:14;:23::i;:::-;-1:-1:-1;;;;;107677:46:0;;;;;;;;;;;107557:174;;:::o;102850:110::-;102926:26;102936:2;102940:7;102926:26;;;;;;;;;;;;:9;:26::i;102244:264::-;102337:4;102354:13;102370:23;102385:7;102370:14;:23::i;:::-;102354:39;;102423:5;-1:-1:-1;;;;;102412:16:0;:7;-1:-1:-1;;;;;102412:16:0;;:52;;;-1:-1:-1;;;;;;99271:25:0;;;99247:4;99271:25;;;:18;:25;;;;;;;;:35;;;;;;;;;;;;102432:32;102412:87;;;;102492:7;-1:-1:-1;;;;;102468:31:0;:20;102480:7;102468:11;:20::i;:::-;-1:-1:-1;;;;;102468:31:0;;102404:96;102244:264;-1:-1:-1;;;;102244:264:0:o;106209:1229::-;106334:4;-1:-1:-1;;;;;106307:31:0;:23;106322:7;106307:14;:23::i;:::-;-1:-1:-1;;;;;106307:31:0;;106299:81;;;;-1:-1:-1;;;106299:81:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;106399:16:0;;106391:65;;;;-1:-1:-1;;;106391:65:0;;41585:2:1;106391:65:0;;;41567:21:1;41624:2;41604:18;;;41597:30;41663:34;41643:18;;;41636:62;-1:-1:-1;;;41714:18:1;;;41707:34;41758:19;;106391:65:0;41383:400:1;106391:65:0;106641:4;-1:-1:-1;;;;;106614:31:0;:23;106629:7;106614:14;:23::i;:::-;-1:-1:-1;;;;;106614:31:0;;106606:81;;;;-1:-1:-1;;;106606:81:0;;;;;;;:::i;:::-;106759:24;;;;:15;:24;;;;;;;;106752:31;;-1:-1:-1;;;;;;106752:31:0;;;;;;-1:-1:-1;;;;;107235:15:0;;;;;;:9;:15;;;;;:20;;-1:-1:-1;;107235:20:0;;;107270:13;;;;;;;;;:18;;106752:31;107270:18;;;107310:16;;;:7;:16;;;;;;:21;;;;;;;;;;107349:27;;106775:7;;107349:27;;;98269:346;98199:416;;:::o;66478:185::-;66590:13;;;66601:1;66590:13;;;;;;;;;66542;;66568:19;;66590:13;;;;;;;;;;;;-1:-1:-1;66590:13:0;66568:35;;66625:7;66614:5;66620:1;66614:8;;;;;;;;:::i;:::-;;;;;;;;;;:18;66650:5;66478:185;-1:-1:-1;;66478:185:0:o;61223:960::-;61498:1;61479:9;:16;:20;61471:52;;;;-1:-1:-1;;;61471:52:0;;41990:2:1;61471:52:0;;;41972:21:1;42029:2;42009:18;;;42002:30;-1:-1:-1;;;42048:18:1;;;42041:49;42107:18;;61471:52:0;41788:343:1;61471:52:0;61542:9;:16;61562:1;61542:21;:80;;;-1:-1:-1;61587:35:0;;;;;;;:22;:35;;;;;;61567:16;;:55;;61542:80;61534:127;;;;-1:-1:-1;;;61534:127:0;;;;;;;:::i;:::-;61679:6;61674:127;61695:9;:16;61691:1;:20;61674:127;;;61733:56;61744:5;61751:11;61764:10;61776:9;61786:1;61776:12;;;;;;;;:::i;:::-;;;;;;;61733:10;:56::i;:::-;61713:3;;;;:::i;:::-;;;;61674:127;;;;61813:20;61847:10;61859:9;61836:33;;;;;;;;;:::i;:::-;;;;;;;;;;;;;61813:56;;61882:120;61897:11;58726:1;61930:14;61985:9;:16;61946:23;:36;61970:11;61946:36;;;;;;;;;;;;;;;;:55;;;;:::i;:::-;61882:14;:120::i;:::-;62013:92;62021:11;62034:7;62043:14;62059:18;62079:14;62095:9;62013:7;:92::i;:::-;62153:10;62121:54;;;;;;:::i;:::-;;;;;;;;62146:5;-1:-1:-1;;;;;62121:54:0;62133:11;62121:54;;;62165:9;62121:54;;;;;;:::i;:::-;;;;;;;;61429:754;61223:960;;;;;;;:::o;62191:976::-;62433:27;62462:22;62499:8;62488:37;;;;;;;;;;;;:::i;:::-;62629:2;62609:23;;62603:30;62432:93;;-1:-1:-1;62432:93:0;-1:-1:-1;62538:17:0;62673:48;62685:11;62603:30;62538:17;62432:93;62673:11;:48::i;:::-;62656:65;;62748:8;:15;62736:9;:27;62732:347;;;62892:19;;;;;;;;;;62957:53;;;;;;;;;;;;;;-1:-1:-1;;;;;62957:53:0;;;;;;;;;;;;;;;63005:4;62957:53;;;;;;62868:21;62926:28;;;:13;:28;;;;;;;:84;;;;;;;;;;;-1:-1:-1;;;;;;62926:84:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;62926:84:0;;;;;;;;;;63030:37;;;;;;62892:19;;62902:8;;63030:37;:::i;:::-;;;;;;;;62765:314;62732:347;63139:9;-1:-1:-1;;;;;63096:63:0;63126:11;63096:63;;;;;;:::i;:::-;;;;;;;;63113:11;63096:63;;;63150:8;63096:63;;;;;;:::i;12659:191::-;12733:16;12752:6;;-1:-1:-1;;;;;12769:17:0;;;-1:-1:-1;;;;;;12769:17:0;;;;;;12802:40;;12752:6;;;;;;;12802:40;;12733:16;12802:40;12722:128;12659:191;:::o;57771:293::-;57173:1;57905:7;;:19;;57897:63;;;;-1:-1:-1;;;57897:63:0;;43580:2:1;57897:63:0;;;43562:21:1;43619:2;43599:18;;;43592:30;43658:33;43638:18;;;43631:61;43709:18;;57897:63:0;43378:355:1;57897:63:0;57173:1;58038:7;:18;57771:293::o;64473:574::-;64595:7;64623:11;64645:263;64656:9;:16;64652:1;:20;64645:263;;;64782:24;;64770:9;:36;64766:47;;;64808:5;;64766:47;64830:48;64840:11;64853:10;64865:9;64875:1;64865:12;;;;;;;;:::i;:::-;;;;;;;64830:9;:48::i;:::-;64893:3;;;;:::i;:::-;;;;64645:263;;29408:2779;29549:12;29603:7;29587:12;29603:7;29597:2;29587:12;:::i;:::-;:23;;29579:50;;;;-1:-1:-1;;;29579:50:0;;44073:2:1;29579:50:0;;;44055:21:1;44112:2;44092:18;;;44085:30;-1:-1:-1;;;44131:18:1;;;44124:44;44185:18;;29579:50:0;43871:338:1;29579:50:0;29665:16;29674:7;29665:6;:16;:::i;:::-;29648:6;:13;:33;;29640:63;;;;-1:-1:-1;;;29640:63:0;;44416:2:1;29640:63:0;;;44398:21:1;44455:2;44435:18;;;44428:30;-1:-1:-1;;;44474:18:1;;;44467:47;44531:18;;29640:63:0;44214:341:1;29640:63:0;29716:22;29782:15;;29811:1933;;;;31888:4;31882:11;31869:24;;32069:1;32058:9;32051:20;32119:4;32108:9;32104:20;32098:4;32091:34;29775:2365;;29811:1933;29988:4;29982:11;29969:24;;30625:2;30616:7;30612:16;30997:9;30990:17;30984:4;30980:28;30968:9;30957;30953:25;30949:60;31046:7;31042:2;31038:16;31295:6;31281:9;31274:17;31268:4;31264:28;31252:9;31244:6;31240:22;31236:57;31232:70;31074:426;31329:3;31325:2;31322:11;31074:426;;;31471:9;;31460:21;;31371:4;31363:13;;;;31404;31074:426;;;-1:-1:-1;;31520:26:0;;;31724:2;31707:11;-1:-1:-1;;31703:25:0;31697:4;31690:39;-1:-1:-1;29775:2365:0;-1:-1:-1;32170:9:0;29408:2779;-1:-1:-1;;;;29408:2779:0:o;107874:281::-;107995:8;-1:-1:-1;;;;;107986:17:0;:5;-1:-1:-1;;;;;107986:17:0;;;107978:55;;;;-1:-1:-1;;;107978:55:0;;44762:2:1;107978:55:0;;;44744:21:1;44801:2;44781:18;;;44774:30;44840:27;44820:18;;;44813:55;44885:18;;107978:55:0;44560:349:1;107978:55:0;-1:-1:-1;;;;;108044:25:0;;;;;;;:18;:25;;;;;;;;:35;;;;;;;;;;;;;:46;;-1:-1:-1;;108044:46:0;;;;;;;;;;108106:41;;2099::1;;;108106::0;;2072:18:1;108106:41:0;;;;;;;107874:281;;;:::o;101135:270::-;101248:28;101258:4;101264:2;101268:7;101248:9;:28::i;:::-;101295:47;101318:4;101324:2;101328:7;101337:4;101295:22;:47::i;:::-;101287:110;;;;-1:-1:-1;;;101287:110:0;;;;;;;:::i;118332:103::-;118384:13;118417:10;118410:17;;;;;:::i;92612:716::-;92668:13;92719:14;92736:17;92747:5;92736:10;:17::i;:::-;92756:1;92736:21;92719:38;;92772:20;92806:6;-1:-1:-1;;;;;92795:18:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;92795:18:0;-1:-1:-1;92772:41:0;-1:-1:-1;92937:28:0;;;92953:2;92937:28;92994:288;-1:-1:-1;;93026:5:0;-1:-1:-1;;;93163:2:0;93152:14;;93147:30;93026:5;93134:44;93224:2;93215:11;;;-1:-1:-1;93249:10:0;93245:21;;93261:5;;93245:21;92994:288;;;-1:-1:-1;93303:6:0;92612:716;-1:-1:-1;;;92612:716:0:o;117013:1042::-;117304:1;117291:10;:14;117283:48;;;;-1:-1:-1;;;117283:48:0;;45667:2:1;117283:48:0;;;45649:21:1;45706:2;45686:18;;;45679:30;-1:-1:-1;;;45725:18:1;;;45718:51;45786:18;;117283:48:0;45465:345:1;117283:48:0;117369:1;117350:9;:16;:20;117342:52;;;;-1:-1:-1;;;117342:52:0;;41990:2:1;117342:52:0;;;41972:21:1;42029:2;42009:18;;;42002:30;-1:-1:-1;;;42048:18:1;;;42041:49;42107:18;;117342:52:0;41788:343:1;117342:52:0;117413:9;:16;117433:1;117413:21;:80;;;-1:-1:-1;117458:35:0;;;;;;;:22;:35;;;;;;117438:16;;:55;;117413:80;117405:127;;;;-1:-1:-1;;;117405:127:0;;;;;;;:::i;:::-;117550:6;117545:127;117566:9;:16;117562:1;:20;117545:127;;;117604:56;117615:5;117622:11;117635:10;117647:9;117657:1;117647:12;;;;;;;;:::i;117604:56::-;117584:3;;;;:::i;:::-;;;;117545:127;;;;117684:20;117718:10;117730:9;117707:33;;;;;;;;;:::i;:::-;;;;;;;;;;;;;117684:56;;117753:120;117768:11;58726:1;117801:14;117856:9;:16;117817:23;:36;117841:11;117817:36;;;;;;;;;;;;;;;;:55;;;;:::i;117753:120::-;117884:93;117892:11;117905:7;117914:14;117930:18;117950:14;117966:10;117884:7;:93::i;:::-;118025:10;117993:54;;;;;;:::i;:::-;;;;;;;;118018:5;-1:-1:-1;;;;;117993:54:0;118005:11;117993:54;;;118037:9;117993:54;;;;;;:::i;:::-;;;;;;;;117241:814;117013:1042;;;;;;;;:::o;47073:1275::-;47235:4;47241:12;47303:15;47329:13;47353:24;47390:8;47380:19;;-1:-1:-1;;;;;47380:19:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;47380:19:0;;47353:46;;47881:1;47855;47821:9;47815:16;47786:4;47775:9;47771:20;47740:1;47705:7;47679:4;47660:247;47648:259;;47972:16;47961:27;;48017:8;48008:7;48005:21;48002:78;;;48057:8;48046:19;;48002:78;48163:7;48150:11;48143:28;48281:7;48278:1;48271:4;48258:11;48254:22;48239:50;48318:8;;;;-1:-1:-1;47073:1275:0;-1:-1:-1;;;;;;47073:1275:0:o;52872:323::-;53096:8;53086:19;;;;;;53035:14;:27;53050:11;53035:27;;;;;;;;;;;;;;;53063:11;53035:40;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;53035:48:0;;;;;;;;;:70;;;;53121:66;;;;53135:11;;53148;;53076:6;;53169:8;;53179:7;;53121:66;:::i;:::-;;;;;;;;52872:323;;;;;:::o;59557:219::-;59659:4;-1:-1:-1;;;;;;59683:45:0;;-1:-1:-1;;;59683:45:0;;:85;;-1:-1:-1;;;;;;;;;;55385:40:0;;;59732:36;55276:157;101949:128;102014:4;101612:16;;;:7;:16;;;;;;-1:-1:-1;;;;;101612:16:0;102038:31;;;101949:128::o;103187:285::-;103282:18;103288:2;103292:7;103282:5;:18::i;:::-;103333:53;103364:1;103368:2;103372:7;103381:4;103333:22;:53::i;:::-;103311:153;;;;-1:-1:-1;;;103311:153:0;;;;;;;:::i;112685:361::-;112802:42;10188:10;112821:12;10108:98;112802:42;112794:101;;;;-1:-1:-1;;;112794:101:0;;46741:2:1;112794:101:0;;;46723:21:1;46780:2;46760:18;;;46753:30;46819:34;46799:18;;;46792:62;-1:-1:-1;;;46870:18:1;;;46863:44;46924:19;;112794:101:0;46539:410:1;112794:101:0;112942:5;-1:-1:-1;;;;;112914:33:0;:24;112929:8;112914:14;:24::i;:::-;-1:-1:-1;;;;;112914:33:0;;112906:80;;;;-1:-1:-1;;;112906:80:0;;47156:2:1;112906:80:0;;;47138:21:1;47195:2;47175:18;;;47168:30;47234:34;47214:18;;;47207:62;-1:-1:-1;;;47285:18:1;;;47278:32;47327:19;;112906:80:0;46954:398:1;112906:80:0;112997:41;113007:5;113022:4;113029:8;112997:9;:41::i;41900:420::-;42036:21;42060:28;42073:14;42060:12;:28::i;:::-;42118;;;;42099:16;42118:28;;;:15;:28;;;;;;;;:35;;;;;;;;;;;;42036:52;;-1:-1:-1;42099:16:0;42118:47;;42156:9;;42118:47;:::i;:::-;42099:66;;42198:1;42184:11;:15;42176:54;;;;-1:-1:-1;;;42176:54:0;;47559:2:1;42176:54:0;;;47541:21:1;47598:2;47578:18;;;47571:30;47637:28;47617:18;;;47610:56;47683:18;;42176:54:0;47357:350:1;42176:54:0;42269:11;42249:16;:31;;42241:71;;;;-1:-1:-1;;;42241:71:0;;47914:2:1;42241:71:0;;;47896:21:1;47953:2;47933:18;;;47926:30;47992:29;47972:18;;;47965:57;48039:18;;42241:71:0;47712:351:1;41339:553:0;41562:32;;;41533:26;41562:32;;;:19;:32;;;;;41533:61;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;41613:13;:20;41637:1;41613:25;;41605:86;;;;-1:-1:-1;;;41605:86:0;;48270:2:1;41605:86:0;;;48252:21:1;48309:2;48289:18;;;48282:30;48348:34;48328:18;;;48321:62;-1:-1:-1;;;48399:18:1;;;48392:46;48455:19;;41605:86:0;48068:412:1;41605:86:0;41702:47;41720:11;41733:8;:15;41702:17;:47::i;:::-;41760:124;;-1:-1:-1;;;41760:124:0;;-1:-1:-1;;;;;41760:10:0;:15;;;;41783:10;;41760:124;;41795:11;;41808:13;;41823:8;;41833:14;;41849:18;;41869:14;;41760:124;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;41522:370;41339:553;;;;;;:::o;113054:373::-;113162:17;113170:8;113162:7;:17::i;:::-;113161:18;:86;;;;113184:17;113192:8;113184:7;:17::i;:::-;:62;;;;-1:-1:-1;113241:4:0;113205:24;113220:8;113205:14;:24::i;:::-;-1:-1:-1;;;;;113205:41:0;;113184:62;113153:95;;;;;;113264:17;113272:8;113264:7;:17::i;:::-;113259:161;;113298:31;113308:10;113320:8;113298:9;:31::i;113259:161::-;113362:46;113380:4;113387:10;113399:8;113362:9;:46::i;108943:853::-;109097:4;-1:-1:-1;;;;;109118:13:0;;70091:19;:23;109114:675;;109154:71;;-1:-1:-1;;;109154:71:0;;-1:-1:-1;;;;;109154:36:0;;;;;:71;;10188:10;;109205:4;;109211:7;;109220:4;;109154:71;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;-1:-1:-1;109154:71:0;;;;;;;;-1:-1:-1;;109154:71:0;;;;;;;;;;;;:::i;:::-;;;109150:584;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;109395:13:0;;109391:328;;109438:60;;-1:-1:-1;;;109438:60:0;;;;;;;:::i;109391:328::-;109669:6;109663:13;109654:6;109650:2;109646:15;109639:38;109150:584;-1:-1:-1;;;;;;109276:51:0;-1:-1:-1;;;109276:51:0;;-1:-1:-1;109269:58:0;;109114:675;-1:-1:-1;109773:4:0;109766:11;;88356:948;88409:7;;-1:-1:-1;;;88487:17:0;;88483:106;;-1:-1:-1;;;88525:17:0;;;-1:-1:-1;88571:2:0;88561:12;88483:106;88616:8;88607:5;:17;88603:106;;88654:8;88645:17;;;-1:-1:-1;88691:2:0;88681:12;88603:106;88736:8;88727:5;:17;88723:106;;88774:8;88765:17;;;-1:-1:-1;88811:2:0;88801:12;88723:106;88856:7;88847:5;:16;88843:103;;88893:7;88884:16;;;-1:-1:-1;88929:1:0;88919:11;88843:103;88973:7;88964:5;:16;88960:103;;89010:7;89001:16;;;-1:-1:-1;89046:1:0;89036:11;88960:103;89090:7;89081:5;:16;89077:103;;89127:7;89118:16;;;-1:-1:-1;89163:1:0;89153:11;89077:103;89207:7;89198:5;:16;89194:68;;89245:1;89235:11;89290:6;88356:948;-1:-1:-1;;88356:948:0:o;103808:942::-;-1:-1:-1;;;;;103888:16:0;;103880:61;;;;-1:-1:-1;;;103880:61:0;;50280:2:1;103880:61:0;;;50262:21:1;;;50299:18;;;50292:30;50358:34;50338:18;;;50331:62;50410:18;;103880:61:0;50078:356:1;103880:61:0;103961:16;103969:7;103961;:16::i;:::-;103960:17;103952:58;;;;-1:-1:-1;;;103952:58:0;;50641:2:1;103952:58:0;;;50623:21:1;50680:2;50660:18;;;50653:30;50719;50699:18;;;50692:58;50767:18;;103952:58:0;50439:352:1;103952:58:0;104170:16;104178:7;104170;:16::i;:::-;104169:17;104161:58;;;;-1:-1:-1;;;104161:58:0;;50641:2:1;104161:58:0;;;50623:21:1;50680:2;50660:18;;;50653:30;50719;50699:18;;;50692:58;50767:18;;104161:58:0;50439:352:1;104161:58:0;-1:-1:-1;;;;;104568:13:0;;;;;;:9;:13;;;;;;;;:18;;104585:1;104568:18;;;104610:16;;;:7;:16;;;;;;:21;;-1:-1:-1;;;;;;104610:21:0;;;;;104649:33;104618:7;;104568:13;;104649:33;;104568:13;;104649:33;115430:153;115303:287;:::o;42328:271::-;42410:13;42469:2;42444:14;:21;:27;;42436:68;;;;-1:-1:-1;;;42436:68:0;;50998:2:1;42436:68:0;;;50980:21:1;51037:2;51017:18;;;51010:30;51076;51056:18;;;51049:58;51124:18;;42436:68:0;50796:352:1;42436:68:0;-1:-1:-1;42577:2:0;42557:23;42551:30;;42328:271::o;42607:389::-;42730:35;;;42706:21;42730:35;;;:22;:35;;;;;;42780:21;42776:125;;-1:-1:-1;39633:5:0;42776:125;42935:16;42919:12;:32;;42911:77;;;;-1:-1:-1;;;42911:77:0;;51355:2:1;42911:77:0;;;51337:21:1;;;51374:18;;;51367:30;51433:34;51413:18;;;51406:62;51485:18;;42911:77:0;51153: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:336::-;6092:5;6121:52;6137:35;6165:6;6137:35;:::i;:::-;6121:52;:::i;:::-;6112:61;;6196:6;6189:5;6182:21;6236:3;6227:6;6222:3;6218:16;6215:25;6212:45;;;6253:1;6250;6243:12;6212:45;6302:6;6297:3;6290:4;6283:5;6279:16;6266:43;6356:1;6349:4;6340:6;6333:5;6329:18;6325:29;6318:40;6028:336;;;;;:::o;6369:220::-;6411:5;6464:3;6457:4;6449:6;6445:17;6441:27;6431:55;;6482:1;6479;6472:12;6431:55;6504:79;6579:3;6570:6;6557:20;6550:4;6542:6;6538:17;6504:79;:::i;6594:160::-;6659:20;;6715:13;;6708:21;6698:32;;6688:60;;6744:1;6741;6734:12;6759:749;6868:6;6876;6884;6892;6900;6953:3;6941:9;6932:7;6928:23;6924:33;6921:53;;;6970:1;6967;6960:12;6921:53;6993:28;7011:9;6993:28;:::i;:::-;6983:38;;7072:2;7061:9;7057:18;7044:32;-1:-1:-1;;;;;7136:2:1;7128:6;7125:14;7122:34;;;7152:1;7149;7142:12;7122:34;7175:49;7216:7;7207:6;7196:9;7192:22;7175:49;:::i;:::-;7165:59;;7271:2;7260:9;7256:18;7243:32;7233:42;;7294:35;7325:2;7314:9;7310:18;7294:35;:::i;:::-;7284:45;;7382:3;7371:9;7367:19;7354:33;7338:49;;7412:2;7402:8;7399:16;7396:36;;;7428:1;7425;7418:12;7396:36;;7451:51;7494:7;7483:8;7472:9;7468:24;7451:51;:::i;:::-;7441:61;;;6759:749;;;;;;;;:::o;7766:481::-;7844:6;7852;7860;7913:2;7901:9;7892:7;7888:23;7884:32;7881:52;;;7929:1;7926;7919:12;7881:52;7952:28;7970:9;7952:28;:::i;:::-;7942:38;;8031:2;8020:9;8016:18;8003:32;-1:-1:-1;;;;;8050:6:1;8047:30;8044:50;;;8090:1;8087;8080:12;8044:50;8129:58;8179:7;8170:6;8159:9;8155:22;8129:58;:::i;:::-;7766:481;;8206:8;;-1:-1:-1;8103:84:1;;-1:-1:-1;;;;7766:481:1:o;8434:1108::-;8572:6;8580;8588;8596;8604;8612;8620;8673:3;8661:9;8652:7;8648:23;8644:33;8641:53;;;8690:1;8687;8680:12;8641:53;8729:9;8716:23;8748:31;8773:5;8748:31;:::i;:::-;8798:5;-1:-1:-1;8822:37:1;8855:2;8840:18;;8822:37;:::i;:::-;8812:47;;8910:2;8899:9;8895:18;8882:32;-1:-1:-1;;;;;8974:2:1;8966:6;8963:14;8960:34;;;8990:1;8987;8980:12;8960:34;9013:49;9054:7;9045:6;9034:9;9030:22;9013:49;:::i;:::-;9003:59;;9109:2;9098:9;9094:18;9081:32;9071:42;;9165:3;9154:9;9150:19;9137:33;9122:48;;9179:33;9204:7;9179:33;:::i;:::-;9231:7;;-1:-1:-1;9290:3:1;9275:19;;9262:33;;9304;9262;9304;:::i;:::-;9356:7;;-1:-1:-1;9416:3:1;9401:19;;9388:33;;9433:16;;;9430:36;;;9462:1;9459;9452:12;9430:36;;9485:51;9528:7;9517:8;9506:9;9502:24;9485:51;:::i;:::-;9475:61;;;8434:1108;;;;;;;;;;:::o;9547:464::-;9631:6;9639;9647;9700:2;9688:9;9679:7;9675:23;9671:32;9668:52;;;9716:1;9713;9706:12;9668:52;9739:28;9757:9;9739:28;:::i;:::-;9729:38;;9818:2;9807:9;9803:18;9790:32;-1:-1:-1;;;;;9837:6:1;9834:30;9831:50;;;9877:1;9874;9867:12;9831:50;9900:49;9941:7;9932:6;9921:9;9917:22;9900:49;:::i;:::-;9890:59;;;9968:37;10001:2;9990:9;9986:18;9968:37;:::i;:::-;9958:47;;9547:464;;;;;:::o;10198:247::-;10257:6;10310:2;10298:9;10289:7;10285:23;10281:32;10278:52;;;10326:1;10323;10316:12;10278:52;10365:9;10352:23;10384:31;10409:5;10384:31;:::i;10673:256::-;10739:6;10747;10800:2;10788:9;10779:7;10775:23;10771:32;10768:52;;;10816:1;10813;10806:12;10768:52;10839:28;10857:9;10839:28;:::i;:::-;10829:38;;10886:37;10919:2;10908:9;10904:18;10886:37;:::i;:::-;10876:47;;10673:256;;;;;:::o;10934:320::-;11002:6;11055:2;11043:9;11034:7;11030:23;11026:32;11023:52;;;11071:1;11068;11061:12;11023:52;11111:9;11098:23;-1:-1:-1;;;;;11136:6:1;11133:30;11130:50;;;11176:1;11173;11166:12;11130:50;11199:49;11240:7;11231:6;11220:9;11216:22;11199:49;:::i;11259:450::-;11328:6;11381:2;11369:9;11360:7;11356:23;11352:32;11349:52;;;11397:1;11394;11387:12;11349:52;11437:9;11424:23;-1:-1:-1;;;;;11462:6:1;11459:30;11456:50;;;11502:1;11499;11492:12;11456:50;11525:22;;11578:4;11570:13;;11566:27;-1:-1:-1;11556:55:1;;11607:1;11604;11597:12;11556:55;11630:73;11695:7;11690:2;11677:16;11672:2;11668;11664:11;11630:73;:::i;11714:315::-;11779:6;11787;11840:2;11828:9;11819:7;11815:23;11811:32;11808:52;;;11856:1;11853;11846:12;11808:52;11895:9;11882:23;11914:31;11939:5;11914:31;:::i;:::-;11964:5;-1:-1:-1;11988:35:1;12019:2;12004:18;;11988:35;:::i;12034:183::-;12094:4;-1:-1:-1;;;;;12119:6:1;12116:30;12113:56;;;12149:18;;:::i;:::-;-1:-1:-1;12194:1:1;12190:14;12206:4;12186:25;;12034:183::o;12222:662::-;12276:5;12329:3;12322:4;12314:6;12310:17;12306:27;12296:55;;12347:1;12344;12337:12;12296:55;12383:6;12370:20;12409:4;12433:60;12449:43;12489:2;12449:43;:::i;12433:60::-;12527:15;;;12613:1;12609:10;;;;12597:23;;12593:32;;;12558:12;;;;12637:15;;;12634:35;;;12665:1;12662;12655:12;12634:35;12701:2;12693:6;12689:15;12713:142;12729:6;12724:3;12721:15;12713:142;;;12795:17;;12783:30;;12833:12;;;;12746;;12713:142;;;-1:-1:-1;12873:5:1;12222:662;-1:-1:-1;;;;;;12222:662:1:o;12889:1199::-;13052:6;13060;13068;13076;13084;13092;13100;13153:3;13141:9;13132:7;13128:23;13124:33;13121:53;;;13170:1;13167;13160:12;13121:53;13209:9;13196:23;13228:31;13253:5;13228:31;:::i;:::-;13278:5;-1:-1:-1;13302:37:1;13335:2;13320:18;;13302:37;:::i;:::-;13292:47;;13390:2;13379:9;13375:18;13362:32;-1:-1:-1;;;;;13454:2:1;13446:6;13443:14;13440:34;;;13470:1;13467;13460:12;13440:34;13493:49;13534:7;13525:6;13514:9;13510:22;13493:49;:::i;:::-;13483:59;;13595:2;13584:9;13580:18;13567:32;13551:48;;13624:2;13614:8;13611:16;13608:36;;;13640:1;13637;13630:12;13608:36;13663:63;13718:7;13707:8;13696:9;13692:24;13663:63;:::i;:::-;13653:73;;13778:3;13767:9;13763:19;13750:33;13735:48;;13792:33;13817:7;13792:33;:::i;:::-;13844:7;13834:17;;13870:39;13904:3;13893:9;13889:19;13870:39;:::i;:::-;13860:49;;13962:3;13951:9;13947:19;13934:33;13918:49;;13992:2;13982:8;13979:16;13976:36;;;14008:1;14005;13998:12;14520:665;14615:6;14623;14631;14639;14692:3;14680:9;14671:7;14667:23;14663:33;14660:53;;;14709:1;14706;14699:12;14660:53;14748:9;14735:23;14767:31;14792:5;14767:31;:::i;:::-;14817:5;-1:-1:-1;14874:2:1;14859:18;;14846:32;14887:33;14846:32;14887:33;:::i;:::-;14939:7;-1:-1:-1;14993:2:1;14978:18;;14965:32;;-1:-1:-1;15048:2:1;15033:18;;15020:32;-1:-1:-1;;;;;15064:30:1;;15061:50;;;15107:1;15104;15097:12;15061:50;15130:49;15171:7;15162:6;15151:9;15147:22;15130:49;:::i;:::-;15120:59;;;14520:665;;;;;;;:::o;15190:622::-;15285:6;15293;15301;15309;15317;15370:3;15358:9;15349:7;15345:23;15341:33;15338:53;;;15387:1;15384;15377:12;15338:53;15410:28;15428:9;15410:28;:::i;:::-;15400:38;;15457:37;15490:2;15479:9;15475:18;15457:37;:::i;:::-;15447:47;;15541:2;15530:9;15526:18;15513:32;15503:42;;15596:2;15585:9;15581:18;15568:32;-1:-1:-1;;;;;15615:6:1;15612:30;15609:50;;;15655:1;15652;15645:12;15609:50;15694:58;15744:7;15735:6;15724:9;15720:22;15694:58;:::i;:::-;15190:622;;;;-1:-1:-1;15190:622:1;;-1:-1:-1;15771:8:1;;15668:84;15190:622;-1:-1:-1;;;15190:622:1:o;15817:324::-;15892:6;15900;15908;15961:2;15949:9;15940:7;15936:23;15932:32;15929:52;;;15977:1;15974;15967:12;15929:52;16000:28;16018:9;16000:28;:::i;:::-;15990:38;;16047:37;16080:2;16069:9;16065:18;16047:37;:::i;:::-;16037:47;;16131:2;16120:9;16116:18;16103:32;16093:42;;15817:324;;;;;:::o;16146:388::-;16214:6;16222;16275:2;16263:9;16254:7;16250:23;16246:32;16243:52;;;16291:1;16288;16281:12;16243:52;16330:9;16317:23;16349:31;16374:5;16349:31;:::i;:::-;16399:5;-1:-1:-1;16456:2:1;16441:18;;16428:32;16469:33;16428:32;16469:33;:::i;:::-;16521:7;16511:17;;;16146:388;;;;;:::o;16539:907::-;16673:6;16681;16689;16697;16705;16758:3;16746:9;16737:7;16733:23;16729:33;16726:53;;;16775:1;16772;16765:12;16726:53;16798:28;16816:9;16798:28;:::i;:::-;16788:38;;16877:2;16866:9;16862:18;16849:32;-1:-1:-1;;;;;16941:2:1;16933:6;16930:14;16927:34;;;16957:1;16954;16947:12;16927:34;16980:49;17021:7;17012:6;17001:9;16997:22;16980:49;:::i;:::-;16970:59;;17082:2;17071:9;17067:18;17054:32;17038:48;;17111:2;17101:8;17098:16;17095:36;;;17127:1;17124;17117:12;17095:36;17150:63;17205:7;17194:8;17183:9;17179:24;17150:63;:::i;:::-;17140:73;;17232:35;17263:2;17252:9;17248:18;17232:35;:::i;17451:460::-;17535:6;17543;17551;17559;17612:3;17600:9;17591:7;17587:23;17583:33;17580:53;;;17629:1;17626;17619:12;17580:53;17652:28;17670:9;17652:28;:::i;:::-;17642:38;;17699:37;17732:2;17721:9;17717:18;17699:37;:::i;:::-;17689:47;;17786:2;17775:9;17771:18;17758:32;17799:31;17824:5;17799:31;:::i;:::-;17451:460;;;;-1:-1:-1;17849:5:1;;17901:2;17886:18;17873:32;;-1:-1:-1;;17451:460:1:o;17916:666::-;17969:5;18022:3;18015:4;18007:6;18003:17;17999:27;17989:55;;18040:1;18037;18030:12;17989:55;18076:6;18063:20;18102:4;18126:60;18142:43;18182:2;18142:43;:::i;18126:60::-;18220:15;;;18306:1;18302:10;;;;18290:23;;18286:32;;;18251:12;;;;18330:15;;;18327:35;;;18358:1;18355;18348:12;18327:35;18394:2;18386:6;18382:15;18406:147;18422:6;18417:3;18414:15;18406:147;;;18488:22;18506:3;18488:22;:::i;:::-;18476:35;;18531:12;;;;18439;;18406:147;;18587:886;18639:5;18692:3;18685:4;18677:6;18673:17;18669:27;18659:55;;18710:1;18707;18700:12;18659:55;18746:6;18733:20;18772:4;18796:60;18812:43;18852:2;18812:43;:::i;18796:60::-;18890:15;;;18976:1;18972:10;;;;18960:23;;18956:32;;;18921:12;;;;19000:15;;;18997:35;;;19028:1;19025;19018:12;18997:35;19064:2;19056:6;19052:15;19076:368;19092:6;19087:3;19084:15;19076:368;;;19178:3;19165:17;-1:-1:-1;;;;;19201:11:1;19198:35;19195:125;;;19274:1;19303:2;19299;19292:14;19195:125;19345:56;19397:3;19392:2;19378:11;19370:6;19366:24;19362:33;19345:56;:::i;:::-;19333:69;;-1:-1:-1;19422:12:1;;;;19109;;19076:368;;19478:1485;19725:6;19733;19741;19749;19757;19765;19773;19781;19834:3;19822:9;19813:7;19809:23;19805:33;19802:53;;;19851:1;19848;19841:12;19802:53;19874:29;19893:9;19874:29;:::i;:::-;19864:39;;19954:2;19943:9;19939:18;19926:32;-1:-1:-1;;;;;20018:2:1;20010:6;20007:14;20004:34;;;20034:1;20031;20024:12;20004:34;20057:60;20109:7;20100:6;20089:9;20085:22;20057:60;:::i;:::-;20047:70;;20170:2;20159:9;20155:18;20142:32;20126:48;;20199:2;20189:8;20186:16;20183:36;;;20215:1;20212;20205:12;20183:36;20238:51;20281:7;20270:8;20259:9;20255:24;20238:51;:::i;:::-;20228:61;;20342:2;20331:9;20327:18;20314:32;20298:48;;20371:2;20361:8;20358:16;20355:36;;;20387:1;20384;20377:12;20355:36;20410:63;20465:7;20454:8;20443:9;20439:24;20410:63;:::i;:::-;20400:73;;20492:39;20526:3;20515:9;20511:19;20492:39;:::i;:::-;20482:49;;20550:39;20584:3;20573:9;20569:19;20550:39;:::i;:::-;20540:49;;20642:3;20631:9;20627:19;20614:33;20598:49;;20672:2;20662:8;20659:16;20656:36;;;20688:1;20685;20678:12;20656:36;20711:61;20764:7;20753:8;20742:9;20738:24;20711:61;:::i;:::-;20701:71;;20825:3;20814:9;20810:19;20797:33;20781:49;;20855:2;20845:8;20842:16;20839:36;;;20871:1;20868;20861:12;20839:36;;20894:63;20949:7;20938:8;20927:9;20923:24;20894:63;:::i;:::-;20884:73;;;19478:1485;;;;;;;;;;;:::o;21327:380::-;21406:1;21402:12;;;;21449;;;21470:61;;21524:4;21516:6;21512:17;21502:27;;21470:61;21577:2;21569:6;21566:14;21546:18;21543:38;21540:161;;;21623:10;21618:3;21614:20;21611:1;21604:31;21658:4;21655:1;21648:15;21686:4;21683:1;21676:15;21540:161;;21327:380;;;:::o;21712:271::-;21895:6;21887;21882:3;21869:33;21851:3;21921:16;;21946:13;;;21921:16;21712:271;-1:-1:-1;21712:271:1:o;24395:127::-;24456:10;24451:3;24447:20;24444:1;24437:31;24487:4;24484:1;24477:15;24511:4;24508:1;24501:15;24527:135;24566:3;-1:-1:-1;;24587:17:1;;24584:43;;;24607:18;;:::i;:::-;-1:-1:-1;24654:1:1;24643:13;;24527:135::o;24667:409::-;24869:2;24851:21;;;24908:2;24888:18;;;24881:30;24947:34;24942:2;24927:18;;24920:62;-1:-1:-1;;;25013:2:1;24998:18;;24991:43;25066:3;25051:19;;24667:409::o;25081:168::-;25121:7;25187:1;25183;25179:6;25175:14;25172:1;25169:21;25164:1;25157:9;25150:17;25146:45;25143:71;;;25194:18;;:::i;:::-;-1:-1:-1;25234:9:1;;25081:168::o;25602:266::-;25690:6;25685:3;25678:19;25742:6;25735:5;25728:4;25723:3;25719:14;25706:43;-1:-1:-1;25794:1:1;25769:16;;;25787:4;25765:27;;;25758:38;;;;25850:2;25829:15;;;-1:-1:-1;;25825:29:1;25816:39;;;25812:50;;25602:266::o;25873:326::-;26068:6;26060;26056:19;26045:9;26038:38;26112:2;26107;26096:9;26092:18;26085:30;26019:4;26132:61;26189:2;26178:9;26174:18;26166:6;26158;26132:61;:::i;27720:428::-;27773:5;27826:3;27819:4;27811:6;27807:17;27803:27;27793:55;;27844:1;27841;27834:12;27793:55;27873:6;27867:13;27904:48;27920:31;27948:2;27920:31;:::i;27904:48::-;27977:2;27968:7;27961:19;28023:3;28016:4;28011:2;28003:6;27999:15;27995:26;27992:35;27989:55;;;28040:1;28037;28030:12;27989:55;28053:64;28114:2;28107:4;28098:7;28094:18;28087:4;28079:6;28075:17;28053:64;:::i;28153:1104::-;28266:6;28274;28327:2;28315:9;28306:7;28302:23;28298:32;28295:52;;;28343:1;28340;28333:12;28295:52;28376:9;28370:16;-1:-1:-1;;;;;28446:2:1;28438:6;28435:14;28432:34;;;28462:1;28459;28452:12;28432:34;28485:60;28537:7;28528:6;28517:9;28513:22;28485:60;:::i;:::-;28475:70;;28564:2;28554:12;;28612:2;28601:9;28597:18;28591:25;28641:2;28631:8;28628:16;28625:36;;;28657:1;28654;28647:12;28625:36;28680:24;;;-1:-1:-1;28735:4:1;28727:13;;28723:27;-1:-1:-1;28713:55:1;;28764:1;28761;28754:12;28713:55;28793:2;28787:9;28816:60;28832:43;28872:2;28832:43;:::i;28816:60::-;28910:15;;;28992:1;28988:10;;;;28980:19;;28976:28;;;28941:12;;;;29016:19;;;29013:39;;;29048:1;29045;29038:12;29013:39;29072:11;;;;29092:135;29108:6;29103:3;29100:15;29092:135;;;29174:10;;29162:23;;29125:12;;;;29205;;;;29092:135;;;29246:5;29236:15;;;;;;;28153:1104;;;;;:::o;30697:125::-;30737:4;30765:1;30762;30759:8;30756:34;;;30770:18;;:::i;:::-;-1:-1:-1;30807:9:1;;30697:125::o;30827:382::-;31038:6;31030;31025:3;31012:33;31130:2;31126:15;;;;-1:-1:-1;;31122:53:1;31064:16;;31111:65;;;31200:2;31192:11;;30827:382;-1:-1:-1;30827:382:1:o;31214:470::-;31393:3;31431:6;31425:13;31447:53;31493:6;31488:3;31481:4;31473:6;31469:17;31447:53;:::i;:::-;31563:13;;31522:16;;;;31585:57;31563:13;31522:16;31619:4;31607:17;;31585:57;:::i;:::-;31658:20;;31214:470;-1:-1:-1;;;;31214:470:1:o;31689:498::-;31889:4;31918:6;31963:2;31955:6;31951:15;31940:9;31933:34;32015:2;32007:6;32003:15;31998:2;31987:9;31983:18;31976:43;;32055:6;32050:2;32039:9;32035:18;32028:34;32098:3;32093:2;32082:9;32078:18;32071:31;32119:62;32176:3;32165:9;32161:19;32153:6;32145;32119:62;:::i;:::-;32111:70;31689:498;-1:-1:-1;;;;;;;31689:498:1:o;33402:493::-;33651:6;33643;33639:19;33628:9;33621:38;33695:3;33690:2;33679:9;33675:18;33668:31;33602:4;33716:62;33773:3;33762:9;33758:19;33750:6;33742;33716:62;:::i;:::-;-1:-1:-1;;;;;33814:31:1;;;;33809:2;33794:18;;33787:59;-1:-1:-1;33877:2:1;33862:18;33855:34;33708:70;33402:493;-1:-1:-1;;;33402:493:1:o;34823:435::-;34876:3;34914:5;34908:12;34941:6;34936:3;34929:19;34967:4;34996:2;34991:3;34987:12;34980:19;;35033:2;35026:5;35022:14;35054:1;35064:169;35078:6;35075:1;35072:13;35064:169;;;35139:13;;35127:26;;35173:12;;;;35208:15;;;;35100:1;35093:9;35064:169;;;-1:-1:-1;35249:3:1;;34823:435;-1:-1:-1;;;;;34823:435:1:o;35263:422::-;35488:2;35477:9;35470:21;35451:4;35514:45;35555:2;35544:9;35540:18;35532:6;35514:45;:::i;:::-;35607:9;35599:6;35595:22;35590:2;35579:9;35575:18;35568:50;35635:44;35672:6;35664;35635:44;:::i;:::-;35627:52;35263:422;-1:-1:-1;;;;;35263:422:1:o;35690:642::-;35971:6;35959:19;;35941:38;;-1:-1:-1;;;;;36015:32:1;;36010:2;35995:18;;35988:60;36035:3;36079:2;36064:18;;36057:31;;;-1:-1:-1;;36111:46:1;;36137:19;;36129:6;36111:46;:::i;:::-;36207:6;36200:14;36193:22;36188:2;36177:9;36173:18;36166:50;36265:9;36257:6;36253:22;36247:3;36236:9;36232:19;36225:51;36293:33;36319:6;36311;36293:33;:::i;:::-;36285:41;35690:642;-1:-1:-1;;;;;;;;35690:642:1:o;36337:245::-;36416:6;36424;36477:2;36465:9;36456:7;36452:23;36448:32;36445:52;;;36493:1;36490;36483:12;36445:52;-1:-1:-1;;36516:16:1;;36572:2;36557:18;;;36551:25;36516:16;;36551:25;;-1:-1:-1;36337:245:1:o;37455:335::-;37534:6;37587:2;37575:9;37566:7;37562:23;37558:32;37555:52;;;37603:1;37600;37593:12;37555:52;37636:9;37630:16;-1:-1:-1;;;;;37661:6:1;37658:30;37655:50;;;37701:1;37698;37691:12;37655:50;37724:60;37776:7;37767:6;37756:9;37752:22;37724:60;:::i;39068:421::-;39270:2;39252:21;;;39309:2;39289:18;;;39282:30;39348:34;39343:2;39328:18;;39321:62;39419:27;39414:2;39399:18;;39392:55;39479:3;39464:19;;39068:421::o;39922:127::-;39983:10;39978:3;39974:20;39971:1;39964:31;40014:4;40011:1;40004:15;40038:4;40035:1;40028:15;40054:557;40311:6;40303;40299:19;40288:9;40281:38;40355:3;40350:2;40339:9;40335:18;40328:31;40262:4;40382:46;40423:3;40412:9;40408:19;40400:6;40382:46;:::i;:::-;-1:-1:-1;;;;;40468:6:1;40464:31;40459:2;40448:9;40444:18;40437:59;40544:9;40536:6;40532:22;40527:2;40516:9;40512:18;40505:50;40572:33;40598:6;40590;40572:33;:::i;40977:401::-;41179:2;41161:21;;;41218:2;41198:18;;;41191:30;41257:34;41252:2;41237:18;;41230:62;-1:-1:-1;;;41323:2:1;41308:18;;41301:35;41368:3;41353:19;;40977:401::o;42136:398::-;42338:2;42320:21;;;42377:2;42357:18;;;42350:30;42416:34;42411:2;42396:18;;42389:62;-1:-1:-1;;;42482:2:1;42467:18;;42460:32;42524:3;42509:19;;42136:398::o;42539:274::-;42668:3;42706:6;42700:13;42722:53;42768:6;42763:3;42756:4;42748:6;42744:17;42722:53;:::i;:::-;42791:16;;;;;42539:274;-1:-1:-1;;42539:274:1:o;42818:261::-;42997:2;42986:9;42979:21;42960:4;43017:56;43069:2;43058:9;43054:18;43046:6;43017:56;:::i;43084:289::-;43259:6;43248:9;43241:25;43302:2;43297;43286:9;43282:18;43275:30;43222:4;43322:45;43363:2;43352:9;43348:18;43340:6;43322:45;:::i;43738:128::-;43778:3;43809:1;43805:6;43802:1;43799:13;43796:39;;;43815:18;;:::i;:::-;-1:-1:-1;43851:9:1;;43738:128::o;44914:414::-;45116:2;45098:21;;;45155:2;45135:18;;;45128:30;45194:34;45189:2;45174:18;;45167:62;-1:-1:-1;;;45260:2:1;45245:18;;45238:48;45318:3;45303:19;;44914:414::o;45815:719::-;46118:6;46110;46106:19;46095:9;46088:38;46162:3;46157:2;46146:9;46142:18;46135:31;46069:4;46189:46;46230:3;46219:9;46215:19;46207:6;46189:46;:::i;:::-;-1:-1:-1;;;;;46275:6:1;46271:31;46266:2;46255:9;46251:18;46244:59;46351:9;46343:6;46339:22;46334:2;46323:9;46319:18;46312:50;46385:33;46411:6;46403;46385:33;:::i;:::-;46371:47;;46467:9;46459:6;46455:22;46449:3;46438:9;46434:19;46427:51;46495:33;46521:6;46513;46495:33;:::i;48485:840::-;48834:6;48826;48822:19;48811:9;48804:38;48878:3;48873:2;48862:9;48858:18;48851:31;48785:4;48905:46;48946:3;48935:9;48931:19;48923:6;48905:46;:::i;:::-;48999:9;48991:6;48987:22;48982:2;48971:9;48967:18;48960:50;49033:33;49059:6;49051;49033:33;:::i;:::-;-1:-1:-1;;;;;49140:15:1;;;49135:2;49120:18;;49113:43;49193:15;;49187:3;49172:19;;49165:44;49246:22;;;49093:3;49225:19;;49218:51;49019:47;-1:-1:-1;49286:33:1;49019:47;49304:6;49286:33;:::i;:::-;49278:41;48485:840;-1:-1:-1;;;;;;;;;48485:840:1:o;49330:489::-;-1:-1:-1;;;;;49599:15:1;;;49581:34;;49651:15;;49646:2;49631:18;;49624:43;49698:2;49683:18;;49676:34;;;49746:3;49741:2;49726:18;;49719:31;;;49524:4;;49767:46;;49793:19;;49785:6;49767:46;:::i;:::-;49759:54;49330:489;-1:-1:-1;;;;;;49330:489:1:o;49824:249::-;49893:6;49946:2;49934:9;49925:7;49921:23;49917:32;49914:52;;;49962:1;49959;49952:12;49914:52;49994:9;49988:16;50013:30;50037:5;50013:30;:::i

Swarm Source

ipfs://df4283bee9755404704503999e3a7ac76220b0946be9a43f9fa9cc3daa3c99c7
[ 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.