ETH Price: $3,423.92 (-1.28%)
 

Overview

Max Total Supply

920,857,433.000583 ISK

Holders

13,430

Transfers

-
63 ( 16.67%)

Market

Price

$0.0026 @ 0.000001 ETH (-4.94%)

Onchain Market Cap

-

Circulating Supply Market Cap

$1,405,788.00

Other Info

Token Contract (WITH 18 Decimals)

Loading...
Loading
Loading...
Loading
Loading...
Loading

OVERVIEW

Iskra offers a premier destination for players, developers and investors to explore the thrill and opportunity of Web3 gaming alongside a vibrant community.

Market

Volume (24H):$50,151.00
Market Capitalization:$1,405,788.00
Circulating Supply:537,417,774.00 ISK
Market Data Source: Coinmarketcap

Contract Source Code Verified (Exact Match)

Contract Name:
OFTPermit

Compiler Version
v0.8.22+commit.4fc1097e

Optimization Enabled:
Yes with 200 runs

Other Settings:
istanbul EvmVersion, MIT license

Contract Source Code (Solidity)

/**
 *Submitted for verification at basescan.org on 2024-04-26
*/

// SPDX-License-Identifier: MIXED

// Sources flattened with hardhat v2.19.1 https://hardhat.org

// License-Identifier: LZBL-1.2 AND MIT

// File @layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/[email protected]

// Original license: SPDX_License_Identifier: MIT

pragma solidity >=0.8.0;

struct SetConfigParam {
    uint32 eid;
    uint32 configType;
    bytes config;
}

interface IMessageLibManager {
    struct Timeout {
        address lib;
        uint256 expiry;
    }

    event LibraryRegistered(address newLib);
    event DefaultSendLibrarySet(uint32 eid, address newLib);
    event DefaultReceiveLibrarySet(uint32 eid, address newLib);
    event DefaultReceiveLibraryTimeoutSet(uint32 eid, address oldLib, uint256 expiry);
    event SendLibrarySet(address sender, uint32 eid, address newLib);
    event ReceiveLibrarySet(address receiver, uint32 eid, address newLib);
    event ReceiveLibraryTimeoutSet(address receiver, uint32 eid, address oldLib, uint256 timeout);

    function registerLibrary(address _lib) external;

    function isRegisteredLibrary(address _lib) external view returns (bool);

    function getRegisteredLibraries() external view returns (address[] memory);

    function setDefaultSendLibrary(uint32 _eid, address _newLib) external;

    function defaultSendLibrary(uint32 _eid) external view returns (address);

    function setDefaultReceiveLibrary(uint32 _eid, address _newLib, uint256 _timeout) external;

    function defaultReceiveLibrary(uint32 _eid) external view returns (address);

    function setDefaultReceiveLibraryTimeout(uint32 _eid, address _lib, uint256 _expiry) external;

    function defaultReceiveLibraryTimeout(uint32 _eid) external view returns (address lib, uint256 expiry);

    function isSupportedEid(uint32 _eid) external view returns (bool);

    function isValidReceiveLibrary(address _receiver, uint32 _eid, address _lib) external view returns (bool);

    /// ------------------- OApp interfaces -------------------
    function setSendLibrary(address _oapp, uint32 _eid, address _newLib) external;

    function getSendLibrary(address _sender, uint32 _eid) external view returns (address lib);

    function isDefaultSendLibrary(address _sender, uint32 _eid) external view returns (bool);

    function setReceiveLibrary(address _oapp, uint32 _eid, address _newLib, uint256 _gracePeriod) external;

    function getReceiveLibrary(address _receiver, uint32 _eid) external view returns (address lib, bool isDefault);

    function setReceiveLibraryTimeout(address _oapp, uint32 _eid, address _lib, uint256 _gracePeriod) external;

    function receiveLibraryTimeout(address _receiver, uint32 _eid) external view returns (address lib, uint256 expiry);

    function setConfig(address _oapp, address _lib, SetConfigParam[] calldata _params) external;

    function getConfig(
        address _oapp,
        address _lib,
        uint32 _eid,
        uint32 _configType
    ) external view returns (bytes memory config);
}


// File @layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/[email protected]

// Original license: SPDX_License_Identifier: MIT

pragma solidity >=0.8.0;

interface IMessagingChannel {
    event InboundNonceSkipped(uint32 srcEid, bytes32 sender, address receiver, uint64 nonce);
    event PacketNilified(uint32 srcEid, bytes32 sender, address receiver, uint64 nonce, bytes32 payloadHash);
    event PacketBurnt(uint32 srcEid, bytes32 sender, address receiver, uint64 nonce, bytes32 payloadHash);

    function eid() external view returns (uint32);

    // this is an emergency function if a message cannot be verified for some reasons
    // required to provide _nextNonce to avoid race condition
    function skip(address _oapp, uint32 _srcEid, bytes32 _sender, uint64 _nonce) external;

    function nilify(address _oapp, uint32 _srcEid, bytes32 _sender, uint64 _nonce, bytes32 _payloadHash) external;

    function burn(address _oapp, uint32 _srcEid, bytes32 _sender, uint64 _nonce, bytes32 _payloadHash) external;

    function nextGuid(address _sender, uint32 _dstEid, bytes32 _receiver) external view returns (bytes32);

    function inboundNonce(address _receiver, uint32 _srcEid, bytes32 _sender) external view returns (uint64);

    function outboundNonce(address _sender, uint32 _dstEid, bytes32 _receiver) external view returns (uint64);

    function inboundPayloadHash(
        address _receiver,
        uint32 _srcEid,
        bytes32 _sender,
        uint64 _nonce
    ) external view returns (bytes32);

    function lazyInboundNonce(address _receiver, uint32 _srcEid, bytes32 _sender) external view returns (uint64);
}


// File @layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/[email protected]

// Original license: SPDX_License_Identifier: MIT

pragma solidity >=0.8.0;

interface IMessagingComposer {
    event ComposeSent(address from, address to, bytes32 guid, uint16 index, bytes message);
    event ComposeDelivered(address from, address to, bytes32 guid, uint16 index);
    event LzComposeAlert(
        address indexed from,
        address indexed to,
        address indexed executor,
        bytes32 guid,
        uint16 index,
        uint256 gas,
        uint256 value,
        bytes message,
        bytes extraData,
        bytes reason
    );

    function composeQueue(
        address _from,
        address _to,
        bytes32 _guid,
        uint16 _index
    ) external view returns (bytes32 messageHash);

    function sendCompose(address _to, bytes32 _guid, uint16 _index, bytes calldata _message) external;

    function lzCompose(
        address _from,
        address _to,
        bytes32 _guid,
        uint16 _index,
        bytes calldata _message,
        bytes calldata _extraData
    ) external payable;
}


// File @layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/[email protected]

// Original license: SPDX_License_Identifier: MIT

pragma solidity >=0.8.0;

interface IMessagingContext {
    function isSendingMessage() external view returns (bool);

    function getSendContext() external view returns (uint32 dstEid, address sender);
}


// File @layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/[email protected]

// Original license: SPDX_License_Identifier: MIT

pragma solidity >=0.8.0;




struct MessagingParams {
    uint32 dstEid;
    bytes32 receiver;
    bytes message;
    bytes options;
    bool payInLzToken;
}

struct MessagingReceipt {
    bytes32 guid;
    uint64 nonce;
    MessagingFee fee;
}

struct MessagingFee {
    uint256 nativeFee;
    uint256 lzTokenFee;
}

struct Origin {
    uint32 srcEid;
    bytes32 sender;
    uint64 nonce;
}

interface ILayerZeroEndpointV2 is IMessageLibManager, IMessagingComposer, IMessagingChannel, IMessagingContext {
    event PacketSent(bytes encodedPayload, bytes options, address sendLibrary);

    event PacketVerified(Origin origin, address receiver, bytes32 payloadHash);

    event PacketDelivered(Origin origin, address receiver);

    event LzReceiveAlert(
        address indexed receiver,
        address indexed executor,
        Origin origin,
        bytes32 guid,
        uint256 gas,
        uint256 value,
        bytes message,
        bytes extraData,
        bytes reason
    );

    event LzTokenSet(address token);

    event DelegateSet(address sender, address delegate);

    function quote(MessagingParams calldata _params, address _sender) external view returns (MessagingFee memory);

    function send(
        MessagingParams calldata _params,
        address _refundAddress
    ) external payable returns (MessagingReceipt memory);

    function verify(Origin calldata _origin, address _receiver, bytes32 _payloadHash) external;

    function verifiable(Origin calldata _origin, address _receiver) external view returns (bool);

    function initializable(Origin calldata _origin, address _receiver) external view returns (bool);

    function lzReceive(
        Origin calldata _origin,
        address _receiver,
        bytes32 _guid,
        bytes calldata _message,
        bytes calldata _extraData
    ) external payable;

    // oapp can burn messages partially by calling this function with its own business logic if messages are verified in order
    function clear(address _oapp, Origin calldata _origin, bytes32 _guid, bytes calldata _message) external;

    function setLzToken(address _lzToken) external;

    function lzToken() external view returns (address);

    function nativeToken() external view returns (address);

    function setDelegate(address _delegate) external;
}


// File @layerzerolabs/lz-evm-oapp-v2/contracts/oapp/interfaces/[email protected]

// Original license: SPDX_License_Identifier: MIT

pragma solidity ^0.8.20;

/**
 * @title IOAppCore
 */
interface IOAppCore {
    // Custom error messages
    error OnlyPeer(uint32 eid, bytes32 sender);
    error NoPeer(uint32 eid);
    error InvalidEndpointCall();
    error InvalidDelegate();

    // Event emitted when a peer (OApp) is set for a corresponding endpoint
    event PeerSet(uint32 eid, bytes32 peer);

    /**
     * @notice Retrieves the OApp version information.
     * @return senderVersion The version of the OAppSender.sol contract.
     * @return receiverVersion The version of the OAppReceiver.sol contract.
     */
    function oAppVersion() external view returns (uint64 senderVersion, uint64 receiverVersion);

    /**
     * @notice Retrieves the LayerZero endpoint associated with the OApp.
     * @return iEndpoint The LayerZero endpoint as an interface.
     */
    function endpoint() external view returns (ILayerZeroEndpointV2 iEndpoint);

    /**
     * @notice Retrieves the peer (OApp) associated with a corresponding endpoint.
     * @param _eid The endpoint ID.
     * @return peer The peer address (OApp instance) associated with the corresponding endpoint.
     */
    function peers(uint32 _eid) external view returns (bytes32 peer);

    /**
     * @notice Sets the peer address (OApp instance) for a corresponding endpoint.
     * @param _eid The endpoint ID.
     * @param _peer The address of the peer to be associated with the corresponding endpoint.
     */
    function setPeer(uint32 _eid, bytes32 _peer) external;

    /**
     * @notice Sets the delegate address for the OApp Core.
     * @param _delegate The address of the delegate to be set.
     */
    function setDelegate(address _delegate) external;
}


// File @layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/[email protected]

// Original license: SPDX_License_Identifier: MIT

pragma solidity >=0.8.0;

interface ILayerZeroReceiver {
    function allowInitializePath(Origin calldata _origin) external view returns (bool);

    function nextNonce(uint32 _eid, bytes32 _sender) external view returns (uint64);

    function lzReceive(
        Origin calldata _origin,
        bytes32 _guid,
        bytes calldata _message,
        address _executor,
        bytes calldata _extraData
    ) external payable;
}


// File @layerzerolabs/lz-evm-oapp-v2/contracts/oapp/interfaces/[email protected]

// Original license: SPDX_License_Identifier: MIT
pragma solidity ^0.8.20;

interface IOAppReceiver is ILayerZeroReceiver {
    /**
     * @notice Indicates whether an address is an approved composeMsg sender to the Endpoint.
     * @param _origin The origin information containing the source endpoint and sender address.
     *  - srcEid: The source chain endpoint ID.
     *  - sender: The sender address on the src chain.
     *  - nonce: The nonce of the message.
     * @param _message The lzReceive payload.
     * @param _sender The sender address.
     * @return isSender Is a valid sender.
     *
     * @dev Applications can optionally choose to implement a separate composeMsg sender that is NOT the bridging layer.
     * @dev The default sender IS the OAppReceiver implementer.
     */
    function isComposeMsgSender(
        Origin calldata _origin,
        bytes calldata _message,
        address _sender
    ) external view returns (bool isSender);
}


// File @layerzerolabs/lz-evm-oapp-v2/contracts/oapp/interfaces/[email protected]

// Original license: SPDX_License_Identifier: MIT

pragma solidity ^0.8.20;

/**
 * @dev Struct representing enforced option parameters.
 */
struct EnforcedOptionParam {
    uint32 eid; // Endpoint ID
    uint16 msgType; // Message Type
    bytes options; // Additional options
}

/**
 * @title IOAppOptionsType3
 * @dev Interface for the OApp with Type 3 Options, allowing the setting and combining of enforced options.
 */
interface IOAppOptionsType3 {
    // Custom error message for invalid options
    error InvalidOptions(bytes options);

    // Event emitted when enforced options are set
    event EnforcedOptionSet(EnforcedOptionParam[] _enforcedOptions);

    /**
     * @notice Sets enforced options for specific endpoint and message type combinations.
     * @param _enforcedOptions An array of EnforcedOptionParam structures specifying enforced options.
     */
    function setEnforcedOptions(EnforcedOptionParam[] calldata _enforcedOptions) external;

    /**
     * @notice Combines options for a given endpoint and message type.
     * @param _eid The endpoint ID.
     * @param _msgType The OApp message type.
     * @param _extraOptions Additional options passed by the caller.
     * @return options The combination of caller specified options AND enforced options.
     */
    function combineOptions(
        uint32 _eid,
        uint16 _msgType,
        bytes calldata _extraOptions
    ) external view returns (bytes memory options);
}


// File @openzeppelin/contracts/utils/[email protected]

// Original license: SPDX_License_Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)

pragma solidity ^0.8.0;

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

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


// File @openzeppelin/contracts/access/[email protected]

// Original license: SPDX_License_Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)

pragma solidity ^0.8.0;

/**
 * @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 anymore. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby removing any functionality that is only available to the owner.
     */
    function renounceOwnership() public virtual onlyOwner {
        _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);
    }
}


// File @layerzerolabs/lz-evm-oapp-v2/contracts/oapp/libs/[email protected]

// Original license: SPDX_License_Identifier: MIT

pragma solidity ^0.8.20;


/**
 * @title OAppOptionsType3
 * @dev Abstract contract implementing the IOAppOptionsType3 interface with type 3 options.
 */
abstract contract OAppOptionsType3 is IOAppOptionsType3, Ownable {
    uint16 internal constant OPTION_TYPE_3 = 3;

    // @dev The "msgType" should be defined in the child contract.
    mapping(uint32 eid => mapping(uint16 msgType => bytes enforcedOption)) public enforcedOptions;

    /**
     * @dev Sets the enforced options for specific endpoint and message type combinations.
     * @param _enforcedOptions An array of EnforcedOptionParam structures specifying enforced options.
     *
     * @dev Only the owner/admin of the OApp can call this function.
     * @dev Provides a way for the OApp to enforce things like paying for PreCrime, AND/OR minimum dst lzReceive gas amounts etc.
     * @dev These enforced options can vary as the potential options/execution on the remote may differ as per the msgType.
     * eg. Amount of lzReceive() gas necessary to deliver a lzCompose() message adds overhead you dont want to pay
     * if you are only making a standard LayerZero message ie. lzReceive() WITHOUT sendCompose().
     */
    function setEnforcedOptions(EnforcedOptionParam[] calldata _enforcedOptions) public virtual onlyOwner {
        _setEnforcedOptions(_enforcedOptions);
    }

    /**
     * @dev Sets the enforced options for specific endpoint and message type combinations.
     * @param _enforcedOptions An array of EnforcedOptionParam structures specifying enforced options.
     *
     * @dev Provides a way for the OApp to enforce things like paying for PreCrime, AND/OR minimum dst lzReceive gas amounts etc.
     * @dev These enforced options can vary as the potential options/execution on the remote may differ as per the msgType.
     * eg. Amount of lzReceive() gas necessary to deliver a lzCompose() message adds overhead you dont want to pay
     * if you are only making a standard LayerZero message ie. lzReceive() WITHOUT sendCompose().
     */
    function _setEnforcedOptions(EnforcedOptionParam[] memory _enforcedOptions) internal virtual {
        for (uint256 i = 0; i < _enforcedOptions.length; i++) {
            // @dev Enforced options are only available for optionType 3, as type 1 and 2 dont support combining.
            _assertOptionsType3(_enforcedOptions[i].options);
            enforcedOptions[_enforcedOptions[i].eid][_enforcedOptions[i].msgType] = _enforcedOptions[i].options;
        }

        emit EnforcedOptionSet(_enforcedOptions);
    }

    /**
     * @notice Combines options for a given endpoint and message type.
     * @param _eid The endpoint ID.
     * @param _msgType The OAPP message type.
     * @param _extraOptions Additional options passed by the caller.
     * @return options The combination of caller specified options AND enforced options.
     *
     * @dev If there is an enforced lzReceive option:
     * - {gasLimit: 200k, msg.value: 1 ether} AND a caller supplies a lzReceive option: {gasLimit: 100k, msg.value: 0.5 ether}
     * - The resulting options will be {gasLimit: 300k, msg.value: 1.5 ether} when the message is executed on the remote lzReceive() function.
     * @dev This presence of duplicated options is handled off-chain in the verifier/executor.
     */
    function combineOptions(
        uint32 _eid,
        uint16 _msgType,
        bytes calldata _extraOptions
    ) public view virtual returns (bytes memory) {
        bytes memory enforced = enforcedOptions[_eid][_msgType];

        // No enforced options, pass whatever the caller supplied, even if it's empty or legacy type 1/2 options.
        if (enforced.length == 0) return _extraOptions;

        // No caller options, return enforced
        if (_extraOptions.length == 0) return enforced;

        // @dev If caller provided _extraOptions, must be type 3 as its the ONLY type that can be combined.
        if (_extraOptions.length >= 2) {
            _assertOptionsType3(_extraOptions);
            // @dev Remove the first 2 bytes containing the type from the _extraOptions and combine with enforced.
            return bytes.concat(enforced, _extraOptions[2:]);
        }

        // No valid set of options was found.
        revert InvalidOptions(_extraOptions);
    }

    /**
     * @dev Internal function to assert that options are of type 3.
     * @param _options The options to be checked.
     */
    function _assertOptionsType3(bytes memory _options) internal pure virtual {
        uint16 optionsType;
        assembly {
            optionsType := mload(add(_options, 2))
        }
        if (optionsType != OPTION_TYPE_3) revert InvalidOptions(_options);
    }
}


// File @layerzerolabs/lz-evm-oapp-v2/contracts/oapp/[email protected]

// Original license: SPDX_License_Identifier: MIT

pragma solidity ^0.8.20;


/**
 * @title OAppCore
 * @dev Abstract contract implementing the IOAppCore interface with basic OApp configurations.
 */
abstract contract OAppCore is IOAppCore, Ownable {
    // The LayerZero endpoint associated with the given OApp
    ILayerZeroEndpointV2 public immutable endpoint;

    // Mapping to store peers associated with corresponding endpoints
    mapping(uint32 eid => bytes32 peer) public peers;

    /**
     * @dev Constructor to initialize the OAppCore with the provided endpoint and delegate.
     * @param _endpoint The address of the LOCAL Layer Zero endpoint.
     * @param _delegate The delegate capable of making OApp configurations inside of the endpoint.
     *
     * @dev The delegate typically should be set as the owner of the contract.
     */
    constructor(address _endpoint, address _delegate) {
        endpoint = ILayerZeroEndpointV2(_endpoint);

        if (_delegate == address(0)) revert InvalidDelegate();
        endpoint.setDelegate(_delegate);
    }

    /**
     * @notice Sets the peer address (OApp instance) for a corresponding endpoint.
     * @param _eid The endpoint ID.
     * @param _peer The address of the peer to be associated with the corresponding endpoint.
     *
     * @dev Only the owner/admin of the OApp can call this function.
     * @dev Indicates that the peer is trusted to send LayerZero messages to this OApp.
     * @dev Set this to bytes32(0) to remove the peer address.
     * @dev Peer is a bytes32 to accommodate non-evm chains.
     */
    function setPeer(uint32 _eid, bytes32 _peer) public virtual onlyOwner {
        _setPeer(_eid, _peer);
    }

    /**
     * @notice Sets the peer address (OApp instance) for a corresponding endpoint.
     * @param _eid The endpoint ID.
     * @param _peer The address of the peer to be associated with the corresponding endpoint.
     *
     * @dev Indicates that the peer is trusted to send LayerZero messages to this OApp.
     * @dev Set this to bytes32(0) to remove the peer address.
     * @dev Peer is a bytes32 to accommodate non-evm chains.
     */
    function _setPeer(uint32 _eid, bytes32 _peer) internal virtual {
        peers[_eid] = _peer;
        emit PeerSet(_eid, _peer);
    }

    /**
     * @notice Internal function to get the peer address associated with a specific endpoint; reverts if NOT set.
     * ie. the peer is set to bytes32(0).
     * @param _eid The endpoint ID.
     * @return peer The address of the peer associated with the specified endpoint.
     */
    function _getPeerOrRevert(uint32 _eid) internal view virtual returns (bytes32) {
        bytes32 peer = peers[_eid];
        if (peer == bytes32(0)) revert NoPeer(_eid);
        return peer;
    }

    /**
     * @notice Sets the delegate address for the OApp.
     * @param _delegate The address of the delegate to be set.
     *
     * @dev Only the owner/admin of the OApp can call this function.
     * @dev Provides the ability for a delegate to set configs, on behalf of the OApp, directly on the Endpoint contract.
     */
    function setDelegate(address _delegate) public onlyOwner {
        endpoint.setDelegate(_delegate);
    }
}


// File @layerzerolabs/lz-evm-oapp-v2/contracts/oapp/[email protected]

// Original license: SPDX_License_Identifier: MIT

pragma solidity ^0.8.20;


/**
 * @title OAppReceiver
 * @dev Abstract contract implementing the ILayerZeroReceiver interface and extending OAppCore for OApp receivers.
 */
abstract contract OAppReceiver is IOAppReceiver, OAppCore {
    // Custom error message for when the caller is not the registered endpoint/
    error OnlyEndpoint(address addr);

    // @dev The version of the OAppReceiver implementation.
    // @dev Version is bumped when changes are made to this contract.
    uint64 internal constant RECEIVER_VERSION = 2;

    /**
     * @notice Retrieves the OApp version information.
     * @return senderVersion The version of the OAppSender.sol contract.
     * @return receiverVersion The version of the OAppReceiver.sol contract.
     *
     * @dev Providing 0 as the default for OAppSender version. Indicates that the OAppSender is not implemented.
     * ie. this is a RECEIVE only OApp.
     * @dev If the OApp uses both OAppSender and OAppReceiver, then this needs to be override returning the correct versions.
     */
    function oAppVersion() public view virtual returns (uint64 senderVersion, uint64 receiverVersion) {
        return (0, RECEIVER_VERSION);
    }

    /**
     * @notice Indicates whether an address is an approved composeMsg sender to the Endpoint.
     * @dev _origin The origin information containing the source endpoint and sender address.
     *  - srcEid: The source chain endpoint ID.
     *  - sender: The sender address on the src chain.
     *  - nonce: The nonce of the message.
     * @dev _message The lzReceive payload.
     * @param _sender The sender address.
     * @return isSender Is a valid sender.
     *
     * @dev Applications can optionally choose to implement separate composeMsg senders that are NOT the bridging layer.
     * @dev The default sender IS the OAppReceiver implementer.
     */
    function isComposeMsgSender(
        Origin calldata /*_origin*/,
        bytes calldata /*_message*/,
        address _sender
    ) public view virtual returns (bool) {
        return _sender == address(this);
    }

    /**
     * @notice Checks if the path initialization is allowed based on the provided origin.
     * @param origin The origin information containing the source endpoint and sender address.
     * @return Whether the path has been initialized.
     *
     * @dev This indicates to the endpoint that the OApp has enabled msgs for this particular path to be received.
     * @dev This defaults to assuming if a peer has been set, its initialized.
     * Can be overridden by the OApp if there is other logic to determine this.
     */
    function allowInitializePath(Origin calldata origin) public view virtual returns (bool) {
        return peers[origin.srcEid] == origin.sender;
    }

    /**
     * @notice Retrieves the next nonce for a given source endpoint and sender address.
     * @dev _srcEid The source endpoint ID.
     * @dev _sender The sender address.
     * @return nonce The next nonce.
     *
     * @dev The path nonce starts from 1. If 0 is returned it means that there is NO nonce ordered enforcement.
     * @dev Is required by the off-chain executor to determine the OApp expects msg execution is ordered.
     * @dev This is also enforced by the OApp.
     * @dev By default this is NOT enabled. ie. nextNonce is hardcoded to return 0.
     */
    function nextNonce(uint32 /*_srcEid*/, bytes32 /*_sender*/) public view virtual returns (uint64 nonce) {
        return 0;
    }

    /**
     * @dev Entry point for receiving messages or packets from the endpoint.
     * @param _origin The origin information containing the source endpoint and sender address.
     *  - srcEid: The source chain endpoint ID.
     *  - sender: The sender address on the src chain.
     *  - nonce: The nonce of the message.
     * @param _guid The unique identifier for the received LayerZero message.
     * @param _message The payload of the received message.
     * @param _executor The address of the executor for the received message.
     * @param _extraData Additional arbitrary data provided by the corresponding executor.
     *
     * @dev Entry point for receiving msg/packet from the LayerZero endpoint.
     */
    function lzReceive(
        Origin calldata _origin,
        bytes32 _guid,
        bytes calldata _message,
        address _executor,
        bytes calldata _extraData
    ) public payable virtual {
        // Ensures that only the endpoint can attempt to lzReceive() messages to this OApp.
        if (address(endpoint) != msg.sender) revert OnlyEndpoint(msg.sender);

        // Ensure that the sender matches the expected peer for the source endpoint.
        if (_getPeerOrRevert(_origin.srcEid) != _origin.sender) revert OnlyPeer(_origin.srcEid, _origin.sender);

        // Call the internal OApp implementation of lzReceive.
        _lzReceive(_origin, _guid, _message, _executor, _extraData);
    }

    /**
     * @dev Internal function to implement lzReceive logic without needing to copy the basic parameter validation.
     */
    function _lzReceive(
        Origin calldata _origin,
        bytes32 _guid,
        bytes calldata _message,
        address _executor,
        bytes calldata _extraData
    ) internal virtual;
}


// File @openzeppelin/contracts/token/ERC20/extensions/[email protected]

// Original license: SPDX_License_Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
 * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
 *
 * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
 * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
 * need to send a transaction, and thus is not required to hold Ether at all.
 */
interface IERC20Permit {
    /**
     * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
     * given ``owner``'s signed approval.
     *
     * IMPORTANT: The same issues {IERC20-approve} has related to transaction
     * ordering also apply here.
     *
     * Emits an {Approval} event.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     * - `deadline` must be a timestamp in the future.
     * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
     * over the EIP712-formatted function arguments.
     * - the signature must use ``owner``'s current nonce (see {nonces}).
     *
     * For more information on the signature format, see the
     * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
     * section].
     */
    function permit(
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external;

    /**
     * @dev Returns the current nonce for `owner`. This value must be
     * included whenever a signature is generated for {permit}.
     *
     * Every successful call to {permit} increases ``owner``'s nonce by one. This
     * prevents a signature from being used multiple times.
     */
    function nonces(address owner) external view returns (uint256);

    /**
     * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.
     */
    // solhint-disable-next-line func-name-mixedcase
    function DOMAIN_SEPARATOR() external view returns (bytes32);
}


// File @openzeppelin/contracts/token/ERC20/[email protected]

// Original license: SPDX_License_Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

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

    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

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

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

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

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

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


// File @openzeppelin/contracts/utils/[email protected]

// Original license: SPDX_License_Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)

pragma solidity ^0.8.1;

/**
 * @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
     * ====
     *
     * [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://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
     *
     * IMPORTANT: because control is transferred to `recipient`, care must be
     * taken to not create reentrancy vulnerabilities. Consider using
     * {ReentrancyGuard} or the
     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
     */
    function sendValue(address payable recipient, uint256 amount) internal {
        require(address(this).balance >= amount, "Address: insufficient balance");

        (bool success, ) = recipient.call{value: amount}("");
        require(success, "Address: unable to send value, recipient may have reverted");
    }

    /**
     * @dev Performs a Solidity function call using a low level `call`. A
     * plain `call` is an unsafe replacement for a function call: use this
     * function instead.
     *
     * If `target` reverts with a revert reason, it is bubbled up by this
     * function (like regular Solidity function calls).
     *
     * Returns the raw returned data. To convert to the expected return value,
     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
     *
     * Requirements:
     *
     * - `target` must be a contract.
     * - calling `target` with `data` must not revert.
     *
     * _Available since v3.1._
     */
    function functionCall(address target, bytes memory data) internal returns (bytes memory) {
        return 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);
        }
    }
}


// File @openzeppelin/contracts/token/ERC20/utils/[email protected]

// Original license: SPDX_License_Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)

pragma solidity ^0.8.0;



/**
 * @title SafeERC20
 * @dev Wrappers around ERC20 operations that throw on failure (when the token
 * contract returns false). Tokens that return no value (and instead revert or
 * throw on failure) are also supported, non-reverting calls are assumed to be
 * successful.
 * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
 * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
 */
library SafeERC20 {
    using Address for address;

    function safeTransfer(
        IERC20 token,
        address to,
        uint256 value
    ) internal {
        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
    }

    function safeTransferFrom(
        IERC20 token,
        address from,
        address to,
        uint256 value
    ) internal {
        _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
    }

    /**
     * @dev Deprecated. This function has issues similar to the ones found in
     * {IERC20-approve}, and its usage is discouraged.
     *
     * Whenever possible, use {safeIncreaseAllowance} and
     * {safeDecreaseAllowance} instead.
     */
    function safeApprove(
        IERC20 token,
        address spender,
        uint256 value
    ) internal {
        // safeApprove should only be called when setting an initial allowance,
        // or when resetting it to zero. To increase and decrease it, use
        // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
        require(
            (value == 0) || (token.allowance(address(this), spender) == 0),
            "SafeERC20: approve from non-zero to non-zero allowance"
        );
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
    }

    function safeIncreaseAllowance(
        IERC20 token,
        address spender,
        uint256 value
    ) internal {
        uint256 newAllowance = token.allowance(address(this), spender) + value;
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
    }

    function safeDecreaseAllowance(
        IERC20 token,
        address spender,
        uint256 value
    ) internal {
        unchecked {
            uint256 oldAllowance = token.allowance(address(this), spender);
            require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
            uint256 newAllowance = oldAllowance - value;
            _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
        }
    }

    function safePermit(
        IERC20Permit token,
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) internal {
        uint256 nonceBefore = token.nonces(owner);
        token.permit(owner, spender, value, deadline, v, r, s);
        uint256 nonceAfter = token.nonces(owner);
        require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed");
    }

    /**
     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
     * on the return value: the return value is optional (but if data is returned, it must not be false).
     * @param token The token targeted by the call.
     * @param data The call data (encoded using abi.encode or one of its variants).
     */
    function _callOptionalReturn(IERC20 token, bytes memory data) private {
        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
        // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that
        // the target address contains contract code and also asserts for success in the low-level call.

        bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
        if (returndata.length > 0) {
            // Return data is optional
            require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
        }
    }
}


// File @layerzerolabs/lz-evm-oapp-v2/contracts/oapp/[email protected]

// Original license: SPDX_License_Identifier: MIT

pragma solidity ^0.8.20;



/**
 * @title OAppSender
 * @dev Abstract contract implementing the OAppSender functionality for sending messages to a LayerZero endpoint.
 */
abstract contract OAppSender is OAppCore {
    using SafeERC20 for IERC20;

    // Custom error messages
    error NotEnoughNative(uint256 msgValue);
    error LzTokenUnavailable();

    // @dev The version of the OAppSender implementation.
    // @dev Version is bumped when changes are made to this contract.
    uint64 internal constant SENDER_VERSION = 1;

    /**
     * @notice Retrieves the OApp version information.
     * @return senderVersion The version of the OAppSender.sol contract.
     * @return receiverVersion The version of the OAppReceiver.sol contract.
     *
     * @dev Providing 0 as the default for OAppReceiver version. Indicates that the OAppReceiver is not implemented.
     * ie. this is a SEND only OApp.
     * @dev If the OApp uses both OAppSender and OAppReceiver, then this needs to be override returning the correct versions
     */
    function oAppVersion() public view virtual returns (uint64 senderVersion, uint64 receiverVersion) {
        return (SENDER_VERSION, 0);
    }

    /**
     * @dev Internal function to interact with the LayerZero EndpointV2.quote() for fee calculation.
     * @param _dstEid The destination endpoint ID.
     * @param _message The message payload.
     * @param _options Additional options for the message.
     * @param _payInLzToken Flag indicating whether to pay the fee in LZ tokens.
     * @return fee The calculated MessagingFee for the message.
     *      - nativeFee: The native fee for the message.
     *      - lzTokenFee: The LZ token fee for the message.
     */
    function _quote(
        uint32 _dstEid,
        bytes memory _message,
        bytes memory _options,
        bool _payInLzToken
    ) internal view virtual returns (MessagingFee memory fee) {
        return
            endpoint.quote(
                MessagingParams(_dstEid, _getPeerOrRevert(_dstEid), _message, _options, _payInLzToken),
                address(this)
            );
    }

    /**
     * @dev Internal function to interact with the LayerZero EndpointV2.send() for sending a message.
     * @param _dstEid The destination endpoint ID.
     * @param _message The message payload.
     * @param _options Additional options for the message.
     * @param _fee The calculated LayerZero fee for the message.
     *      - nativeFee: The native fee.
     *      - lzTokenFee: The lzToken fee.
     * @param _refundAddress The address to receive any excess fee values sent to the endpoint.
     * @return receipt The receipt for the sent message.
     *      - guid: The unique identifier for the sent message.
     *      - nonce: The nonce of the sent message.
     *      - fee: The LayerZero fee incurred for the message.
     */
    function _lzSend(
        uint32 _dstEid,
        bytes memory _message,
        bytes memory _options,
        MessagingFee memory _fee,
        address _refundAddress
    ) internal virtual returns (MessagingReceipt memory receipt) {
        // @dev Push corresponding fees to the endpoint, any excess is sent back to the _refundAddress from the endpoint.
        uint256 messageValue = _payNative(_fee.nativeFee);
        if (_fee.lzTokenFee > 0) _payLzToken(_fee.lzTokenFee);

        return
            // solhint-disable-next-line check-send-result
            endpoint.send{ value: messageValue }(
                MessagingParams(_dstEid, _getPeerOrRevert(_dstEid), _message, _options, _fee.lzTokenFee > 0),
                _refundAddress
            );
    }

    /**
     * @dev Internal function to pay the native fee associated with the message.
     * @param _nativeFee The native fee to be paid.
     * @return nativeFee The amount of native currency paid.
     *
     * @dev If the OApp needs to initiate MULTIPLE LayerZero messages in a single transaction,
     * this will need to be overridden because msg.value would contain multiple lzFees.
     * @dev Should be overridden in the event the LayerZero endpoint requires a different native currency.
     * @dev Some EVMs use an ERC20 as a method for paying transactions/gasFees.
     * @dev The endpoint is EITHER/OR, ie. it will NOT support both types of native payment at a time.
     */
    function _payNative(uint256 _nativeFee) internal virtual returns (uint256 nativeFee) {
        if (msg.value != _nativeFee) revert NotEnoughNative(msg.value);
        return _nativeFee;
    }

    /**
     * @dev Internal function to pay the LZ token fee associated with the message.
     * @param _lzTokenFee The LZ token fee to be paid.
     *
     * @dev If the caller is trying to pay in the specified lzToken, then the lzTokenFee is passed to the endpoint.
     * @dev Any excess sent, is passed back to the specified _refundAddress in the _lzSend().
     */
    function _payLzToken(uint256 _lzTokenFee) internal virtual {
        // @dev Cannot cache the token because it is not immutable in the endpoint.
        address lzToken = endpoint.lzToken();
        if (lzToken == address(0)) revert LzTokenUnavailable();

        // Pay LZ token fee by sending tokens to the endpoint.
        IERC20(lzToken).safeTransferFrom(msg.sender, address(endpoint), _lzTokenFee);
    }
}


// File @layerzerolabs/lz-evm-oapp-v2/contracts/oapp/[email protected]

// Original license: SPDX_License_Identifier: MIT

pragma solidity ^0.8.20;

// @dev Import the 'MessagingFee' and 'MessagingReceipt' so it's exposed to OApp implementers
// solhint-disable-next-line no-unused-import

// @dev Import the 'Origin' so it's exposed to OApp implementers
// solhint-disable-next-line no-unused-import


/**
 * @title OApp
 * @dev Abstract contract serving as the base for OApp implementation, combining OAppSender and OAppReceiver functionality.
 */
abstract contract OApp is OAppSender, OAppReceiver {
    /**
     * @dev Constructor to initialize the OApp with the provided endpoint and owner.
     * @param _endpoint The address of the LOCAL LayerZero endpoint.
     * @param _delegate The delegate capable of making OApp configurations inside of the endpoint.
     */
    constructor(address _endpoint, address _delegate) OAppCore(_endpoint, _delegate) {}

    /**
     * @notice Retrieves the OApp version information.
     * @return senderVersion The version of the OAppSender.sol implementation.
     * @return receiverVersion The version of the OAppReceiver.sol implementation.
     */
    function oAppVersion()
        public
        pure
        virtual
        override(OAppSender, OAppReceiver)
        returns (uint64 senderVersion, uint64 receiverVersion)
    {
        return (SENDER_VERSION, RECEIVER_VERSION);
    }
}


// File @layerzerolabs/lz-evm-oapp-v2/contracts/oft/interfaces/[email protected]

// Original license: SPDX_License_Identifier: MIT

pragma solidity ^0.8.20;

/**
 * @dev Struct representing token parameters for the OFT send() operation.
 */
struct SendParam {
    uint32 dstEid; // Destination endpoint ID.
    bytes32 to; // Recipient address.
    uint256 amountLD; // Amount to send in local decimals.
    uint256 minAmountLD; // Minimum amount to send in local decimals.
    bytes extraOptions; // Additional options supplied by the caller to be used in the LayerZero message.
    bytes composeMsg; // The composed message for the send() operation.
    bytes oftCmd; // The OFT command to be executed, unused in default OFT implementations.
}

/**
 * @dev Struct representing OFT limit information.
 * @dev These amounts can change dynamically and are up the the specific oft implementation.
 */
struct OFTLimit {
    uint256 minAmountLD; // Minimum amount in local decimals that can be sent to the recipient.
    uint256 maxAmountLD; // Maximum amount in local decimals that can be sent to the recipient.
}

/**
 * @dev Struct representing OFT receipt information.
 */
struct OFTReceipt {
    uint256 amountSentLD; // Amount of tokens ACTUALLY debited from the sender in local decimals.
    // @dev In non-default implementations, the amountReceivedLD COULD differ from this value.
    uint256 amountReceivedLD; // Amount of tokens to be received on the remote side.
}

/**
 * @dev Struct representing OFT fee details.
 * @dev Future proof mechanism to provide a standardized way to communicate fees to things like a UI.
 */
struct OFTFeeDetail {
    int256 feeAmountLD; // Amount of the fee in local decimals.
    string description; // Description of the fee.
}

/**
 * @title IOFT
 * @dev Interface for the OftChain (OFT) token.
 * @dev Does not inherit ERC20 to accommodate usage by OFTAdapter as well.
 * @dev This specific interface ID is '0x02e49c2c'.
 */
interface IOFT {
    // Custom error messages
    error InvalidLocalDecimals();
    error SlippageExceeded(uint256 amountLD, uint256 minAmountLD);

    // Events
    event OFTSent(
        bytes32 indexed guid, // GUID of the OFT message.
        uint32 dstEid, // Destination Endpoint ID.
        address indexed fromAddress, // Address of the sender on the src chain.
        uint256 amountSentLD, // Amount of tokens sent in local decimals.
        uint256 amountReceivedLD // Amount of tokens received in local decimals.
    );
    event OFTReceived(
        bytes32 indexed guid, // GUID of the OFT message.
        uint32 srcEid, // Source Endpoint ID.
        address indexed toAddress, // Address of the recipient on the dst chain.
        uint256 amountReceivedLD // Amount of tokens received in local decimals.
    );

    /**
     * @notice Retrieves interfaceID and the version of the OFT.
     * @return interfaceId The interface ID.
     * @return version The version.
     *
     * @dev interfaceId: This specific interface ID is '0x02e49c2c'.
     * @dev version: Indicates a cross-chain compatible msg encoding with other OFTs.
     * @dev If a new feature is added to the OFT cross-chain msg encoding, the version will be incremented.
     * ie. localOFT version(x,1) CAN send messages to remoteOFT version(x,1)
     */
    function oftVersion() external view returns (bytes4 interfaceId, uint64 version);

    /**
     * @notice Retrieves the address of the token associated with the OFT.
     * @return token The address of the ERC20 token implementation.
     */
    function token() external view returns (address);

    /**
     * @notice Indicates whether the OFT contract requires approval of the 'token()' to send.
     * @return requiresApproval Needs approval of the underlying token implementation.
     *
     * @dev Allows things like wallet implementers to determine integration requirements,
     * without understanding the underlying token implementation.
     */
    function approvalRequired() external view returns (bool);

    /**
     * @notice Retrieves the shared decimals of the OFT.
     * @return sharedDecimals The shared decimals of the OFT.
     */
    function sharedDecimals() external view returns (uint8);

    /**
     * @notice Provides a quote for OFT-related operations.
     * @param _sendParam The parameters for the send operation.
     * @return limit The OFT limit information.
     * @return oftFeeDetails The details of OFT fees.
     * @return receipt The OFT receipt information.
     */
    function quoteOFT(
        SendParam calldata _sendParam
    ) external view returns (OFTLimit memory, OFTFeeDetail[] memory oftFeeDetails, OFTReceipt memory);

    /**
     * @notice Provides a quote for the send() operation.
     * @param _sendParam The parameters for the send() operation.
     * @param _payInLzToken Flag indicating whether the caller is paying in the LZ token.
     * @return fee The calculated LayerZero messaging fee from the send() operation.
     *
     * @dev MessagingFee: LayerZero msg fee
     *  - nativeFee: The native fee.
     *  - lzTokenFee: The lzToken fee.
     */
    function quoteSend(SendParam calldata _sendParam, bool _payInLzToken) external view returns (MessagingFee memory);

    /**
     * @notice Executes the send() operation.
     * @param _sendParam The parameters for the send operation.
     * @param _fee The fee information supplied by the caller.
     *      - nativeFee: The native fee.
     *      - lzTokenFee: The lzToken fee.
     * @param _refundAddress The address to receive any excess funds from fees etc. on the src.
     * @return receipt The LayerZero messaging receipt from the send() operation.
     * @return oftReceipt The OFT receipt information.
     *
     * @dev MessagingReceipt: LayerZero msg receipt
     *  - guid: The unique identifier for the sent message.
     *  - nonce: The nonce of the sent message.
     *  - fee: The LayerZero fee incurred for the message.
     */
    function send(
        SendParam calldata _sendParam,
        MessagingFee calldata _fee,
        address _refundAddress
    ) external payable returns (MessagingReceipt memory, OFTReceipt memory);
}


// File @layerzerolabs/lz-evm-oapp-v2/contracts/oapp/interfaces/[email protected]

// Original license: SPDX_License_Identifier: MIT

pragma solidity ^0.8.20;

/**
 * @title IOAppMsgInspector
 * @dev Interface for the OApp Message Inspector, allowing examination of message and options contents.
 */
interface IOAppMsgInspector {
    // Custom error message for inspection failure
    error InspectionFailed(bytes message, bytes options);

    /**
     * @notice Allows the inspector to examine LayerZero message contents and optionally throw a revert if invalid.
     * @param _message The message payload to be inspected.
     * @param _options Additional options or parameters for inspection.
     * @return valid A boolean indicating whether the inspection passed (true) or failed (false).
     *
     * @dev Optionally done as a revert, OR use the boolean provided to handle the failure.
     */
    function inspect(bytes calldata _message, bytes calldata _options) external view returns (bool valid);
}


// File @layerzerolabs/lz-evm-oapp-v2/contracts/oft/libs/[email protected]

// Original license: SPDX_License_Identifier: MIT

pragma solidity ^0.8.20;

library OFTComposeMsgCodec {
    // Offset constants for decoding composed messages
    uint8 private constant NONCE_OFFSET = 8;
    uint8 private constant SRC_EID_OFFSET = 12;
    uint8 private constant AMOUNT_LD_OFFSET = 44;
    uint8 private constant COMPOSE_FROM_OFFSET = 76;

    /**
     * @dev Encodes a OFT composed message.
     * @param _nonce The nonce value.
     * @param _srcEid The source endpoint ID.
     * @param _amountLD The amount in local decimals.
     * @param _composeMsg The composed message.
     * @return _msg The encoded Composed message.
     */
    function encode(
        uint64 _nonce,
        uint32 _srcEid,
        uint256 _amountLD,
        bytes memory _composeMsg // 0x[composeFrom][composeMsg]
    ) internal pure returns (bytes memory _msg) {
        _msg = abi.encodePacked(_nonce, _srcEid, _amountLD, _composeMsg);
    }

    /**
     * @dev Retrieves the nonce from the composed message.
     * @param _msg The message.
     * @return The nonce value.
     */
    function nonce(bytes calldata _msg) internal pure returns (uint64) {
        return uint64(bytes8(_msg[:NONCE_OFFSET]));
    }

    /**
     * @dev Retrieves the source endpoint ID from the composed message.
     * @param _msg The message.
     * @return The source endpoint ID.
     */
    function srcEid(bytes calldata _msg) internal pure returns (uint32) {
        return uint32(bytes4(_msg[NONCE_OFFSET:SRC_EID_OFFSET]));
    }

    /**
     * @dev Retrieves the amount in local decimals from the composed message.
     * @param _msg The message.
     * @return The amount in local decimals.
     */
    function amountLD(bytes calldata _msg) internal pure returns (uint256) {
        return uint256(bytes32(_msg[SRC_EID_OFFSET:AMOUNT_LD_OFFSET]));
    }

    /**
     * @dev Retrieves the composeFrom value from the composed message.
     * @param _msg The message.
     * @return The composeFrom value.
     */
    function composeFrom(bytes calldata _msg) internal pure returns (bytes32) {
        return bytes32(_msg[AMOUNT_LD_OFFSET:COMPOSE_FROM_OFFSET]);
    }

    /**
     * @dev Retrieves the composed message.
     * @param _msg The message.
     * @return The composed message.
     */
    function composeMsg(bytes calldata _msg) internal pure returns (bytes memory) {
        return _msg[COMPOSE_FROM_OFFSET:];
    }

    /**
     * @dev Converts an address to bytes32.
     * @param _addr The address to convert.
     * @return The bytes32 representation of the address.
     */
    function addressToBytes32(address _addr) internal pure returns (bytes32) {
        return bytes32(uint256(uint160(_addr)));
    }

    /**
     * @dev Converts bytes32 to an address.
     * @param _b The bytes32 value to convert.
     * @return The address representation of bytes32.
     */
    function bytes32ToAddress(bytes32 _b) internal pure returns (address) {
        return address(uint160(uint256(_b)));
    }
}


// File @layerzerolabs/lz-evm-oapp-v2/contracts/oft/libs/[email protected]

// Original license: SPDX_License_Identifier: MIT

pragma solidity ^0.8.20;

library OFTMsgCodec {
    // Offset constants for encoding and decoding OFT messages
    uint8 private constant SEND_TO_OFFSET = 32;
    uint8 private constant SEND_AMOUNT_SD_OFFSET = 40;

    /**
     * @dev Encodes an OFT LayerZero message.
     * @param _sendTo The recipient address.
     * @param _amountShared The amount in shared decimals.
     * @param _composeMsg The composed message.
     * @return _msg The encoded message.
     * @return hasCompose A boolean indicating whether the message has a composed payload.
     */
    function encode(
        bytes32 _sendTo,
        uint64 _amountShared,
        bytes memory _composeMsg
    ) internal view returns (bytes memory _msg, bool hasCompose) {
        hasCompose = _composeMsg.length > 0;
        // @dev Remote chains will want to know the composed function caller ie. msg.sender on the src.
        _msg = hasCompose
            ? abi.encodePacked(_sendTo, _amountShared, addressToBytes32(msg.sender), _composeMsg)
            : abi.encodePacked(_sendTo, _amountShared);
    }

    /**
     * @dev Checks if the OFT message is composed.
     * @param _msg The OFT message.
     * @return A boolean indicating whether the message is composed.
     */
    function isComposed(bytes calldata _msg) internal pure returns (bool) {
        return _msg.length > SEND_AMOUNT_SD_OFFSET;
    }

    /**
     * @dev Retrieves the recipient address from the OFT message.
     * @param _msg The OFT message.
     * @return The recipient address.
     */
    function sendTo(bytes calldata _msg) internal pure returns (bytes32) {
        return bytes32(_msg[:SEND_TO_OFFSET]);
    }

    /**
     * @dev Retrieves the amount in shared decimals from the OFT message.
     * @param _msg The OFT message.
     * @return The amount in shared decimals.
     */
    function amountSD(bytes calldata _msg) internal pure returns (uint64) {
        return uint64(bytes8(_msg[SEND_TO_OFFSET:SEND_AMOUNT_SD_OFFSET]));
    }

    /**
     * @dev Retrieves the composed message from the OFT message.
     * @param _msg The OFT message.
     * @return The composed message.
     */
    function composeMsg(bytes calldata _msg) internal pure returns (bytes memory) {
        return _msg[SEND_AMOUNT_SD_OFFSET:];
    }

    /**
     * @dev Converts an address to bytes32.
     * @param _addr The address to convert.
     * @return The bytes32 representation of the address.
     */
    function addressToBytes32(address _addr) internal pure returns (bytes32) {
        return bytes32(uint256(uint160(_addr)));
    }

    /**
     * @dev Converts bytes32 to an address.
     * @param _b The bytes32 value to convert.
     * @return The address representation of bytes32.
     */
    function bytes32ToAddress(bytes32 _b) internal pure returns (address) {
        return address(uint160(uint256(_b)));
    }
}


// File @openzeppelin/contracts/utils/introspection/[email protected]

// Original license: SPDX_License_Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC165 standard, as defined in the
 * https://eips.ethereum.org/EIPS/eip-165[EIP].
 *
 * Implementers can declare support of contract interfaces, which can then be
 * queried by others ({ERC165Checker}).
 *
 * For an implementation, see {ERC165}.
 */
interface IERC165 {
    /**
     * @dev Returns true if this contract implements the interface defined by
     * `interfaceId`. See the corresponding
     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
     * to learn more about how these ids are created.
     *
     * This function call must use less than 30 000 gas.
     */
    function supportsInterface(bytes4 interfaceId) external view returns (bool);
}


// File @layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/[email protected]

// Original license: SPDX_License_Identifier: MIT

pragma solidity >=0.8.0;

enum MessageLibType {
    Send,
    Receive,
    SendAndReceive
}

interface IMessageLib is IERC165 {
    function setConfig(address _oapp, SetConfigParam[] calldata _config) external;

    function getConfig(uint32 _eid, address _oapp, uint32 _configType) external view returns (bytes memory config);

    function isSupportedEid(uint32 _eid) external view returns (bool);

    // message libs of same major version are compatible
    function version() external view returns (uint64 major, uint8 minor, uint8 endpointVersion);

    function messageLibType() external view returns (MessageLibType);
}


// File @layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/[email protected]

// Original license: SPDX_License_Identifier: MIT

pragma solidity >=0.8.0;


struct Packet {
    uint64 nonce;
    uint32 srcEid;
    address sender;
    uint32 dstEid;
    bytes32 receiver;
    bytes32 guid;
    bytes message;
}

interface ISendLib is IMessageLib {
    function send(
        Packet calldata _packet,
        bytes calldata _options,
        bool _payInLzToken
    ) external returns (MessagingFee memory, bytes memory encodedPacket);

    function quote(
        Packet calldata _packet,
        bytes calldata _options,
        bool _payInLzToken
    ) external view returns (MessagingFee memory);

    function setTreasury(address _treasury) external;

    function withdrawFee(address _to, uint256 _amount) external;

    function withdrawLzTokenFee(address _lzToken, address _to, uint256 _amount) external;
}


// File @layerzerolabs/lz-evm-protocol-v2/contracts/libs/[email protected]

// Original license: SPDX_License_Identifier: LZBL-1.2

pragma solidity ^0.8.20;

library AddressCast {
    error AddressCast_InvalidSizeForAddress();
    error AddressCast_InvalidAddress();

    function toBytes32(bytes calldata _addressBytes) internal pure returns (bytes32 result) {
        if (_addressBytes.length > 32) revert AddressCast_InvalidAddress();
        result = bytes32(_addressBytes);
        unchecked {
            uint256 offset = 32 - _addressBytes.length;
            result = result >> (offset * 8);
        }
    }

    function toBytes32(address _address) internal pure returns (bytes32 result) {
        result = bytes32(uint256(uint160(_address)));
    }

    function toBytes(bytes32 _addressBytes32, uint256 _size) internal pure returns (bytes memory result) {
        if (_size == 0 || _size > 32) revert AddressCast_InvalidSizeForAddress();
        result = new bytes(_size);
        unchecked {
            uint256 offset = 256 - _size * 8;
            assembly {
                mstore(add(result, 32), shl(offset, _addressBytes32))
            }
        }
    }

    function toAddress(bytes32 _addressBytes32) internal pure returns (address result) {
        result = address(uint160(uint256(_addressBytes32)));
    }

    function toAddress(bytes calldata _addressBytes) internal pure returns (address result) {
        if (_addressBytes.length != 20) revert AddressCast_InvalidAddress();
        result = address(bytes20(_addressBytes));
    }
}


// File @layerzerolabs/lz-evm-protocol-v2/contracts/messagelib/libs/[email protected]

// Original license: SPDX_License_Identifier: LZBL-1.2

pragma solidity ^0.8.20;


library PacketV1Codec {
    using AddressCast for address;
    using AddressCast for bytes32;

    uint8 internal constant PACKET_VERSION = 1;

    // header (version + nonce + path)
    // version
    uint256 private constant PACKET_VERSION_OFFSET = 0;
    //    nonce
    uint256 private constant NONCE_OFFSET = 1;
    //    path
    uint256 private constant SRC_EID_OFFSET = 9;
    uint256 private constant SENDER_OFFSET = 13;
    uint256 private constant DST_EID_OFFSET = 45;
    uint256 private constant RECEIVER_OFFSET = 49;
    // payload (guid + message)
    uint256 private constant GUID_OFFSET = 81; // keccak256(nonce + path)
    uint256 private constant MESSAGE_OFFSET = 113;

    function encode(Packet memory _packet) internal pure returns (bytes memory encodedPacket) {
        encodedPacket = abi.encodePacked(
            PACKET_VERSION,
            _packet.nonce,
            _packet.srcEid,
            _packet.sender.toBytes32(),
            _packet.dstEid,
            _packet.receiver,
            _packet.guid,
            _packet.message
        );
    }

    function encodePacketHeader(Packet memory _packet) internal pure returns (bytes memory) {
        return
            abi.encodePacked(
                PACKET_VERSION,
                _packet.nonce,
                _packet.srcEid,
                _packet.sender.toBytes32(),
                _packet.dstEid,
                _packet.receiver
            );
    }

    function encodePayload(Packet memory _packet) internal pure returns (bytes memory) {
        return abi.encodePacked(_packet.guid, _packet.message);
    }

    function header(bytes calldata _packet) internal pure returns (bytes calldata) {
        return _packet[0:GUID_OFFSET];
    }

    function version(bytes calldata _packet) internal pure returns (uint8) {
        return uint8(bytes1(_packet[PACKET_VERSION_OFFSET:NONCE_OFFSET]));
    }

    function nonce(bytes calldata _packet) internal pure returns (uint64) {
        return uint64(bytes8(_packet[NONCE_OFFSET:SRC_EID_OFFSET]));
    }

    function srcEid(bytes calldata _packet) internal pure returns (uint32) {
        return uint32(bytes4(_packet[SRC_EID_OFFSET:SENDER_OFFSET]));
    }

    function sender(bytes calldata _packet) internal pure returns (bytes32) {
        return bytes32(_packet[SENDER_OFFSET:DST_EID_OFFSET]);
    }

    function senderAddressB20(bytes calldata _packet) internal pure returns (address) {
        return sender(_packet).toAddress();
    }

    function dstEid(bytes calldata _packet) internal pure returns (uint32) {
        return uint32(bytes4(_packet[DST_EID_OFFSET:RECEIVER_OFFSET]));
    }

    function receiver(bytes calldata _packet) internal pure returns (bytes32) {
        return bytes32(_packet[RECEIVER_OFFSET:GUID_OFFSET]);
    }

    function receiverB20(bytes calldata _packet) internal pure returns (address) {
        return receiver(_packet).toAddress();
    }

    function guid(bytes calldata _packet) internal pure returns (bytes32) {
        return bytes32(_packet[GUID_OFFSET:MESSAGE_OFFSET]);
    }

    function message(bytes calldata _packet) internal pure returns (bytes calldata) {
        return bytes(_packet[MESSAGE_OFFSET:]);
    }

    function payload(bytes calldata _packet) internal pure returns (bytes calldata) {
        return bytes(_packet[GUID_OFFSET:]);
    }

    function payloadHash(bytes calldata _packet) internal pure returns (bytes32) {
        return keccak256(payload(_packet));
    }
}


// File @layerzerolabs/lz-evm-oapp-v2/contracts/precrime/libs/[email protected]

// Original license: SPDX_License_Identifier: MIT

pragma solidity ^0.8.20;


/**
 * @title InboundPacket
 * @dev Structure representing an inbound packet received by the contract.
 */
struct InboundPacket {
    Origin origin; // Origin information of the packet.
    uint32 dstEid; // Destination endpointId of the packet.
    address receiver; // Receiver address for the packet.
    bytes32 guid; // Unique identifier of the packet.
    uint256 value; // msg.value of the packet.
    address executor; // Executor address for the packet.
    bytes message; // Message payload of the packet.
    bytes extraData; // Additional arbitrary data for the packet.
}

/**
 * @title PacketDecoder
 * @dev Library for decoding LayerZero packets.
 */
library PacketDecoder {
    using PacketV1Codec for bytes;

    /**
     * @dev Decode an inbound packet from the given packet data.
     * @param _packet The packet data to decode.
     * @return packet An InboundPacket struct representing the decoded packet.
     */
    function decode(bytes calldata _packet) internal pure returns (InboundPacket memory packet) {
        packet.origin = Origin(_packet.srcEid(), _packet.sender(), _packet.nonce());
        packet.dstEid = _packet.dstEid();
        packet.receiver = _packet.receiverB20();
        packet.guid = _packet.guid();
        packet.message = _packet.message();
    }

    /**
     * @dev Decode multiple inbound packets from the given packet data and associated message values.
     * @param _packets An array of packet data to decode.
     * @param _packetMsgValues An array of associated message values for each packet.
     * @return packets An array of InboundPacket structs representing the decoded packets.
     */
    function decode(
        bytes[] calldata _packets,
        uint256[] memory _packetMsgValues
    ) internal pure returns (InboundPacket[] memory packets) {
        packets = new InboundPacket[](_packets.length);
        for (uint256 i = 0; i < _packets.length; i++) {
            bytes calldata packet = _packets[i];
            packets[i] = PacketDecoder.decode(packet);
            // @dev Allows the verifier to specify the msg.value that gets passed in lzReceive.
            packets[i].value = _packetMsgValues[i];
        }
    }
}


// File @layerzerolabs/lz-evm-oapp-v2/contracts/precrime/interfaces/[email protected]

// Original license: SPDX_License_Identifier: MIT

pragma solidity ^0.8.20;

// @dev Import the Origin so it's exposed to OAppPreCrimeSimulator implementers.
// solhint-disable-next-line no-unused-import

/**
 * @title IOAppPreCrimeSimulator Interface
 * @dev Interface for the preCrime simulation functionality in an OApp.
 */
interface IOAppPreCrimeSimulator {
    // @dev simulation result used in PreCrime implementation
    error SimulationResult(bytes result);
    error OnlySelf();

    /**
     * @dev Emitted when the preCrime contract address is set.
     * @param preCrimeAddress The address of the preCrime contract.
     */
    event PreCrimeSet(address preCrimeAddress);

    /**
     * @dev Retrieves the address of the preCrime contract implementation.
     * @return The address of the preCrime contract.
     */
    function preCrime() external view returns (address);

    /**
     * @dev Retrieves the address of the OApp contract.
     * @return The address of the OApp contract.
     */
    function oApp() external view returns (address);

    /**
     * @dev Sets the preCrime contract address.
     * @param _preCrime The address of the preCrime contract.
     */
    function setPreCrime(address _preCrime) external;

    /**
     * @dev Mocks receiving a packet, then reverts with a series of data to infer the state/result.
     * @param _packets An array of LayerZero InboundPacket objects representing received packets.
     */
    function lzReceiveAndRevert(InboundPacket[] calldata _packets) external payable;

    /**
     * @dev checks if the specified peer is considered 'trusted' by the OApp.
     * @param _eid The endpoint Id to check.
     * @param _peer The peer to check.
     * @return Whether the peer passed is considered 'trusted' by the OApp.
     */
    function isPeer(uint32 _eid, bytes32 _peer) external view returns (bool);
}


// File @layerzerolabs/lz-evm-oapp-v2/contracts/precrime/interfaces/[email protected]

// Original license: SPDX_License_Identifier: MIT

pragma solidity ^0.8.20;
struct PreCrimePeer {
    uint32 eid;
    bytes32 preCrime;
    bytes32 oApp;
}

// TODO not done yet
interface IPreCrime {
    error OnlyOffChain();

    // for simulate()
    error PacketOversize(uint256 max, uint256 actual);
    error PacketUnsorted();
    error SimulationFailed(bytes reason);

    // for preCrime()
    error SimulationResultNotFound(uint32 eid);
    error InvalidSimulationResult(uint32 eid, bytes reason);
    error CrimeFound(bytes crime);

    function getConfig(bytes[] calldata _packets, uint256[] calldata _packetMsgValues) external returns (bytes memory);

    function simulate(
        bytes[] calldata _packets,
        uint256[] calldata _packetMsgValues
    ) external payable returns (bytes memory);

    function buildSimulationResult() external view returns (bytes memory);

    function preCrime(
        bytes[] calldata _packets,
        uint256[] calldata _packetMsgValues,
        bytes[] calldata _simulations
    ) external;

    function version() external view returns (uint64 major, uint8 minor);
}


// File @layerzerolabs/lz-evm-oapp-v2/contracts/precrime/[email protected]

// Original license: SPDX_License_Identifier: MIT

pragma solidity ^0.8.20;



/**
 * @title OAppPreCrimeSimulator
 * @dev Abstract contract serving as the base for preCrime simulation functionality in an OApp.
 */
abstract contract OAppPreCrimeSimulator is IOAppPreCrimeSimulator, Ownable {
    // The address of the preCrime implementation.
    address public preCrime;

    /**
     * @dev Retrieves the address of the OApp contract.
     * @return The address of the OApp contract.
     *
     * @dev The simulator contract is the base contract for the OApp by default.
     * @dev If the simulator is a separate contract, override this function.
     */
    function oApp() external view virtual returns (address) {
        return address(this);
    }

    /**
     * @dev Sets the preCrime contract address.
     * @param _preCrime The address of the preCrime contract.
     */
    function setPreCrime(address _preCrime) public virtual onlyOwner {
        preCrime = _preCrime;
        emit PreCrimeSet(_preCrime);
    }

    /**
     * @dev Interface for pre-crime simulations. Always reverts at the end with the simulation results.
     * @param _packets An array of InboundPacket objects representing received packets to be delivered.
     *
     * @dev WARNING: MUST revert at the end with the simulation results.
     * @dev Gives the preCrime implementation the ability to mock sending packets to the lzReceive function,
     * WITHOUT actually executing them.
     */
    function lzReceiveAndRevert(InboundPacket[] calldata _packets) public payable virtual {
        for (uint256 i = 0; i < _packets.length; i++) {
            InboundPacket calldata packet = _packets[i];

            // Ignore packets that are not from trusted peers.
            if (!isPeer(packet.origin.srcEid, packet.origin.sender)) continue;

            // @dev Because a verifier is calling this function, it doesnt have access to executor params:
            //  - address _executor
            //  - bytes calldata _extraData
            // preCrime will NOT work for OApps that rely on these two parameters inside of their _lzReceive().
            // They are instead stubbed to default values, address(0) and bytes("")
            // @dev Calling this.lzReceiveSimulate removes ability for assembly return 0 callstack exit,
            // which would cause the revert to be ignored.
            this.lzReceiveSimulate{ value: packet.value }(
                packet.origin,
                packet.guid,
                packet.message,
                packet.executor,
                packet.extraData
            );
        }

        // @dev Revert with the simulation results. msg.sender must implement IPreCrime.buildSimulationResult().
        revert SimulationResult(IPreCrime(msg.sender).buildSimulationResult());
    }

    /**
     * @dev Is effectively an internal function because msg.sender must be address(this).
     * Allows resetting the call stack for 'internal' calls.
     * @param _origin The origin information containing the source endpoint and sender address.
     *  - srcEid: The source chain endpoint ID.
     *  - sender: The sender address on the src chain.
     *  - nonce: The nonce of the message.
     * @param _guid The unique identifier of the packet.
     * @param _message The message payload of the packet.
     * @param _executor The executor address for the packet.
     * @param _extraData Additional data for the packet.
     */
    function lzReceiveSimulate(
        Origin calldata _origin,
        bytes32 _guid,
        bytes calldata _message,
        address _executor,
        bytes calldata _extraData
    ) external payable virtual {
        // @dev Ensure ONLY can be called 'internally'.
        if (msg.sender != address(this)) revert OnlySelf();
        _lzReceiveSimulate(_origin, _guid, _message, _executor, _extraData);
    }

    /**
     * @dev Internal function to handle the OAppPreCrimeSimulator simulated receive.
     * @param _origin The origin information.
     *  - srcEid: The source chain endpoint ID.
     *  - sender: The sender address from the src chain.
     *  - nonce: The nonce of the LayerZero message.
     * @param _guid The GUID of the LayerZero message.
     * @param _message The LayerZero message.
     * @param _executor The address of the off-chain executor.
     * @param _extraData Arbitrary data passed by the msg executor.
     *
     * @dev Enables the preCrime simulator to mock sending lzReceive() messages,
     * routes the msg down from the OAppPreCrimeSimulator, and back up to the OAppReceiver.
     */
    function _lzReceiveSimulate(
        Origin calldata _origin,
        bytes32 _guid,
        bytes calldata _message,
        address _executor,
        bytes calldata _extraData
    ) internal virtual;

    /**
     * @dev checks if the specified peer is considered 'trusted' by the OApp.
     * @param _eid The endpoint Id to check.
     * @param _peer The peer to check.
     * @return Whether the peer passed is considered 'trusted' by the OApp.
     */
    function isPeer(uint32 _eid, bytes32 _peer) public view virtual returns (bool);
}


// File @layerzerolabs/lz-evm-oapp-v2/contracts/oft/[email protected]

// Original license: SPDX_License_Identifier: MIT

pragma solidity ^0.8.20;





/**
 * @title OFTCore
 * @dev Abstract contract for the OftChain (OFT) token.
 */
abstract contract OFTCore is IOFT, OApp, OAppPreCrimeSimulator, OAppOptionsType3 {
    using OFTMsgCodec for bytes;
    using OFTMsgCodec for bytes32;

    // @notice Provides a conversion rate when swapping between denominations of SD and LD
    //      - shareDecimals == SD == shared Decimals
    //      - localDecimals == LD == local decimals
    // @dev Considers that tokens have different decimal amounts on various chains.
    // @dev eg.
    //  For a token
    //      - locally with 4 decimals --> 1.2345 => uint(12345)
    //      - remotely with 2 decimals --> 1.23 => uint(123)
    //      - The conversion rate would be 10 ** (4 - 2) = 100
    //  @dev If you want to send 1.2345 -> (uint 12345), you CANNOT represent that value on the remote,
    //  you can only display 1.23 -> uint(123).
    //  @dev To preserve the dust that would otherwise be lost on that conversion,
    //  we need to unify a denomination that can be represented on ALL chains inside of the OFT mesh
    uint256 public immutable decimalConversionRate;

    // @notice Msg types that are used to identify the various OFT operations.
    // @dev This can be extended in child contracts for non-default oft operations
    // @dev These values are used in things like combineOptions() in OAppOptionsType3.sol.
    uint16 public constant SEND = 1;
    uint16 public constant SEND_AND_CALL = 2;

    // Address of an optional contract to inspect both 'message' and 'options'
    address public msgInspector;
    event MsgInspectorSet(address inspector);

    /**
     * @dev Constructor.
     * @param _localDecimals The decimals of the token on the local chain (this chain).
     * @param _endpoint The address of the LayerZero endpoint.
     * @param _delegate The delegate capable of making OApp configurations inside of the endpoint.
     */
    constructor(uint8 _localDecimals, address _endpoint, address _delegate) OApp(_endpoint, _delegate) {
        if (_localDecimals < sharedDecimals()) revert InvalidLocalDecimals();
        decimalConversionRate = 10 ** (_localDecimals - sharedDecimals());
    }

    /**
     * @notice Retrieves interfaceID and the version of the OFT.
     * @return interfaceId The interface ID.
     * @return version The version.
     *
     * @dev interfaceId: This specific interface ID is '0x02e49c2c'.
     * @dev version: Indicates a cross-chain compatible msg encoding with other OFTs.
     * @dev If a new feature is added to the OFT cross-chain msg encoding, the version will be incremented.
     * ie. localOFT version(x,1) CAN send messages to remoteOFT version(x,1)
     */
    function oftVersion() external pure virtual returns (bytes4 interfaceId, uint64 version) {
        return (type(IOFT).interfaceId, 1);
    }

    /**
     * @dev Retrieves the shared decimals of the OFT.
     * @return The shared decimals of the OFT.
     *
     * @dev Sets an implicit cap on the amount of tokens, over uint64.max() will need some sort of outbound cap / totalSupply cap
     * Lowest common decimal denominator between chains.
     * Defaults to 6 decimal places to provide up to 18,446,744,073,709.551615 units (max uint64).
     * For tokens exceeding this totalSupply(), they will need to override the sharedDecimals function with something smaller.
     * ie. 4 sharedDecimals would be 1,844,674,407,370,955.1615
     */
    function sharedDecimals() public view virtual returns (uint8) {
        return 6;
    }

    /**
     * @dev Sets the message inspector address for the OFT.
     * @param _msgInspector The address of the message inspector.
     *
     * @dev This is an optional contract that can be used to inspect both 'message' and 'options'.
     * @dev Set it to address(0) to disable it, or set it to a contract address to enable it.
     */
    function setMsgInspector(address _msgInspector) public virtual onlyOwner {
        msgInspector = _msgInspector;
        emit MsgInspectorSet(_msgInspector);
    }

    /**
     * @notice Provides a quote for OFT-related operations.
     * @param _sendParam The parameters for the send operation.
     * @return oftLimit The OFT limit information.
     * @return oftFeeDetails The details of OFT fees.
     * @return oftReceipt The OFT receipt information.
     */
    function quoteOFT(
        SendParam calldata _sendParam
    )
        external
        view
        virtual
        returns (OFTLimit memory oftLimit, OFTFeeDetail[] memory oftFeeDetails, OFTReceipt memory oftReceipt)
    {
        uint256 minAmountLD = 0; // Unused in the default implementation.
        uint256 maxAmountLD = type(uint64).max; // Unused in the default implementation.
        oftLimit = OFTLimit(minAmountLD, maxAmountLD);

        // Unused in the default implementation; reserved for future complex fee details.
        oftFeeDetails = new OFTFeeDetail[](0);

        // @dev This is the same as the send() operation, but without the actual send.
        // - amountSentLD is the amount in local decimals that would be sent from the sender.
        // - amountReceivedLD is the amount in local decimals that will be credited to the recipient on the remote OFT instance.
        // @dev The amountSentLD MIGHT not equal the amount the user actually receives. HOWEVER, the default does.
        (uint256 amountSentLD, uint256 amountReceivedLD) = _debitView(
            _sendParam.amountLD,
            _sendParam.minAmountLD,
            _sendParam.dstEid
        );
        oftReceipt = OFTReceipt(amountSentLD, amountReceivedLD);
    }

    /**
     * @notice Provides a quote for the send() operation.
     * @param _sendParam The parameters for the send() operation.
     * @param _payInLzToken Flag indicating whether the caller is paying in the LZ token.
     * @return msgFee The calculated LayerZero messaging fee from the send() operation.
     *
     * @dev MessagingFee: LayerZero msg fee
     *  - nativeFee: The native fee.
     *  - lzTokenFee: The lzToken fee.
     */
    function quoteSend(
        SendParam calldata _sendParam,
        bool _payInLzToken
    ) external view virtual returns (MessagingFee memory msgFee) {
        // @dev mock the amount to receive, this is the same operation used in the send().
        // The quote is as similar as possible to the actual send() operation.
        (, uint256 amountReceivedLD) = _debitView(_sendParam.amountLD, _sendParam.minAmountLD, _sendParam.dstEid);

        // @dev Builds the options and OFT message to quote in the endpoint.
        (bytes memory message, bytes memory options) = _buildMsgAndOptions(_sendParam, amountReceivedLD);

        // @dev Calculates the LayerZero fee for the send() operation.
        return _quote(_sendParam.dstEid, message, options, _payInLzToken);
    }

    /**
     * @dev Executes the send operation.
     * @param _sendParam The parameters for the send operation.
     * @param _fee The calculated fee for the send() operation.
     *      - nativeFee: The native fee.
     *      - lzTokenFee: The lzToken fee.
     * @param _refundAddress The address to receive any excess funds.
     * @return msgReceipt The receipt for the send operation.
     * @return oftReceipt The OFT receipt information.
     *
     * @dev MessagingReceipt: LayerZero msg receipt
     *  - guid: The unique identifier for the sent message.
     *  - nonce: The nonce of the sent message.
     *  - fee: The LayerZero fee incurred for the message.
     */
    function send(
        SendParam calldata _sendParam,
        MessagingFee calldata _fee,
        address _refundAddress
    ) external payable virtual returns (MessagingReceipt memory msgReceipt, OFTReceipt memory oftReceipt) {
        // @dev Applies the token transfers regarding this send() operation.
        // - amountSentLD is the amount in local decimals that was ACTUALLY sent/debited from the sender.
        // - amountReceivedLD is the amount in local decimals that will be received/credited to the recipient on the remote OFT instance.
        (uint256 amountSentLD, uint256 amountReceivedLD) = _debit(
            msg.sender,
            _sendParam.amountLD,
            _sendParam.minAmountLD,
            _sendParam.dstEid
        );

        // @dev Builds the options and OFT message to quote in the endpoint.
        (bytes memory message, bytes memory options) = _buildMsgAndOptions(_sendParam, amountReceivedLD);

        // @dev Sends the message to the LayerZero endpoint and returns the LayerZero msg receipt.
        msgReceipt = _lzSend(_sendParam.dstEid, message, options, _fee, _refundAddress);
        // @dev Formulate the OFT receipt.
        oftReceipt = OFTReceipt(amountSentLD, amountReceivedLD);

        emit OFTSent(msgReceipt.guid, _sendParam.dstEid, msg.sender, amountSentLD, amountReceivedLD);
    }

    /**
     * @dev Internal function to build the message and options.
     * @param _sendParam The parameters for the send() operation.
     * @param _amountLD The amount in local decimals.
     * @return message The encoded message.
     * @return options The encoded options.
     */
    function _buildMsgAndOptions(
        SendParam calldata _sendParam,
        uint256 _amountLD
    ) internal view virtual returns (bytes memory message, bytes memory options) {
        bool hasCompose;
        // @dev This generated message has the msg.sender encoded into the payload so the remote knows who the caller is.
        (message, hasCompose) = OFTMsgCodec.encode(
            _sendParam.to,
            _toSD(_amountLD),
            // @dev Must be include a non empty bytes if you want to compose, EVEN if you dont need it on the remote.
            // EVEN if you dont require an arbitrary payload to be sent... eg. '0x01'
            _sendParam.composeMsg
        );
        // @dev Change the msg type depending if its composed or not.
        uint16 msgType = hasCompose ? SEND_AND_CALL : SEND;
        // @dev Combine the callers _extraOptions with the enforced options via the OAppOptionsType3.
        options = combineOptions(_sendParam.dstEid, msgType, _sendParam.extraOptions);

        // @dev Optionally inspect the message and options depending if the OApp owner has set a msg inspector.
        // @dev If it fails inspection, needs to revert in the implementation. ie. does not rely on return boolean
        if (msgInspector != address(0)) IOAppMsgInspector(msgInspector).inspect(message, options);
    }

    /**
     * @dev Internal function to handle the receive on the LayerZero endpoint.
     * @param _origin The origin information.
     *  - srcEid: The source chain endpoint ID.
     *  - sender: The sender address from the src chain.
     *  - nonce: The nonce of the LayerZero message.
     * @param _guid The unique identifier for the received LayerZero message.
     * @param _message The encoded message.
     * @dev _executor The address of the executor.
     * @dev _extraData Additional data.
     */
    function _lzReceive(
        Origin calldata _origin,
        bytes32 _guid,
        bytes calldata _message,
        address /*_executor*/, // @dev unused in the default implementation.
        bytes calldata /*_extraData*/ // @dev unused in the default implementation.
    ) internal virtual override {
        // @dev The src sending chain doesnt know the address length on this chain (potentially non-evm)
        // Thus everything is bytes32() encoded in flight.
        address toAddress = _message.sendTo().bytes32ToAddress();
        // @dev Credit the amountLD to the recipient and return the ACTUAL amount the recipient received in local decimals
        uint256 amountReceivedLD = _credit(toAddress, _toLD(_message.amountSD()), _origin.srcEid);

        if (_message.isComposed()) {
            // @dev Proprietary composeMsg format for the OFT.
            bytes memory composeMsg = OFTComposeMsgCodec.encode(
                _origin.nonce,
                _origin.srcEid,
                amountReceivedLD,
                _message.composeMsg()
            );

            // @dev Stores the lzCompose payload that will be executed in a separate tx.
            // Standardizes functionality for executing arbitrary contract invocation on some non-evm chains.
            // @dev The off-chain executor will listen and process the msg based on the src-chain-callers compose options passed.
            // @dev The index is used when a OApp needs to compose multiple msgs on lzReceive.
            // For default OFT implementation there is only 1 compose msg per lzReceive, thus its always 0.
            endpoint.sendCompose(toAddress, _guid, 0 /* the index of the composed message*/, composeMsg);
        }

        emit OFTReceived(_guid, _origin.srcEid, toAddress, amountReceivedLD);
    }

    /**
     * @dev Internal function to handle the OAppPreCrimeSimulator simulated receive.
     * @param _origin The origin information.
     *  - srcEid: The source chain endpoint ID.
     *  - sender: The sender address from the src chain.
     *  - nonce: The nonce of the LayerZero message.
     * @param _guid The unique identifier for the received LayerZero message.
     * @param _message The LayerZero message.
     * @param _executor The address of the off-chain executor.
     * @param _extraData Arbitrary data passed by the msg executor.
     *
     * @dev Enables the preCrime simulator to mock sending lzReceive() messages,
     * routes the msg down from the OAppPreCrimeSimulator, and back up to the OAppReceiver.
     */
    function _lzReceiveSimulate(
        Origin calldata _origin,
        bytes32 _guid,
        bytes calldata _message,
        address _executor,
        bytes calldata _extraData
    ) internal virtual override {
        _lzReceive(_origin, _guid, _message, _executor, _extraData);
    }

    /**
     * @dev Check if the peer is considered 'trusted' by the OApp.
     * @param _eid The endpoint ID to check.
     * @param _peer The peer to check.
     * @return Whether the peer passed is considered 'trusted' by the OApp.
     *
     * @dev Enables OAppPreCrimeSimulator to check whether a potential Inbound Packet is from a trusted source.
     */
    function isPeer(uint32 _eid, bytes32 _peer) public view virtual override returns (bool) {
        return peers[_eid] == _peer;
    }

    /**
     * @dev Internal function to remove dust from the given local decimal amount.
     * @param _amountLD The amount in local decimals.
     * @return amountLD The amount after removing dust.
     *
     * @dev Prevents the loss of dust when moving amounts between chains with different decimals.
     * @dev eg. uint(123) with a conversion rate of 100 becomes uint(100).
     */
    function _removeDust(uint256 _amountLD) internal view virtual returns (uint256 amountLD) {
        return (_amountLD / decimalConversionRate) * decimalConversionRate;
    }

    /**
     * @dev Internal function to convert an amount from shared decimals into local decimals.
     * @param _amountSD The amount in shared decimals.
     * @return amountLD The amount in local decimals.
     */
    function _toLD(uint64 _amountSD) internal view virtual returns (uint256 amountLD) {
        return _amountSD * decimalConversionRate;
    }

    /**
     * @dev Internal function to convert an amount from local decimals into shared decimals.
     * @param _amountLD The amount in local decimals.
     * @return amountSD The amount in shared decimals.
     */
    function _toSD(uint256 _amountLD) internal view virtual returns (uint64 amountSD) {
        return uint64(_amountLD / decimalConversionRate);
    }

    /**
     * @dev Internal function to mock the amount mutation from a OFT debit() operation.
     * @param _amountLD The amount to send in local decimals.
     * @param _minAmountLD The minimum amount to send in local decimals.
     * @dev _dstEid The destination endpoint ID.
     * @return amountSentLD The amount sent, in local decimals.
     * @return amountReceivedLD The amount to be received on the remote chain, in local decimals.
     *
     * @dev This is where things like fees would be calculated and deducted from the amount to be received on the remote.
     */
    function _debitView(
        uint256 _amountLD,
        uint256 _minAmountLD,
        uint32 /*_dstEid*/
    ) internal view virtual returns (uint256 amountSentLD, uint256 amountReceivedLD) {
        // @dev Remove the dust so nothing is lost on the conversion between chains with different decimals for the token.
        amountSentLD = _removeDust(_amountLD);
        // @dev The amount to send is the same as amount received in the default implementation.
        amountReceivedLD = amountSentLD;

        // @dev Check for slippage.
        if (amountReceivedLD < _minAmountLD) {
            revert SlippageExceeded(amountReceivedLD, _minAmountLD);
        }
    }

    /**
     * @dev Internal function to perform a debit operation.
     * @param _from The address to debit.
     * @param _amountLD The amount to send in local decimals.
     * @param _minAmountLD The minimum amount to send in local decimals.
     * @param _dstEid The destination endpoint ID.
     * @return amountSentLD The amount sent in local decimals.
     * @return amountReceivedLD The amount received in local decimals on the remote.
     *
     * @dev Defined here but are intended to be overriden depending on the OFT implementation.
     * @dev Depending on OFT implementation the _amountLD could differ from the amountReceivedLD.
     */
    function _debit(
        address _from,
        uint256 _amountLD,
        uint256 _minAmountLD,
        uint32 _dstEid
    ) internal virtual returns (uint256 amountSentLD, uint256 amountReceivedLD);

    /**
     * @dev Internal function to perform a credit operation.
     * @param _to The address to credit.
     * @param _amountLD The amount to credit in local decimals.
     * @param _srcEid The source endpoint ID.
     * @return amountReceivedLD The amount ACTUALLY received in local decimals.
     *
     * @dev Defined here but are intended to be overriden depending on the OFT implementation.
     * @dev Depending on OFT implementation the _amountLD could differ from the amountReceivedLD.
     */
    function _credit(
        address _to,
        uint256 _amountLD,
        uint32 _srcEid
    ) internal virtual returns (uint256 amountReceivedLD);
}


// File @openzeppelin/contracts/token/ERC20/extensions/[email protected]

// Original license: SPDX_License_Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface for the optional metadata functions from the ERC20 standard.
 *
 * _Available since v4.1._
 */
interface IERC20Metadata is IERC20 {
    /**
     * @dev Returns the name of the token.
     */
    function name() external view returns (string memory);

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

    /**
     * @dev Returns the decimals places of the token.
     */
    function decimals() external view returns (uint8);
}


// File @openzeppelin/contracts/token/ERC20/[email protected]

// Original license: SPDX_License_Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/ERC20.sol)

pragma solidity ^0.8.0;



/**
 * @dev Implementation of the {IERC20} interface.
 *
 * This implementation is agnostic to the way tokens are created. This means
 * that a supply mechanism has to be added in a derived contract using {_mint}.
 * For a generic mechanism see {ERC20PresetMinterPauser}.
 *
 * TIP: For a detailed writeup see our guide
 * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How
 * to implement supply mechanisms].
 *
 * We have followed general OpenZeppelin Contracts guidelines: functions revert
 * instead returning `false` on failure. This behavior is nonetheless
 * conventional and does not conflict with the expectations of ERC20
 * applications.
 *
 * Additionally, an {Approval} event is emitted on calls to {transferFrom}.
 * This allows applications to reconstruct the allowance for all accounts just
 * by listening to said events. Other implementations of the EIP may not emit
 * these events, as it isn't required by the specification.
 *
 * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}
 * functions have been added to mitigate the well-known issues around setting
 * allowances. See {IERC20-approve}.
 */
contract ERC20 is Context, IERC20, IERC20Metadata {
    mapping(address => uint256) private _balances;

    mapping(address => mapping(address => uint256)) private _allowances;

    uint256 private _totalSupply;

    string private _name;
    string private _symbol;

    /**
     * @dev Sets the values for {name} and {symbol}.
     *
     * The default value of {decimals} is 18. To select a different value for
     * {decimals} you should overload it.
     *
     * All two of these values are immutable: they can only be set once during
     * construction.
     */
    constructor(string memory name_, string memory symbol_) {
        _name = name_;
        _symbol = symbol_;
    }

    /**
     * @dev Returns the name of the token.
     */
    function name() public view virtual override returns (string memory) {
        return _name;
    }

    /**
     * @dev Returns the symbol of the token, usually a shorter version of the
     * name.
     */
    function symbol() public view virtual override returns (string memory) {
        return _symbol;
    }

    /**
     * @dev Returns the number of decimals used to get its user representation.
     * For example, if `decimals` equals `2`, a balance of `505` tokens should
     * be displayed to a user as `5.05` (`505 / 10 ** 2`).
     *
     * Tokens usually opt for a value of 18, imitating the relationship between
     * Ether and Wei. This is the value {ERC20} uses, unless this function is
     * overridden;
     *
     * NOTE: This information is only used for _display_ purposes: it in
     * no way affects any of the arithmetic of the contract, including
     * {IERC20-balanceOf} and {IERC20-transfer}.
     */
    function decimals() public view virtual override returns (uint8) {
        return 18;
    }

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

    /**
     * @dev See {IERC20-balanceOf}.
     */
    function balanceOf(address account) public view virtual override returns (uint256) {
        return _balances[account];
    }

    /**
     * @dev See {IERC20-transfer}.
     *
     * Requirements:
     *
     * - `to` cannot be the zero address.
     * - the caller must have a balance of at least `amount`.
     */
    function transfer(address to, uint256 amount) public virtual override returns (bool) {
        address owner = _msgSender();
        _transfer(owner, to, amount);
        return true;
    }

    /**
     * @dev See {IERC20-allowance}.
     */
    function allowance(address owner, address spender) public view virtual override returns (uint256) {
        return _allowances[owner][spender];
    }

    /**
     * @dev See {IERC20-approve}.
     *
     * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on
     * `transferFrom`. This is semantically equivalent to an infinite approval.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function approve(address spender, uint256 amount) public virtual override returns (bool) {
        address owner = _msgSender();
        _approve(owner, spender, amount);
        return true;
    }

    /**
     * @dev See {IERC20-transferFrom}.
     *
     * Emits an {Approval} event indicating the updated allowance. This is not
     * required by the EIP. See the note at the beginning of {ERC20}.
     *
     * NOTE: Does not update the allowance if the current allowance
     * is the maximum `uint256`.
     *
     * Requirements:
     *
     * - `from` and `to` cannot be the zero address.
     * - `from` must have a balance of at least `amount`.
     * - the caller must have allowance for ``from``'s tokens of at least
     * `amount`.
     */
    function transferFrom(
        address from,
        address to,
        uint256 amount
    ) public virtual override returns (bool) {
        address spender = _msgSender();
        _spendAllowance(from, spender, amount);
        _transfer(from, to, amount);
        return true;
    }

    /**
     * @dev Atomically increases the allowance granted to `spender` by the caller.
     *
     * This is an alternative to {approve} that can be used as a mitigation for
     * problems described in {IERC20-approve}.
     *
     * Emits an {Approval} event indicating the updated allowance.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
        address owner = _msgSender();
        _approve(owner, spender, allowance(owner, spender) + addedValue);
        return true;
    }

    /**
     * @dev Atomically decreases the allowance granted to `spender` by the caller.
     *
     * This is an alternative to {approve} that can be used as a mitigation for
     * problems described in {IERC20-approve}.
     *
     * Emits an {Approval} event indicating the updated allowance.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     * - `spender` must have allowance for the caller of at least
     * `subtractedValue`.
     */
    function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
        address owner = _msgSender();
        uint256 currentAllowance = allowance(owner, spender);
        require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero");
        unchecked {
            _approve(owner, spender, currentAllowance - subtractedValue);
        }

        return true;
    }

    /**
     * @dev Moves `amount` of tokens from `from` to `to`.
     *
     * This internal function is equivalent to {transfer}, and can be used to
     * e.g. implement automatic token fees, slashing mechanisms, etc.
     *
     * Emits a {Transfer} event.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `from` must have a balance of at least `amount`.
     */
    function _transfer(
        address from,
        address to,
        uint256 amount
    ) internal virtual {
        require(from != address(0), "ERC20: transfer from the zero address");
        require(to != address(0), "ERC20: transfer to the zero address");

        _beforeTokenTransfer(from, to, amount);

        uint256 fromBalance = _balances[from];
        require(fromBalance >= amount, "ERC20: transfer amount exceeds balance");
        unchecked {
            _balances[from] = fromBalance - amount;
            // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by
            // decrementing then incrementing.
            _balances[to] += amount;
        }

        emit Transfer(from, to, amount);

        _afterTokenTransfer(from, to, amount);
    }

    /** @dev Creates `amount` tokens and assigns them to `account`, increasing
     * the total supply.
     *
     * Emits a {Transfer} event with `from` set to the zero address.
     *
     * Requirements:
     *
     * - `account` cannot be the zero address.
     */
    function _mint(address account, uint256 amount) internal virtual {
        require(account != address(0), "ERC20: mint to the zero address");

        _beforeTokenTransfer(address(0), account, amount);

        _totalSupply += amount;
        unchecked {
            // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above.
            _balances[account] += amount;
        }
        emit Transfer(address(0), account, amount);

        _afterTokenTransfer(address(0), account, amount);
    }

    /**
     * @dev Destroys `amount` tokens from `account`, reducing the
     * total supply.
     *
     * Emits a {Transfer} event with `to` set to the zero address.
     *
     * Requirements:
     *
     * - `account` cannot be the zero address.
     * - `account` must have at least `amount` tokens.
     */
    function _burn(address account, uint256 amount) internal virtual {
        require(account != address(0), "ERC20: burn from the zero address");

        _beforeTokenTransfer(account, address(0), amount);

        uint256 accountBalance = _balances[account];
        require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
        unchecked {
            _balances[account] = accountBalance - amount;
            // Overflow not possible: amount <= accountBalance <= totalSupply.
            _totalSupply -= amount;
        }

        emit Transfer(account, address(0), amount);

        _afterTokenTransfer(account, address(0), amount);
    }

    /**
     * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.
     *
     * This internal function is equivalent to `approve`, and can be used to
     * e.g. set automatic allowances for certain subsystems, etc.
     *
     * Emits an {Approval} event.
     *
     * Requirements:
     *
     * - `owner` cannot be the zero address.
     * - `spender` cannot be the zero address.
     */
    function _approve(
        address owner,
        address spender,
        uint256 amount
    ) internal virtual {
        require(owner != address(0), "ERC20: approve from the zero address");
        require(spender != address(0), "ERC20: approve to the zero address");

        _allowances[owner][spender] = amount;
        emit Approval(owner, spender, amount);
    }

    /**
     * @dev Updates `owner` s allowance for `spender` based on spent `amount`.
     *
     * Does not update the allowance amount in case of infinite allowance.
     * Revert if not enough allowance is available.
     *
     * Might emit an {Approval} event.
     */
    function _spendAllowance(
        address owner,
        address spender,
        uint256 amount
    ) internal virtual {
        uint256 currentAllowance = allowance(owner, spender);
        if (currentAllowance != type(uint256).max) {
            require(currentAllowance >= amount, "ERC20: insufficient allowance");
            unchecked {
                _approve(owner, spender, currentAllowance - amount);
            }
        }
    }

    /**
     * @dev Hook that is called before any transfer of tokens. This includes
     * minting and burning.
     *
     * Calling conditions:
     *
     * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
     * will be transferred to `to`.
     * - when `from` is zero, `amount` tokens will be minted for `to`.
     * - when `to` is zero, `amount` of ``from``'s tokens will be burned.
     * - `from` and `to` are never both zero.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _beforeTokenTransfer(
        address from,
        address to,
        uint256 amount
    ) internal virtual {}

    /**
     * @dev Hook that is called after any transfer of tokens. This includes
     * minting and burning.
     *
     * Calling conditions:
     *
     * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
     * has been transferred to `to`.
     * - when `from` is zero, `amount` tokens have been minted for `to`.
     * - when `to` is zero, `amount` of ``from``'s tokens have been burned.
     * - `from` and `to` are never both zero.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _afterTokenTransfer(
        address from,
        address to,
        uint256 amount
    ) internal virtual {}
}


// File @layerzerolabs/lz-evm-oapp-v2/contracts/oft/[email protected]

// Original license: SPDX_License_Identifier: MIT

pragma solidity ^0.8.20;


/**
 * @title OFT Contract
 * @dev OFT is an ERC-20 token that extends the functionality of the OFTCore contract.
 */
abstract contract OFT is OFTCore, ERC20 {
    /**
     * @dev Constructor for the OFT contract.
     * @param _name The name of the OFT.
     * @param _symbol The symbol of the OFT.
     * @param _lzEndpoint The LayerZero endpoint address.
     * @param _delegate The delegate capable of making OApp configurations inside of the endpoint.
     */
    constructor(
        string memory _name,
        string memory _symbol,
        address _lzEndpoint,
        address _delegate
    ) ERC20(_name, _symbol) OFTCore(decimals(), _lzEndpoint, _delegate) {}

    /**
     * @dev Retrieves the address of the underlying ERC20 implementation.
     * @return The address of the OFT token.
     *
     * @dev In the case of OFT, address(this) and erc20 are the same contract.
     */
    function token() public view returns (address) {
        return address(this);
    }

    /**
     * @notice Indicates whether the OFT contract requires approval of the 'token()' to send.
     * @return requiresApproval Needs approval of the underlying token implementation.
     *
     * @dev In the case of OFT where the contract IS the token, approval is NOT required.
     */
    function approvalRequired() external pure virtual returns (bool) {
        return false;
    }

    /**
     * @dev Burns tokens from the sender's specified balance.
     * @param _from The address to debit the tokens from.
     * @param _amountLD The amount of tokens to send in local decimals.
     * @param _minAmountLD The minimum amount to send in local decimals.
     * @param _dstEid The destination chain ID.
     * @return amountSentLD The amount sent in local decimals.
     * @return amountReceivedLD The amount received in local decimals on the remote.
     */
    function _debit(
        address _from,
        uint256 _amountLD,
        uint256 _minAmountLD,
        uint32 _dstEid
    ) internal virtual override returns (uint256 amountSentLD, uint256 amountReceivedLD) {
        (amountSentLD, amountReceivedLD) = _debitView(_amountLD, _minAmountLD, _dstEid);

        // @dev In NON-default OFT, amountSentLD could be 100, with a 10% fee, the amountReceivedLD amount is 90,
        // therefore amountSentLD CAN differ from amountReceivedLD.

        // @dev Default OFT burns on src.
        _burn(_from, amountSentLD);
    }

    /**
     * @dev Credits tokens to the specified address.
     * @param _to The address to credit the tokens to.
     * @param _amountLD The amount of tokens to credit in local decimals.
     * @dev _srcEid The source chain ID.
     * @return amountReceivedLD The amount of tokens ACTUALLY received in local decimals.
     */
    function _credit(
        address _to,
        uint256 _amountLD,
        uint32 /*_srcEid*/
    ) internal virtual override returns (uint256 amountReceivedLD) {
        // @dev Default OFT mints on dst.
        _mint(_to, _amountLD);
        // @dev In the case of NON-default OFT, the _amountLD MIGHT not be == amountReceivedLD.
        return _amountLD;
    }
}


// File @openzeppelin/contracts/utils/[email protected]

// Original license: SPDX_License_Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Counters.sol)

pragma solidity ^0.8.0;

/**
 * @title Counters
 * @author Matt Condon (@shrugs)
 * @dev Provides counters that can only be incremented, decremented or reset. This can be used e.g. to track the number
 * of elements in a mapping, issuing ERC721 ids, or counting request ids.
 *
 * Include with `using Counters for Counters.Counter;`
 */
library Counters {
    struct Counter {
        // This variable should never be directly accessed by users of the library: interactions must be restricted to
        // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add
        // this feature: see https://github.com/ethereum/solidity/issues/4637
        uint256 _value; // default: 0
    }

    function current(Counter storage counter) internal view returns (uint256) {
        return counter._value;
    }

    function increment(Counter storage counter) internal {
        unchecked {
            counter._value += 1;
        }
    }

    function decrement(Counter storage counter) internal {
        uint256 value = counter._value;
        require(value > 0, "Counter: decrement overflow");
        unchecked {
            counter._value = value - 1;
        }
    }

    function reset(Counter storage counter) internal {
        counter._value = 0;
    }
}


// File @openzeppelin/contracts/utils/math/[email protected]

// Original license: SPDX_License_Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)

pragma solidity ^0.8.0;

/**
 * @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) {
                return prod0 / denominator;
            }

            // Make sure the result is less than 2^256. Also prevents denominator == 0.
            require(denominator > prod1);

            ///////////////////////////////////////////////
            // 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 10, 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 * 8) < value ? 1 : 0);
        }
    }
}


// File @openzeppelin/contracts/utils/[email protected]

// Original license: SPDX_License_Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)

pragma solidity ^0.8.0;

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


// File @openzeppelin/contracts/utils/cryptography/[email protected]

// Original license: SPDX_License_Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/ECDSA.sol)

pragma solidity ^0.8.0;

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

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

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

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

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

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

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

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

        return (signer, RecoverError.NoError);
    }

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

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

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

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


// File @openzeppelin/contracts/utils/cryptography/[email protected]

// Original license: SPDX_License_Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/EIP712.sol)

pragma solidity ^0.8.0;

/**
 * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.
 *
 * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,
 * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding
 * they need in their contracts using a combination of `abi.encode` and `keccak256`.
 *
 * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding
 * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA
 * ({_hashTypedDataV4}).
 *
 * The implementation of the domain separator was designed to be as efficient as possible while still properly updating
 * the chain id to protect against replay attacks on an eventual fork of the chain.
 *
 * NOTE: This contract implements the version of the encoding known as "v4", as implemented by the JSON RPC method
 * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].
 *
 * _Available since v3.4._
 */
abstract contract EIP712 {
    /* solhint-disable var-name-mixedcase */
    // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to
    // invalidate the cached domain separator if the chain id changes.
    bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;
    uint256 private immutable _CACHED_CHAIN_ID;
    address private immutable _CACHED_THIS;

    bytes32 private immutable _HASHED_NAME;
    bytes32 private immutable _HASHED_VERSION;
    bytes32 private immutable _TYPE_HASH;

    /* solhint-enable var-name-mixedcase */

    /**
     * @dev Initializes the domain separator and parameter caches.
     *
     * The meaning of `name` and `version` is specified in
     * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:
     *
     * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.
     * - `version`: the current major version of the signing domain.
     *
     * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart
     * contract upgrade].
     */
    constructor(string memory name, string memory version) {
        bytes32 hashedName = keccak256(bytes(name));
        bytes32 hashedVersion = keccak256(bytes(version));
        bytes32 typeHash = keccak256(
            "EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"
        );
        _HASHED_NAME = hashedName;
        _HASHED_VERSION = hashedVersion;
        _CACHED_CHAIN_ID = block.chainid;
        _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);
        _CACHED_THIS = address(this);
        _TYPE_HASH = typeHash;
    }

    /**
     * @dev Returns the domain separator for the current chain.
     */
    function _domainSeparatorV4() internal view returns (bytes32) {
        if (address(this) == _CACHED_THIS && block.chainid == _CACHED_CHAIN_ID) {
            return _CACHED_DOMAIN_SEPARATOR;
        } else {
            return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);
        }
    }

    function _buildDomainSeparator(
        bytes32 typeHash,
        bytes32 nameHash,
        bytes32 versionHash
    ) private view returns (bytes32) {
        return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this)));
    }

    /**
     * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this
     * function returns the hash of the fully encoded EIP712 message for this domain.
     *
     * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:
     *
     * ```solidity
     * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(
     *     keccak256("Mail(address to,string contents)"),
     *     mailTo,
     *     keccak256(bytes(mailContents))
     * )));
     * address signer = ECDSA.recover(digest, signature);
     * ```
     */
    function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {
        return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash);
    }
}


// File @openzeppelin/contracts/token/ERC20/extensions/[email protected]

// Original license: SPDX_License_Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/extensions/draft-ERC20Permit.sol)

pragma solidity ^0.8.0;





/**
 * @dev Implementation of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
 * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
 *
 * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
 * presenting a message signed by the account. By not relying on `{IERC20-approve}`, the token holder account doesn't
 * need to send a transaction, and thus is not required to hold Ether at all.
 *
 * _Available since v3.4._
 */
abstract contract ERC20Permit is ERC20, IERC20Permit, EIP712 {
    using Counters for Counters.Counter;

    mapping(address => Counters.Counter) private _nonces;

    // solhint-disable-next-line var-name-mixedcase
    bytes32 private constant _PERMIT_TYPEHASH =
        keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)");
    /**
     * @dev In previous versions `_PERMIT_TYPEHASH` was declared as `immutable`.
     * However, to ensure consistency with the upgradeable transpiler, we will continue
     * to reserve a slot.
     * @custom:oz-renamed-from _PERMIT_TYPEHASH
     */
    // solhint-disable-next-line var-name-mixedcase
    bytes32 private _PERMIT_TYPEHASH_DEPRECATED_SLOT;

    /**
     * @dev Initializes the {EIP712} domain separator using the `name` parameter, and setting `version` to `"1"`.
     *
     * It's a good idea to use the same `name` that is defined as the ERC20 token name.
     */
    constructor(string memory name) EIP712(name, "1") {}

    /**
     * @dev See {IERC20Permit-permit}.
     */
    function permit(
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) public virtual override {
        require(block.timestamp <= deadline, "ERC20Permit: expired deadline");

        bytes32 structHash = keccak256(abi.encode(_PERMIT_TYPEHASH, owner, spender, value, _useNonce(owner), deadline));

        bytes32 hash = _hashTypedDataV4(structHash);

        address signer = ECDSA.recover(hash, v, r, s);
        require(signer == owner, "ERC20Permit: invalid signature");

        _approve(owner, spender, value);
    }

    /**
     * @dev See {IERC20Permit-nonces}.
     */
    function nonces(address owner) public view virtual override returns (uint256) {
        return _nonces[owner].current();
    }

    /**
     * @dev See {IERC20Permit-DOMAIN_SEPARATOR}.
     */
    // solhint-disable-next-line func-name-mixedcase
    function DOMAIN_SEPARATOR() external view override returns (bytes32) {
        return _domainSeparatorV4();
    }

    /**
     * @dev "Consume a nonce": return the current value and increment.
     *
     * _Available since v4.1._
     */
    function _useNonce(address owner) internal virtual returns (uint256 current) {
        Counters.Counter storage nonce = _nonces[owner];
        current = nonce.current();
        nonce.increment();
    }
}


// File contracts/layerzero/OFTPermit.sol

// Original license: SPDX_License_Identifier: MIT
pragma solidity ^0.8.0;


contract OFTPermit is OFT, ERC20Permit {
    constructor(
        string memory _name,
        string memory _symbol,
        address _lzEndpoint,
        address _delegate
    )
        OFT(_name, _symbol, _lzEndpoint, _delegate)
        ERC20Permit(_name) // solhint-disable-next-line no-empty-blocks
    {}
}

Contract Security Audit

Contract ABI

API
[{"inputs":[{"internalType":"string","name":"_name","type":"string"},{"internalType":"string","name":"_symbol","type":"string"},{"internalType":"address","name":"_lzEndpoint","type":"address"},{"internalType":"address","name":"_delegate","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"InvalidDelegate","type":"error"},{"inputs":[],"name":"InvalidEndpointCall","type":"error"},{"inputs":[],"name":"InvalidLocalDecimals","type":"error"},{"inputs":[{"internalType":"bytes","name":"options","type":"bytes"}],"name":"InvalidOptions","type":"error"},{"inputs":[],"name":"LzTokenUnavailable","type":"error"},{"inputs":[{"internalType":"uint32","name":"eid","type":"uint32"}],"name":"NoPeer","type":"error"},{"inputs":[{"internalType":"uint256","name":"msgValue","type":"uint256"}],"name":"NotEnoughNative","type":"error"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"OnlyEndpoint","type":"error"},{"inputs":[{"internalType":"uint32","name":"eid","type":"uint32"},{"internalType":"bytes32","name":"sender","type":"bytes32"}],"name":"OnlyPeer","type":"error"},{"inputs":[],"name":"OnlySelf","type":"error"},{"inputs":[{"internalType":"bytes","name":"result","type":"bytes"}],"name":"SimulationResult","type":"error"},{"inputs":[{"internalType":"uint256","name":"amountLD","type":"uint256"},{"internalType":"uint256","name":"minAmountLD","type":"uint256"}],"name":"SlippageExceeded","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"components":[{"internalType":"uint32","name":"eid","type":"uint32"},{"internalType":"uint16","name":"msgType","type":"uint16"},{"internalType":"bytes","name":"options","type":"bytes"}],"indexed":false,"internalType":"struct EnforcedOptionParam[]","name":"_enforcedOptions","type":"tuple[]"}],"name":"EnforcedOptionSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"inspector","type":"address"}],"name":"MsgInspectorSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"guid","type":"bytes32"},{"indexed":false,"internalType":"uint32","name":"srcEid","type":"uint32"},{"indexed":true,"internalType":"address","name":"toAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountReceivedLD","type":"uint256"}],"name":"OFTReceived","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"guid","type":"bytes32"},{"indexed":false,"internalType":"uint32","name":"dstEid","type":"uint32"},{"indexed":true,"internalType":"address","name":"fromAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountSentLD","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountReceivedLD","type":"uint256"}],"name":"OFTSent","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"eid","type":"uint32"},{"indexed":false,"internalType":"bytes32","name":"peer","type":"bytes32"}],"name":"PeerSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"preCrimeAddress","type":"address"}],"name":"PreCrimeSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SEND","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SEND_AND_CALL","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint32","name":"srcEid","type":"uint32"},{"internalType":"bytes32","name":"sender","type":"bytes32"},{"internalType":"uint64","name":"nonce","type":"uint64"}],"internalType":"struct Origin","name":"origin","type":"tuple"}],"name":"allowInitializePath","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"approvalRequired","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"_eid","type":"uint32"},{"internalType":"uint16","name":"_msgType","type":"uint16"},{"internalType":"bytes","name":"_extraOptions","type":"bytes"}],"name":"combineOptions","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimalConversionRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"endpoint","outputs":[{"internalType":"contract ILayerZeroEndpointV2","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"eid","type":"uint32"},{"internalType":"uint16","name":"msgType","type":"uint16"}],"name":"enforcedOptions","outputs":[{"internalType":"bytes","name":"enforcedOption","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint32","name":"srcEid","type":"uint32"},{"internalType":"bytes32","name":"sender","type":"bytes32"},{"internalType":"uint64","name":"nonce","type":"uint64"}],"internalType":"struct Origin","name":"","type":"tuple"},{"internalType":"bytes","name":"","type":"bytes"},{"internalType":"address","name":"_sender","type":"address"}],"name":"isComposeMsgSender","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"_eid","type":"uint32"},{"internalType":"bytes32","name":"_peer","type":"bytes32"}],"name":"isPeer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint32","name":"srcEid","type":"uint32"},{"internalType":"bytes32","name":"sender","type":"bytes32"},{"internalType":"uint64","name":"nonce","type":"uint64"}],"internalType":"struct Origin","name":"_origin","type":"tuple"},{"internalType":"bytes32","name":"_guid","type":"bytes32"},{"internalType":"bytes","name":"_message","type":"bytes"},{"internalType":"address","name":"_executor","type":"address"},{"internalType":"bytes","name":"_extraData","type":"bytes"}],"name":"lzReceive","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"uint32","name":"srcEid","type":"uint32"},{"internalType":"bytes32","name":"sender","type":"bytes32"},{"internalType":"uint64","name":"nonce","type":"uint64"}],"internalType":"struct Origin","name":"origin","type":"tuple"},{"internalType":"uint32","name":"dstEid","type":"uint32"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"bytes32","name":"guid","type":"bytes32"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"address","name":"executor","type":"address"},{"internalType":"bytes","name":"message","type":"bytes"},{"internalType":"bytes","name":"extraData","type":"bytes"}],"internalType":"struct InboundPacket[]","name":"_packets","type":"tuple[]"}],"name":"lzReceiveAndRevert","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"uint32","name":"srcEid","type":"uint32"},{"internalType":"bytes32","name":"sender","type":"bytes32"},{"internalType":"uint64","name":"nonce","type":"uint64"}],"internalType":"struct Origin","name":"_origin","type":"tuple"},{"internalType":"bytes32","name":"_guid","type":"bytes32"},{"internalType":"bytes","name":"_message","type":"bytes"},{"internalType":"address","name":"_executor","type":"address"},{"internalType":"bytes","name":"_extraData","type":"bytes"}],"name":"lzReceiveSimulate","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"msgInspector","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"","type":"uint32"},{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"nextNonce","outputs":[{"internalType":"uint64","name":"nonce","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"oApp","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"oAppVersion","outputs":[{"internalType":"uint64","name":"senderVersion","type":"uint64"},{"internalType":"uint64","name":"receiverVersion","type":"uint64"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"oftVersion","outputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"},{"internalType":"uint64","name":"version","type":"uint64"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"eid","type":"uint32"}],"name":"peers","outputs":[{"internalType":"bytes32","name":"peer","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"permit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"preCrime","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint32","name":"dstEid","type":"uint32"},{"internalType":"bytes32","name":"to","type":"bytes32"},{"internalType":"uint256","name":"amountLD","type":"uint256"},{"internalType":"uint256","name":"minAmountLD","type":"uint256"},{"internalType":"bytes","name":"extraOptions","type":"bytes"},{"internalType":"bytes","name":"composeMsg","type":"bytes"},{"internalType":"bytes","name":"oftCmd","type":"bytes"}],"internalType":"struct SendParam","name":"_sendParam","type":"tuple"}],"name":"quoteOFT","outputs":[{"components":[{"internalType":"uint256","name":"minAmountLD","type":"uint256"},{"internalType":"uint256","name":"maxAmountLD","type":"uint256"}],"internalType":"struct OFTLimit","name":"oftLimit","type":"tuple"},{"components":[{"internalType":"int256","name":"feeAmountLD","type":"int256"},{"internalType":"string","name":"description","type":"string"}],"internalType":"struct OFTFeeDetail[]","name":"oftFeeDetails","type":"tuple[]"},{"components":[{"internalType":"uint256","name":"amountSentLD","type":"uint256"},{"internalType":"uint256","name":"amountReceivedLD","type":"uint256"}],"internalType":"struct OFTReceipt","name":"oftReceipt","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint32","name":"dstEid","type":"uint32"},{"internalType":"bytes32","name":"to","type":"bytes32"},{"internalType":"uint256","name":"amountLD","type":"uint256"},{"internalType":"uint256","name":"minAmountLD","type":"uint256"},{"internalType":"bytes","name":"extraOptions","type":"bytes"},{"internalType":"bytes","name":"composeMsg","type":"bytes"},{"internalType":"bytes","name":"oftCmd","type":"bytes"}],"internalType":"struct SendParam","name":"_sendParam","type":"tuple"},{"internalType":"bool","name":"_payInLzToken","type":"bool"}],"name":"quoteSend","outputs":[{"components":[{"internalType":"uint256","name":"nativeFee","type":"uint256"},{"internalType":"uint256","name":"lzTokenFee","type":"uint256"}],"internalType":"struct MessagingFee","name":"msgFee","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint32","name":"dstEid","type":"uint32"},{"internalType":"bytes32","name":"to","type":"bytes32"},{"internalType":"uint256","name":"amountLD","type":"uint256"},{"internalType":"uint256","name":"minAmountLD","type":"uint256"},{"internalType":"bytes","name":"extraOptions","type":"bytes"},{"internalType":"bytes","name":"composeMsg","type":"bytes"},{"internalType":"bytes","name":"oftCmd","type":"bytes"}],"internalType":"struct SendParam","name":"_sendParam","type":"tuple"},{"components":[{"internalType":"uint256","name":"nativeFee","type":"uint256"},{"internalType":"uint256","name":"lzTokenFee","type":"uint256"}],"internalType":"struct MessagingFee","name":"_fee","type":"tuple"},{"internalType":"address","name":"_refundAddress","type":"address"}],"name":"send","outputs":[{"components":[{"internalType":"bytes32","name":"guid","type":"bytes32"},{"internalType":"uint64","name":"nonce","type":"uint64"},{"components":[{"internalType":"uint256","name":"nativeFee","type":"uint256"},{"internalType":"uint256","name":"lzTokenFee","type":"uint256"}],"internalType":"struct MessagingFee","name":"fee","type":"tuple"}],"internalType":"struct MessagingReceipt","name":"msgReceipt","type":"tuple"},{"components":[{"internalType":"uint256","name":"amountSentLD","type":"uint256"},{"internalType":"uint256","name":"amountReceivedLD","type":"uint256"}],"internalType":"struct OFTReceipt","name":"oftReceipt","type":"tuple"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_delegate","type":"address"}],"name":"setDelegate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint32","name":"eid","type":"uint32"},{"internalType":"uint16","name":"msgType","type":"uint16"},{"internalType":"bytes","name":"options","type":"bytes"}],"internalType":"struct EnforcedOptionParam[]","name":"_enforcedOptions","type":"tuple[]"}],"name":"setEnforcedOptions","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_msgInspector","type":"address"}],"name":"setMsgInspector","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"_eid","type":"uint32"},{"internalType":"bytes32","name":"_peer","type":"bytes32"}],"name":"setPeer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_preCrime","type":"address"}],"name":"setPreCrime","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"sharedDecimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"token","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}]

6101806040523480156200001257600080fd5b506040516200424238038062004242833981016040819052620000359162000377565b8380604051806040016040528060018152602001603160f81b815250868686868383620000676200023860201b60201c565b84848181818162000078336200023d565b6001600160a01b038083166080528116620000a657604051632d618d8160e21b815260040160405180910390fd5b60805160405163ca5eb5e160e01b81526001600160a01b0383811660048301529091169063ca5eb5e190602401600060405180830381600087803b158015620000ee57600080fd5b505af115801562000103573d6000803e3d6000fd5b50505050505050506200011b6200028d60201b60201c565b60ff168360ff16101562000142576040516301e9714b60e41b815260040160405180910390fd5b6200014f6006846200041c565b6200015c90600a6200053b565b60a05250600891506200017290508382620005e4565b506009620001818282620005e4565b505086516020808901919091208751888301206101208290526101408190524660e0819052604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f8187018190528183018690526060820185905260808201939093523060a0808301919091528251808303909101815260c09091019091528051940193909320919750955090935091506200021c9050565b60c05230610100526101605250620006b0975050505050505050565b601290565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b600690565b634e487b7160e01b600052604160045260246000fd5b600082601f830112620002ba57600080fd5b81516001600160401b0380821115620002d757620002d762000292565b604051601f8301601f19908116603f0116810190828211818310171562000302576200030262000292565b81604052838152602092508660208588010111156200032057600080fd5b600091505b8382101562000344578582018301518183018401529082019062000325565b6000602085830101528094505050505092915050565b80516001600160a01b03811681146200037257600080fd5b919050565b600080600080608085870312156200038e57600080fd5b84516001600160401b0380821115620003a657600080fd5b620003b488838901620002a8565b95506020870151915080821115620003cb57600080fd5b50620003da87828801620002a8565b935050620003eb604086016200035a565b9150620003fb606086016200035a565b905092959194509250565b634e487b7160e01b600052601160045260246000fd5b60ff828116828216039081111562000438576200043862000406565b92915050565b600181815b808511156200047f57816000190482111562000463576200046362000406565b808516156200047157918102915b93841c939080029062000443565b509250929050565b600082620004985750600162000438565b81620004a75750600062000438565b8160018114620004c05760028114620004cb57620004eb565b600191505062000438565b60ff841115620004df57620004df62000406565b50506001821b62000438565b5060208310610133831016604e8410600b841016171562000510575081810a62000438565b6200051c83836200043e565b806000190482111562000533576200053362000406565b029392505050565b60006200054c60ff84168362000487565b9392505050565b600181811c908216806200056857607f821691505b6020821081036200058957634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115620005df576000816000526020600020601f850160051c81016020861015620005ba5750805b601f850160051c820191505b81811015620005db57828155600101620005c6565b5050505b505050565b81516001600160401b0381111562000600576200060062000292565b620006188162000611845462000553565b846200058f565b602080601f831160018114620006505760008415620006375750858301515b600019600386901b1c1916600185901b178555620005db565b600085815260208120601f198616915b82811015620006815788860151825594840194600190910190840162000660565b5085821015620006a05787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60805160a05160c05160e05161010051610120516101405161016051613ae66200075c6000396000611baa01526000611bf901526000611bd401526000611b2d01526000611b5701526000611b810152600081816106aa015281816121a20152818161221701526122e201526000818161054901528181610a330152818161121f0152818161177a01528181611d8101528181612028015281816124e1015261259a0152613ae66000f3fe6080604052600436106102885760003560e01c80637d25a05e1161015a578063bb0b6a53116100c1578063d42438851161007a578063d424388514610814578063d505accf14610834578063dd62ed3e14610854578063f2fde38b14610874578063fc0c546a146104cd578063ff7bd03d1461089457600080fd5b8063bb0b6a5314610760578063bc70b3541461078d578063bd815db0146107ad578063c7c7f5b3146107c0578063ca5eb5e1146107e1578063d045a0dc1461080157600080fd5b8063963efcaa11610113578063963efcaa146106985780639f68b964146106cc578063a457c2d7146106e0578063a9059cbb14610700578063b731ea0a14610720578063b98bd0701461074057600080fd5b80637d25a05e146105d65780637ecebe001461061157806382413eac14610631578063857749b0146106515780638da5cb5b1461066557806395d89b411461068357600080fd5b8063313ce567116101fe5780635535d461116101b75780635535d461146104e05780635a0dfe4d146105005780635e280f11146105375780636fc1b31e1461056b57806370a082311461058b578063715018a6146105c157600080fd5b8063313ce567146104295780633400288b1461044b5780633644e5151461046b57806339509351146104805780633b6f743b146104a057806352ae2879146104cd57600080fd5b8063134d4f2511610250578063134d4f2514610364578063156a0d0f1461038c57806317442b70146103b357806318160ddd146103d55780631f5e1334146103f457806323b872dd1461040957600080fd5b806306fdde031461028d578063095ea7b3146102b85780630d35b415146102e8578063111ecdad1461031757806313137d651461034f575b600080fd5b34801561029957600080fd5b506102a26108b4565b6040516102af9190612b4a565b60405180910390f35b3480156102c457600080fd5b506102d86102d3366004612b72565b610946565b60405190151581526020016102af565b3480156102f457600080fd5b50610308610303366004612bb0565b610960565b6040516102af93929190612be4565b34801561032357600080fd5b50600454610337906001600160a01b031681565b6040516001600160a01b0390911681526020016102af565b61036261035d366004612cd7565b610a31565b005b34801561037057600080fd5b50610379600281565b60405161ffff90911681526020016102af565b34801561039857600080fd5b506040805162b9270b60e21b815260016020820152016102af565b3480156103bf57600080fd5b50604080516001815260026020820152016102af565b3480156103e157600080fd5b506007545b6040519081526020016102af565b34801561040057600080fd5b50610379600181565b34801561041557600080fd5b506102d8610424366004612d76565b610af1565b34801561043557600080fd5b5060125b60405160ff90911681526020016102af565b34801561045757600080fd5b50610362610466366004612dd0565b610b17565b34801561047757600080fd5b506103e6610b2d565b34801561048c57600080fd5b506102d861049b366004612b72565b610b3c565b3480156104ac57600080fd5b506104c06104bb366004612dfa565b610b5e565b6040516102af9190612e4b565b3480156104d957600080fd5b5030610337565b3480156104ec57600080fd5b506102a26104fb366004612e74565b610bc5565b34801561050c57600080fd5b506102d861051b366004612dd0565b63ffffffff919091166000908152600160205260409020541490565b34801561054357600080fd5b506103377f000000000000000000000000000000000000000000000000000000000000000081565b34801561057757600080fd5b50610362610586366004612ea7565b610c6a565b34801561059757600080fd5b506103e66105a6366004612ea7565b6001600160a01b031660009081526005602052604090205490565b3480156105cd57600080fd5b50610362610cc7565b3480156105e257600080fd5b506105f96105f1366004612dd0565b600092915050565b6040516001600160401b0390911681526020016102af565b34801561061d57600080fd5b506103e661062c366004612ea7565b610cdb565b34801561063d57600080fd5b506102d861064c366004612ec4565b610cf9565b34801561065d57600080fd5b506006610439565b34801561067157600080fd5b506000546001600160a01b0316610337565b34801561068f57600080fd5b506102a2610d0e565b3480156106a457600080fd5b506103e67f000000000000000000000000000000000000000000000000000000000000000081565b3480156106d857600080fd5b5060006102d8565b3480156106ec57600080fd5b506102d86106fb366004612b72565b610d1d565b34801561070c57600080fd5b506102d861071b366004612b72565b610da3565b34801561072c57600080fd5b50600254610337906001600160a01b031681565b34801561074c57600080fd5b5061036261075b366004612f6e565b610db1565b34801561076c57600080fd5b506103e661077b366004612faf565b60016020526000908152604090205481565b34801561079957600080fd5b506102a26107a8366004612fca565b610dcb565b6103626107bb366004612f6e565b610f73565b6107d36107ce36600461302a565b6110fd565b6040516102af929190613097565b3480156107ed57600080fd5b506103626107fc366004612ea7565b6111f8565b61036261080f366004612cd7565b61127e565b34801561082057600080fd5b5061036261082f366004612ea7565b6112ad565b34801561084057600080fd5b5061036261084f3660046130e9565b611303565b34801561086057600080fd5b506103e661086f366004613160565b611467565b34801561088057600080fd5b5061036261088f366004612ea7565b611492565b3480156108a057600080fd5b506102d86108af36600461318e565b61150b565b6060600880546108c3906131aa565b80601f01602080910402602001604051908101604052809291908181526020018280546108ef906131aa565b801561093c5780601f106109115761010080835404028352916020019161093c565b820191906000526020600020905b81548152906001019060200180831161091f57829003601f168201915b5050505050905090565b600033610954818585611541565b60019150505b92915050565b60408051808201909152600080825260208201526060610993604051806040016040528060008152602001600081525090565b60408051808201825260008082526001600160401b036020808401829052845183815290810190945291955091826109ee565b6040805180820190915260008152606060208201528152602001906001900390816109c65790505b509350600080610a13604089013560608a0135610a0e60208c018c612faf565b611665565b60408051808201909152918252602082015296989597505050505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03163314610a81576040516391ac5e4f60e01b81523360048201526024015b60405180910390fd5b60208701803590610a9b90610a96908a612faf565b6116a9565b14610ad957610aad6020880188612faf565b60405163309afaf360e21b815263ffffffff909116600482015260208801356024820152604401610a78565b610ae8878787878787876116e5565b50505050505050565b600033610aff85828561184c565b610b0a8585856118c6565b60019150505b9392505050565b610b1f611a71565b610b298282611acb565b5050565b6000610b37611b20565b905090565b600033610954818585610b4f8383611467565b610b59919061320a565b611541565b60408051808201909152600080825260208201526000610b8e60408501356060860135610a0e6020880188612faf565b915050600080610b9e8684611c47565b9092509050610bbb610bb36020880188612faf565b838388611d6b565b9695505050505050565b600360209081526000928352604080842090915290825290208054610be9906131aa565b80601f0160208091040260200160405190810160405280929190818152602001828054610c15906131aa565b8015610c625780601f10610c3757610100808354040283529160200191610c62565b820191906000526020600020905b815481529060010190602001808311610c4557829003601f168201915b505050505081565b610c72611a71565b600480546001600160a01b0319166001600160a01b0383169081179091556040519081527ff0be4f1e87349231d80c36b33f9e8639658eeaf474014dee15a3e6a4d4414197906020015b60405180910390a150565b610ccf611a71565b610cd96000611e4c565b565b6001600160a01b0381166000908152600a602052604081205461095a565b6001600160a01b03811630145b949350505050565b6060600980546108c3906131aa565b60003381610d2b8286611467565b905083811015610d8b5760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b6064820152608401610a78565b610d988286868403611541565b506001949350505050565b6000336109548185856118c6565b610db9611a71565b610b29610dc682846132be565b611e9c565b63ffffffff8416600090815260036020908152604080832061ffff87168452909152812080546060929190610dff906131aa565b80601f0160208091040260200160405190810160405280929190818152602001828054610e2b906131aa565b8015610e785780601f10610e4d57610100808354040283529160200191610e78565b820191906000526020600020905b815481529060010190602001808311610e5b57829003601f168201915b505050505090508051600003610ec85783838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929450610d069350505050565b6000839003610ed8579050610d06565b60028310610f5657610f1f84848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611fa392505050565b80610f2d84600281886133d3565b604051602001610f3f939291906133fd565b604051602081830303815290604052915050610d06565b8383604051639a6d49cd60e01b8152600401610a7892919061344e565b60005b8181101561107c5736838383818110610f9157610f91613462565b9050602002810190610fa39190613478565b9050610fd6610fb56020830183612faf565b602083013563ffffffff919091166000908152600160205260409020541490565b610fe05750611074565b3063d045a0dc60c08301358360a0810135610fff610100830183613499565b611010610100890160e08a01612ea7565b61101e6101208a018a613499565b6040518963ffffffff1660e01b815260040161104097969594939291906134f4565b6000604051808303818588803b15801561105957600080fd5b505af115801561106d573d6000803e3d6000fd5b5050505050505b600101610f76565b50336001600160a01b0316638e9e70996040518163ffffffff1660e01b8152600401600060405180830381865afa1580156110bb573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526110e3919081019061357a565b604051638351eea760e01b8152600401610a789190612b4a565b611105612ab3565b604080518082019091526000808252602082015260008061113c33604089013560608a013561113760208c018c612faf565b611fcf565b9150915060008061114d8984611c47565b909250905061117961116260208b018b612faf565b8383611173368d90038d018d6135e7565b8b611ff5565b60408051808201909152858152602080820186905282519298509096503391907f85496b760a4b7f8d66384b9df21b381f5d1b1e79f229a47aaf4c232edc2fe59a906111c7908d018d612faf565b6040805163ffffffff909216825260208201899052810187905260600160405180910390a350505050935093915050565b611200611a71565b60405163ca5eb5e160e01b81526001600160a01b0382811660048301527f0000000000000000000000000000000000000000000000000000000000000000169063ca5eb5e190602401600060405180830381600087803b15801561126357600080fd5b505af1158015611277573d6000803e3d6000fd5b5050505050565b33301461129e5760405163029a949d60e31b815260040160405180910390fd5b610ae887878787878787610ad9565b6112b5611a71565b600280546001600160a01b0319166001600160a01b0383169081179091556040519081527fd48d879cef83a1c0bdda516f27b13ddb1b3f8bbac1c9e1511bb2a659c242776090602001610cbc565b834211156113535760405162461bcd60e51b815260206004820152601d60248201527f45524332305065726d69743a206578706972656420646561646c696e650000006044820152606401610a78565b60007f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c98888886113828c612100565b6040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810186905260e00160405160208183030381529060405280519060200120905060006113dd82612128565b905060006113ed82878787612176565b9050896001600160a01b0316816001600160a01b0316146114505760405162461bcd60e51b815260206004820152601e60248201527f45524332305065726d69743a20696e76616c6964207369676e617475726500006044820152606401610a78565b61145b8a8a8a611541565b50505050505050505050565b6001600160a01b03918216600090815260066020908152604080832093909416825291909152205490565b61149a611a71565b6001600160a01b0381166114ff5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610a78565b61150881611e4c565b50565b60006020820180359060019083906115239086612faf565b63ffffffff1681526020810191909152604001600020541492915050565b6001600160a01b0383166115a35760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b6064820152608401610a78565b6001600160a01b0382166116045760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b6064820152608401610a78565b6001600160a01b0383811660008181526006602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b6000806116718561219e565b9150819050838110156116a1576040516371c4efed60e01b81526004810182905260248101859052604401610a78565b935093915050565b63ffffffff81166000908152600160205260408120548061095a5760405163f6ff4fb760e01b815263ffffffff84166004820152602401610a78565b60006116f76116f487876121d5565b90565b905060006117238261171161170c8a8a6121ed565b612210565b61171e60208d018d612faf565b612245565b905060288611156117ea57600061176061174360608c0160408d01613619565b61175060208d018d612faf565b8461175b8c8c612259565b6122a4565b604051633e5ac80960e11b81529091506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690637cb59012906117b69086908d906000908790600401613636565b600060405180830381600087803b1580156117d057600080fd5b505af11580156117e4573d6000803e3d6000fd5b50505050505b6001600160a01b038216887fefed6d3500546b29533b128a29e3a94d70788727f0507505ac12eaf2e578fd9c61182360208d018d612faf565b6040805163ffffffff9092168252602082018690520160405180910390a3505050505050505050565b60006118588484611467565b905060001981146118c057818110156118b35760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610a78565b6118c08484848403611541565b50505050565b6001600160a01b03831661192a5760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b6064820152608401610a78565b6001600160a01b03821661198c5760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b6064820152608401610a78565b6001600160a01b03831660009081526005602052604090205481811015611a045760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b6064820152608401610a78565b6001600160a01b0380851660008181526005602052604080822086860390559286168082529083902080548601905591517fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90611a649086815260200190565b60405180910390a36118c0565b6000546001600160a01b03163314610cd95760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610a78565b63ffffffff8216600081815260016020908152604091829020849055815192835282018390527f238399d427b947898edb290f5ff0f9109849b1c3ba196a42e35f00c50a54b98b910160405180910390a15050565b6000306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016148015611b7957507f000000000000000000000000000000000000000000000000000000000000000046145b15611ba357507f000000000000000000000000000000000000000000000000000000000000000090565b50604080517f00000000000000000000000000000000000000000000000000000000000000006020808301919091527f0000000000000000000000000000000000000000000000000000000000000000828401527f000000000000000000000000000000000000000000000000000000000000000060608301524660808301523060a0808401919091528351808403909101815260c0909201909252805191012090565b6060806000611ca48560200135611c5d866122db565b611c6a60a0890189613499565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061230792505050565b9093509050600081611cb7576001611cba565b60025b9050611cda611ccc6020880188612faf565b826107a860808a018a613499565b6004549093506001600160a01b031615611d62576004805460405163043a78eb60e01b81526001600160a01b039091169163043a78eb91611d1f918891889101613667565b602060405180830381865afa158015611d3c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d60919061368c565b505b50509250929050565b60408051808201909152600080825260208201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663ddc28c586040518060a001604052808863ffffffff168152602001611dce896116a9565b8152602001878152602001868152602001851515815250306040518363ffffffff1660e01b8152600401611e039291906136a9565b6040805180830381865afa158015611e1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e439190613752565b95945050505050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60005b8151811015611f7357611ece828281518110611ebd57611ebd613462565b602002602001015160400151611fa3565b818181518110611ee057611ee0613462565b60200260200101516040015160036000848481518110611f0257611f02613462565b60200260200101516000015163ffffffff1663ffffffff1681526020019081526020016000206000848481518110611f3c57611f3c613462565b60200260200101516020015161ffff1661ffff1681526020019081526020016000209081611f6a91906137be565b50600101611e9f565b507fbe4864a8e820971c0247f5992e2da559595f7bf076a21cb5928d443d2a13b67481604051610cbc919061387d565b600281015161ffff8116600314610b295781604051639a6d49cd60e01b8152600401610a789190612b4a565b600080611fdd858585611665565b9092509050611fec8683612381565b94509492505050565b611ffd612ab3565b600061200c84600001516124b5565b6020850151909150156120265761202684602001516124dd565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632637a450826040518060a001604052808b63ffffffff1681526020016120768c6116a9565b81526020018a815260200189815260200160008960200151111515815250866040518463ffffffff1660e01b81526004016120b29291906136a9565b60806040518083038185885af11580156120d0573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052508101906120f59190613908565b979650505050505050565b6001600160a01b0381166000908152600a602052604090208054600181018255905b50919050565b600061095a612135611b20565b8360405161190160f01b6020820152602281018390526042810182905260009060620160405160208183030381529060405280519060200120905092915050565b6000806000612187878787876125bf565b9150915061219481612680565b5095945050505050565b60007f00000000000000000000000000000000000000000000000000000000000000006121cb8184613952565b61095a9190613974565b60006121e460208284866133d3565b610b109161398b565b60006121fd6028602084866133d3565b612206916139a9565b60c01c9392505050565b600061095a7f00000000000000000000000000000000000000000000000000000000000000006001600160401b038416613974565b600061225184846127ca565b509092915050565b606061226882602881866133d3565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929695505050505050565b6060848484846040516020016122bd94939291906139d9565b6040516020818303038152906040529050949350505050565b505050565b600061095a7f000000000000000000000000000000000000000000000000000000000000000083613952565b805160609015158061235057848460405160200161233c92919091825260c01b6001600160c01b031916602082015260280190565b604051602081830303815290604052612377565b848433856040516020016123679493929190613a28565b6040516020818303038152906040525b9150935093915050565b6001600160a01b0382166123e15760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b6064820152608401610a78565b6001600160a01b038216600090815260056020526040902054818110156124555760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b6064820152608401610a78565b6001600160a01b03831660008181526005602090815260408083208686039055600780548790039055518581529192917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a3505050565b60008134146124d9576040516304fb820960e51b8152346004820152602401610a78565b5090565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663e4fe1d946040518163ffffffff1660e01b8152600401602060405180830381865afa15801561253d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125619190613a6b565b90506001600160a01b03811661258a576040516329b99a9560e11b815260040160405180910390fd5b610b296001600160a01b038216337f00000000000000000000000000000000000000000000000000000000000000008561288b565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08311156125f65750600090506003611fec565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa15801561264a573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811661267357600060019250925050611fec565b9660009650945050505050565b600081600481111561269457612694613a88565b0361269c5750565b60018160048111156126b0576126b0613a88565b036126fd5760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e617475726500000000000000006044820152606401610a78565b600281600481111561271157612711613a88565b0361275e5760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606401610a78565b600381600481111561277257612772613a88565b036115085760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b6064820152608401610a78565b6001600160a01b0382166128205760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610a78565b8060076000828254612832919061320a565b90915550506001600160a01b0382166000818152600560209081526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35050565b604080516001600160a01b038581166024830152848116604483015260648083018590528351808403909101815260849092018352602080830180516001600160e01b03166323b872dd60e01b17905283518085019094528084527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564908401526118c0928792916000916129239185169084906129a0565b8051909150156122d65780806020019051810190612941919061368c565b6122d65760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610a78565b6060610d06848460008585600080866001600160a01b031685876040516129c79190613a9e565b60006040518083038185875af1925050503d8060008114612a04576040519150601f19603f3d011682016040523d82523d6000602084013e612a09565b606091505b50915091506120f58783838760608315612a84578251600003612a7d576001600160a01b0385163b612a7d5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610a78565b5081610d06565b610d068383815115612a995781518083602001fd5b8060405162461bcd60e51b8152600401610a789190612b4a565b60405180606001604052806000801916815260200160006001600160401b03168152602001612af5604051806040016040528060008152602001600081525090565b905290565b60005b83811015612b15578181015183820152602001612afd565b50506000910152565b60008151808452612b36816020860160208601612afa565b601f01601f19169290920160200192915050565b602081526000610b106020830184612b1e565b6001600160a01b038116811461150857600080fd5b60008060408385031215612b8557600080fd5b8235612b9081612b5d565b946020939093013593505050565b600060e0828403121561212257600080fd5b600060208284031215612bc257600080fd5b81356001600160401b03811115612bd857600080fd5b610d0684828501612b9e565b8351815260208085015190820152600060a08201604060a0604085015281865180845260c08601915060c08160051b8701019350602080890160005b83811015612c5f5788870360bf19018552815180518852830151838801879052612c4c87890182612b1e565b9750509382019390820190600101612c20565b50508751606088015250505060208501516080850152509050610d06565b60006060828403121561212257600080fd5b60008083601f840112612ca157600080fd5b5081356001600160401b03811115612cb857600080fd5b602083019150836020828501011115612cd057600080fd5b9250929050565b600080600080600080600060e0888a031215612cf257600080fd5b612cfc8989612c7d565b96506060880135955060808801356001600160401b0380821115612d1f57600080fd5b612d2b8b838c01612c8f565b909750955060a08a01359150612d4082612b5d565b90935060c08901359080821115612d5657600080fd5b50612d638a828b01612c8f565b989b979a50959850939692959293505050565b600080600060608486031215612d8b57600080fd5b8335612d9681612b5d565b92506020840135612da681612b5d565b929592945050506040919091013590565b803563ffffffff81168114612dcb57600080fd5b919050565b60008060408385031215612de357600080fd5b612b9083612db7565b801515811461150857600080fd5b60008060408385031215612e0d57600080fd5b82356001600160401b03811115612e2357600080fd5b612e2f85828601612b9e565b9250506020830135612e4081612dec565b809150509250929050565b81518152602080830151908201526040810161095a565b803561ffff81168114612dcb57600080fd5b60008060408385031215612e8757600080fd5b612e9083612db7565b9150612e9e60208401612e62565b90509250929050565b600060208284031215612eb957600080fd5b8135610b1081612b5d565b60008060008060a08587031215612eda57600080fd5b612ee48686612c7d565b935060608501356001600160401b03811115612eff57600080fd5b612f0b87828801612c8f565b9094509250506080850135612f1f81612b5d565b939692955090935050565b60008083601f840112612f3c57600080fd5b5081356001600160401b03811115612f5357600080fd5b6020830191508360208260051b8501011115612cd057600080fd5b60008060208385031215612f8157600080fd5b82356001600160401b03811115612f9757600080fd5b612fa385828601612f2a565b90969095509350505050565b600060208284031215612fc157600080fd5b610b1082612db7565b60008060008060608587031215612fe057600080fd5b612fe985612db7565b9350612ff760208601612e62565b925060408501356001600160401b0381111561301257600080fd5b61301e87828801612c8f565b95989497509550505050565b6000806000838503608081121561304057600080fd5b84356001600160401b0381111561305657600080fd5b61306287828801612b9e565b9450506040601f198201121561307757600080fd5b50602084019150606084013561308c81612b5d565b809150509250925092565b600060c082019050835182526001600160401b03602085015116602083015260408401516130d2604084018280518252602090810151910152565b5082516080830152602083015160a0830152610b10565b600080600080600080600060e0888a03121561310457600080fd5b873561310f81612b5d565b9650602088013561311f81612b5d565b95506040880135945060608801359350608088013560ff8116811461314357600080fd5b9699959850939692959460a0840135945060c09093013592915050565b6000806040838503121561317357600080fd5b823561317e81612b5d565b91506020830135612e4081612b5d565b6000606082840312156131a057600080fd5b610b108383612c7d565b600181811c908216806131be57607f821691505b60208210810361212257634e487b7160e01b600052602260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052601160045260246000fd5b8082018082111561095a5761095a6131f4565b604051606081016001600160401b038111828210171561323f5761323f6131de565b60405290565b604080519081016001600160401b038111828210171561323f5761323f6131de565b604051601f8201601f191681016001600160401b038111828210171561328f5761328f6131de565b604052919050565b60006001600160401b038211156132b0576132b06131de565b50601f01601f191660200190565b60006001600160401b03808411156132d8576132d86131de565b8360051b60206132e9818301613267565b86815291850191818101903684111561330157600080fd5b865b848110156133c75780358681111561331b5760008081fd5b8801606036829003121561332f5760008081fd5b61333761321d565b61334082612db7565b815261334d868301612e62565b86820152604080830135898111156133655760008081fd5b929092019136601f84011261337a5760008081fd5b823561338d61338882613297565b613267565b81815236898387010111156133a25760008081fd5b818986018a830137600091810189019190915290820152845250918301918301613303565b50979650505050505050565b600080858511156133e357600080fd5b838611156133f057600080fd5b5050820193919092039150565b6000845161340f818460208901612afa565b8201838582376000930192835250909392505050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b602081526000610d06602083018486613425565b634e487b7160e01b600052603260045260246000fd5b6000823561013e1983360301811261348f57600080fd5b9190910192915050565b6000808335601e198436030181126134b057600080fd5b8301803591506001600160401b038211156134ca57600080fd5b602001915036819003821315612cd057600080fd5b6001600160401b038116811461150857600080fd5b63ffffffff61350289612db7565b168152602088013560208201526000604089013561351f816134df565b6001600160401b03811660408401525087606083015260e0608083015261354a60e083018789613425565b6001600160a01b03861660a084015282810360c084015261356c818587613425565b9a9950505050505050505050565b60006020828403121561358c57600080fd5b81516001600160401b038111156135a257600080fd5b8201601f810184136135b357600080fd5b80516135c161338882613297565b8181528560208385010111156135d657600080fd5b611e43826020830160208601612afa565b6000604082840312156135f957600080fd5b613601613245565b82358152602083013560208201528091505092915050565b60006020828403121561362b57600080fd5b8135610b10816134df565b60018060a01b038516815283602082015261ffff83166040820152608060608201526000610bbb6080830184612b1e565b60408152600061367a6040830185612b1e565b8281036020840152611e438185612b1e565b60006020828403121561369e57600080fd5b8151610b1081612dec565b6040815263ffffffff8351166040820152602083015160608201526000604084015160a060808401526136df60e0840182612b1e565b90506060850151603f198483030160a08501526136fc8282612b1e565b60809690960151151560c08501525050506001600160a01b039190911660209091015290565b60006040828403121561373457600080fd5b61373c613245565b9050815181526020820151602082015292915050565b60006040828403121561376457600080fd5b610b108383613722565b601f8211156122d6576000816000526020600020601f850160051c810160208610156137975750805b601f850160051c820191505b818110156137b6578281556001016137a3565b505050505050565b81516001600160401b038111156137d7576137d76131de565b6137eb816137e584546131aa565b8461376e565b602080601f83116001811461382057600084156138085750858301515b600019600386901b1c1916600185901b1785556137b6565b600085815260208120601f198616915b8281101561384f57888601518255948401946001909101908401613830565b508582101561386d5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b600060208083018184528085518083526040925060408601915060408160051b87010184880160005b838110156138fa57888303603f190185528151805163ffffffff1684528781015161ffff168885015286015160608785018190526138e681860183612b1e565b9689019694505050908601906001016138a6565b509098975050505050505050565b60006080828403121561391a57600080fd5b61392261321d565b825181526020830151613934816134df565b60208201526139468460408501613722565b60408201529392505050565b60008261396f57634e487b7160e01b600052601260045260246000fd5b500490565b808202811582820484141761095a5761095a6131f4565b8035602083101561095a57600019602084900360031b1b1692915050565b6001600160c01b031981358181169160088510156139d15780818660080360031b1b83161692505b505092915050565b6001600160401b0360c01b8560c01b16815263ffffffff60e01b8460e01b16600882015282600c82015260008251613a1881602c850160208701612afa565b91909101602c0195945050505050565b8481526001600160401b0360c01b8460c01b16602082015282602882015260008251613a5b816048850160208701612afa565b9190910160480195945050505050565b600060208284031215613a7d57600080fd5b8151610b1081612b5d565b634e487b7160e01b600052602160045260246000fd5b6000825161348f818460208701612afa56fea264697066735822122015896e89c7b056e0c3d5861a0b299c70d4df5ed8f71f89fd49c054cc8b4280d264736f6c63430008160033000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000001a44076050125825900e736c501f859c50fe728c0000000000000000000000006727b22867e7ece399aa306f94d5521f59a59a12000000000000000000000000000000000000000000000000000000000000000b49534b524120544f4b454e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000349534b0000000000000000000000000000000000000000000000000000000000

Deployed Bytecode

0x6080604052600436106102885760003560e01c80637d25a05e1161015a578063bb0b6a53116100c1578063d42438851161007a578063d424388514610814578063d505accf14610834578063dd62ed3e14610854578063f2fde38b14610874578063fc0c546a146104cd578063ff7bd03d1461089457600080fd5b8063bb0b6a5314610760578063bc70b3541461078d578063bd815db0146107ad578063c7c7f5b3146107c0578063ca5eb5e1146107e1578063d045a0dc1461080157600080fd5b8063963efcaa11610113578063963efcaa146106985780639f68b964146106cc578063a457c2d7146106e0578063a9059cbb14610700578063b731ea0a14610720578063b98bd0701461074057600080fd5b80637d25a05e146105d65780637ecebe001461061157806382413eac14610631578063857749b0146106515780638da5cb5b1461066557806395d89b411461068357600080fd5b8063313ce567116101fe5780635535d461116101b75780635535d461146104e05780635a0dfe4d146105005780635e280f11146105375780636fc1b31e1461056b57806370a082311461058b578063715018a6146105c157600080fd5b8063313ce567146104295780633400288b1461044b5780633644e5151461046b57806339509351146104805780633b6f743b146104a057806352ae2879146104cd57600080fd5b8063134d4f2511610250578063134d4f2514610364578063156a0d0f1461038c57806317442b70146103b357806318160ddd146103d55780631f5e1334146103f457806323b872dd1461040957600080fd5b806306fdde031461028d578063095ea7b3146102b85780630d35b415146102e8578063111ecdad1461031757806313137d651461034f575b600080fd5b34801561029957600080fd5b506102a26108b4565b6040516102af9190612b4a565b60405180910390f35b3480156102c457600080fd5b506102d86102d3366004612b72565b610946565b60405190151581526020016102af565b3480156102f457600080fd5b50610308610303366004612bb0565b610960565b6040516102af93929190612be4565b34801561032357600080fd5b50600454610337906001600160a01b031681565b6040516001600160a01b0390911681526020016102af565b61036261035d366004612cd7565b610a31565b005b34801561037057600080fd5b50610379600281565b60405161ffff90911681526020016102af565b34801561039857600080fd5b506040805162b9270b60e21b815260016020820152016102af565b3480156103bf57600080fd5b50604080516001815260026020820152016102af565b3480156103e157600080fd5b506007545b6040519081526020016102af565b34801561040057600080fd5b50610379600181565b34801561041557600080fd5b506102d8610424366004612d76565b610af1565b34801561043557600080fd5b5060125b60405160ff90911681526020016102af565b34801561045757600080fd5b50610362610466366004612dd0565b610b17565b34801561047757600080fd5b506103e6610b2d565b34801561048c57600080fd5b506102d861049b366004612b72565b610b3c565b3480156104ac57600080fd5b506104c06104bb366004612dfa565b610b5e565b6040516102af9190612e4b565b3480156104d957600080fd5b5030610337565b3480156104ec57600080fd5b506102a26104fb366004612e74565b610bc5565b34801561050c57600080fd5b506102d861051b366004612dd0565b63ffffffff919091166000908152600160205260409020541490565b34801561054357600080fd5b506103377f0000000000000000000000001a44076050125825900e736c501f859c50fe728c81565b34801561057757600080fd5b50610362610586366004612ea7565b610c6a565b34801561059757600080fd5b506103e66105a6366004612ea7565b6001600160a01b031660009081526005602052604090205490565b3480156105cd57600080fd5b50610362610cc7565b3480156105e257600080fd5b506105f96105f1366004612dd0565b600092915050565b6040516001600160401b0390911681526020016102af565b34801561061d57600080fd5b506103e661062c366004612ea7565b610cdb565b34801561063d57600080fd5b506102d861064c366004612ec4565b610cf9565b34801561065d57600080fd5b506006610439565b34801561067157600080fd5b506000546001600160a01b0316610337565b34801561068f57600080fd5b506102a2610d0e565b3480156106a457600080fd5b506103e67f000000000000000000000000000000000000000000000000000000e8d4a5100081565b3480156106d857600080fd5b5060006102d8565b3480156106ec57600080fd5b506102d86106fb366004612b72565b610d1d565b34801561070c57600080fd5b506102d861071b366004612b72565b610da3565b34801561072c57600080fd5b50600254610337906001600160a01b031681565b34801561074c57600080fd5b5061036261075b366004612f6e565b610db1565b34801561076c57600080fd5b506103e661077b366004612faf565b60016020526000908152604090205481565b34801561079957600080fd5b506102a26107a8366004612fca565b610dcb565b6103626107bb366004612f6e565b610f73565b6107d36107ce36600461302a565b6110fd565b6040516102af929190613097565b3480156107ed57600080fd5b506103626107fc366004612ea7565b6111f8565b61036261080f366004612cd7565b61127e565b34801561082057600080fd5b5061036261082f366004612ea7565b6112ad565b34801561084057600080fd5b5061036261084f3660046130e9565b611303565b34801561086057600080fd5b506103e661086f366004613160565b611467565b34801561088057600080fd5b5061036261088f366004612ea7565b611492565b3480156108a057600080fd5b506102d86108af36600461318e565b61150b565b6060600880546108c3906131aa565b80601f01602080910402602001604051908101604052809291908181526020018280546108ef906131aa565b801561093c5780601f106109115761010080835404028352916020019161093c565b820191906000526020600020905b81548152906001019060200180831161091f57829003601f168201915b5050505050905090565b600033610954818585611541565b60019150505b92915050565b60408051808201909152600080825260208201526060610993604051806040016040528060008152602001600081525090565b60408051808201825260008082526001600160401b036020808401829052845183815290810190945291955091826109ee565b6040805180820190915260008152606060208201528152602001906001900390816109c65790505b509350600080610a13604089013560608a0135610a0e60208c018c612faf565b611665565b60408051808201909152918252602082015296989597505050505050565b7f0000000000000000000000001a44076050125825900e736c501f859c50fe728c6001600160a01b03163314610a81576040516391ac5e4f60e01b81523360048201526024015b60405180910390fd5b60208701803590610a9b90610a96908a612faf565b6116a9565b14610ad957610aad6020880188612faf565b60405163309afaf360e21b815263ffffffff909116600482015260208801356024820152604401610a78565b610ae8878787878787876116e5565b50505050505050565b600033610aff85828561184c565b610b0a8585856118c6565b60019150505b9392505050565b610b1f611a71565b610b298282611acb565b5050565b6000610b37611b20565b905090565b600033610954818585610b4f8383611467565b610b59919061320a565b611541565b60408051808201909152600080825260208201526000610b8e60408501356060860135610a0e6020880188612faf565b915050600080610b9e8684611c47565b9092509050610bbb610bb36020880188612faf565b838388611d6b565b9695505050505050565b600360209081526000928352604080842090915290825290208054610be9906131aa565b80601f0160208091040260200160405190810160405280929190818152602001828054610c15906131aa565b8015610c625780601f10610c3757610100808354040283529160200191610c62565b820191906000526020600020905b815481529060010190602001808311610c4557829003601f168201915b505050505081565b610c72611a71565b600480546001600160a01b0319166001600160a01b0383169081179091556040519081527ff0be4f1e87349231d80c36b33f9e8639658eeaf474014dee15a3e6a4d4414197906020015b60405180910390a150565b610ccf611a71565b610cd96000611e4c565b565b6001600160a01b0381166000908152600a602052604081205461095a565b6001600160a01b03811630145b949350505050565b6060600980546108c3906131aa565b60003381610d2b8286611467565b905083811015610d8b5760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b6064820152608401610a78565b610d988286868403611541565b506001949350505050565b6000336109548185856118c6565b610db9611a71565b610b29610dc682846132be565b611e9c565b63ffffffff8416600090815260036020908152604080832061ffff87168452909152812080546060929190610dff906131aa565b80601f0160208091040260200160405190810160405280929190818152602001828054610e2b906131aa565b8015610e785780601f10610e4d57610100808354040283529160200191610e78565b820191906000526020600020905b815481529060010190602001808311610e5b57829003601f168201915b505050505090508051600003610ec85783838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929450610d069350505050565b6000839003610ed8579050610d06565b60028310610f5657610f1f84848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611fa392505050565b80610f2d84600281886133d3565b604051602001610f3f939291906133fd565b604051602081830303815290604052915050610d06565b8383604051639a6d49cd60e01b8152600401610a7892919061344e565b60005b8181101561107c5736838383818110610f9157610f91613462565b9050602002810190610fa39190613478565b9050610fd6610fb56020830183612faf565b602083013563ffffffff919091166000908152600160205260409020541490565b610fe05750611074565b3063d045a0dc60c08301358360a0810135610fff610100830183613499565b611010610100890160e08a01612ea7565b61101e6101208a018a613499565b6040518963ffffffff1660e01b815260040161104097969594939291906134f4565b6000604051808303818588803b15801561105957600080fd5b505af115801561106d573d6000803e3d6000fd5b5050505050505b600101610f76565b50336001600160a01b0316638e9e70996040518163ffffffff1660e01b8152600401600060405180830381865afa1580156110bb573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526110e3919081019061357a565b604051638351eea760e01b8152600401610a789190612b4a565b611105612ab3565b604080518082019091526000808252602082015260008061113c33604089013560608a013561113760208c018c612faf565b611fcf565b9150915060008061114d8984611c47565b909250905061117961116260208b018b612faf565b8383611173368d90038d018d6135e7565b8b611ff5565b60408051808201909152858152602080820186905282519298509096503391907f85496b760a4b7f8d66384b9df21b381f5d1b1e79f229a47aaf4c232edc2fe59a906111c7908d018d612faf565b6040805163ffffffff909216825260208201899052810187905260600160405180910390a350505050935093915050565b611200611a71565b60405163ca5eb5e160e01b81526001600160a01b0382811660048301527f0000000000000000000000001a44076050125825900e736c501f859c50fe728c169063ca5eb5e190602401600060405180830381600087803b15801561126357600080fd5b505af1158015611277573d6000803e3d6000fd5b5050505050565b33301461129e5760405163029a949d60e31b815260040160405180910390fd5b610ae887878787878787610ad9565b6112b5611a71565b600280546001600160a01b0319166001600160a01b0383169081179091556040519081527fd48d879cef83a1c0bdda516f27b13ddb1b3f8bbac1c9e1511bb2a659c242776090602001610cbc565b834211156113535760405162461bcd60e51b815260206004820152601d60248201527f45524332305065726d69743a206578706972656420646561646c696e650000006044820152606401610a78565b60007f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c98888886113828c612100565b6040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810186905260e00160405160208183030381529060405280519060200120905060006113dd82612128565b905060006113ed82878787612176565b9050896001600160a01b0316816001600160a01b0316146114505760405162461bcd60e51b815260206004820152601e60248201527f45524332305065726d69743a20696e76616c6964207369676e617475726500006044820152606401610a78565b61145b8a8a8a611541565b50505050505050505050565b6001600160a01b03918216600090815260066020908152604080832093909416825291909152205490565b61149a611a71565b6001600160a01b0381166114ff5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610a78565b61150881611e4c565b50565b60006020820180359060019083906115239086612faf565b63ffffffff1681526020810191909152604001600020541492915050565b6001600160a01b0383166115a35760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b6064820152608401610a78565b6001600160a01b0382166116045760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b6064820152608401610a78565b6001600160a01b0383811660008181526006602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b6000806116718561219e565b9150819050838110156116a1576040516371c4efed60e01b81526004810182905260248101859052604401610a78565b935093915050565b63ffffffff81166000908152600160205260408120548061095a5760405163f6ff4fb760e01b815263ffffffff84166004820152602401610a78565b60006116f76116f487876121d5565b90565b905060006117238261171161170c8a8a6121ed565b612210565b61171e60208d018d612faf565b612245565b905060288611156117ea57600061176061174360608c0160408d01613619565b61175060208d018d612faf565b8461175b8c8c612259565b6122a4565b604051633e5ac80960e11b81529091506001600160a01b037f0000000000000000000000001a44076050125825900e736c501f859c50fe728c1690637cb59012906117b69086908d906000908790600401613636565b600060405180830381600087803b1580156117d057600080fd5b505af11580156117e4573d6000803e3d6000fd5b50505050505b6001600160a01b038216887fefed6d3500546b29533b128a29e3a94d70788727f0507505ac12eaf2e578fd9c61182360208d018d612faf565b6040805163ffffffff9092168252602082018690520160405180910390a3505050505050505050565b60006118588484611467565b905060001981146118c057818110156118b35760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610a78565b6118c08484848403611541565b50505050565b6001600160a01b03831661192a5760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b6064820152608401610a78565b6001600160a01b03821661198c5760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b6064820152608401610a78565b6001600160a01b03831660009081526005602052604090205481811015611a045760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b6064820152608401610a78565b6001600160a01b0380851660008181526005602052604080822086860390559286168082529083902080548601905591517fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90611a649086815260200190565b60405180910390a36118c0565b6000546001600160a01b03163314610cd95760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610a78565b63ffffffff8216600081815260016020908152604091829020849055815192835282018390527f238399d427b947898edb290f5ff0f9109849b1c3ba196a42e35f00c50a54b98b910160405180910390a15050565b6000306001600160a01b037f000000000000000000000000d85eff20288ca72ea9eecffb428f89ee5066ca5c16148015611b7957507f000000000000000000000000000000000000000000000000000000000000210546145b15611ba357507f3617d3f500816717cf7bbb32bb1efe12246c58dd15d18eea0dd2a83bf167c9d990565b50604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6020808301919091527fecd5ed41eb2e5866afa63691692e0dfd3f5a652ccd4c4ab0028fecc2ce0bb9a2828401527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608301524660808301523060a0808401919091528351808403909101815260c0909201909252805191012090565b6060806000611ca48560200135611c5d866122db565b611c6a60a0890189613499565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061230792505050565b9093509050600081611cb7576001611cba565b60025b9050611cda611ccc6020880188612faf565b826107a860808a018a613499565b6004549093506001600160a01b031615611d62576004805460405163043a78eb60e01b81526001600160a01b039091169163043a78eb91611d1f918891889101613667565b602060405180830381865afa158015611d3c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d60919061368c565b505b50509250929050565b60408051808201909152600080825260208201527f0000000000000000000000001a44076050125825900e736c501f859c50fe728c6001600160a01b031663ddc28c586040518060a001604052808863ffffffff168152602001611dce896116a9565b8152602001878152602001868152602001851515815250306040518363ffffffff1660e01b8152600401611e039291906136a9565b6040805180830381865afa158015611e1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e439190613752565b95945050505050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60005b8151811015611f7357611ece828281518110611ebd57611ebd613462565b602002602001015160400151611fa3565b818181518110611ee057611ee0613462565b60200260200101516040015160036000848481518110611f0257611f02613462565b60200260200101516000015163ffffffff1663ffffffff1681526020019081526020016000206000848481518110611f3c57611f3c613462565b60200260200101516020015161ffff1661ffff1681526020019081526020016000209081611f6a91906137be565b50600101611e9f565b507fbe4864a8e820971c0247f5992e2da559595f7bf076a21cb5928d443d2a13b67481604051610cbc919061387d565b600281015161ffff8116600314610b295781604051639a6d49cd60e01b8152600401610a789190612b4a565b600080611fdd858585611665565b9092509050611fec8683612381565b94509492505050565b611ffd612ab3565b600061200c84600001516124b5565b6020850151909150156120265761202684602001516124dd565b7f0000000000000000000000001a44076050125825900e736c501f859c50fe728c6001600160a01b0316632637a450826040518060a001604052808b63ffffffff1681526020016120768c6116a9565b81526020018a815260200189815260200160008960200151111515815250866040518463ffffffff1660e01b81526004016120b29291906136a9565b60806040518083038185885af11580156120d0573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052508101906120f59190613908565b979650505050505050565b6001600160a01b0381166000908152600a602052604090208054600181018255905b50919050565b600061095a612135611b20565b8360405161190160f01b6020820152602281018390526042810182905260009060620160405160208183030381529060405280519060200120905092915050565b6000806000612187878787876125bf565b9150915061219481612680565b5095945050505050565b60007f000000000000000000000000000000000000000000000000000000e8d4a510006121cb8184613952565b61095a9190613974565b60006121e460208284866133d3565b610b109161398b565b60006121fd6028602084866133d3565b612206916139a9565b60c01c9392505050565b600061095a7f000000000000000000000000000000000000000000000000000000e8d4a510006001600160401b038416613974565b600061225184846127ca565b509092915050565b606061226882602881866133d3565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929695505050505050565b6060848484846040516020016122bd94939291906139d9565b6040516020818303038152906040529050949350505050565b505050565b600061095a7f000000000000000000000000000000000000000000000000000000e8d4a5100083613952565b805160609015158061235057848460405160200161233c92919091825260c01b6001600160c01b031916602082015260280190565b604051602081830303815290604052612377565b848433856040516020016123679493929190613a28565b6040516020818303038152906040525b9150935093915050565b6001600160a01b0382166123e15760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b6064820152608401610a78565b6001600160a01b038216600090815260056020526040902054818110156124555760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b6064820152608401610a78565b6001600160a01b03831660008181526005602090815260408083208686039055600780548790039055518581529192917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a3505050565b60008134146124d9576040516304fb820960e51b8152346004820152602401610a78565b5090565b60007f0000000000000000000000001a44076050125825900e736c501f859c50fe728c6001600160a01b031663e4fe1d946040518163ffffffff1660e01b8152600401602060405180830381865afa15801561253d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125619190613a6b565b90506001600160a01b03811661258a576040516329b99a9560e11b815260040160405180910390fd5b610b296001600160a01b038216337f0000000000000000000000001a44076050125825900e736c501f859c50fe728c8561288b565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08311156125f65750600090506003611fec565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa15801561264a573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811661267357600060019250925050611fec565b9660009650945050505050565b600081600481111561269457612694613a88565b0361269c5750565b60018160048111156126b0576126b0613a88565b036126fd5760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e617475726500000000000000006044820152606401610a78565b600281600481111561271157612711613a88565b0361275e5760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606401610a78565b600381600481111561277257612772613a88565b036115085760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b6064820152608401610a78565b6001600160a01b0382166128205760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610a78565b8060076000828254612832919061320a565b90915550506001600160a01b0382166000818152600560209081526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35050565b604080516001600160a01b038581166024830152848116604483015260648083018590528351808403909101815260849092018352602080830180516001600160e01b03166323b872dd60e01b17905283518085019094528084527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564908401526118c0928792916000916129239185169084906129a0565b8051909150156122d65780806020019051810190612941919061368c565b6122d65760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610a78565b6060610d06848460008585600080866001600160a01b031685876040516129c79190613a9e565b60006040518083038185875af1925050503d8060008114612a04576040519150601f19603f3d011682016040523d82523d6000602084013e612a09565b606091505b50915091506120f58783838760608315612a84578251600003612a7d576001600160a01b0385163b612a7d5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610a78565b5081610d06565b610d068383815115612a995781518083602001fd5b8060405162461bcd60e51b8152600401610a789190612b4a565b60405180606001604052806000801916815260200160006001600160401b03168152602001612af5604051806040016040528060008152602001600081525090565b905290565b60005b83811015612b15578181015183820152602001612afd565b50506000910152565b60008151808452612b36816020860160208601612afa565b601f01601f19169290920160200192915050565b602081526000610b106020830184612b1e565b6001600160a01b038116811461150857600080fd5b60008060408385031215612b8557600080fd5b8235612b9081612b5d565b946020939093013593505050565b600060e0828403121561212257600080fd5b600060208284031215612bc257600080fd5b81356001600160401b03811115612bd857600080fd5b610d0684828501612b9e565b8351815260208085015190820152600060a08201604060a0604085015281865180845260c08601915060c08160051b8701019350602080890160005b83811015612c5f5788870360bf19018552815180518852830151838801879052612c4c87890182612b1e565b9750509382019390820190600101612c20565b50508751606088015250505060208501516080850152509050610d06565b60006060828403121561212257600080fd5b60008083601f840112612ca157600080fd5b5081356001600160401b03811115612cb857600080fd5b602083019150836020828501011115612cd057600080fd5b9250929050565b600080600080600080600060e0888a031215612cf257600080fd5b612cfc8989612c7d565b96506060880135955060808801356001600160401b0380821115612d1f57600080fd5b612d2b8b838c01612c8f565b909750955060a08a01359150612d4082612b5d565b90935060c08901359080821115612d5657600080fd5b50612d638a828b01612c8f565b989b979a50959850939692959293505050565b600080600060608486031215612d8b57600080fd5b8335612d9681612b5d565b92506020840135612da681612b5d565b929592945050506040919091013590565b803563ffffffff81168114612dcb57600080fd5b919050565b60008060408385031215612de357600080fd5b612b9083612db7565b801515811461150857600080fd5b60008060408385031215612e0d57600080fd5b82356001600160401b03811115612e2357600080fd5b612e2f85828601612b9e565b9250506020830135612e4081612dec565b809150509250929050565b81518152602080830151908201526040810161095a565b803561ffff81168114612dcb57600080fd5b60008060408385031215612e8757600080fd5b612e9083612db7565b9150612e9e60208401612e62565b90509250929050565b600060208284031215612eb957600080fd5b8135610b1081612b5d565b60008060008060a08587031215612eda57600080fd5b612ee48686612c7d565b935060608501356001600160401b03811115612eff57600080fd5b612f0b87828801612c8f565b9094509250506080850135612f1f81612b5d565b939692955090935050565b60008083601f840112612f3c57600080fd5b5081356001600160401b03811115612f5357600080fd5b6020830191508360208260051b8501011115612cd057600080fd5b60008060208385031215612f8157600080fd5b82356001600160401b03811115612f9757600080fd5b612fa385828601612f2a565b90969095509350505050565b600060208284031215612fc157600080fd5b610b1082612db7565b60008060008060608587031215612fe057600080fd5b612fe985612db7565b9350612ff760208601612e62565b925060408501356001600160401b0381111561301257600080fd5b61301e87828801612c8f565b95989497509550505050565b6000806000838503608081121561304057600080fd5b84356001600160401b0381111561305657600080fd5b61306287828801612b9e565b9450506040601f198201121561307757600080fd5b50602084019150606084013561308c81612b5d565b809150509250925092565b600060c082019050835182526001600160401b03602085015116602083015260408401516130d2604084018280518252602090810151910152565b5082516080830152602083015160a0830152610b10565b600080600080600080600060e0888a03121561310457600080fd5b873561310f81612b5d565b9650602088013561311f81612b5d565b95506040880135945060608801359350608088013560ff8116811461314357600080fd5b9699959850939692959460a0840135945060c09093013592915050565b6000806040838503121561317357600080fd5b823561317e81612b5d565b91506020830135612e4081612b5d565b6000606082840312156131a057600080fd5b610b108383612c7d565b600181811c908216806131be57607f821691505b60208210810361212257634e487b7160e01b600052602260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052601160045260246000fd5b8082018082111561095a5761095a6131f4565b604051606081016001600160401b038111828210171561323f5761323f6131de565b60405290565b604080519081016001600160401b038111828210171561323f5761323f6131de565b604051601f8201601f191681016001600160401b038111828210171561328f5761328f6131de565b604052919050565b60006001600160401b038211156132b0576132b06131de565b50601f01601f191660200190565b60006001600160401b03808411156132d8576132d86131de565b8360051b60206132e9818301613267565b86815291850191818101903684111561330157600080fd5b865b848110156133c75780358681111561331b5760008081fd5b8801606036829003121561332f5760008081fd5b61333761321d565b61334082612db7565b815261334d868301612e62565b86820152604080830135898111156133655760008081fd5b929092019136601f84011261337a5760008081fd5b823561338d61338882613297565b613267565b81815236898387010111156133a25760008081fd5b818986018a830137600091810189019190915290820152845250918301918301613303565b50979650505050505050565b600080858511156133e357600080fd5b838611156133f057600080fd5b5050820193919092039150565b6000845161340f818460208901612afa565b8201838582376000930192835250909392505050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b602081526000610d06602083018486613425565b634e487b7160e01b600052603260045260246000fd5b6000823561013e1983360301811261348f57600080fd5b9190910192915050565b6000808335601e198436030181126134b057600080fd5b8301803591506001600160401b038211156134ca57600080fd5b602001915036819003821315612cd057600080fd5b6001600160401b038116811461150857600080fd5b63ffffffff61350289612db7565b168152602088013560208201526000604089013561351f816134df565b6001600160401b03811660408401525087606083015260e0608083015261354a60e083018789613425565b6001600160a01b03861660a084015282810360c084015261356c818587613425565b9a9950505050505050505050565b60006020828403121561358c57600080fd5b81516001600160401b038111156135a257600080fd5b8201601f810184136135b357600080fd5b80516135c161338882613297565b8181528560208385010111156135d657600080fd5b611e43826020830160208601612afa565b6000604082840312156135f957600080fd5b613601613245565b82358152602083013560208201528091505092915050565b60006020828403121561362b57600080fd5b8135610b10816134df565b60018060a01b038516815283602082015261ffff83166040820152608060608201526000610bbb6080830184612b1e565b60408152600061367a6040830185612b1e565b8281036020840152611e438185612b1e565b60006020828403121561369e57600080fd5b8151610b1081612dec565b6040815263ffffffff8351166040820152602083015160608201526000604084015160a060808401526136df60e0840182612b1e565b90506060850151603f198483030160a08501526136fc8282612b1e565b60809690960151151560c08501525050506001600160a01b039190911660209091015290565b60006040828403121561373457600080fd5b61373c613245565b9050815181526020820151602082015292915050565b60006040828403121561376457600080fd5b610b108383613722565b601f8211156122d6576000816000526020600020601f850160051c810160208610156137975750805b601f850160051c820191505b818110156137b6578281556001016137a3565b505050505050565b81516001600160401b038111156137d7576137d76131de565b6137eb816137e584546131aa565b8461376e565b602080601f83116001811461382057600084156138085750858301515b600019600386901b1c1916600185901b1785556137b6565b600085815260208120601f198616915b8281101561384f57888601518255948401946001909101908401613830565b508582101561386d5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b600060208083018184528085518083526040925060408601915060408160051b87010184880160005b838110156138fa57888303603f190185528151805163ffffffff1684528781015161ffff168885015286015160608785018190526138e681860183612b1e565b9689019694505050908601906001016138a6565b509098975050505050505050565b60006080828403121561391a57600080fd5b61392261321d565b825181526020830151613934816134df565b60208201526139468460408501613722565b60408201529392505050565b60008261396f57634e487b7160e01b600052601260045260246000fd5b500490565b808202811582820484141761095a5761095a6131f4565b8035602083101561095a57600019602084900360031b1b1692915050565b6001600160c01b031981358181169160088510156139d15780818660080360031b1b83161692505b505092915050565b6001600160401b0360c01b8560c01b16815263ffffffff60e01b8460e01b16600882015282600c82015260008251613a1881602c850160208701612afa565b91909101602c0195945050505050565b8481526001600160401b0360c01b8460c01b16602082015282602882015260008251613a5b816048850160208701612afa565b9190910160480195945050505050565b600060208284031215613a7d57600080fd5b8151610b1081612b5d565b634e487b7160e01b600052602160045260246000fd5b6000825161348f818460208701612afa56fea264697066735822122015896e89c7b056e0c3d5861a0b299c70d4df5ed8f71f89fd49c054cc8b4280d264736f6c63430008160033

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

000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000001a44076050125825900e736c501f859c50fe728c0000000000000000000000006727b22867e7ece399aa306f94d5521f59a59a12000000000000000000000000000000000000000000000000000000000000000b49534b524120544f4b454e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000349534b0000000000000000000000000000000000000000000000000000000000

-----Decoded View---------------
Arg [0] : _name (string): ISKRA TOKEN
Arg [1] : _symbol (string): ISK
Arg [2] : _lzEndpoint (address): 0x1a44076050125825900e736c501f859c50fE728c
Arg [3] : _delegate (address): 0x6727b22867e7ecE399aa306f94D5521F59A59a12

-----Encoded View---------------
8 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000080
Arg [1] : 00000000000000000000000000000000000000000000000000000000000000c0
Arg [2] : 0000000000000000000000001a44076050125825900e736c501f859c50fe728c
Arg [3] : 0000000000000000000000006727b22867e7ece399aa306f94d5521f59a59a12
Arg [4] : 000000000000000000000000000000000000000000000000000000000000000b
Arg [5] : 49534b524120544f4b454e000000000000000000000000000000000000000000
Arg [6] : 0000000000000000000000000000000000000000000000000000000000000003
Arg [7] : 49534b0000000000000000000000000000000000000000000000000000000000


Deployed Bytecode Sourcemap

161259:321:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;112901:100;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;115252:201;;;;;;;;;;-1:-1:-1;115252:201:0;;;;;:::i;:::-;;:::i;:::-;;;1391:14:1;;1384:22;1366:41;;1354:2;1339:18;115252:201:0;1226:187:1;95545:1283:0;;;;;;;;;;-1:-1:-1;95545:1283:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;;;:::i;92688:27::-;;;;;;;;;;-1:-1:-1;92688:27:0;;;;-1:-1:-1;;;;;92688:27:0;;;;;;-1:-1:-1;;;;;3605:32:1;;;3587:51;;3575:2;3560:18;92688:27:0;3441:203:1;30556:723:0;;;;;;:::i;:::-;;:::i;:::-;;92559:40;;;;;;;;;;;;92598:1;92559:40;;;;;5386:6:1;5374:19;;;5356:38;;5344:2;5329:18;92559:40:0;5212:188:1;93857:142:0;;;;;;;;;;-1:-1:-1;93857:142:0;;;-1:-1:-1;;;5575:52:1;;93989:1:0;5658:2:1;5643:18;;5636:59;5548:18;93857:142:0;5405:296:1;57829:243:0;;;;;;;;;;-1:-1:-1;57829:243:0;;;51708:1;5913:34:1;;26789:1:0;5978:2:1;5963:18;;5956:43;5849:18;57829:243:0;5706:299:1;114021:108:0;;;;;;;;;;-1:-1:-1;114109:12:0;;114021:108;;;6156:25:1;;;6144:2;6129:18;114021:108:0;6010:177:1;92521:31:0;;;;;;;;;;;;92551:1;92521:31;;116033:295;;;;;;;;;;-1:-1:-1;116033:295:0;;;;;:::i;:::-;;:::i;113863:93::-;;;;;;;;;;-1:-1:-1;113946:2:0;113863:93;;;6825:4:1;6813:17;;;6795:36;;6783:2;6768:18;113863:93:0;6653:184:1;24432:110:0;;;;;;;;;;-1:-1:-1;24432:110:0;;;;;:::i;:::-;;:::i;160665:115::-;;;;;;;;;;;;;:::i;116737:238::-;;;;;;;;;;-1:-1:-1;116737:238:0;;;;;:::i;:::-;;:::i;97291:787::-;;;;;;;;;;-1:-1:-1;97291:787:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;86362:95::-;;;;;;;;;;-1:-1:-1;86444:4:0;86362:95;;18275:93;;;;;;;;;;-1:-1:-1;18275:93:0;;;;;:::i;:::-;;:::i;105608:134::-;;;;;;;;;;-1:-1:-1;105608:134:0;;;;;:::i;:::-;105714:11;;;;;105690:4;105714:11;;;:5;:11;;;;;;:20;;105608:134;23125:46;;;;;;;;;;;;;;;95064:166;;;;;;;;;;-1:-1:-1;95064:166:0;;;;;:::i;:::-;;:::i;114192:127::-;;;;;;;;;;-1:-1:-1;114192:127:0;;;;;:::i;:::-;-1:-1:-1;;;;;114293:18:0;114266:7;114293:18;;;:9;:18;;;;;;;114192:127;16962:103;;;;;;;;;;;;;:::i;29678:130::-;;;;;;;;;;-1:-1:-1;29678:130:0;;;;;:::i;:::-;29767:12;29678:130;;;;;;;;-1:-1:-1;;;;;9624:31:1;;;9606:50;;9594:2;9579:18;29678:130:0;9462:200:1;160407:128:0;;;;;;;;;;-1:-1:-1;160407:128:0;;;;;:::i;:::-;;:::i;28152:222::-;;;;;;;;;;-1:-1:-1;28152:222:0;;;;;:::i;:::-;;:::i;94618:89::-;;;;;;;;;;-1:-1:-1;94698:1:0;94618:89;;16314:87;;;;;;;;;;-1:-1:-1;16360:7:0;16387:6;-1:-1:-1;;;;;16387:6:0;16314:87;;113120:104;;;;;;;;;;;;;:::i;92210:46::-;;;;;;;;;;;;;;;125561:96;;;;;;;;;;-1:-1:-1;125620:4:0;125561:96;;117478:436;;;;;;;;;;-1:-1:-1;117478:436:0;;;;;:::i;:::-;;:::i;114525:193::-;;;;;;;;;;-1:-1:-1;114525:193:0;;;;;:::i;:::-;;:::i;86037:23::-;;;;;;;;;;-1:-1:-1;86037:23:0;;;;-1:-1:-1;;;;;86037:23:0;;;19140:158;;;;;;;;;;-1:-1:-1;19140:158:0;;;;;:::i;:::-;;:::i;23251:48::-;;;;;;;;;;-1:-1:-1;23251:48:0;;;;;:::i;:::-;;;;;;;;;;;;;;21294:1003;;;;;;;;;;-1:-1:-1;21294:1003:0;;;;;:::i;:::-;;:::i;87206:1358::-;;;;;;:::i;:::-;;:::i;98783:1364::-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;:::i;25997:107::-;;;;;;;;;;-1:-1:-1;25997:107:0;;;;;:::i;:::-;;:::i;89226:419::-;;;;;;:::i;:::-;;:::i;86595:142::-;;;;;;;;;;-1:-1:-1;86595:142:0;;;;;:::i;:::-;;:::i;159696:645::-;;;;;;;;;;-1:-1:-1;159696:645:0;;;;;:::i;:::-;;:::i;114781:151::-;;;;;;;;;;-1:-1:-1;114781:151:0;;;;;:::i;:::-;;:::i;17220:201::-;;;;;;;;;;-1:-1:-1;17220:201:0;;;;;:::i;:::-;;:::i;28927:151::-;;;;;;;;;;-1:-1:-1;28927:151:0;;;;;:::i;:::-;;:::i;112901:100::-;112955:13;112988:5;112981:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;112901:100;:::o;115252:201::-;115335:4;14890:10;115391:32;14890:10;115407:7;115416:6;115391:8;:32::i;:::-;115441:4;115434:11;;;115252:201;;;;;:::o;95545:1283::-;-1:-1:-1;;;;;;;;;;;;;;;;;95703:35:0;95740:28;-1:-1:-1;;;;;;;;;;;;;;;;;;;95740:28:0;95962:34;;;;;;;;-1:-1:-1;95962:34:0;;;-1:-1:-1;;;;;95962:34:0;;;;;;;96116:21;;;;;;;;;;;95962:34;;-1:-1:-1;;;96116:21:0;;;-1:-1:-1;;;;;;;;;;;;;;;;;96116:21:0;;;;;;;;;;;;;;;-1:-1:-1;96100:37:0;-1:-1:-1;96580:20:0;;96630:124;96655:19;;;;96689:22;;;;96726:17;;;;96655:10;96726:17;:::i;:::-;96630:10;:124::i;:::-;96778:42;;;;;;;;;;;;;;;;95545:1283;;;;-1:-1:-1;;;;;;95545:1283:0:o;30556:723::-;30877:8;-1:-1:-1;;;;;30869:31:0;30890:10;30869:31;30865:68;;30909:24;;-1:-1:-1;;;30909:24:0;;30922:10;30909:24;;;3587:51:1;3560:18;;30909:24:0;;;;;;;;30865:68;31072:14;;;;;;31036:32;;31053:14;;31072:7;31053:14;:::i;:::-;31036:16;:32::i;:::-;:50;31032:103;;31104:14;;;;:7;:14;:::i;:::-;31095:40;;-1:-1:-1;;;31095:40:0;;15962:10:1;15950:23;;;31095:40:0;;;15932:42:1;31120:14:0;;;;15990:18:1;;;15983:34;15905:18;;31095:40:0;15760:263:1;31032:103:0;31212:59;31223:7;31232:5;31239:8;;31249:9;31260:10;;31212;:59::i;:::-;30556:723;;;;;;;:::o;116033:295::-;116164:4;14890:10;116222:38;116238:4;14890:10;116253:6;116222:15;:38::i;:::-;116271:27;116281:4;116287:2;116291:6;116271:9;:27::i;:::-;116316:4;116309:11;;;116033:295;;;;;;:::o;24432:110::-;16200:13;:11;:13::i;:::-;24513:21:::1;24522:4;24528:5;24513:8;:21::i;:::-;24432:110:::0;;:::o;160665:115::-;160725:7;160752:20;:18;:20::i;:::-;160745:27;;160665:115;:::o;116737:238::-;116825:4;14890:10;116881:64;14890:10;116897:7;116934:10;116906:25;14890:10;116897:7;116906:9;:25::i;:::-;:38;;;;:::i;:::-;116881:8;:64::i;97291:787::-;-1:-1:-1;;;;;;;;;;;;;;;;;97631:24:0;97659:74;97670:19;;;;97691:22;;;;97715:17;;;;97670:10;97715:17;:::i;97659:74::-;97628:105;;;97825:20;97847;97871:49;97891:10;97903:16;97871:19;:49::i;:::-;97824:96;;-1:-1:-1;97824:96:0;-1:-1:-1;98012:58:0;98019:17;;;;:10;:17;:::i;:::-;98038:7;98047;98056:13;98012:6;:58::i;:::-;98005:65;97291:787;-1:-1:-1;;;;;;97291:787:0:o;18275:93::-;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;95064:166::-;16200:13;:11;:13::i;:::-;95148:12:::1;:28:::0;;-1:-1:-1;;;;;;95148:28:0::1;-1:-1:-1::0;;;;;95148:28:0;::::1;::::0;;::::1;::::0;;;95192:30:::1;::::0;3587:51:1;;;95192:30:0::1;::::0;3575:2:1;3560:18;95192:30:0::1;;;;;;;;95064:166:::0;:::o;16962:103::-;16200:13;:11;:13::i;:::-;17027:30:::1;17054:1;17027:18;:30::i;:::-;16962:103::o:0;160407:128::-;-1:-1:-1;;;;;160503:14:0;;160476:7;160503:14;;;:7;:14;;;;;128474;160503:24;128382:114;28152:222;-1:-1:-1;;;;;28342:24:0;;28361:4;28342:24;28152:222;;;;;;;:::o;113120:104::-;113176:13;113209:7;113202:14;;;;;:::i;117478:436::-;117571:4;14890:10;117571:4;117654:25;14890:10;117671:7;117654:9;:25::i;:::-;117627:52;;117718:15;117698:16;:35;;117690:85;;;;-1:-1:-1;;;117690:85:0;;16492:2:1;117690:85:0;;;16474:21:1;16531:2;16511:18;;;16504:30;16570:34;16550:18;;;16543:62;-1:-1:-1;;;16621:18:1;;;16614:35;16666:19;;117690:85:0;16290:401:1;117690:85:0;117811:60;117820:5;117827:7;117855:15;117836:16;:34;117811:8;:60::i;:::-;-1:-1:-1;117902:4:0;;117478:436;-1:-1:-1;;;;117478:436:0:o;114525:193::-;114604:4;14890:10;114660:28;14890:10;114677:2;114681:6;114660:9;:28::i;19140:158::-;16200:13;:11;:13::i;:::-;19253:37:::1;;19273:16:::0;;19253:37:::1;:::i;:::-;:19;:37::i;21294:1003::-:0;21490:21;;;21466;21490;;;:15;:21;;;;;;;;:31;;;;;;;;;;21466:55;;21441:12;;21466:21;21490:31;21466:55;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;21653:8;:15;21672:1;21653:20;21649:46;;21682:13;;21675:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;21675:20:0;;-1:-1:-1;21675:20:0;;-1:-1:-1;;;;21675:20:0;21649:46;21783:1;21759:25;;;21755:46;;21793:8;-1:-1:-1;21786:15:0;;21755:46;21951:1;21927:25;;21923:271;;21969:34;21989:13;;21969:34;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;21969:19:0;;-1:-1:-1;;;21969:34:0:i;:::-;22154:8;22164:17;:13;22178:1;22164:13;;:17;:::i;:::-;22141:41;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;22134:48;;;;;21923:271;22275:13;;22260:29;;-1:-1:-1;;;22260:29:0;;;;;;;;;:::i;87206:1358::-;87308:9;87303:1057;87323:19;;;87303:1057;;;87364:29;87396:8;;87405:1;87396:11;;;;;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;87364:43;-1:-1:-1;87493:50:0;87500:20;;;;87364:43;87500:20;:::i;:::-;87522;;;;105714:11;;;;;105690:4;105714:11;;;:5;:11;;;;;;:20;;105608:134;87493:50;87488:65;;87545:8;;;87488:65;88124:4;:22;88155:12;;;;:6;88220:11;;;;88250:14;;;;88155:6;88250:14;:::i;:::-;88283:15;;;;;;;;:::i;:::-;88317:16;;;;:6;:16;:::i;:::-;88124:224;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;87349:1011;87303:1057;87344:3;;87303:1057;;;;88520:10;-1:-1:-1;;;;;88510:43:0;;:45;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;88510:45:0;;;;;;;;;;;;:::i;:::-;88493:63;;-1:-1:-1;;;88493:63:0;;;;;;;;:::i;98783:1364::-;98948:34;;:::i;:::-;-1:-1:-1;;;;;;;;;;;;;;;;;99350:20:0;;99400:145;99421:10;99446:19;;;;99480:22;;;;99517:17;;;;99446:10;99517:17;:::i;:::-;99400:6;:145::i;:::-;99349:196;;;;99637:20;99659;99683:49;99703:10;99715:16;99683:19;:49::i;:::-;99636:96;;-1:-1:-1;99636:96:0;-1:-1:-1;99858:66:0;99866:17;;;;:10;:17;:::i;:::-;99885:7;99894;99858:66;;;;;;;99903:4;99858:66;:::i;:::-;99909:14;99858:7;:66::i;:::-;99992:42;;;;;;;;;;;;;;;;;;;100060:15;;99845:79;;-1:-1:-1;99992:42:0;;-1:-1:-1;100096:10:0;;100060:15;100052:87;;100077:17;;;;:10;:17;:::i;:::-;100052:87;;;24495:10:1;24483:23;;;24465:42;;24538:2;24523:18;;24516:34;;;24566:18;;24559:34;;;24453:2;24438:18;100052:87:0;;;;;;;99014:1133;;;;98783:1364;;;;;;:::o;25997:107::-;16200:13;:11;:13::i;:::-;26065:31:::1;::::0;-1:-1:-1;;;26065:31:0;;-1:-1:-1;;;;;3605:32:1;;;26065:31:0::1;::::0;::::1;3587:51:1::0;26065:8:0::1;:20;::::0;::::1;::::0;3560:18:1;;26065:31:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;25997:107:::0;:::o;89226:419::-;89513:10;89535:4;89513:27;89509:50;;89549:10;;-1:-1:-1;;;89549:10:0;;;;;;;;;;;89509:50;89570:67;89589:7;89598:5;89605:8;;89615:9;89626:10;;89570:18;:67::i;86595:142::-;16200:13;:11;:13::i;:::-;86671:8:::1;:20:::0;;-1:-1:-1;;;;;;86671:20:0::1;-1:-1:-1::0;;;;;86671:20:0;::::1;::::0;;::::1;::::0;;;86707:22:::1;::::0;3587:51:1;;;86707:22:0::1;::::0;3575:2:1;3560:18;86707:22:0::1;3441:203:1::0;159696:645:0;159940:8;159921:15;:27;;159913:69;;;;-1:-1:-1;;;159913:69:0;;24806:2:1;159913:69:0;;;24788:21:1;24845:2;24825:18;;;24818:30;24884:31;24864:18;;;24857:59;24933:18;;159913:69:0;24604:353:1;159913:69:0;159995:18;158871:95;160055:5;160062:7;160071:5;160078:16;160088:5;160078:9;:16::i;:::-;160026:79;;;;;;25249:25:1;;;;-1:-1:-1;;;;;25348:15:1;;;25328:18;;;25321:43;25400:15;;;;25380:18;;;25373:43;25432:18;;;25425:34;25475:19;;;25468:35;25519:19;;;25512:35;;;25221:19;;160026:79:0;;;;;;;;;;;;160016:90;;;;;;159995:111;;160119:12;160134:28;160151:10;160134:16;:28::i;:::-;160119:43;;160175:14;160192:28;160206:4;160212:1;160215;160218;160192:13;:28::i;:::-;160175:45;;160249:5;-1:-1:-1;;;;;160239:15:0;:6;-1:-1:-1;;;;;160239:15:0;;160231:58;;;;-1:-1:-1;;;160231:58:0;;25760:2:1;160231:58:0;;;25742:21:1;25799:2;25779:18;;;25772:30;25838:32;25818:18;;;25811:60;25888:18;;160231:58:0;25558:354:1;160231:58:0;160302:31;160311:5;160318:7;160327:5;160302:8;:31::i;:::-;159902:439;;;159696:645;;;;;;;:::o;114781:151::-;-1:-1:-1;;;;;114897:18:0;;;114870:7;114897:18;;;:11;:18;;;;;;;;:27;;;;;;;;;;;;;114781:151::o;17220:201::-;16200:13;:11;:13::i;:::-;-1:-1:-1;;;;;17309:22:0;::::1;17301:73;;;::::0;-1:-1:-1;;;17301:73:0;;26119:2:1;17301:73:0::1;::::0;::::1;26101:21:1::0;26158:2;26138:18;;;26131:30;26197:34;26177:18;;;26170:62;-1:-1:-1;;;26248:18:1;;;26241:36;26294:19;;17301:73:0::1;25917:402:1::0;17301:73:0::1;17385:28;17404:8;17385:18;:28::i;:::-;17220:201:::0;:::o;28927:151::-;29009:4;29057:13;;;;;;29033:5;;29009:4;;29039:13;;29057:6;29039:13;:::i;:::-;29033:20;;;;;;;;;;;;;-1:-1:-1;29033:20:0;;:37;;28927:151;-1:-1:-1;;28927:151:0:o;121505:380::-;-1:-1:-1;;;;;121641:19:0;;121633:68;;;;-1:-1:-1;;;121633:68:0;;26526:2:1;121633:68:0;;;26508:21:1;26565:2;26545:18;;;26538:30;26604:34;26584:18;;;26577:62;-1:-1:-1;;;26655:18:1;;;26648:34;26699:19;;121633:68:0;26324:400:1;121633:68:0;-1:-1:-1;;;;;121720:21:0;;121712:68;;;;-1:-1:-1;;;121712:68:0;;26931:2:1;121712:68:0;;;26913:21:1;26970:2;26950:18;;;26943:30;27009:34;26989:18;;;26982:62;-1:-1:-1;;;27060:18:1;;;27053:32;27102:19;;121712:68:0;26729:398:1;121712:68:0;-1:-1:-1;;;;;121793:18:0;;;;;;;:11;:18;;;;;;;;:27;;;;;;;;;;;;;:36;;;121845:32;;6156:25:1;;;121845:32:0;;6129:18:1;121845:32:0;;;;;;;121505:380;;;:::o;107669:682::-;107815:20;107837:24;108013:22;108025:9;108013:11;:22::i;:::-;107998:37;;108163:12;108144:31;;108248:12;108229:16;:31;108225:119;;;108284:48;;-1:-1:-1;;;108284:48:0;;;;;27306:25:1;;;27347:18;;;27340:34;;;27279:18;;108284:48:0;27132:248:1;108225:119:0;107669:682;;;;;;:::o;25450:200::-;25555:11;;;25520:7;25555:11;;;:5;:11;;;;;;;25577:43;;25608:12;;-1:-1:-1;;;25608:12:0;;27559:10:1;27547:23;;25608:12:0;;;27529:42:1;27502:18;;25608:12:0;27385:192:1;102336:1837:0;102822:17;102842:36;:17;:8;;:15;:17::i;:::-;71733:2;71621:125;102842:36;102822:56;;103013:24;103040:62;103048:9;103059:26;103065:19;:8;;:17;:19::i;:::-;103059:5;:26::i;:::-;103087:14;;;;:7;:14;:::i;:::-;103040:7;:62::i;:::-;103013:89;-1:-1:-1;69012:2:0;-1:-1:-1;;103115:970:0;;;103221:23;103247:180;103291:13;;;;;;;;:::i;:::-;103323:14;;;;:7;:14;:::i;:::-;103356:16;103391:21;:8;;:19;:21::i;:::-;103247:25;:180::i;:::-;103981:92;;-1:-1:-1;;;103981:92:0;;103221:206;;-1:-1:-1;;;;;;103981:8:0;:20;;;;:92;;104002:9;;104013:5;;104020:1;;103221:206;;103981:92;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;103142:943;103115:970;-1:-1:-1;;;;;104102:63:0;;104114:5;104102:63;104121:14;;;;:7;:14;:::i;:::-;104102:63;;;15962:10:1;15950:23;;;15932:42;;16005:2;15990:18;;15983:34;;;15905:18;104102:63:0;;;;;;;102645:1528;;102336:1837;;;;;;;:::o;122176:453::-;122311:24;122338:25;122348:5;122355:7;122338:9;:25::i;:::-;122311:52;;-1:-1:-1;;122378:16:0;:37;122374:248;;122460:6;122440:16;:26;;122432:68;;;;-1:-1:-1;;;122432:68:0;;28786:2:1;122432:68:0;;;28768:21:1;28825:2;28805:18;;;28798:30;28864:31;28844:18;;;28837:59;28913:18;;122432:68:0;28584:353:1;122432:68:0;122544:51;122553:5;122560:7;122588:6;122569:16;:25;122544:8;:51::i;:::-;122300:329;122176:453;;;:::o;118384:840::-;-1:-1:-1;;;;;118515:18:0;;118507:68;;;;-1:-1:-1;;;118507:68:0;;29144:2:1;118507:68:0;;;29126:21:1;29183:2;29163:18;;;29156:30;29222:34;29202:18;;;29195:62;-1:-1:-1;;;29273:18:1;;;29266:35;29318:19;;118507:68:0;28942:401:1;118507:68:0;-1:-1:-1;;;;;118594:16:0;;118586:64;;;;-1:-1:-1;;;118586:64:0;;29550:2:1;118586:64:0;;;29532:21:1;29589:2;29569:18;;;29562:30;29628:34;29608:18;;;29601:62;-1:-1:-1;;;29679:18:1;;;29672:33;29722:19;;118586:64:0;29348:399:1;118586:64:0;-1:-1:-1;;;;;118736:15:0;;118714:19;118736:15;;;:9;:15;;;;;;118770:21;;;;118762:72;;;;-1:-1:-1;;;118762:72:0;;29954:2:1;118762:72:0;;;29936:21:1;29993:2;29973:18;;;29966:30;30032:34;30012:18;;;30005:62;-1:-1:-1;;;30083:18:1;;;30076:36;30129:19;;118762:72:0;29752:402:1;118762:72:0;-1:-1:-1;;;;;118870:15:0;;;;;;;:9;:15;;;;;;118888:20;;;118870:38;;119088:13;;;;;;;;;;:23;;;;;;119140:26;;;;;;118902:6;6156:25:1;;6144:2;6129:18;;6010:177;119140:26:0;;;;;;;;119179:37;123229:125;16479:132;16360:7;16387:6;-1:-1:-1;;;;;16387:6:0;14890:10;16543:23;16535:68;;;;-1:-1:-1;;;16535:68:0;;30361:2:1;16535:68:0;;;30343:21:1;;;30380:18;;;30373:30;30439:34;30419:18;;;30412:62;30491:18;;16535:68:0;30159:356:1;25007:137:0;25081:11;;;;;;;:5;:11;;;;;;;;;:19;;;25116:20;;15932:42:1;;;15990:18;;15983:34;;;25116:20:0;;15905:18:1;25116:20:0;;;;;;;25007:137;;:::o;156390:314::-;156443:7;156475:4;-1:-1:-1;;;;;156484:12:0;156467:29;;:66;;;;;156517:16;156500:13;:33;156467:66;156463:234;;;-1:-1:-1;156557:24:0;;156390:314::o;156463:234::-;-1:-1:-1;156893:73:0;;;156643:10;156893:73;;;;38308:25:1;;;;156655:12:0;38349:18:1;;;38342:34;156669:15:0;38392:18:1;;;38385:34;156937:13:0;38435:18:1;;;38428:34;156960:4:0;38478:19:1;;;;38471:61;;;;156893:73:0;;;;;;;;;;38280:19:1;;;;156893:73:0;;;156883:84;;;;;;160665:115::o;100450:1355::-;100585:20;100607;100640:15;100813:330;100846:10;:13;;;100874:16;100880:9;100874:5;:16::i;:::-;101111:21;;;;:10;:21;:::i;:::-;100813:330;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;100813:18:0;;-1:-1:-1;;;100813:330:0:i;:::-;100789:354;;-1:-1:-1;100789:354:0;-1:-1:-1;101225:14:0;100789:354;101242:33;;92551:1;101242:33;;;92598:1;101242:33;101225:50;-1:-1:-1;101399:67:0;101414:17;;;;:10;:17;:::i;:::-;101433:7;101442:23;;;;:10;:23;:::i;101399:67::-;101712:12;;101389:77;;-1:-1:-1;;;;;;101712:12:0;:26;101708:89;;101758:12;;;101740:57;;-1:-1:-1;;;101740:57:0;;-1:-1:-1;;;;;101758:12:0;;;;101740:39;;:57;;101780:7;;101789;;101740:57;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;101708:89;100629:1176;;100450:1355;;;;;:::o;52928:402::-;-1:-1:-1;;;;;;;;;;;;;;;;;53156:8:0;-1:-1:-1;;;;;53156:14:0;;53189:86;;;;;;;;53205:7;53189:86;;;;;;53214:25;53231:7;53214:16;:25::i;:::-;53189:86;;;;53241:8;53189:86;;;;53251:8;53189:86;;;;53261:13;53189:86;;;;;53302:4;53156:166;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;53136:186;52928:402;-1:-1:-1;;;;;52928:402:0:o;17581:191::-;17655:16;17674:6;;-1:-1:-1;;;;;17691:17:0;;;-1:-1:-1;;;;;;17691:17:0;;;;;;17724:40;;17674:6;;;;;;;17724:40;;17655:16;17724:40;17644:128;17581:191;:::o;19999:522::-;20108:9;20103:358;20127:16;:23;20123:1;:27;20103:358;;;20287:48;20307:16;20324:1;20307:19;;;;;;;;:::i;:::-;;;;;;;:27;;;20287:19;:48::i;:::-;20422:16;20439:1;20422:19;;;;;;;;:::i;:::-;;;;;;;:27;;;20350:15;:40;20366:16;20383:1;20366:19;;;;;;;;:::i;:::-;;;;;;;:23;;;20350:40;;;;;;;;;;;;;;;:69;20391:16;20408:1;20391:19;;;;;;;;:::i;:::-;;;;;;;:27;;;20350:69;;;;;;;;;;;;;;;:99;;;;;;:::i;:::-;-1:-1:-1;20152:3:0;;20103:358;;;;20478:35;20496:16;20478:35;;;;;;:::i;22443:270::-;22616:1;22602:16;;22596:23;22644:28;;;18197:1;22644:28;22640:65;;22696:8;22681:24;;-1:-1:-1;;;22681:24:0;;;;;;;;:::i;126151:580::-;126317:20;126339:24;126411:44;126422:9;126433:12;126447:7;126411:10;:44::i;:::-;126376:79;;-1:-1:-1;126376:79:0;-1:-1:-1;126697:26:0;126703:5;126376:79;126697:5;:26::i;:::-;126151:580;;;;;;;:::o;54105:783::-;54312:31;;:::i;:::-;54479:20;54502:26;54513:4;:14;;;54502:10;:26::i;:::-;54543:15;;;;54479:49;;-1:-1:-1;54543:19:0;54539:53;;54564:28;54576:4;:15;;;54564:11;:28::i;:::-;54685:8;-1:-1:-1;;;;;54685:13:0;;54707:12;54740:92;;;;;;;;54756:7;54740:92;;;;;;54765:25;54782:7;54765:16;:25::i;:::-;54740:92;;;;54792:8;54740:92;;;;54802:8;54740:92;;;;54830:1;54812:4;:15;;;:19;54740:92;;;;;54851:14;54685:195;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;54605:275;54105:783;-1:-1:-1;;;;;;;54105:783:0:o;160918:207::-;-1:-1:-1;;;;;161039:14:0;;160978:15;161039:14;;;:7;:14;;;;;128474;;128611:1;128593:19;;;;128474:14;161100:17;160995:130;160918:207;;;:::o;157617:167::-;157694:7;157721:55;157743:20;:18;:20::i;:::-;157765:10;153029:57;;-1:-1:-1;;;153029:57:0;;;40694:27:1;40737:11;;;40730:27;;;40773:12;;;40766:28;;;152992:7:0;;40810:12:1;;153029:57:0;;;;;;;;;;;;153019:68;;;;;;153012:75;;152899:196;;;;;151208:279;151336:7;151357:17;151376:18;151398:25;151409:4;151415:1;151418;151421;151398:10;:25::i;:::-;151356:67;;;;151434:18;151446:5;151434:11;:18::i;:::-;-1:-1:-1;151470:9:0;151208:279;-1:-1:-1;;;;;151208:279:0:o;106146:174::-;106217:16;106291:21;106254:33;106291:21;106254:9;:33;:::i;:::-;106253:59;;;;:::i;70378:125::-;70438:7;70473:21;68956:2;70438:7;70473:4;;:21;:::i;:::-;70465:30;;;:::i;70688:154::-;70750:6;70790:42;69012:2;68956;70790:4;;:42;:::i;:::-;70783:50;;;:::i;:::-;70776:58;;;70688:154;-1:-1:-1;;;70688:154:0:o;106551:141::-;106615:16;106651:33;106663:21;-1:-1:-1;;;;;106651:33:0;;;:::i;127075:371::-;127213:24;127293:21;127299:3;127304:9;127293:5;:21::i;:::-;-1:-1:-1;127429:9:0;;127075:371;-1:-1:-1;;127075:371:0:o;71009:132::-;71073:12;71105:28;:4;69012:2;71105:4;;:28;:::i;:::-;71098:35;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;71098:35:0;;71009:132;-1:-1:-1;;;;;;71009:132:0:o;66232:291::-;66421:17;66475:6;66483:7;66492:9;66503:11;66458:57;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;66451:64;;66232:291;;;;;;:::o;123229:125::-;;;;:::o;106923:149::-;106988:15;107030:33;107042:21;107030:9;:33;:::i;69377:516::-;69575:18;;69515:17;;69575:22;;;69720:165;;69862:7;69871:13;69845:40;;;;;;;;38698:19:1;;;38773:3;38751:16;-1:-1:-1;;;;;;38747:51:1;38742:2;38733:12;;38726:73;38824:2;38815:12;;38543:290;69845:40:0;;;;;;;;;;;;;69720:165;;;69763:7;69772:13;69804:10;69817:11;69746:83;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;69720:165;69713:172;;69377:516;;;;;;:::o;120392:675::-;-1:-1:-1;;;;;120476:21:0;;120468:67;;;;-1:-1:-1;;;120468:67:0;;39577:2:1;120468:67:0;;;39559:21:1;39616:2;39596:18;;;39589:30;39655:34;39635:18;;;39628:62;-1:-1:-1;;;39706:18:1;;;39699:31;39747:19;;120468:67:0;39375:397:1;120468:67:0;-1:-1:-1;;;;;120635:18:0;;120610:22;120635:18;;;:9;:18;;;;;;120672:24;;;;120664:71;;;;-1:-1:-1;;;120664:71:0;;39979:2:1;120664:71:0;;;39961:21:1;40018:2;39998:18;;;39991:30;40057:34;40037:18;;;40030:62;-1:-1:-1;;;40108:18:1;;;40101:32;40150:19;;120664:71:0;39777:398:1;120664:71:0;-1:-1:-1;;;;;120771:18:0;;;;;;:9;:18;;;;;;;;120792:23;;;120771:44;;120910:12;:22;;;;;;;120961:37;6156:25:1;;;120771:18:0;;;120961:37;;6129:18:1;120961:37:0;;;;;;;123229:125;;;:::o;55597:194::-;55663:17;55710:10;55697:9;:23;55693:62;;55729:26;;-1:-1:-1;;;55729:26:0;;55745:9;55729:26;;;6156:25:1;6129:18;;55729:26:0;6010:177:1;55693:62:0;-1:-1:-1;55773:10:0;55597:194::o;56177:417::-;56332:15;56350:8;-1:-1:-1;;;;;56350:16:0;;:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;56332:36;-1:-1:-1;;;;;;56383:21:0;;56379:54;;56413:20;;-1:-1:-1;;;56413:20:0;;;;;;;;;;;56379:54;56510:76;-1:-1:-1;;;;;56510:32:0;;56543:10;56563:8;56574:11;56510:32;:76::i;149549:1520::-;149680:7;;150614:66;150601:79;;150597:163;;;-1:-1:-1;150713:1:0;;-1:-1:-1;150717:30:0;150697:51;;150597:163;150874:24;;;150857:14;150874:24;;;;;;;;;41060:25:1;;;41133:4;41121:17;;41101:18;;;41094:45;;;;41155:18;;;41148:34;;;41198:18;;;41191:34;;;150874:24:0;;41032:19:1;;150874:24:0;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;150874:24:0;;-1:-1:-1;;150874:24:0;;;-1:-1:-1;;;;;;;150913:20:0;;150909:103;;150966:1;150970:29;150950:50;;;;;;;150909:103;151032:6;151040:20;;-1:-1:-1;149549:1520:0;-1:-1:-1;;;;;149549:1520:0:o;144941:521::-;145019:20;145010:5;:29;;;;;;;;:::i;:::-;;145006:449;;144941:521;:::o;145006:449::-;145117:29;145108:5;:38;;;;;;;;:::i;:::-;;145104:351;;145163:34;;-1:-1:-1;;;145163:34:0;;41570:2:1;145163:34:0;;;41552:21:1;41609:2;41589:18;;;41582:30;41648:26;41628:18;;;41621:54;41692:18;;145163:34:0;41368:348:1;145104:351:0;145228:35;145219:5;:44;;;;;;;;:::i;:::-;;145215:240;;145280:41;;-1:-1:-1;;;145280:41:0;;41923:2:1;145280:41:0;;;41905:21:1;41962:2;41942:18;;;41935:30;42001:33;41981:18;;;41974:61;42052:18;;145280:41:0;41721:355:1;145215:240:0;145352:30;145343:5;:39;;;;;;;;:::i;:::-;;145339:116;;145399:44;;-1:-1:-1;;;145399:44:0;;42283:2:1;145399:44:0;;;42265:21:1;42322:2;42302:18;;;42295:30;42361:34;42341:18;;;42334:62;-1:-1:-1;;;42412:18:1;;;42405:32;42454:19;;145399:44:0;42081:398:1;119511:548:0;-1:-1:-1;;;;;119595:21:0;;119587:65;;;;-1:-1:-1;;;119587:65:0;;42686:2:1;119587:65:0;;;42668:21:1;42725:2;42705:18;;;42698:30;42764:33;42744:18;;;42737:61;42815:18;;119587:65:0;42484:355:1;119587:65:0;119743:6;119727:12;;:22;;;;;;;:::i;:::-;;;;-1:-1:-1;;;;;;;119898:18:0;;;;;;:9;:18;;;;;;;;:28;;;;;;119953:37;6156:25:1;;;119953:37:0;;6129:18:1;119953:37:0;;;;;;;24432:110;;:::o;47459:248::-;47630:68;;;-1:-1:-1;;;;;43102:15:1;;;47630:68:0;;;43084:34:1;43154:15;;;43134:18;;;43127:43;43186:18;;;;43179:34;;;47630:68:0;;;;;;;;;;43019:18:1;;;;47630:68:0;;;;;;;;-1:-1:-1;;;;;47630:68:0;-1:-1:-1;;;47630:68:0;;;50757:69;;;;;;;;;;;;;;;;47603:96;;47623:5;;47630:68;-1:-1:-1;;50757:69:0;;:27;;;47630:68;;50757:27;:69::i;:::-;50841:17;;50731:95;;-1:-1:-1;50841:21:0;50837:179;;50938:10;50927:30;;;;;;;;;;;;:::i;:::-;50919:85;;;;-1:-1:-1;;;50919:85:0;;43426:2:1;50919:85:0;;;43408:21:1;43465:2;43445:18;;;43438:30;43504:34;43484:18;;;43477:62;-1:-1:-1;;;43555:18:1;;;43548:40;43605:19;;50919:85:0;43224:406:1;41033:229:0;41170:12;41202:52;41224:6;41232:4;41238:1;41241:12;41170;42441;42455:23;42482:6;-1:-1:-1;;;;;42482:11:0;42501:5;42508:4;42482:31;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;42440:73;;;;42531:69;42558:6;42566:7;42575:10;42587:12;44911;44940:7;44936:427;;;44968:10;:17;44989:1;44968:22;44964:290;;-1:-1:-1;;;;;38571:19:0;;;45178:60;;;;-1:-1:-1;;;45178:60:0;;44536:2:1;45178:60:0;;;44518:21:1;44575:2;44555:18;;;44548:30;44614:31;44594:18;;;44587:59;44663:18;;45178:60:0;44334:353:1;45178:60:0;-1:-1:-1;45275:10:0;45268:17;;44936:427;45318:33;45326:10;45338:12;46073:17;;:21;46069:388;;46305:10;46299:17;46362:15;46349:10;46345:2;46341:19;46334:44;46069:388;46432:12;46425:20;;-1:-1:-1;;;46425:20:0;;;;;;;;:::i;-1:-1:-1:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;14:250:1:-;99:1;109:113;123:6;120:1;117:13;109:113;;;199:11;;;193:18;180:11;;;173:39;145:2;138:10;109:113;;;-1:-1:-1;;256:1:1;238:16;;231:27;14:250::o;269:271::-;311:3;349:5;343:12;376:6;371:3;364:19;392:76;461:6;454:4;449:3;445:14;438:4;431:5;427:16;392:76;:::i;:::-;522:2;501:15;-1:-1:-1;;497:29:1;488:39;;;;529:4;484:50;;269:271;-1:-1:-1;;269:271:1:o;545:220::-;694:2;683:9;676:21;657:4;714:45;755:2;744:9;740:18;732:6;714:45;:::i;770:131::-;-1:-1:-1;;;;;845:31:1;;835:42;;825:70;;891:1;888;881:12;906:315;974:6;982;1035:2;1023:9;1014:7;1010:23;1006:32;1003:52;;;1051:1;1048;1041:12;1003:52;1090:9;1077:23;1109:31;1134:5;1109:31;:::i;:::-;1159:5;1211:2;1196:18;;;;1183:32;;-1:-1:-1;;;906:315:1:o;1418:158::-;1480:5;1525:3;1516:6;1511:3;1507:16;1503:26;1500:46;;;1542:1;1539;1532:12;1581:360;1669:6;1722:2;1710:9;1701:7;1697:23;1693:32;1690:52;;;1738:1;1735;1728:12;1690:52;1778:9;1765:23;-1:-1:-1;;;;;1803:6:1;1800:30;1797:50;;;1843:1;1840;1833:12;1797:50;1866:69;1927:7;1918:6;1907:9;1903:22;1866:69;:::i;2100:1336::-;2020:12;;2008:25;;2082:4;2071:16;;;2065:23;2049:14;;;2042:47;2466:4;2514:3;2499:19;;2591:2;2629:3;2624:2;2613:9;2609:18;2602:31;2653:6;2688;2682:13;2719:6;2711;2704:22;2757:3;2746:9;2742:19;2735:26;;2820:3;2810:6;2807:1;2803:14;2792:9;2788:30;2784:40;2770:54;;2843:4;2882;2874:6;2870:17;2905:1;2915:429;2929:6;2926:1;2923:13;2915:429;;;2994:22;;;-1:-1:-1;;2990:37:1;2978:50;;3051:13;;3092:9;;3077:25;;3141:11;;3135:18;3173:15;;;3166:27;;;3216:48;3248:15;;;3135:18;3216:48;:::i;:::-;3206:58;-1:-1:-1;;3322:12:1;;;;3287:15;;;;2951:1;2944:9;2915:429;;;-1:-1:-1;;2020:12:1;;3426:2;3411:18;;2008:25;-1:-1:-1;;;2082:4:1;2071:16;;2065:23;2049:14;;;2042:47;-1:-1:-1;3361:6:1;-1:-1:-1;3376:54:1;1946:149;3649:154;3708:5;3753:2;3744:6;3739:3;3735:16;3731:25;3728:45;;;3769:1;3766;3759:12;3808:347;3859:8;3869:6;3923:3;3916:4;3908:6;3904:17;3900:27;3890:55;;3941:1;3938;3931:12;3890:55;-1:-1:-1;3964:20:1;;-1:-1:-1;;;;;3996:30:1;;3993:50;;;4039:1;4036;4029:12;3993:50;4076:4;4068:6;4064:17;4052:29;;4128:3;4121:4;4112:6;4104;4100:19;4096:30;4093:39;4090:59;;;4145:1;4142;4135:12;4090:59;3808:347;;;;;:::o;4160:1047::-;4302:6;4310;4318;4326;4334;4342;4350;4403:3;4391:9;4382:7;4378:23;4374:33;4371:53;;;4420:1;4417;4410:12;4371:53;4443;4488:7;4477:9;4443:53;:::i;:::-;4433:63;;4543:2;4532:9;4528:18;4515:32;4505:42;;4598:3;4587:9;4583:19;4570:33;-1:-1:-1;;;;;4663:2:1;4655:6;4652:14;4649:34;;;4679:1;4676;4669:12;4649:34;4718:58;4768:7;4759:6;4748:9;4744:22;4718:58;:::i;:::-;4795:8;;-1:-1:-1;4692:84:1;-1:-1:-1;4880:3:1;4865:19;;4852:33;;-1:-1:-1;4894:31:1;4852:33;4894:31;:::i;:::-;4944:5;;-1:-1:-1;5002:3:1;4987:19;;4974:33;;5019:16;;;5016:36;;;5048:1;5045;5038:12;5016:36;;5087:60;5139:7;5128:8;5117:9;5113:24;5087:60;:::i;:::-;4160:1047;;;;-1:-1:-1;4160:1047:1;;-1:-1:-1;4160:1047:1;;;;5061:86;;-1:-1:-1;;;4160:1047:1:o;6192:456::-;6269:6;6277;6285;6338:2;6326:9;6317:7;6313:23;6309:32;6306:52;;;6354:1;6351;6344:12;6306:52;6393:9;6380:23;6412:31;6437:5;6412:31;:::i;:::-;6462:5;-1:-1:-1;6519:2:1;6504:18;;6491:32;6532:33;6491:32;6532:33;:::i;:::-;6192:456;;6584:7;;-1:-1:-1;;;6638:2:1;6623:18;;;;6610:32;;6192:456::o;6842:163::-;6909:20;;6969:10;6958:22;;6948:33;;6938:61;;6995:1;6992;6985:12;6938:61;6842:163;;;:::o;7010:252::-;7077:6;7085;7138:2;7126:9;7117:7;7113:23;7109:32;7106:52;;;7154:1;7151;7144:12;7106:52;7177:28;7195:9;7177:28;:::i;7449:118::-;7535:5;7528:13;7521:21;7514:5;7511:32;7501:60;;7557:1;7554;7547:12;7572:489;7666:6;7674;7727:2;7715:9;7706:7;7702:23;7698:32;7695:52;;;7743:1;7740;7733:12;7695:52;7783:9;7770:23;-1:-1:-1;;;;;7808:6:1;7805:30;7802:50;;;7848:1;7845;7838:12;7802:50;7871:69;7932:7;7923:6;7912:9;7908:22;7871:69;:::i;:::-;7861:79;;;7990:2;7979:9;7975:18;7962:32;8003:28;8025:5;8003:28;:::i;:::-;8050:5;8040:15;;;7572:489;;;;;:::o;8066:255::-;2020:12;;2008:25;;2082:4;2071:16;;;2065:23;2049:14;;;2042:47;8258:2;8243:18;;8270:45;1946:149;8326:159;8393:20;;8453:6;8442:18;;8432:29;;8422:57;;8475:1;8472;8465:12;8490:256;8556:6;8564;8617:2;8605:9;8596:7;8592:23;8588:32;8585:52;;;8633:1;8630;8623:12;8585:52;8656:28;8674:9;8656:28;:::i;:::-;8646:38;;8703:37;8736:2;8725:9;8721:18;8703:37;:::i;:::-;8693:47;;8490:256;;;;;:::o;9210:247::-;9269:6;9322:2;9310:9;9301:7;9297:23;9293:32;9290:52;;;9338:1;9335;9328:12;9290:52;9377:9;9364:23;9396:31;9421:5;9396:31;:::i;9667:669::-;9780:6;9788;9796;9804;9857:3;9845:9;9836:7;9832:23;9828:33;9825:53;;;9874:1;9871;9864:12;9825:53;9897;9942:7;9931:9;9897:53;:::i;:::-;9887:63;;10001:2;9990:9;9986:18;9973:32;-1:-1:-1;;;;;10020:6:1;10017:30;10014:50;;;10060:1;10057;10050:12;10014:50;10099:58;10149:7;10140:6;10129:9;10125:22;10099:58;:::i;:::-;10176:8;;-1:-1:-1;10073:84:1;-1:-1:-1;;10261:3:1;10246:19;;10233:33;10275:31;10233:33;10275:31;:::i;:::-;9667:669;;;;-1:-1:-1;9667:669:1;;-1:-1:-1;;9667:669:1:o;10341:395::-;10432:8;10442:6;10496:3;10489:4;10481:6;10477:17;10473:27;10463:55;;10514:1;10511;10504:12;10463:55;-1:-1:-1;10537:20:1;;-1:-1:-1;;;;;10569:30:1;;10566:50;;;10612:1;10609;10602:12;10566:50;10649:4;10641:6;10637:17;10625:29;;10709:3;10702:4;10692:6;10689:1;10685:14;10677:6;10673:27;10669:38;10666:47;10663:67;;;10726:1;10723;10716:12;10741:503;10865:6;10873;10926:2;10914:9;10905:7;10901:23;10897:32;10894:52;;;10942:1;10939;10932:12;10894:52;10982:9;10969:23;-1:-1:-1;;;;;11007:6:1;11004:30;11001:50;;;11047:1;11044;11037:12;11001:50;11086:98;11176:7;11167:6;11156:9;11152:22;11086:98;:::i;:::-;11203:8;;11060:124;;-1:-1:-1;10741:503:1;-1:-1:-1;;;;10741:503:1:o;11249:184::-;11307:6;11360:2;11348:9;11339:7;11335:23;11331:32;11328:52;;;11376:1;11373;11366:12;11328:52;11399:28;11417:9;11399:28;:::i;11438:553::-;11524:6;11532;11540;11548;11601:2;11589:9;11580:7;11576:23;11572:32;11569:52;;;11617:1;11614;11607:12;11569:52;11640:28;11658:9;11640:28;:::i;:::-;11630:38;;11687:37;11720:2;11709:9;11705:18;11687:37;:::i;:::-;11677:47;;11775:2;11764:9;11760:18;11747:32;-1:-1:-1;;;;;11794:6:1;11791:30;11788:50;;;11834:1;11831;11824:12;11788:50;11873:58;11923:7;11914:6;11903:9;11899:22;11873:58;:::i;:::-;11438:553;;;;-1:-1:-1;11950:8:1;-1:-1:-1;;;;11438:553:1:o;12499:656::-;12636:6;12644;12652;12696:9;12687:7;12683:23;12726:3;12722:2;12718:12;12715:32;;;12743:1;12740;12733:12;12715:32;12783:9;12770:23;-1:-1:-1;;;;;12808:6:1;12805:30;12802:50;;;12848:1;12845;12838:12;12802:50;12871:69;12932:7;12923:6;12912:9;12908:22;12871:69;:::i;:::-;12861:79;-1:-1:-1;;12974:2:1;-1:-1:-1;;12956:16:1;;12952:25;12949:45;;;12990:1;12987;12980:12;12949:45;;13028:2;13017:9;13013:18;13003:28;;13081:2;13070:9;13066:18;13053:32;13094:31;13119:5;13094:31;:::i;:::-;13144:5;13134:15;;;12499:656;;;;;:::o;13160:611::-;13402:4;13444:3;13433:9;13429:19;13421:27;;13481:6;13475:13;13464:9;13457:32;-1:-1:-1;;;;;13549:4:1;13541:6;13537:17;13531:24;13527:49;13520:4;13509:9;13505:20;13498:79;13624:4;13616:6;13612:17;13606:24;13639:62;13695:4;13684:9;13680:20;13666:12;2020;;2008:25;;2082:4;2071:16;;;2065:23;2049:14;;2042:47;1946:149;13639:62;-1:-1:-1;2020:12:1;;13760:3;13745:19;;2008:25;2082:4;2071:16;;2065:23;2049:14;;;2042:47;13710:55;1946:149;13776:829;13887:6;13895;13903;13911;13919;13927;13935;13988:3;13976:9;13967:7;13963:23;13959:33;13956:53;;;14005:1;14002;13995:12;13956:53;14044:9;14031:23;14063:31;14088:5;14063:31;:::i;:::-;14113:5;-1:-1:-1;14170:2:1;14155:18;;14142:32;14183:33;14142:32;14183:33;:::i;:::-;14235:7;-1:-1:-1;14289:2:1;14274:18;;14261:32;;-1:-1:-1;14340:2:1;14325:18;;14312:32;;-1:-1:-1;14396:3:1;14381:19;;14368:33;14445:4;14432:18;;14420:31;;14410:59;;14465:1;14462;14455:12;14410:59;13776:829;;;;-1:-1:-1;13776:829:1;;;;14488:7;14542:3;14527:19;;14514:33;;-1:-1:-1;14594:3:1;14579:19;;;14566:33;;13776:829;-1:-1:-1;;13776:829:1:o;14610:388::-;14678:6;14686;14739:2;14727:9;14718:7;14714:23;14710:32;14707:52;;;14755:1;14752;14745:12;14707:52;14794:9;14781:23;14813:31;14838:5;14813:31;:::i;:::-;14863:5;-1:-1:-1;14920:2:1;14905:18;;14892:32;14933:33;14892:32;14933:33;:::i;15003:235::-;15087:6;15140:2;15128:9;15119:7;15115:23;15111:32;15108:52;;;15156:1;15153;15146:12;15108:52;15179:53;15224:7;15213:9;15179:53;:::i;15243:380::-;15322:1;15318:12;;;;15365;;;15386:61;;15440:4;15432:6;15428:17;15418:27;;15386:61;15493:2;15485:6;15482:14;15462:18;15459:38;15456:161;;15539:10;15534:3;15530:20;15527:1;15520:31;15574:4;15571:1;15564:15;15602:4;15599:1;15592:15;15628:127;15689:10;15684:3;15680:20;15677:1;15670:31;15720:4;15717:1;15710:15;15744:4;15741:1;15734:15;16028:127;16089:10;16084:3;16080:20;16077:1;16070:31;16120:4;16117:1;16110:15;16144:4;16141:1;16134:15;16160:125;16225:9;;;16246:10;;;16243:36;;;16259:18;;:::i;16696:253::-;16768:2;16762:9;16810:4;16798:17;;-1:-1:-1;;;;;16830:34:1;;16866:22;;;16827:62;16824:88;;;16892:18;;:::i;:::-;16928:2;16921:22;16696:253;:::o;16954:251::-;17026:2;17020:9;;;17056:15;;-1:-1:-1;;;;;17086:34:1;;17122:22;;;17083:62;17080:88;;;17148:18;;:::i;17210:275::-;17281:2;17275:9;17346:2;17327:13;;-1:-1:-1;;17323:27:1;17311:40;;-1:-1:-1;;;;;17366:34:1;;17402:22;;;17363:62;17360:88;;;17428:18;;:::i;:::-;17464:2;17457:22;17210:275;;-1:-1:-1;17210:275:1:o;17490:186::-;17538:4;-1:-1:-1;;;;;17563:6:1;17560:30;17557:56;;;17593:18;;:::i;:::-;-1:-1:-1;17659:2:1;17638:15;-1:-1:-1;;17634:29:1;17665:4;17630:40;;17490:186::o;17681:2115::-;17871:9;-1:-1:-1;;;;;17946:2:1;17938:6;17935:14;17932:40;;;17952:18;;:::i;:::-;17998:6;17995:1;17991:14;18024:4;18048:28;18072:2;18068;18064:11;18048:28;:::i;:::-;18110:19;;;18180:14;;;;18145:12;;;;18217:14;18206:26;;18203:46;;;18245:1;18242;18235:12;18203:46;18269:5;18283:1480;18299:6;18294:3;18291:15;18283:1480;;;18385:3;18372:17;18421:2;18408:11;18405:19;18402:109;;;18465:1;18494:2;18490;18483:14;18402:109;18534:23;;18602:4;18581:14;18577:23;;;18573:34;18570:124;;;18648:1;18677:2;18673;18666:14;18570:124;18722:22;;:::i;:::-;18773:21;18791:2;18773:21;:::i;:::-;18764:7;18757:38;18833:30;18859:2;18855;18851:11;18833:30;:::i;:::-;18828:2;18819:7;18815:16;18808:56;18887:2;18937;18933;18929:11;18916:25;18968:2;18960:6;18957:14;18954:104;;;19012:1;19041:2;19037;19030:14;18954:104;19081:15;;;;;19138:14;19131:4;19123:13;;19119:34;19109:135;;19196:1;19226:3;19221;19214:16;19109:135;19281:2;19268:16;19310:49;19326:32;19354:3;19326:32;:::i;:::-;19310:49;:::i;:::-;19386:3;19379:5;19372:18;19432:14;19427:2;19421:3;19417:2;19413:12;19409:21;19406:41;19403:134;;;19489:1;19519:3;19514;19507:16;19403:134;19592:3;19587:2;19583;19579:11;19574:2;19567:5;19563:14;19550:46;19642:1;19620:15;;;19616:24;;19609:35;;;;19664:16;;;19657:31;19701:20;;-1:-1:-1;19741:12:1;;;;18316;;18283:1480;;;-1:-1:-1;19785:5:1;17681:2115;-1:-1:-1;;;;;;;17681:2115:1:o;19801:331::-;19906:9;19917;19959:8;19947:10;19944:24;19941:44;;;19981:1;19978;19971:12;19941:44;20010:6;20000:8;19997:20;19994:40;;;20030:1;20027;20020:12;19994:40;-1:-1:-1;;20056:23:1;;;20101:25;;;;;-1:-1:-1;19801:331:1:o;20137:476::-;20328:3;20366:6;20360:13;20382:66;20441:6;20436:3;20429:4;20421:6;20417:17;20382:66;:::i;:::-;20470:16;;20523:6;20515;20470:16;20495:35;20587:1;20549:18;;20576:13;;;-1:-1:-1;20549:18:1;;20137:476;-1:-1:-1;;;20137:476:1:o;20618:266::-;20706:6;20701:3;20694:19;20758:6;20751:5;20744:4;20739:3;20735:14;20722:43;-1:-1:-1;20810:1:1;20785:16;;;20803:4;20781:27;;;20774:38;;;;20866:2;20845:15;;;-1:-1:-1;;20841:29:1;20832:39;;;20828:50;;20618:266::o;20889:244::-;21046:2;21035:9;21028:21;21009:4;21066:61;21123:2;21112:9;21108:18;21100:6;21092;21066:61;:::i;21138:127::-;21199:10;21194:3;21190:20;21187:1;21180:31;21230:4;21227:1;21220:15;21254:4;21251:1;21244:15;21270:331;21369:4;21427:11;21414:25;21521:3;21517:8;21506;21490:14;21486:29;21482:44;21462:18;21458:69;21448:97;;21541:1;21538;21531:12;21448:97;21562:33;;;;;21270:331;-1:-1:-1;;21270:331:1:o;21606:521::-;21683:4;21689:6;21749:11;21736:25;21843:2;21839:7;21828:8;21812:14;21808:29;21804:43;21784:18;21780:68;21770:96;;21862:1;21859;21852:12;21770:96;21889:33;;21941:20;;;-1:-1:-1;;;;;;21973:30:1;;21970:50;;;22016:1;22013;22006:12;21970:50;22049:4;22037:17;;-1:-1:-1;22080:14:1;22076:27;;;22066:38;;22063:58;;;22117:1;22114;22107:12;22132:129;-1:-1:-1;;;;;22210:5:1;22206:30;22199:5;22196:41;22186:69;;22251:1;22248;22241:12;22266:990;22642:10;22615:25;22633:6;22615:25;:::i;:::-;22611:42;22600:9;22593:61;22717:4;22709:6;22705:17;22692:31;22685:4;22674:9;22670:20;22663:61;22574:4;22771;22763:6;22759:17;22746:31;22786:30;22810:5;22786:30;:::i;:::-;-1:-1:-1;;;;;22858:5:1;22854:30;22847:4;22836:9;22832:20;22825:60;;22921:6;22916:2;22905:9;22901:18;22894:34;22965:3;22959;22948:9;22944:19;22937:32;22992:62;23049:3;23038:9;23034:19;23026:6;23018;22992:62;:::i;:::-;-1:-1:-1;;;;;23091:32:1;;23111:3;23070:19;;23063:61;23161:22;;;23155:3;23140:19;;23133:51;23201:49;23165:6;23235;23227;23201:49;:::i;:::-;23193:57;22266:990;-1:-1:-1;;;;;;;;;;22266:990:1:o;23261:647::-;23340:6;23393:2;23381:9;23372:7;23368:23;23364:32;23361:52;;;23409:1;23406;23399:12;23361:52;23442:9;23436:16;-1:-1:-1;;;;;23467:6:1;23464:30;23461:50;;;23507:1;23504;23497:12;23461:50;23530:22;;23583:4;23575:13;;23571:27;-1:-1:-1;23561:55:1;;23612:1;23609;23602:12;23561:55;23641:2;23635:9;23666:48;23682:31;23710:2;23682:31;:::i;23666:48::-;23737:2;23730:5;23723:17;23777:7;23772:2;23767;23763;23759:11;23755:20;23752:33;23749:53;;;23798:1;23795;23788:12;23749:53;23811:67;23875:2;23870;23863:5;23859:14;23854:2;23850;23846:11;23811:67;:::i;23913:347::-;24001:6;24054:2;24042:9;24033:7;24029:23;24025:32;24022:52;;;24070:1;24067;24060:12;24022:52;24096:22;;:::i;:::-;24154:9;24141:23;24134:5;24127:38;24225:2;24214:9;24210:18;24197:32;24192:2;24185:5;24181:14;24174:56;24249:5;24239:15;;;23913:347;;;;:::o;27582:245::-;27640:6;27693:2;27681:9;27672:7;27668:23;27664:32;27661:52;;;27709:1;27706;27699:12;27661:52;27748:9;27735:23;27767:30;27791:5;27767:30;:::i;27832:479::-;28099:1;28095;28090:3;28086:11;28082:19;28074:6;28070:32;28059:9;28052:51;28139:6;28134:2;28123:9;28119:18;28112:34;28194:6;28186;28182:19;28177:2;28166:9;28162:18;28155:47;28238:3;28233:2;28222:9;28218:18;28211:31;28033:4;28259:46;28300:3;28289:9;28285:19;28277:6;28259:46;:::i;30520:379::-;30713:2;30702:9;30695:21;30676:4;30739:45;30780:2;30769:9;30765:18;30757:6;30739:45;:::i;:::-;30832:9;30824:6;30820:22;30815:2;30804:9;30800:18;30793:50;30860:33;30886:6;30878;30860:33;:::i;30904:245::-;30971:6;31024:2;31012:9;31003:7;30999:23;30995:32;30992:52;;;31040:1;31037;31030:12;30992:52;31072:9;31066:16;31091:28;31113:5;31091:28;:::i;31154:889::-;31375:2;31364:9;31357:21;31433:10;31424:6;31418:13;31414:30;31409:2;31398:9;31394:18;31387:58;31499:4;31491:6;31487:17;31481:24;31476:2;31465:9;31461:18;31454:52;31338:4;31553:2;31545:6;31541:15;31535:22;31594:4;31588:3;31577:9;31573:19;31566:33;31622:52;31669:3;31658:9;31654:19;31640:12;31622:52;:::i;:::-;31608:66;;31723:2;31715:6;31711:15;31705:22;31797:2;31793:7;31781:9;31773:6;31769:22;31765:36;31758:4;31747:9;31743:20;31736:66;31825:41;31859:6;31843:14;31825:41;:::i;:::-;31935:3;31923:16;;;;31917:23;31910:31;31903:39;31897:3;31882:19;;31875:68;-1:-1:-1;;;;;;;;32004:32:1;;;;31997:4;31982:20;;;31975:62;31811:55;31154:889::o;32048:284::-;32118:5;32166:4;32154:9;32149:3;32145:19;32141:30;32138:50;;;32184:1;32181;32174:12;32138:50;32206:22;;:::i;:::-;32197:31;;32257:9;32251:16;32244:5;32237:31;32321:2;32310:9;32306:18;32300:25;32295:2;32288:5;32284:14;32277:49;32048:284;;;;:::o;32337:258::-;32436:6;32489:2;32477:9;32468:7;32464:23;32460:32;32457:52;;;32505:1;32502;32495:12;32457:52;32528:61;32581:7;32570:9;32528:61;:::i;32725:542::-;32826:2;32821:3;32818:11;32815:446;;;32862:1;32886:5;32883:1;32876:16;32930:4;32927:1;32917:18;33000:2;32988:10;32984:19;32981:1;32977:27;32971:4;32967:38;33036:4;33024:10;33021:20;33018:47;;;-1:-1:-1;33059:4:1;33018:47;33114:2;33109:3;33105:12;33102:1;33098:20;33092:4;33088:31;33078:41;;33169:82;33187:2;33180:5;33177:13;33169:82;;;33232:17;;;33213:1;33202:13;33169:82;;;33173:3;;;32725:542;;;:::o;33443:1341::-;33567:3;33561:10;-1:-1:-1;;;;;33586:6:1;33583:30;33580:56;;;33616:18;;:::i;:::-;33645:96;33734:6;33694:38;33726:4;33720:11;33694:38;:::i;:::-;33688:4;33645:96;:::i;:::-;33796:4;;33853:2;33842:14;;33870:1;33865:662;;;;34571:1;34588:6;34585:89;;;-1:-1:-1;34640:19:1;;;34634:26;34585:89;-1:-1:-1;;33400:1:1;33396:11;;;33392:24;33388:29;33378:40;33424:1;33420:11;;;33375:57;34687:81;;33835:943;;33865:662;32672:1;32665:14;;;32709:4;32696:18;;-1:-1:-1;;33901:20:1;;;34018:236;34032:7;34029:1;34026:14;34018:236;;;34121:19;;;34115:26;34100:42;;34213:27;;;;34181:1;34169:14;;;;34048:19;;34018:236;;;34022:3;34282:6;34273:7;34270:19;34267:201;;;34343:19;;;34337:26;-1:-1:-1;;34426:1:1;34422:14;;;34438:3;34418:24;34414:37;34410:42;34395:58;34380:74;;34267:201;-1:-1:-1;;;;;34514:1:1;34498:14;;;34494:22;34481:36;;-1:-1:-1;33443:1341:1:o;34789:1162::-;35003:4;35032:2;35072;35061:9;35057:18;35102:2;35091:9;35084:21;35125:6;35160;35154:13;35191:6;35183;35176:22;35217:2;35207:12;;35250:2;35239:9;35235:18;35228:25;;35312:2;35302:6;35299:1;35295:14;35284:9;35280:30;35276:39;35350:2;35342:6;35338:15;35371:1;35381:541;35395:6;35392:1;35389:13;35381:541;;;35460:22;;;-1:-1:-1;;35456:36:1;35444:49;;35516:13;;35588:9;;35599:10;35584:26;35569:42;;35658:11;;;35652:18;35672:6;35648:31;35631:15;;;35624:56;35719:11;;35713:18;35552:4;35751:15;;;35744:27;;;35794:48;35826:15;;;35713:18;35794:48;:::i;:::-;35900:12;;;;35784:58;-1:-1:-1;;;35865:15:1;;;;35417:1;35410:9;35381:541;;;-1:-1:-1;35939:6:1;;34789:1162;-1:-1:-1;;;;;;;;34789:1162:1:o;35956:524::-;36059:6;36112:3;36100:9;36091:7;36087:23;36083:33;36080:53;;;36129:1;36126;36119:12;36080:53;36155:22;;:::i;:::-;36206:9;36200:16;36193:5;36186:31;36262:2;36251:9;36247:18;36241:25;36275:32;36299:7;36275:32;:::i;:::-;36334:2;36323:14;;36316:31;36379:70;36441:7;36436:2;36421:18;;36379:70;:::i;:::-;36374:2;36363:14;;36356:94;36367:5;35956:524;-1:-1:-1;;;35956:524:1:o;36485:217::-;36525:1;36551;36541:132;;36595:10;36590:3;36586:20;36583:1;36576:31;36630:4;36627:1;36620:15;36658:4;36655:1;36648:15;36541:132;-1:-1:-1;36687:9:1;;36485:217::o;36707:168::-;36780:9;;;36811;;36828:15;;;36822:22;;36808:37;36798:71;;36849:18;;:::i;36880:255::-;37000:19;;37039:2;37031:11;;37028:101;;;-1:-1:-1;;37100:2:1;37096:12;;;37093:1;37089:20;37085:33;37074:45;36880:255;;;;:::o;37140:331::-;-1:-1:-1;;;;;;37260:19:1;;37344:11;;;;37375:1;37367:10;;37364:101;;;37452:2;37446;37439:3;37436:1;37432:11;37429:1;37425:19;37421:28;37417:2;37413:37;37409:46;37400:55;;37364:101;;;37140:331;;;;:::o;37476:568::-;-1:-1:-1;;;;;37741:3:1;37737:28;37728:6;37723:3;37719:16;37715:51;37710:3;37703:64;37827:10;37822:3;37818:20;37809:6;37804:3;37800:16;37796:43;37792:1;37787:3;37783:11;37776:64;37870:6;37865:2;37860:3;37856:12;37849:28;37685:3;37906:6;37900:13;37922:75;37990:6;37985:2;37980:3;37976:12;37969:4;37961:6;37957:17;37922:75;:::i;:::-;38017:16;;;;38035:2;38013:25;;37476:568;-1:-1:-1;;;;;37476:568:1:o;38838:532::-;39079:6;39074:3;39067:19;-1:-1:-1;;;;;39142:3:1;39138:28;39129:6;39124:3;39120:16;39116:51;39111:2;39106:3;39102:12;39095:73;39198:6;39193:2;39188:3;39184:12;39177:28;39049:3;39234:6;39228:13;39250:73;39316:6;39311:2;39306:3;39302:12;39297:2;39289:6;39285:15;39250:73;:::i;:::-;39343:16;;;;39361:2;39339:25;;38838:532;-1:-1:-1;;;;;38838:532:1:o;40180:251::-;40250:6;40303:2;40291:9;40282:7;40278:23;40274:32;40271:52;;;40319:1;40316;40309:12;40271:52;40351:9;40345:16;40370:31;40395:5;40370:31;:::i;41236:127::-;41297:10;41292:3;41288:20;41285:1;41278:31;41328:4;41325:1;41318:15;41352:4;41349:1;41342:15;44042:287;44171:3;44209:6;44203:13;44225:66;44284:6;44279:3;44272:4;44264:6;44260:17;44225:66;:::i

Swarm Source

ipfs://15896e89c7b056e0c3d5861a0b299c70d4df5ed8f71f89fd49c054cc8b4280d2
Loading...
Loading
Loading...
Loading
[ Download: CSV Export  ]
[ Download: CSV Export  ]

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