BNB Price: $628.57 (-0.51%)
 

Overview

Max Total Supply

11,836,719.664085RION

Holders

16,088

Transfers

-
0

Market

Price

$0.00 @ 0.000000 BNB

Onchain Market Cap

-

Circulating Supply Market Cap

-

Other Info

Token Contract (WITH 18 Decimals)

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

Click here to update the token information / general information

Contract Source Code Verified (Exact Match)

Contract Name:
HyperionOFT

Compiler Version
v0.8.22+commit.4fc1097e

Optimization Enabled:
Yes with 200 runs

Other Settings:
paris EvmVersion, MIT license
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.22;

import { Pausable } from "@openzeppelin/contracts/utils/Pausable.sol";
import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import { OFT } from "@layerzerolabs/oft-evm/contracts/OFT.sol";

contract HyperionOFT is OFT, Pausable {

    uint256 public constant NORMAL = 0;
    uint256 public constant RESTRICTED = 1;
    uint256 public constant CONTROLLED = 2;
    uint256 public _mode;
    address public _modeAdmin;

    // Blacklist
    mapping(address => bool) public isBlackListed;

    event SetBlackList(address account, bool state);
    event ChangeModeAdmin(address prevModeAdmin, address newModeAdmin);
    event SwitchTransferMode(uint256 prevMode, uint256 newMode);
    event PausedOrNot(bool pauseStatus);

    constructor(
        string memory _name,
        string memory _symbol,
        address _lzEndpoint,
        address _delegate
    ) OFT(_name, _symbol, _lzEndpoint, _delegate) Ownable(_delegate) {
        _mode = CONTROLLED;
        _modeAdmin = _delegate;
    }

    function _update(address from, address to, uint256 value) internal override whenNotPaused {
        if (_mode == RESTRICTED) {
            revert("Token: Transfer is restricted");
        }
        if (_mode == CONTROLLED) {
            require(from == _modeAdmin || to == _modeAdmin, "Token: Invalid transfer");
        }
        require(!isBlackListed[from], "from is in blackList");
        require(!isBlackListed[to], "to is in blackList");
        super._update(from, to, value);
    }

    function setTransferMode(uint256 v) external onlyModeAdmin() {
        uint256 prevMode = _mode;
        require(v == NORMAL || v == RESTRICTED || v == CONTROLLED, "Invalid mode");
        if (_mode != NORMAL) {
            _mode = v;
            emit SwitchTransferMode(prevMode, _mode);
        }
    }

    function setBlackList(address account, bool state) public onlyOwner {
        isBlackListed[account] = state;
        emit SetBlackList(account, state);
    }

    function isBlocked(address account) public view returns(bool) {
        return isBlackListed[account];
    }

    function transferModeAdmin(address newModeAdmin) public onlyOwner() {
        address prevModeAdmin = _modeAdmin;
        _modeAdmin = newModeAdmin;
        emit ChangeModeAdmin(prevModeAdmin, newModeAdmin);
    }

    modifier onlyModeAdmin() {
        require(_modeAdmin == _msgSender(), "Caller is not the mode admin");
        _;
    }

    function setPaused(bool _paused) external onlyOwner {
        if (_paused) {
            _pause();
        } else {
            _unpause();
        }
        emit PausedOrNot(_paused);
    }

    function isTransferController(address account) external view returns (bool) {
        return account == _modeAdmin;
    }

    function recoverERC20(address token, address to, uint256 amount) external onlyOwner {
        require(to != address(0), "Cannot send to zero address");
        IERC20(token).transfer(to, amount);
    }

  
}

// SPDX-License-Identifier: MIT

pragma solidity >=0.8.0;

import { IMessageLibManager } from "./IMessageLibManager.sol";
import { IMessagingComposer } from "./IMessagingComposer.sol";
import { IMessagingChannel } from "./IMessagingChannel.sol";
import { IMessagingContext } from "./IMessagingContext.sol";

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

// SPDX-License-Identifier: MIT

pragma solidity >=0.8.0;

import { Origin } from "./ILayerZeroEndpointV2.sol";

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

// SPDX-License-Identifier: MIT

pragma solidity >=0.8.0;

import { IERC165 } from "@openzeppelin/contracts/utils/introspection/IERC165.sol";

import { SetConfigParam } from "./IMessageLibManager.sol";

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

// 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 _gracePeriod) 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 _expiry) 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);
}

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

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

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

// SPDX-License-Identifier: MIT

pragma solidity >=0.8.0;

import { MessagingFee } from "./ILayerZeroEndpointV2.sol";
import { IMessageLib } from "./IMessageLib.sol";

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

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

// SPDX-License-Identifier: LZBL-1.2

pragma solidity ^0.8.20;

import { Packet } from "../../interfaces/ISendLib.sol";
import { AddressCast } from "../../libs/AddressCast.sol";

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

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.20;

import { ILayerZeroEndpointV2 } from "@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroEndpointV2.sol";

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

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

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

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import { ILayerZeroReceiver, Origin } from "@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroReceiver.sol";

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

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.20;

import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
import { IOAppOptionsType3, EnforcedOptionParam } from "../interfaces/IOAppOptionsType3.sol";

/**
 * @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 17 of 41 : OApp.sol
// 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
import { OAppSender, MessagingFee, MessagingReceipt } from "./OAppSender.sol";
// @dev Import the 'Origin' so it's exposed to OApp implementers
// solhint-disable-next-line no-unused-import
import { OAppReceiver, Origin } from "./OAppReceiver.sol";
import { OAppCore } from "./OAppCore.sol";

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

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.20;

import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
import { IOAppCore, ILayerZeroEndpointV2 } from "./interfaces/IOAppCore.sol";

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

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.20;

import { IOAppReceiver, Origin } from "./interfaces/IOAppReceiver.sol";
import { OAppCore } from "./OAppCore.sol";

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

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.20;

import { SafeERC20, IERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import { MessagingParams, MessagingFee, MessagingReceipt } from "@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroEndpointV2.sol";
import { OAppCore } from "./OAppCore.sol";

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

// 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
import { InboundPacket, Origin } from "../libs/Packet.sol";

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

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

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.20;

import { Origin } from "@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroEndpointV2.sol";
import { PacketV1Codec } from "@layerzerolabs/lz-evm-protocol-v2/contracts/messagelib/libs/PacketV1Codec.sol";

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

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.20;

import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
import { IPreCrime } from "./interfaces/IPreCrime.sol";
import { IOAppPreCrimeSimulator, InboundPacket, Origin } from "./interfaces/IOAppPreCrimeSimulator.sol";

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

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.20;

import { MessagingReceipt, MessagingFee } from "@layerzerolabs/oapp-evm/contracts/oapp/OAppSender.sol";

/**
 * @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 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 the fee breakdown and settings data for an OFT. Unused in the default implementation.
     * @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);
}

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

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

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.20;

import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import { IOFT, OFTCore } from "./OFTCore.sol";

/**
 * @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) {
        if (_to == address(0x0)) _to = address(0xdead); // _mint(...) does not support address(0x0)
        // @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;
    }
}

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.20;

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

import { OApp, Origin } from "@layerzerolabs/oapp-evm/contracts/oapp/OApp.sol";
import { OAppOptionsType3 } from "@layerzerolabs/oapp-evm/contracts/oapp/libs/OAppOptionsType3.sol";
import { IOAppMsgInspector } from "@layerzerolabs/oapp-evm/contracts/oapp/interfaces/IOAppMsgInspector.sol";

import { OAppPreCrimeSimulator } from "@layerzerolabs/oapp-evm/contracts/precrime/OAppPreCrimeSimulator.sol";

import { IOFT, SendParam, OFTLimit, OFTReceipt, OFTFeeDetail, MessagingReceipt, MessagingFee } from "./interfaces/IOFT.sol";
import { OFTMsgCodec } from "./libs/OFTMsgCodec.sol";
import { OFTComposeMsgCodec } from "./libs/OFTComposeMsgCodec.sol";

/**
 * @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 the fee breakdown and settings data for an OFT. Unused in the default implementation.
     * @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 = IERC20(this.token()).totalSupply(); // 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) {
        return _send(_sendParam, _fee, _refundAddress);
    }

    /**
     * @dev Internal function to execute 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
    ) internal 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
        address inspector = msgInspector; // caches the msgInspector to avoid potential double storage read
        if (inspector != address(0)) IOAppMsgInspector(inspector).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);
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)

pragma solidity ^0.8.20;

import {Context} from "../utils/Context.sol";

/**
 * @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.
 *
 * The initial owner is set to the address provided by the deployer. 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;

    /**
     * @dev The caller account is not authorized to perform an operation.
     */
    error OwnableUnauthorizedAccount(address account);

    /**
     * @dev The owner is not a valid owner account. (eg. `address(0)`)
     */
    error OwnableInvalidOwner(address owner);

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

    /**
     * @dev Initializes the contract setting the address provided by the deployer as the initial owner.
     */
    constructor(address initialOwner) {
        if (initialOwner == address(0)) {
            revert OwnableInvalidOwner(address(0));
        }
        _transferOwnership(initialOwner);
    }

    /**
     * @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 {
        if (owner() != _msgSender()) {
            revert OwnableUnauthorizedAccount(_msgSender());
        }
    }

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

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        if (newOwner == address(0)) {
            revert OwnableInvalidOwner(address(0));
        }
        _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);
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/draft-IERC6093.sol)
pragma solidity ^0.8.20;

/**
 * @dev Standard ERC-20 Errors
 * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-20 tokens.
 */
interface IERC20Errors {
    /**
     * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     * @param balance Current balance for the interacting account.
     * @param needed Minimum amount required to perform a transfer.
     */
    error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed);

    /**
     * @dev Indicates a failure with the token `sender`. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     */
    error ERC20InvalidSender(address sender);

    /**
     * @dev Indicates a failure with the token `receiver`. Used in transfers.
     * @param receiver Address to which tokens are being transferred.
     */
    error ERC20InvalidReceiver(address receiver);

    /**
     * @dev Indicates a failure with the `spender`’s `allowance`. Used in transfers.
     * @param spender Address that may be allowed to operate on tokens without being their owner.
     * @param allowance Amount of tokens a `spender` is allowed to operate with.
     * @param needed Minimum amount required to perform a transfer.
     */
    error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed);

    /**
     * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
     * @param approver Address initiating an approval operation.
     */
    error ERC20InvalidApprover(address approver);

    /**
     * @dev Indicates a failure with the `spender` to be approved. Used in approvals.
     * @param spender Address that may be allowed to operate on tokens without being their owner.
     */
    error ERC20InvalidSpender(address spender);
}

/**
 * @dev Standard ERC-721 Errors
 * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-721 tokens.
 */
interface IERC721Errors {
    /**
     * @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in ERC-20.
     * Used in balance queries.
     * @param owner Address of the current owner of a token.
     */
    error ERC721InvalidOwner(address owner);

    /**
     * @dev Indicates a `tokenId` whose `owner` is the zero address.
     * @param tokenId Identifier number of a token.
     */
    error ERC721NonexistentToken(uint256 tokenId);

    /**
     * @dev Indicates an error related to the ownership over a particular token. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     * @param tokenId Identifier number of a token.
     * @param owner Address of the current owner of a token.
     */
    error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner);

    /**
     * @dev Indicates a failure with the token `sender`. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     */
    error ERC721InvalidSender(address sender);

    /**
     * @dev Indicates a failure with the token `receiver`. Used in transfers.
     * @param receiver Address to which tokens are being transferred.
     */
    error ERC721InvalidReceiver(address receiver);

    /**
     * @dev Indicates a failure with the `operator`’s approval. Used in transfers.
     * @param operator Address that may be allowed to operate on tokens without being their owner.
     * @param tokenId Identifier number of a token.
     */
    error ERC721InsufficientApproval(address operator, uint256 tokenId);

    /**
     * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
     * @param approver Address initiating an approval operation.
     */
    error ERC721InvalidApprover(address approver);

    /**
     * @dev Indicates a failure with the `operator` to be approved. Used in approvals.
     * @param operator Address that may be allowed to operate on tokens without being their owner.
     */
    error ERC721InvalidOperator(address operator);
}

/**
 * @dev Standard ERC-1155 Errors
 * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-1155 tokens.
 */
interface IERC1155Errors {
    /**
     * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     * @param balance Current balance for the interacting account.
     * @param needed Minimum amount required to perform a transfer.
     * @param tokenId Identifier number of a token.
     */
    error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId);

    /**
     * @dev Indicates a failure with the token `sender`. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     */
    error ERC1155InvalidSender(address sender);

    /**
     * @dev Indicates a failure with the token `receiver`. Used in transfers.
     * @param receiver Address to which tokens are being transferred.
     */
    error ERC1155InvalidReceiver(address receiver);

    /**
     * @dev Indicates a failure with the `operator`’s approval. Used in transfers.
     * @param operator Address that may be allowed to operate on tokens without being their owner.
     * @param owner Address of the current owner of a token.
     */
    error ERC1155MissingApprovalForAll(address operator, address owner);

    /**
     * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
     * @param approver Address initiating an approval operation.
     */
    error ERC1155InvalidApprover(address approver);

    /**
     * @dev Indicates a failure with the `operator` to be approved. Used in approvals.
     * @param operator Address that may be allowed to operate on tokens without being their owner.
     */
    error ERC1155InvalidOperator(address operator);

    /**
     * @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation.
     * Used in batch transfers.
     * @param idsLength Length of the array of token identifiers
     * @param valuesLength Length of the array of token amounts
     */
    error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength);
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/IERC1363.sol)

pragma solidity ^0.8.20;

import {IERC20} from "./IERC20.sol";
import {IERC165} from "./IERC165.sol";

/**
 * @title IERC1363
 * @dev Interface of the ERC-1363 standard as defined in the https://eips.ethereum.org/EIPS/eip-1363[ERC-1363].
 *
 * Defines an extension interface for ERC-20 tokens that supports executing code on a recipient contract
 * after `transfer` or `transferFrom`, or code on a spender contract after `approve`, in a single transaction.
 */
interface IERC1363 is IERC20, IERC165 {
    /*
     * Note: the ERC-165 identifier for this interface is 0xb0202a11.
     * 0xb0202a11 ===
     *   bytes4(keccak256('transferAndCall(address,uint256)')) ^
     *   bytes4(keccak256('transferAndCall(address,uint256,bytes)')) ^
     *   bytes4(keccak256('transferFromAndCall(address,address,uint256)')) ^
     *   bytes4(keccak256('transferFromAndCall(address,address,uint256,bytes)')) ^
     *   bytes4(keccak256('approveAndCall(address,uint256)')) ^
     *   bytes4(keccak256('approveAndCall(address,uint256,bytes)'))
     */

    /**
     * @dev Moves a `value` amount of tokens from the caller's account to `to`
     * and then calls {IERC1363Receiver-onTransferReceived} on `to`.
     * @param to The address which you want to transfer to.
     * @param value The amount of tokens to be transferred.
     * @return A boolean value indicating whether the operation succeeded unless throwing.
     */
    function transferAndCall(address to, uint256 value) external returns (bool);

    /**
     * @dev Moves a `value` amount of tokens from the caller's account to `to`
     * and then calls {IERC1363Receiver-onTransferReceived} on `to`.
     * @param to The address which you want to transfer to.
     * @param value The amount of tokens to be transferred.
     * @param data Additional data with no specified format, sent in call to `to`.
     * @return A boolean value indicating whether the operation succeeded unless throwing.
     */
    function transferAndCall(address to, uint256 value, bytes calldata data) external returns (bool);

    /**
     * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism
     * and then calls {IERC1363Receiver-onTransferReceived} on `to`.
     * @param from The address which you want to send tokens from.
     * @param to The address which you want to transfer to.
     * @param value The amount of tokens to be transferred.
     * @return A boolean value indicating whether the operation succeeded unless throwing.
     */
    function transferFromAndCall(address from, address to, uint256 value) external returns (bool);

    /**
     * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism
     * and then calls {IERC1363Receiver-onTransferReceived} on `to`.
     * @param from The address which you want to send tokens from.
     * @param to The address which you want to transfer to.
     * @param value The amount of tokens to be transferred.
     * @param data Additional data with no specified format, sent in call to `to`.
     * @return A boolean value indicating whether the operation succeeded unless throwing.
     */
    function transferFromAndCall(address from, address to, uint256 value, bytes calldata data) external returns (bool);

    /**
     * @dev Sets a `value` amount of tokens as the allowance of `spender` over the
     * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.
     * @param spender The address which will spend the funds.
     * @param value The amount of tokens to be spent.
     * @return A boolean value indicating whether the operation succeeded unless throwing.
     */
    function approveAndCall(address spender, uint256 value) external returns (bool);

    /**
     * @dev Sets a `value` amount of tokens as the allowance of `spender` over the
     * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.
     * @param spender The address which will spend the funds.
     * @param value The amount of tokens to be spent.
     * @param data Additional data with no specified format, sent in call to `spender`.
     * @return A boolean value indicating whether the operation succeeded unless throwing.
     */
    function approveAndCall(address spender, uint256 value, bytes calldata data) external returns (bool);
}

File 33 of 41 : IERC165.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC165.sol)

pragma solidity ^0.8.20;

import {IERC165} from "../utils/introspection/IERC165.sol";

File 34 of 41 : IERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC20.sol)

pragma solidity ^0.8.20;

import {IERC20} from "../token/ERC20/IERC20.sol";

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.3.0) (token/ERC20/ERC20.sol)

pragma solidity ^0.8.20;

import {IERC20} from "./IERC20.sol";
import {IERC20Metadata} from "./extensions/IERC20Metadata.sol";
import {Context} from "../../utils/Context.sol";
import {IERC20Errors} from "../../interfaces/draft-IERC6093.sol";

/**
 * @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}.
 *
 * 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].
 *
 * The default value of {decimals} is 18. To change this, you should override
 * this function so it returns a different value.
 *
 * 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 ERC-20
 * applications.
 */
abstract contract ERC20 is Context, IERC20, IERC20Metadata, IERC20Errors {
    mapping(address account => uint256) private _balances;

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

    uint256 private _totalSupply;

    string private _name;
    string private _symbol;

    /**
     * @dev Sets the values for {name} and {symbol}.
     *
     * Both 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 returns (string memory) {
        return _name;
    }

    /**
     * @dev Returns the symbol of the token, usually a shorter version of the
     * name.
     */
    function symbol() public view virtual 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 default value returned by this function, unless
     * it's 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 returns (uint8) {
        return 18;
    }

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

    /**
     * @dev See {IERC20-balanceOf}.
     */
    function balanceOf(address account) public view virtual 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 `value`.
     */
    function transfer(address to, uint256 value) public virtual returns (bool) {
        address owner = _msgSender();
        _transfer(owner, to, value);
        return true;
    }

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

    /**
     * @dev See {IERC20-approve}.
     *
     * NOTE: If `value` 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 value) public virtual returns (bool) {
        address owner = _msgSender();
        _approve(owner, spender, value);
        return true;
    }

    /**
     * @dev See {IERC20-transferFrom}.
     *
     * Skips emitting an {Approval} event indicating an allowance update. This is not
     * required by the ERC. See {xref-ERC20-_approve-address-address-uint256-bool-}[_approve].
     *
     * 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 `value`.
     * - the caller must have allowance for ``from``'s tokens of at least
     * `value`.
     */
    function transferFrom(address from, address to, uint256 value) public virtual returns (bool) {
        address spender = _msgSender();
        _spendAllowance(from, spender, value);
        _transfer(from, to, value);
        return true;
    }

    /**
     * @dev Moves a `value` 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.
     *
     * NOTE: This function is not virtual, {_update} should be overridden instead.
     */
    function _transfer(address from, address to, uint256 value) internal {
        if (from == address(0)) {
            revert ERC20InvalidSender(address(0));
        }
        if (to == address(0)) {
            revert ERC20InvalidReceiver(address(0));
        }
        _update(from, to, value);
    }

    /**
     * @dev Transfers a `value` amount of tokens from `from` to `to`, or alternatively mints (or burns) if `from`
     * (or `to`) is the zero address. All customizations to transfers, mints, and burns should be done by overriding
     * this function.
     *
     * Emits a {Transfer} event.
     */
    function _update(address from, address to, uint256 value) internal virtual {
        if (from == address(0)) {
            // Overflow check required: The rest of the code assumes that totalSupply never overflows
            _totalSupply += value;
        } else {
            uint256 fromBalance = _balances[from];
            if (fromBalance < value) {
                revert ERC20InsufficientBalance(from, fromBalance, value);
            }
            unchecked {
                // Overflow not possible: value <= fromBalance <= totalSupply.
                _balances[from] = fromBalance - value;
            }
        }

        if (to == address(0)) {
            unchecked {
                // Overflow not possible: value <= totalSupply or value <= fromBalance <= totalSupply.
                _totalSupply -= value;
            }
        } else {
            unchecked {
                // Overflow not possible: balance + value is at most totalSupply, which we know fits into a uint256.
                _balances[to] += value;
            }
        }

        emit Transfer(from, to, value);
    }

    /**
     * @dev Creates a `value` amount of tokens and assigns them to `account`, by transferring it from address(0).
     * Relies on the `_update` mechanism
     *
     * Emits a {Transfer} event with `from` set to the zero address.
     *
     * NOTE: This function is not virtual, {_update} should be overridden instead.
     */
    function _mint(address account, uint256 value) internal {
        if (account == address(0)) {
            revert ERC20InvalidReceiver(address(0));
        }
        _update(address(0), account, value);
    }

    /**
     * @dev Destroys a `value` amount of tokens from `account`, lowering the total supply.
     * Relies on the `_update` mechanism.
     *
     * Emits a {Transfer} event with `to` set to the zero address.
     *
     * NOTE: This function is not virtual, {_update} should be overridden instead
     */
    function _burn(address account, uint256 value) internal {
        if (account == address(0)) {
            revert ERC20InvalidSender(address(0));
        }
        _update(account, address(0), value);
    }

    /**
     * @dev Sets `value` 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.
     *
     * Overrides to this logic should be done to the variant with an additional `bool emitEvent` argument.
     */
    function _approve(address owner, address spender, uint256 value) internal {
        _approve(owner, spender, value, true);
    }

    /**
     * @dev Variant of {_approve} with an optional flag to enable or disable the {Approval} event.
     *
     * By default (when calling {_approve}) the flag is set to true. On the other hand, approval changes made by
     * `_spendAllowance` during the `transferFrom` operation set the flag to false. This saves gas by not emitting any
     * `Approval` event during `transferFrom` operations.
     *
     * Anyone who wishes to continue emitting `Approval` events on the`transferFrom` operation can force the flag to
     * true using the following override:
     *
     * ```solidity
     * function _approve(address owner, address spender, uint256 value, bool) internal virtual override {
     *     super._approve(owner, spender, value, true);
     * }
     * ```
     *
     * Requirements are the same as {_approve}.
     */
    function _approve(address owner, address spender, uint256 value, bool emitEvent) internal virtual {
        if (owner == address(0)) {
            revert ERC20InvalidApprover(address(0));
        }
        if (spender == address(0)) {
            revert ERC20InvalidSpender(address(0));
        }
        _allowances[owner][spender] = value;
        if (emitEvent) {
            emit Approval(owner, spender, value);
        }
    }

    /**
     * @dev Updates `owner`'s allowance for `spender` based on spent `value`.
     *
     * Does not update the allowance value in case of infinite allowance.
     * Revert if not enough allowance is available.
     *
     * Does not emit an {Approval} event.
     */
    function _spendAllowance(address owner, address spender, uint256 value) internal virtual {
        uint256 currentAllowance = allowance(owner, spender);
        if (currentAllowance < type(uint256).max) {
            if (currentAllowance < value) {
                revert ERC20InsufficientAllowance(spender, currentAllowance, value);
            }
            unchecked {
                _approve(owner, spender, currentAllowance - value, false);
            }
        }
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/extensions/IERC20Metadata.sol)

pragma solidity ^0.8.20;

import {IERC20} from "../IERC20.sol";

/**
 * @dev Interface for the optional metadata functions from the ERC-20 standard.
 */
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);
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.20;

/**
 * @dev Interface of the ERC-20 standard as defined in the ERC.
 */
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 value of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

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

    /**
     * @dev Moves a `value` amount of 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 value) 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 a `value` amount of tokens 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 value) external returns (bool);

    /**
     * @dev Moves a `value` amount of tokens from `from` to `to` using the
     * allowance mechanism. `value` 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 value) external returns (bool);
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.3.0) (token/ERC20/utils/SafeERC20.sol)

pragma solidity ^0.8.20;

import {IERC20} from "../IERC20.sol";
import {IERC1363} from "../../../interfaces/IERC1363.sol";

/**
 * @title SafeERC20
 * @dev Wrappers around ERC-20 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 {
    /**
     * @dev An operation with an ERC-20 token failed.
     */
    error SafeERC20FailedOperation(address token);

    /**
     * @dev Indicates a failed `decreaseAllowance` request.
     */
    error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);

    /**
     * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,
     * non-reverting calls are assumed to be successful.
     */
    function safeTransfer(IERC20 token, address to, uint256 value) internal {
        _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));
    }

    /**
     * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the
     * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.
     */
    function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
        _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));
    }

    /**
     * @dev Variant of {safeTransfer} that returns a bool instead of reverting if the operation is not successful.
     */
    function trySafeTransfer(IERC20 token, address to, uint256 value) internal returns (bool) {
        return _callOptionalReturnBool(token, abi.encodeCall(token.transfer, (to, value)));
    }

    /**
     * @dev Variant of {safeTransferFrom} that returns a bool instead of reverting if the operation is not successful.
     */
    function trySafeTransferFrom(IERC20 token, address from, address to, uint256 value) internal returns (bool) {
        return _callOptionalReturnBool(token, abi.encodeCall(token.transferFrom, (from, to, value)));
    }

    /**
     * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
     * non-reverting calls are assumed to be successful.
     *
     * IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the "client"
     * smart contract uses ERC-7674 to set temporary allowances, then the "client" smart contract should avoid using
     * this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract
     * that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.
     */
    function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
        uint256 oldAllowance = token.allowance(address(this), spender);
        forceApprove(token, spender, oldAllowance + value);
    }

    /**
     * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no
     * value, non-reverting calls are assumed to be successful.
     *
     * IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the "client"
     * smart contract uses ERC-7674 to set temporary allowances, then the "client" smart contract should avoid using
     * this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract
     * that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.
     */
    function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {
        unchecked {
            uint256 currentAllowance = token.allowance(address(this), spender);
            if (currentAllowance < requestedDecrease) {
                revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);
            }
            forceApprove(token, spender, currentAllowance - requestedDecrease);
        }
    }

    /**
     * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,
     * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval
     * to be set to zero before setting it to a non-zero value, such as USDT.
     *
     * NOTE: If the token implements ERC-7674, this function will not modify any temporary allowance. This function
     * only sets the "standard" allowance. Any temporary allowance will remain active, in addition to the value being
     * set here.
     */
    function forceApprove(IERC20 token, address spender, uint256 value) internal {
        bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));

        if (!_callOptionalReturnBool(token, approvalCall)) {
            _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));
            _callOptionalReturn(token, approvalCall);
        }
    }

    /**
     * @dev Performs an {ERC1363} transferAndCall, with a fallback to the simple {ERC20} transfer if the target has no
     * code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when
     * targeting contracts.
     *
     * Reverts if the returned value is other than `true`.
     */
    function transferAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {
        if (to.code.length == 0) {
            safeTransfer(token, to, value);
        } else if (!token.transferAndCall(to, value, data)) {
            revert SafeERC20FailedOperation(address(token));
        }
    }

    /**
     * @dev Performs an {ERC1363} transferFromAndCall, with a fallback to the simple {ERC20} transferFrom if the target
     * has no code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when
     * targeting contracts.
     *
     * Reverts if the returned value is other than `true`.
     */
    function transferFromAndCallRelaxed(
        IERC1363 token,
        address from,
        address to,
        uint256 value,
        bytes memory data
    ) internal {
        if (to.code.length == 0) {
            safeTransferFrom(token, from, to, value);
        } else if (!token.transferFromAndCall(from, to, value, data)) {
            revert SafeERC20FailedOperation(address(token));
        }
    }

    /**
     * @dev Performs an {ERC1363} approveAndCall, with a fallback to the simple {ERC20} approve if the target has no
     * code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when
     * targeting contracts.
     *
     * NOTE: When the recipient address (`to`) has no code (i.e. is an EOA), this function behaves as {forceApprove}.
     * Opposedly, when the recipient address (`to`) has code, this function only attempts to call {ERC1363-approveAndCall}
     * once without retrying, and relies on the returned value to be true.
     *
     * Reverts if the returned value is other than `true`.
     */
    function approveAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {
        if (to.code.length == 0) {
            forceApprove(token, to, value);
        } else if (!token.approveAndCall(to, value, data)) {
            revert SafeERC20FailedOperation(address(token));
        }
    }

    /**
     * @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).
     *
     * This is a variant of {_callOptionalReturnBool} that reverts if call fails to meet the requirements.
     */
    function _callOptionalReturn(IERC20 token, bytes memory data) private {
        uint256 returnSize;
        uint256 returnValue;
        assembly ("memory-safe") {
            let success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20)
            // bubble errors
            if iszero(success) {
                let ptr := mload(0x40)
                returndatacopy(ptr, 0, returndatasize())
                revert(ptr, returndatasize())
            }
            returnSize := returndatasize()
            returnValue := mload(0)
        }

        if (returnSize == 0 ? address(token).code.length == 0 : returnValue != 1) {
            revert SafeERC20FailedOperation(address(token));
        }
    }

    /**
     * @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).
     *
     * This is a variant of {_callOptionalReturn} that silently catches all reverts and returns a bool instead.
     */
    function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
        bool success;
        uint256 returnSize;
        uint256 returnValue;
        assembly ("memory-safe") {
            success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20)
            returnSize := returndatasize()
            returnValue := mload(0)
        }
        return success && (returnSize == 0 ? address(token).code.length > 0 : returnValue == 1);
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)

pragma solidity ^0.8.20;

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

    function _contextSuffixLength() internal view virtual returns (uint256) {
        return 0;
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol)

pragma solidity ^0.8.20;

/**
 * @dev Interface of the ERC-165 standard, as defined in the
 * https://eips.ethereum.org/EIPS/eip-165[ERC].
 *
 * 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[ERC 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);
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.3.0) (utils/Pausable.sol)

pragma solidity ^0.8.20;

import {Context} from "../utils/Context.sol";

/**
 * @dev Contract module which allows children to implement an emergency stop
 * mechanism that can be triggered by an authorized account.
 *
 * This module is used through inheritance. It will make available the
 * modifiers `whenNotPaused` and `whenPaused`, which can be applied to
 * the functions of your contract. Note that they will not be pausable by
 * simply including this module, only once the modifiers are put in place.
 */
abstract contract Pausable is Context {
    bool private _paused;

    /**
     * @dev Emitted when the pause is triggered by `account`.
     */
    event Paused(address account);

    /**
     * @dev Emitted when the pause is lifted by `account`.
     */
    event Unpaused(address account);

    /**
     * @dev The operation failed because the contract is paused.
     */
    error EnforcedPause();

    /**
     * @dev The operation failed because the contract is not paused.
     */
    error ExpectedPause();

    /**
     * @dev Modifier to make a function callable only when the contract is not paused.
     *
     * Requirements:
     *
     * - The contract must not be paused.
     */
    modifier whenNotPaused() {
        _requireNotPaused();
        _;
    }

    /**
     * @dev Modifier to make a function callable only when the contract is paused.
     *
     * Requirements:
     *
     * - The contract must be paused.
     */
    modifier whenPaused() {
        _requirePaused();
        _;
    }

    /**
     * @dev Returns true if the contract is paused, and false otherwise.
     */
    function paused() public view virtual returns (bool) {
        return _paused;
    }

    /**
     * @dev Throws if the contract is paused.
     */
    function _requireNotPaused() internal view virtual {
        if (paused()) {
            revert EnforcedPause();
        }
    }

    /**
     * @dev Throws if the contract is not paused.
     */
    function _requirePaused() internal view virtual {
        if (!paused()) {
            revert ExpectedPause();
        }
    }

    /**
     * @dev Triggers stopped state.
     *
     * Requirements:
     *
     * - The contract must not be paused.
     */
    function _pause() internal virtual whenNotPaused {
        _paused = true;
        emit Paused(_msgSender());
    }

    /**
     * @dev Returns to normal state.
     *
     * Requirements:
     *
     * - The contract must be paused.
     */
    function _unpause() internal virtual whenPaused {
        _paused = false;
        emit Unpaused(_msgSender());
    }
}

Settings
{
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "evmVersion": "paris",
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "abi"
      ]
    }
  },
  "metadata": {
    "useLiteralContent": true
  }
}

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":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"allowance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"}],"name":"ERC20InsufficientAllowance","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"}],"name":"ERC20InsufficientBalance","type":"error"},{"inputs":[{"internalType":"address","name":"approver","type":"address"}],"name":"ERC20InvalidApprover","type":"error"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC20InvalidReceiver","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"ERC20InvalidSender","type":"error"},{"inputs":[{"internalType":"address","name":"spender","type":"address"}],"name":"ERC20InvalidSpender","type":"error"},{"inputs":[],"name":"EnforcedPause","type":"error"},{"inputs":[],"name":"ExpectedPause","type":"error"},{"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":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","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":[{"indexed":false,"internalType":"address","name":"prevModeAdmin","type":"address"},{"indexed":false,"internalType":"address","name":"newModeAdmin","type":"address"}],"name":"ChangeModeAdmin","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":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"pauseStatus","type":"bool"}],"name":"PausedOrNot","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":false,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"bool","name":"state","type":"bool"}],"name":"SetBlackList","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"prevMode","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newMode","type":"uint256"}],"name":"SwitchTransferMode","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"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"inputs":[],"name":"CONTROLLED","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"NORMAL","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"RESTRICTED","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"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":[],"name":"_mode","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_modeAdmin","outputs":[{"internalType":"address","name":"","type":"address"}],"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":"value","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":[],"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":"","type":"address"}],"name":"isBlackListed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"isBlocked","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":"","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":[{"internalType":"address","name":"account","type":"address"}],"name":"isTransferController","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":[],"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":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"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":[],"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":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"recoverERC20","outputs":[],"stateMutability":"nonpayable","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":"account","type":"address"},{"internalType":"bool","name":"state","type":"bool"}],"name":"setBlackList","outputs":[],"stateMutability":"nonpayable","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":"bool","name":"_paused","type":"bool"}],"name":"setPaused","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":[{"internalType":"uint256","name":"v","type":"uint256"}],"name":"setTransferMode","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":"value","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":"value","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newModeAdmin","type":"address"}],"name":"transferModeAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}]

60c06040523480156200001157600080fd5b506040516200400d3803806200400d8339810160408190526200003491620002f8565b83838383838360128484818181818d6001600160a01b0381166200007257604051631e4fbdf760e01b81526000600482015260240160405180910390fd5b6200007d81620001be565b506001600160a01b038083166080528116620000ac57604051632d618d8160e21b815260040160405180910390fd5b60805160405163ca5eb5e160e01b81526001600160a01b0383811660048301529091169063ca5eb5e190602401600060405180830381600087803b158015620000f457600080fd5b505af115801562000109573d6000803e3d6000fd5b5050505050505050620001216200020e60201b60201c565b60ff168360ff16101562000148576040516301e9714b60e41b815260040160405180910390fd5b620001556006846200039d565b6200016290600a620004bc565b60a0525060089150620001789050838262000565565b50600962000187828262000565565b50506002600b555050600c80546001600160a01b0319166001600160a01b0395909516949094179093555062000631945050505050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b600690565b634e487b7160e01b600052604160045260246000fd5b600082601f8301126200023b57600080fd5b81516001600160401b038082111562000258576200025862000213565b604051601f8301601f19908116603f0116810190828211818310171562000283576200028362000213565b8160405283815260209250866020858801011115620002a157600080fd5b600091505b83821015620002c55785820183015181830184015290820190620002a6565b6000602085830101528094505050505092915050565b80516001600160a01b0381168114620002f357600080fd5b919050565b600080600080608085870312156200030f57600080fd5b84516001600160401b03808211156200032757600080fd5b620003358883890162000229565b955060208701519150808211156200034c57600080fd5b506200035b8782880162000229565b9350506200036c60408601620002db565b91506200037c60608601620002db565b905092959194509250565b634e487b7160e01b600052601160045260246000fd5b60ff8281168282160390811115620003b957620003b962000387565b92915050565b600181815b8085111562000400578160001904821115620003e457620003e462000387565b80851615620003f257918102915b93841c9390800290620003c4565b509250929050565b6000826200041957506001620003b9565b816200042857506000620003b9565b81600181146200044157600281146200044c576200046c565b6001915050620003b9565b60ff84111562000460576200046062000387565b50506001821b620003b9565b5060208310610133831016604e8410600b841016171562000491575081810a620003b9565b6200049d8383620003bf565b8060001904821115620004b457620004b462000387565b029392505050565b6000620004cd60ff84168362000408565b9392505050565b600181811c90821680620004e957607f821691505b6020821081036200050a57634e487b7160e01b600052602260045260246000fd5b50919050565b601f82111562000560576000816000526020600020601f850160051c810160208610156200053b5750805b601f850160051c820191505b818110156200055c5782815560010162000547565b5050505b505050565b81516001600160401b0381111562000581576200058162000213565b6200059981620005928454620004d4565b8462000510565b602080601f831160018114620005d15760008415620005b85750858301515b600019600386901b1c1916600185901b1785556200055c565b600085815260208120601f198616915b828110156200060257888601518255948401946001909101908401620005e1565b5085821015620006215787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60805160a0516139706200069d600039600081816107fe015281816120f70152818161216c015261242f01526000818161068801528181610e0c0152818161166d0152818161191101528181611cd501528181612527015281816127c1015261287801526139706000f3fe60806040526004361061036b5760003560e01c80637d25a05e116101c6578063bc70b354116100f7578063d424388511610095578063f2fde38b1161006f578063f2fde38b14610a78578063fbac395114610a98578063fc0c546a146105f4578063ff7bd03d14610ad157600080fd5b8063d4243885146109e2578063dd62ed3e14610a02578063e47d606014610a4857600080fd5b8063c5c03af3116100d1578063c5c03af314610978578063c7c7f5b31461098e578063ca5eb5e1146109af578063d045a0dc146109cf57600080fd5b8063bc70b35414610925578063bce6227014610945578063bd815db01461096557600080fd5b80639f68b96411610164578063b217ee971161013e578063b217ee9714610889578063b731ea0a146108b8578063b98bd070146108d8578063bb0b6a53146108f857600080fd5b80639f68b96414610840578063a9059cbb14610854578063ae24595c1461087457600080fd5b80638da5cb5b116101a05780638da5cb5b146107b957806395d89b41146107d7578063963efcaa146107ec57806399d742241461082057600080fd5b80637d25a05e1461074a57806382413eac14610785578063857749b0146107a557600080fd5b806330de344c116102a05780635c975abb1161023e5780636a1fbec9116102185780636a1fbec9146106ca5780636fc1b31e146106df57806370a08231146106ff578063715018a61461073557600080fd5b80635c975abb1461065e5780635e280f111461067657806368092bd9146106aa57600080fd5b80633b6f743b1161027a5780633b6f743b146105c757806352ae2879146105f45780635535d461146106075780635a0dfe4d1461062757600080fd5b806330de344c14610565578063313ce567146105855780633400288b146105a757600080fd5b8063134d4f251161030d57806317442b70116102e757806317442b70146104f957806318160ddd1461051b5780631f5e13341461053057806323b872dd1461054557600080fd5b8063134d4f251461048a578063156a0d0f146104b257806316c38b3c146104d957600080fd5b80630d35b415116103495780630d35b415146103ee578063111ecdad1461041d5780631171bda91461045557806313137d651461047757600080fd5b806306fdde031461037057806307589f701461039b578063095ea7b3146103be575b600080fd5b34801561037c57600080fd5b50610385610af1565b60405161039291906129f0565b60405180910390f35b3480156103a757600080fd5b506103b0600181565b604051908152602001610392565b3480156103ca57600080fd5b506103de6103d9366004612a18565b610b83565b6040519015158152602001610392565b3480156103fa57600080fd5b5061040e610409366004612a5c565b610b9d565b60405161039293929190612a90565b34801561042957600080fd5b5060045461043d906001600160a01b031681565b6040516001600160a01b039091168152602001610392565b34801561046157600080fd5b50610475610470366004612b29565b610d2e565b005b610475610485366004612bc4565b610e0a565b34801561049657600080fd5b5061049f600281565b60405161ffff9091168152602001610392565b3480156104be57600080fd5b506040805162b9270b60e21b81526001602082015201610392565b3480156104e557600080fd5b506104756104f4366004612c71565b610ec5565b34801561050557600080fd5b5060408051600181526002602082015201610392565b34801561052757600080fd5b506007546103b0565b34801561053c57600080fd5b5061049f600181565b34801561055157600080fd5b506103de610560366004612b29565b610f21565b34801561057157600080fd5b50600c5461043d906001600160a01b031681565b34801561059157600080fd5b5060125b60405160ff9091168152602001610392565b3480156105b357600080fd5b506104756105c2366004612ca7565b610f47565b3480156105d357600080fd5b506105e76105e2366004612cc3565b610f5d565b6040516103929190612d14565b34801561060057600080fd5b503061043d565b34801561061357600080fd5b50610385610622366004612d3d565b610fc4565b34801561063357600080fd5b506103de610642366004612ca7565b63ffffffff919091166000908152600160205260409020541490565b34801561066a57600080fd5b50600a5460ff166103de565b34801561068257600080fd5b5061043d7f000000000000000000000000000000000000000000000000000000000000000081565b3480156106b657600080fd5b506104756106c5366004612d70565b611069565b3480156106d657600080fd5b506103b0600281565b3480156106eb57600080fd5b506104756106fa366004612d9e565b6110d5565b34801561070b57600080fd5b506103b061071a366004612d9e565b6001600160a01b031660009081526005602052604090205490565b34801561074157600080fd5b5061047561112b565b34801561075657600080fd5b5061076d610765366004612ca7565b600092915050565b6040516001600160401b039091168152602001610392565b34801561079157600080fd5b506103de6107a0366004612dbb565b61113f565b3480156107b157600080fd5b506006610595565b3480156107c557600080fd5b506000546001600160a01b031661043d565b3480156107e357600080fd5b50610385611154565b3480156107f857600080fd5b506103b07f000000000000000000000000000000000000000000000000000000000000000081565b34801561082c57600080fd5b5061047561083b366004612d9e565b611163565b34801561084c57600080fd5b5060006103de565b34801561086057600080fd5b506103de61086f366004612a18565b6111c5565b34801561088057600080fd5b506103b0600081565b34801561089557600080fd5b506103de6108a4366004612d9e565b600c546001600160a01b0391821691161490565b3480156108c457600080fd5b5060025461043d906001600160a01b031681565b3480156108e457600080fd5b506104756108f3366004612e65565b6111d3565b34801561090457600080fd5b506103b0610913366004612ea6565b60016020526000908152604090205481565b34801561093157600080fd5b50610385610940366004612ec1565b6111ed565b34801561095157600080fd5b50610475610960366004612f21565b611395565b610475610973366004612e65565b611488565b34801561098457600080fd5b506103b0600b5481565b6109a161099c366004612f3a565b611612565b604051610392929190612fa7565b3480156109bb57600080fd5b506104756109ca366004612d9e565b611646565b6104756109dd366004612bc4565b6116cc565b3480156109ee57600080fd5b506104756109fd366004612d9e565b6116fb565b348015610a0e57600080fd5b506103b0610a1d366004612ff9565b6001600160a01b03918216600090815260066020908152604080832093909416825291909152205490565b348015610a5457600080fd5b506103de610a63366004612d9e565b600d6020526000908152604090205460ff1681565b348015610a8457600080fd5b50610475610a93366004612d9e565b611751565b348015610aa457600080fd5b506103de610ab3366004612d9e565b6001600160a01b03166000908152600d602052604090205460ff1690565b348015610add57600080fd5b506103de610aec366004613027565b61178f565b606060088054610b0090613043565b80601f0160208091040260200160405190810160405280929190818152602001828054610b2c90613043565b8015610b795780601f10610b4e57610100808354040283529160200191610b79565b820191906000526020600020905b815481529060010190602001808311610b5c57829003601f168201915b5050505050905090565b600033610b918185856117c5565b60019150505b92915050565b60408051808201909152600080825260208201526060610bd0604051806040016040528060008152602001600081525090565b600080306001600160a01b031663fc0c546a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c11573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c359190613077565b6001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c72573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c969190613094565b60408051808201825284815260208082018490528251600080825291810190935290975091925090610ceb565b604080518082019091526000815260606020820152815260200190600190039081610cc35790505b509350600080610d10604089013560608a0135610d0b60208c018c612ea6565b6117d7565b60408051808201909152918252602082015296989597505050505050565b610d36611813565b6001600160a01b038216610d915760405162461bcd60e51b815260206004820152601b60248201527f43616e6e6f742073656e6420746f207a65726f2061646472657373000000000060448201526064015b60405180910390fd5b60405163a9059cbb60e01b81526001600160a01b0383811660048301526024820183905284169063a9059cbb906044016020604051808303816000875af1158015610de0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e0491906130c3565b50505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03163314610e55576040516391ac5e4f60e01b8152336004820152602401610d88565b60208701803590610e6f90610e6a908a612ea6565b611840565b14610ead57610e816020880188612ea6565b60405163309afaf360e21b815263ffffffff909116600482015260208801356024820152604401610d88565b610ebc8787878787878761187c565b50505050505050565b610ecd611813565b8015610ee057610edb6119e3565b610ee8565b610ee8611a3d565b60405181151581527fe040b95757781c9ef852f20b42f255df7379d6ecb3bcc7f2f87d8e14c2f135e4906020015b60405180910390a150565b600033610f2f858285611a76565b610f3a858585611aef565b60019150505b9392505050565b610f4f611813565b610f598282611b4e565b5050565b60408051808201909152600080825260208201526000610f8d60408501356060860135610d0b6020880188612ea6565b915050600080610f9d8684611b9c565b9092509050610fba610fb26020880188612ea6565b838388611cbf565b9695505050505050565b600360209081526000928352604080842090915290825290208054610fe890613043565b80601f016020809104026020016040519081016040528092919081815260200182805461101490613043565b80156110615780601f1061103657610100808354040283529160200191611061565b820191906000526020600020905b81548152906001019060200180831161104457829003601f168201915b505050505081565b611071611813565b6001600160a01b0382166000818152600d6020908152604091829020805460ff19168515159081179091558251938452908301527f1365a36244c5f48793fe8c34e438f543de193bdea38c4f133c166dce6fc1214591015b60405180910390a15050565b6110dd611813565b600480546001600160a01b0319166001600160a01b0383169081179091556040519081527ff0be4f1e87349231d80c36b33f9e8639658eeaf474014dee15a3e6a4d441419790602001610f16565b611133611813565b61113d6000611da0565b565b6001600160a01b03811630145b949350505050565b606060098054610b0090613043565b61116b611813565b600c80546001600160a01b038381166001600160a01b031983168117909355604080519190921680825260208201939093527fa7631e1464420958ae901b68c255315085d659164f0f8fba4e7c10dccf5adc1091016110c9565b600033610b91818585611aef565b6111db611813565b610f596111e88284613181565b611df0565b63ffffffff8416600090815260036020908152604080832061ffff8716845290915281208054606092919061122190613043565b80601f016020809104026020016040519081016040528092919081815260200182805461124d90613043565b801561129a5780601f1061126f5761010080835404028352916020019161129a565b820191906000526020600020905b81548152906001019060200180831161127d57829003601f168201915b5050505050905080516000036112ea5783838080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092945061114c9350505050565b60008390036112fa57905061114c565b600283106113785761134184848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611ef792505050565b8061134f8460028188613296565b604051602001611361939291906132c0565b60405160208183030381529060405291505061114c565b8383604051639a6d49cd60e01b8152600401610d88929190613311565b600c546001600160a01b031633146113ef5760405162461bcd60e51b815260206004820152601c60248201527f43616c6c6572206973206e6f7420746865206d6f64652061646d696e000000006044820152606401610d88565b600b548115806113ff5750600182145b8061140a5750600282145b6114455760405162461bcd60e51b815260206004820152600c60248201526b496e76616c6964206d6f646560a01b6044820152606401610d88565b600b5415610f5957600b82905560408051828152602081018490527f147c9b5c65a9fb4f870eff291dfb2dd14e4d984ed3354b00459ebf34261a674191016110c9565b60005b8181101561159157368383838181106114a6576114a6613325565b90506020028101906114b8919061333b565b90506114eb6114ca6020830183612ea6565b602083013563ffffffff919091166000908152600160205260409020541490565b6114f55750611589565b3063d045a0dc60c08301358360a081013561151461010083018361335c565b611525610100890160e08a01612d9e565b6115336101208a018a61335c565b6040518963ffffffff1660e01b815260040161155597969594939291906133b7565b6000604051808303818588803b15801561156e57600080fd5b505af1158015611582573d6000803e3d6000fd5b5050505050505b60010161148b565b50336001600160a01b0316638e9e70996040518163ffffffff1660e01b8152600401600060405180830381865afa1580156115d0573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526115f8919081019061343d565b604051638351eea760e01b8152600401610d8891906129f0565b61161a612959565b6040805180820190915260008082526020820152611639858585611f23565b915091505b935093915050565b61164e611813565b60405163ca5eb5e160e01b81526001600160a01b0382811660048301527f0000000000000000000000000000000000000000000000000000000000000000169063ca5eb5e190602401600060405180830381600087803b1580156116b157600080fd5b505af11580156116c5573d6000803e3d6000fd5b5050505050565b3330146116ec5760405163029a949d60e31b815260040160405180910390fd5b610ebc87878787878787610ead565b611703611813565b600280546001600160a01b0319166001600160a01b0383169081179091556040519081527fd48d879cef83a1c0bdda516f27b13ddb1b3f8bbac1c9e1511bb2a659c242776090602001610f16565b611759611813565b6001600160a01b03811661178357604051631e4fbdf760e01b815260006004820152602401610d88565b61178c81611da0565b50565b60006020820180359060019083906117a79086612ea6565b63ffffffff1681526020810191909152604001600020541492915050565b6117d2838383600161201e565b505050565b6000806117e3856120f3565b91508190508381101561163e576040516371c4efed60e01b81526004810182905260248101859052604401610d88565b6000546001600160a01b0316331461113d5760405163118cdaa760e01b8152336004820152602401610d88565b63ffffffff811660009081526001602052604081205480610b975760405163f6ff4fb760e01b815263ffffffff84166004820152602401610d88565b600061188e61188b878761212a565b90565b905060006118ba826118a86118a38a8a612142565b612165565b6118b560208d018d612ea6565b61219a565b905060288611156119815760006118f76118da60608c0160408d016134aa565b6118e760208d018d612ea6565b846118f28c8c6121c2565b61220d565b604051633e5ac80960e11b81529091506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690637cb590129061194d9086908d9060009087906004016134c7565b600060405180830381600087803b15801561196757600080fd5b505af115801561197b573d6000803e3d6000fd5b50505050505b6001600160a01b038216887fefed6d3500546b29533b128a29e3a94d70788727f0507505ac12eaf2e578fd9c6119ba60208d018d612ea6565b6040805163ffffffff9092168252602082018690520160405180910390a3505050505050505050565b6119eb61223f565b600a805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258611a203390565b6040516001600160a01b03909116815260200160405180910390a1565b611a45612263565b600a805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa33611a20565b6001600160a01b03838116600090815260066020908152604080832093861683529290522054600019811015610e045781811015611ae057604051637dc7a0d960e11b81526001600160a01b03841660048201526024810182905260448101839052606401610d88565b610e048484848403600061201e565b6001600160a01b038316611b1957604051634b637e8f60e11b815260006004820152602401610d88565b6001600160a01b038216611b435760405163ec442f0560e01b815260006004820152602401610d88565b6117d2838383612286565b63ffffffff8216600081815260016020908152604091829020849055815192835282018390527f238399d427b947898edb290f5ff0f9109849b1c3ba196a42e35f00c50a54b98b91016110c9565b6060806000611bf98560200135611bb286612428565b611bbf60a089018961335c565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061245492505050565b9093509050600081611c0c576001611c0f565b60025b9050611c2f611c216020880188612ea6565b8261094060808a018a61335c565b6004549093506001600160a01b03168015611cb55760405163043a78eb60e01b81526001600160a01b0382169063043a78eb90611c7290889088906004016134f8565b602060405180830381865afa158015611c8f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cb391906130c3565b505b5050509250929050565b60408051808201909152600080825260208201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663ddc28c586040518060a001604052808863ffffffff168152602001611d2289611840565b8152602001878152602001868152602001851515815250306040518363ffffffff1660e01b8152600401611d5792919061351d565b6040805180830381865afa158015611d73573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d9791906135c6565b95945050505050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60005b8151811015611ec757611e22828281518110611e1157611e11613325565b602002602001015160400151611ef7565b818181518110611e3457611e34613325565b60200260200101516040015160036000848481518110611e5657611e56613325565b60200260200101516000015163ffffffff1663ffffffff1681526020019081526020016000206000848481518110611e9057611e90613325565b60200260200101516020015161ffff1661ffff1681526020019081526020016000209081611ebe9190613632565b50600101611df3565b507fbe4864a8e820971c0247f5992e2da559595f7bf076a21cb5928d443d2a13b67481604051610f1691906136f1565b600281015161ffff8116600314610f595781604051639a6d49cd60e01b8152600401610d8891906129f0565b611f2b612959565b6040805180820190915260008082526020820152600080611f6233604089013560608a0135611f5d60208c018c612ea6565b6124ce565b91509150600080611f738984611b9c565b9092509050611f9f611f8860208b018b612ea6565b8383611f99368d90038d018d61377c565b8b6124f4565b60408051808201909152858152602080820186905282519298509096503391907f85496b760a4b7f8d66384b9df21b381f5d1b1e79f229a47aaf4c232edc2fe59a90611fed908d018d612ea6565b6040805163ffffffff909216825260208201899052810187905260600160405180910390a350505050935093915050565b6001600160a01b0384166120485760405163e602df0560e01b815260006004820152602401610d88565b6001600160a01b03831661207257604051634a1406b160e11b815260006004820152602401610d88565b6001600160a01b0380851660009081526006602090815260408083209387168352929052208290558015610e0457826001600160a01b0316846001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040516120e591815260200190565b60405180910390a350505050565b60007f000000000000000000000000000000000000000000000000000000000000000061212081846137c4565b610b9791906137e6565b60006121396020828486613296565b610f40916137fd565b6000612152602860208486613296565b61215b9161381b565b60c01c9392505050565b6000610b977f00000000000000000000000000000000000000000000000000000000000000006001600160401b0384166137e6565b60006001600160a01b0384166121b05761dead93505b6121ba84846125ff565b509092915050565b60606121d18260288186613296565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929695505050505050565b606084848484604051602001612226949392919061384b565b6040516020818303038152906040529050949350505050565b600a5460ff161561113d5760405163d93c066560e01b815260040160405180910390fd5b600a5460ff1661113d57604051638dfc202b60e01b815260040160405180910390fd5b61228e61223f565b6001600b54036122e05760405162461bcd60e51b815260206004820152601d60248201527f546f6b656e3a205472616e7366657220697320726573747269637465640000006044820152606401610d88565b6002600b540361235f57600c546001600160a01b03848116911614806123135750600c546001600160a01b038381169116145b61235f5760405162461bcd60e51b815260206004820152601760248201527f546f6b656e3a20496e76616c6964207472616e736665720000000000000000006044820152606401610d88565b6001600160a01b0383166000908152600d602052604090205460ff16156123bf5760405162461bcd60e51b8152602060048201526014602482015273199c9bdb481a5cc81a5b88189b1858dad31a5cdd60621b6044820152606401610d88565b6001600160a01b0382166000908152600d602052604090205460ff161561241d5760405162461bcd60e51b81526020600482015260126024820152711d1bc81a5cc81a5b88189b1858dad31a5cdd60721b6044820152606401610d88565b6117d2838383612635565b6000610b977f0000000000000000000000000000000000000000000000000000000000000000836137c4565b805160609015158061249d57848460405160200161248992919091825260c01b6001600160c01b031916602082015260280190565b6040516020818303038152906040526124c4565b848433856040516020016124b4949392919061389a565b6040516020818303038152906040525b9150935093915050565b6000806124dc8585856117d7565b90925090506124eb868361275f565b94509492505050565b6124fc612959565b600061250b8460000151612795565b6020850151909150156125255761252584602001516127bd565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632637a450826040518060a001604052808b63ffffffff1681526020016125758c611840565b81526020018a815260200189815260200160008960200151111515815250866040518463ffffffff1660e01b81526004016125b192919061351d565b60806040518083038185885af11580156125cf573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052508101906125f491906138dd565b979650505050505050565b6001600160a01b0382166126295760405163ec442f0560e01b815260006004820152602401610d88565b610f5960008383612286565b6001600160a01b0383166126605780600760008282546126559190613927565b909155506126d29050565b6001600160a01b038316600090815260056020526040902054818110156126b35760405163391434e360e21b81526001600160a01b03851660048201526024810182905260448101839052606401610d88565b6001600160a01b03841660009081526005602052604090209082900390555b6001600160a01b0382166126ee5760078054829003905561270d565b6001600160a01b03821660009081526005602052604090208054820190555b816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8360405161275291815260200190565b60405180910390a3505050565b6001600160a01b03821661278957604051634b637e8f60e11b815260006004820152602401610d88565b610f5982600083612286565b60008134146127b9576040516304fb820960e51b8152346004820152602401610d88565b5090565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663e4fe1d946040518163ffffffff1660e01b8152600401602060405180830381865afa15801561281d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128419190613077565b90506001600160a01b03811661286a576040516329b99a9560e11b815260040160405180910390fd5b6040805133602482018190527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0381811660448501526064808501889052855180860390910181526084909401909452602080840180516001600160e01b03166323b872dd60e01b1781528451610f59968816958993610e0493889360009283929091839182885af18061290b576040513d6000823e3d81fd5b50506000513d91508115612923578060011415612930565b6001600160a01b0384163b155b15610e0457604051635274afe760e01b81526001600160a01b0385166004820152602401610d88565b60405180606001604052806000801916815260200160006001600160401b0316815260200161299b604051806040016040528060008152602001600081525090565b905290565b60005b838110156129bb5781810151838201526020016129a3565b50506000910152565b600081518084526129dc8160208601602086016129a0565b601f01601f19169290920160200192915050565b602081526000610f4060208301846129c4565b6001600160a01b038116811461178c57600080fd5b60008060408385031215612a2b57600080fd5b8235612a3681612a03565b946020939093013593505050565b600060e08284031215612a5657600080fd5b50919050565b600060208284031215612a6e57600080fd5b81356001600160401b03811115612a8457600080fd5b61114c84828501612a44565b8351815260208085015190820152600060a08201604060a0604085015281865180845260c08601915060c08160051b8701019350602080890160005b83811015612b0b5788870360bf19018552815180518852830151838801879052612af8878901826129c4565b9750509382019390820190600101612acc565b5050875160608801525050506020850151608085015250905061114c565b600080600060608486031215612b3e57600080fd5b8335612b4981612a03565b92506020840135612b5981612a03565b929592945050506040919091013590565b600060608284031215612a5657600080fd5b60008083601f840112612b8e57600080fd5b5081356001600160401b03811115612ba557600080fd5b602083019150836020828501011115612bbd57600080fd5b9250929050565b600080600080600080600060e0888a031215612bdf57600080fd5b612be98989612b6a565b96506060880135955060808801356001600160401b0380821115612c0c57600080fd5b612c188b838c01612b7c565b909750955060a08a01359150612c2d82612a03565b90935060c08901359080821115612c4357600080fd5b50612c508a828b01612b7c565b989b979a50959850939692959293505050565b801515811461178c57600080fd5b600060208284031215612c8357600080fd5b8135610f4081612c63565b803563ffffffff81168114612ca257600080fd5b919050565b60008060408385031215612cba57600080fd5b612a3683612c8e565b60008060408385031215612cd657600080fd5b82356001600160401b03811115612cec57600080fd5b612cf885828601612a44565b9250506020830135612d0981612c63565b809150509250929050565b815181526020808301519082015260408101610b97565b803561ffff81168114612ca257600080fd5b60008060408385031215612d5057600080fd5b612d5983612c8e565b9150612d6760208401612d2b565b90509250929050565b60008060408385031215612d8357600080fd5b8235612d8e81612a03565b91506020830135612d0981612c63565b600060208284031215612db057600080fd5b8135610f4081612a03565b60008060008060a08587031215612dd157600080fd5b612ddb8686612b6a565b935060608501356001600160401b03811115612df657600080fd5b612e0287828801612b7c565b9094509250506080850135612e1681612a03565b939692955090935050565b60008083601f840112612e3357600080fd5b5081356001600160401b03811115612e4a57600080fd5b6020830191508360208260051b8501011115612bbd57600080fd5b60008060208385031215612e7857600080fd5b82356001600160401b03811115612e8e57600080fd5b612e9a85828601612e21565b90969095509350505050565b600060208284031215612eb857600080fd5b610f4082612c8e565b60008060008060608587031215612ed757600080fd5b612ee085612c8e565b9350612eee60208601612d2b565b925060408501356001600160401b03811115612f0957600080fd5b612f1587828801612b7c565b95989497509550505050565b600060208284031215612f3357600080fd5b5035919050565b60008060008385036080811215612f5057600080fd5b84356001600160401b03811115612f6657600080fd5b612f7287828801612a44565b9450506040601f1982011215612f8757600080fd5b506020840191506060840135612f9c81612a03565b809150509250925092565b600060c082019050835182526001600160401b0360208501511660208301526040840151612fe2604084018280518252602090810151910152565b5082516080830152602083015160a0830152610f40565b6000806040838503121561300c57600080fd5b823561301781612a03565b91506020830135612d0981612a03565b60006060828403121561303957600080fd5b610f408383612b6a565b600181811c9082168061305757607f821691505b602082108103612a5657634e487b7160e01b600052602260045260246000fd5b60006020828403121561308957600080fd5b8151610f4081612a03565b6000602082840312156130a657600080fd5b5051919050565b634e487b7160e01b600052604160045260246000fd5b6000602082840312156130d557600080fd5b8151610f4081612c63565b604051606081016001600160401b0381118282101715613102576131026130ad565b60405290565b604080519081016001600160401b0381118282101715613102576131026130ad565b604051601f8201601f191681016001600160401b0381118282101715613152576131526130ad565b604052919050565b60006001600160401b03821115613173576131736130ad565b50601f01601f191660200190565b60006001600160401b038084111561319b5761319b6130ad565b8360051b60206131ac81830161312a565b8681529185019181810190368411156131c457600080fd5b865b8481101561328a578035868111156131de5760008081fd5b880160603682900312156131f25760008081fd5b6131fa6130e0565b61320382612c8e565b8152613210868301612d2b565b86820152604080830135898111156132285760008081fd5b929092019136601f84011261323d5760008081fd5b823561325061324b8261315a565b61312a565b81815236898387010111156132655760008081fd5b818986018a8301376000918101890191909152908201528452509183019183016131c6565b50979650505050505050565b600080858511156132a657600080fd5b838611156132b357600080fd5b5050820193919092039150565b600084516132d28184602089016129a0565b8201838582376000930192835250909392505050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b60208152600061114c6020830184866132e8565b634e487b7160e01b600052603260045260246000fd5b6000823561013e1983360301811261335257600080fd5b9190910192915050565b6000808335601e1984360301811261337357600080fd5b8301803591506001600160401b0382111561338d57600080fd5b602001915036819003821315612bbd57600080fd5b6001600160401b038116811461178c57600080fd5b63ffffffff6133c589612c8e565b16815260208801356020820152600060408901356133e2816133a2565b6001600160401b03811660408401525087606083015260e0608083015261340d60e0830187896132e8565b6001600160a01b03861660a084015282810360c084015261342f8185876132e8565b9a9950505050505050505050565b60006020828403121561344f57600080fd5b81516001600160401b0381111561346557600080fd5b8201601f8101841361347657600080fd5b805161348461324b8261315a565b81815285602083850101111561349957600080fd5b611d978260208301602086016129a0565b6000602082840312156134bc57600080fd5b8135610f40816133a2565b60018060a01b038516815283602082015261ffff83166040820152608060608201526000610fba60808301846129c4565b60408152600061350b60408301856129c4565b8281036020840152611d9781856129c4565b6040815263ffffffff8351166040820152602083015160608201526000604084015160a0608084015261355360e08401826129c4565b90506060850151603f198483030160a085015261357082826129c4565b60809690960151151560c08501525050506001600160a01b039190911660209091015290565b6000604082840312156135a857600080fd5b6135b0613108565b9050815181526020820151602082015292915050565b6000604082840312156135d857600080fd5b610f408383613596565b601f8211156117d2576000816000526020600020601f850160051c8101602086101561360b5750805b601f850160051c820191505b8181101561362a57828155600101613617565b505050505050565b81516001600160401b0381111561364b5761364b6130ad565b61365f816136598454613043565b846135e2565b602080601f831160018114613694576000841561367c5750858301515b600019600386901b1c1916600185901b17855561362a565b600085815260208120601f198616915b828110156136c3578886015182559484019460019091019084016136a4565b50858210156136e15787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b600060208083018184528085518083526040925060408601915060408160051b87010184880160005b8381101561376e57888303603f190185528151805163ffffffff1684528781015161ffff1688850152860151606087850181905261375a818601836129c4565b96890196945050509086019060010161371a565b509098975050505050505050565b60006040828403121561378e57600080fd5b613796613108565b82358152602083013560208201528091505092915050565b634e487b7160e01b600052601160045260246000fd5b6000826137e157634e487b7160e01b600052601260045260246000fd5b500490565b8082028115828204841417610b9757610b976137ae565b80356020831015610b9757600019602084900360031b1b1692915050565b6001600160c01b031981358181169160088510156138435780818660080360031b1b83161692505b505092915050565b6001600160401b0360c01b8560c01b16815263ffffffff60e01b8460e01b16600882015282600c8201526000825161388a81602c8501602087016129a0565b91909101602c0195945050505050565b8481526001600160401b0360c01b8460c01b166020820152826028820152600082516138cd8160488501602087016129a0565b9190910160480195945050505050565b6000608082840312156138ef57600080fd5b6138f76130e0565b825181526020830151613909816133a2565b602082015261391b8460408501613596565b60408201529392505050565b80820180821115610b9757610b976137ae56fea26469706673582212208cdcc1c04c9f55e5e452b377a7de41cb0bff8330b3a792e337650d60bf202d8564736f6c63430008160033000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000001a44076050125825900e736c501f859c50fe728c000000000000000000000000b839a86a29c18c10999c131d68bf9f736775151200000000000000000000000000000000000000000000000000000000000000084879706572696f6e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000452494f4e00000000000000000000000000000000000000000000000000000000

Deployed Bytecode

0x60806040526004361061036b5760003560e01c80637d25a05e116101c6578063bc70b354116100f7578063d424388511610095578063f2fde38b1161006f578063f2fde38b14610a78578063fbac395114610a98578063fc0c546a146105f4578063ff7bd03d14610ad157600080fd5b8063d4243885146109e2578063dd62ed3e14610a02578063e47d606014610a4857600080fd5b8063c5c03af3116100d1578063c5c03af314610978578063c7c7f5b31461098e578063ca5eb5e1146109af578063d045a0dc146109cf57600080fd5b8063bc70b35414610925578063bce6227014610945578063bd815db01461096557600080fd5b80639f68b96411610164578063b217ee971161013e578063b217ee9714610889578063b731ea0a146108b8578063b98bd070146108d8578063bb0b6a53146108f857600080fd5b80639f68b96414610840578063a9059cbb14610854578063ae24595c1461087457600080fd5b80638da5cb5b116101a05780638da5cb5b146107b957806395d89b41146107d7578063963efcaa146107ec57806399d742241461082057600080fd5b80637d25a05e1461074a57806382413eac14610785578063857749b0146107a557600080fd5b806330de344c116102a05780635c975abb1161023e5780636a1fbec9116102185780636a1fbec9146106ca5780636fc1b31e146106df57806370a08231146106ff578063715018a61461073557600080fd5b80635c975abb1461065e5780635e280f111461067657806368092bd9146106aa57600080fd5b80633b6f743b1161027a5780633b6f743b146105c757806352ae2879146105f45780635535d461146106075780635a0dfe4d1461062757600080fd5b806330de344c14610565578063313ce567146105855780633400288b146105a757600080fd5b8063134d4f251161030d57806317442b70116102e757806317442b70146104f957806318160ddd1461051b5780631f5e13341461053057806323b872dd1461054557600080fd5b8063134d4f251461048a578063156a0d0f146104b257806316c38b3c146104d957600080fd5b80630d35b415116103495780630d35b415146103ee578063111ecdad1461041d5780631171bda91461045557806313137d651461047757600080fd5b806306fdde031461037057806307589f701461039b578063095ea7b3146103be575b600080fd5b34801561037c57600080fd5b50610385610af1565b60405161039291906129f0565b60405180910390f35b3480156103a757600080fd5b506103b0600181565b604051908152602001610392565b3480156103ca57600080fd5b506103de6103d9366004612a18565b610b83565b6040519015158152602001610392565b3480156103fa57600080fd5b5061040e610409366004612a5c565b610b9d565b60405161039293929190612a90565b34801561042957600080fd5b5060045461043d906001600160a01b031681565b6040516001600160a01b039091168152602001610392565b34801561046157600080fd5b50610475610470366004612b29565b610d2e565b005b610475610485366004612bc4565b610e0a565b34801561049657600080fd5b5061049f600281565b60405161ffff9091168152602001610392565b3480156104be57600080fd5b506040805162b9270b60e21b81526001602082015201610392565b3480156104e557600080fd5b506104756104f4366004612c71565b610ec5565b34801561050557600080fd5b5060408051600181526002602082015201610392565b34801561052757600080fd5b506007546103b0565b34801561053c57600080fd5b5061049f600181565b34801561055157600080fd5b506103de610560366004612b29565b610f21565b34801561057157600080fd5b50600c5461043d906001600160a01b031681565b34801561059157600080fd5b5060125b60405160ff9091168152602001610392565b3480156105b357600080fd5b506104756105c2366004612ca7565b610f47565b3480156105d357600080fd5b506105e76105e2366004612cc3565b610f5d565b6040516103929190612d14565b34801561060057600080fd5b503061043d565b34801561061357600080fd5b50610385610622366004612d3d565b610fc4565b34801561063357600080fd5b506103de610642366004612ca7565b63ffffffff919091166000908152600160205260409020541490565b34801561066a57600080fd5b50600a5460ff166103de565b34801561068257600080fd5b5061043d7f0000000000000000000000001a44076050125825900e736c501f859c50fe728c81565b3480156106b657600080fd5b506104756106c5366004612d70565b611069565b3480156106d657600080fd5b506103b0600281565b3480156106eb57600080fd5b506104756106fa366004612d9e565b6110d5565b34801561070b57600080fd5b506103b061071a366004612d9e565b6001600160a01b031660009081526005602052604090205490565b34801561074157600080fd5b5061047561112b565b34801561075657600080fd5b5061076d610765366004612ca7565b600092915050565b6040516001600160401b039091168152602001610392565b34801561079157600080fd5b506103de6107a0366004612dbb565b61113f565b3480156107b157600080fd5b506006610595565b3480156107c557600080fd5b506000546001600160a01b031661043d565b3480156107e357600080fd5b50610385611154565b3480156107f857600080fd5b506103b07f000000000000000000000000000000000000000000000000000000e8d4a5100081565b34801561082c57600080fd5b5061047561083b366004612d9e565b611163565b34801561084c57600080fd5b5060006103de565b34801561086057600080fd5b506103de61086f366004612a18565b6111c5565b34801561088057600080fd5b506103b0600081565b34801561089557600080fd5b506103de6108a4366004612d9e565b600c546001600160a01b0391821691161490565b3480156108c457600080fd5b5060025461043d906001600160a01b031681565b3480156108e457600080fd5b506104756108f3366004612e65565b6111d3565b34801561090457600080fd5b506103b0610913366004612ea6565b60016020526000908152604090205481565b34801561093157600080fd5b50610385610940366004612ec1565b6111ed565b34801561095157600080fd5b50610475610960366004612f21565b611395565b610475610973366004612e65565b611488565b34801561098457600080fd5b506103b0600b5481565b6109a161099c366004612f3a565b611612565b604051610392929190612fa7565b3480156109bb57600080fd5b506104756109ca366004612d9e565b611646565b6104756109dd366004612bc4565b6116cc565b3480156109ee57600080fd5b506104756109fd366004612d9e565b6116fb565b348015610a0e57600080fd5b506103b0610a1d366004612ff9565b6001600160a01b03918216600090815260066020908152604080832093909416825291909152205490565b348015610a5457600080fd5b506103de610a63366004612d9e565b600d6020526000908152604090205460ff1681565b348015610a8457600080fd5b50610475610a93366004612d9e565b611751565b348015610aa457600080fd5b506103de610ab3366004612d9e565b6001600160a01b03166000908152600d602052604090205460ff1690565b348015610add57600080fd5b506103de610aec366004613027565b61178f565b606060088054610b0090613043565b80601f0160208091040260200160405190810160405280929190818152602001828054610b2c90613043565b8015610b795780601f10610b4e57610100808354040283529160200191610b79565b820191906000526020600020905b815481529060010190602001808311610b5c57829003601f168201915b5050505050905090565b600033610b918185856117c5565b60019150505b92915050565b60408051808201909152600080825260208201526060610bd0604051806040016040528060008152602001600081525090565b600080306001600160a01b031663fc0c546a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c11573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c359190613077565b6001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c72573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c969190613094565b60408051808201825284815260208082018490528251600080825291810190935290975091925090610ceb565b604080518082019091526000815260606020820152815260200190600190039081610cc35790505b509350600080610d10604089013560608a0135610d0b60208c018c612ea6565b6117d7565b60408051808201909152918252602082015296989597505050505050565b610d36611813565b6001600160a01b038216610d915760405162461bcd60e51b815260206004820152601b60248201527f43616e6e6f742073656e6420746f207a65726f2061646472657373000000000060448201526064015b60405180910390fd5b60405163a9059cbb60e01b81526001600160a01b0383811660048301526024820183905284169063a9059cbb906044016020604051808303816000875af1158015610de0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e0491906130c3565b50505050565b7f0000000000000000000000001a44076050125825900e736c501f859c50fe728c6001600160a01b03163314610e55576040516391ac5e4f60e01b8152336004820152602401610d88565b60208701803590610e6f90610e6a908a612ea6565b611840565b14610ead57610e816020880188612ea6565b60405163309afaf360e21b815263ffffffff909116600482015260208801356024820152604401610d88565b610ebc8787878787878761187c565b50505050505050565b610ecd611813565b8015610ee057610edb6119e3565b610ee8565b610ee8611a3d565b60405181151581527fe040b95757781c9ef852f20b42f255df7379d6ecb3bcc7f2f87d8e14c2f135e4906020015b60405180910390a150565b600033610f2f858285611a76565b610f3a858585611aef565b60019150505b9392505050565b610f4f611813565b610f598282611b4e565b5050565b60408051808201909152600080825260208201526000610f8d60408501356060860135610d0b6020880188612ea6565b915050600080610f9d8684611b9c565b9092509050610fba610fb26020880188612ea6565b838388611cbf565b9695505050505050565b600360209081526000928352604080842090915290825290208054610fe890613043565b80601f016020809104026020016040519081016040528092919081815260200182805461101490613043565b80156110615780601f1061103657610100808354040283529160200191611061565b820191906000526020600020905b81548152906001019060200180831161104457829003601f168201915b505050505081565b611071611813565b6001600160a01b0382166000818152600d6020908152604091829020805460ff19168515159081179091558251938452908301527f1365a36244c5f48793fe8c34e438f543de193bdea38c4f133c166dce6fc1214591015b60405180910390a15050565b6110dd611813565b600480546001600160a01b0319166001600160a01b0383169081179091556040519081527ff0be4f1e87349231d80c36b33f9e8639658eeaf474014dee15a3e6a4d441419790602001610f16565b611133611813565b61113d6000611da0565b565b6001600160a01b03811630145b949350505050565b606060098054610b0090613043565b61116b611813565b600c80546001600160a01b038381166001600160a01b031983168117909355604080519190921680825260208201939093527fa7631e1464420958ae901b68c255315085d659164f0f8fba4e7c10dccf5adc1091016110c9565b600033610b91818585611aef565b6111db611813565b610f596111e88284613181565b611df0565b63ffffffff8416600090815260036020908152604080832061ffff8716845290915281208054606092919061122190613043565b80601f016020809104026020016040519081016040528092919081815260200182805461124d90613043565b801561129a5780601f1061126f5761010080835404028352916020019161129a565b820191906000526020600020905b81548152906001019060200180831161127d57829003601f168201915b5050505050905080516000036112ea5783838080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092945061114c9350505050565b60008390036112fa57905061114c565b600283106113785761134184848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611ef792505050565b8061134f8460028188613296565b604051602001611361939291906132c0565b60405160208183030381529060405291505061114c565b8383604051639a6d49cd60e01b8152600401610d88929190613311565b600c546001600160a01b031633146113ef5760405162461bcd60e51b815260206004820152601c60248201527f43616c6c6572206973206e6f7420746865206d6f64652061646d696e000000006044820152606401610d88565b600b548115806113ff5750600182145b8061140a5750600282145b6114455760405162461bcd60e51b815260206004820152600c60248201526b496e76616c6964206d6f646560a01b6044820152606401610d88565b600b5415610f5957600b82905560408051828152602081018490527f147c9b5c65a9fb4f870eff291dfb2dd14e4d984ed3354b00459ebf34261a674191016110c9565b60005b8181101561159157368383838181106114a6576114a6613325565b90506020028101906114b8919061333b565b90506114eb6114ca6020830183612ea6565b602083013563ffffffff919091166000908152600160205260409020541490565b6114f55750611589565b3063d045a0dc60c08301358360a081013561151461010083018361335c565b611525610100890160e08a01612d9e565b6115336101208a018a61335c565b6040518963ffffffff1660e01b815260040161155597969594939291906133b7565b6000604051808303818588803b15801561156e57600080fd5b505af1158015611582573d6000803e3d6000fd5b5050505050505b60010161148b565b50336001600160a01b0316638e9e70996040518163ffffffff1660e01b8152600401600060405180830381865afa1580156115d0573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526115f8919081019061343d565b604051638351eea760e01b8152600401610d8891906129f0565b61161a612959565b6040805180820190915260008082526020820152611639858585611f23565b915091505b935093915050565b61164e611813565b60405163ca5eb5e160e01b81526001600160a01b0382811660048301527f0000000000000000000000001a44076050125825900e736c501f859c50fe728c169063ca5eb5e190602401600060405180830381600087803b1580156116b157600080fd5b505af11580156116c5573d6000803e3d6000fd5b5050505050565b3330146116ec5760405163029a949d60e31b815260040160405180910390fd5b610ebc87878787878787610ead565b611703611813565b600280546001600160a01b0319166001600160a01b0383169081179091556040519081527fd48d879cef83a1c0bdda516f27b13ddb1b3f8bbac1c9e1511bb2a659c242776090602001610f16565b611759611813565b6001600160a01b03811661178357604051631e4fbdf760e01b815260006004820152602401610d88565b61178c81611da0565b50565b60006020820180359060019083906117a79086612ea6565b63ffffffff1681526020810191909152604001600020541492915050565b6117d2838383600161201e565b505050565b6000806117e3856120f3565b91508190508381101561163e576040516371c4efed60e01b81526004810182905260248101859052604401610d88565b6000546001600160a01b0316331461113d5760405163118cdaa760e01b8152336004820152602401610d88565b63ffffffff811660009081526001602052604081205480610b975760405163f6ff4fb760e01b815263ffffffff84166004820152602401610d88565b600061188e61188b878761212a565b90565b905060006118ba826118a86118a38a8a612142565b612165565b6118b560208d018d612ea6565b61219a565b905060288611156119815760006118f76118da60608c0160408d016134aa565b6118e760208d018d612ea6565b846118f28c8c6121c2565b61220d565b604051633e5ac80960e11b81529091506001600160a01b037f0000000000000000000000001a44076050125825900e736c501f859c50fe728c1690637cb590129061194d9086908d9060009087906004016134c7565b600060405180830381600087803b15801561196757600080fd5b505af115801561197b573d6000803e3d6000fd5b50505050505b6001600160a01b038216887fefed6d3500546b29533b128a29e3a94d70788727f0507505ac12eaf2e578fd9c6119ba60208d018d612ea6565b6040805163ffffffff9092168252602082018690520160405180910390a3505050505050505050565b6119eb61223f565b600a805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258611a203390565b6040516001600160a01b03909116815260200160405180910390a1565b611a45612263565b600a805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa33611a20565b6001600160a01b03838116600090815260066020908152604080832093861683529290522054600019811015610e045781811015611ae057604051637dc7a0d960e11b81526001600160a01b03841660048201526024810182905260448101839052606401610d88565b610e048484848403600061201e565b6001600160a01b038316611b1957604051634b637e8f60e11b815260006004820152602401610d88565b6001600160a01b038216611b435760405163ec442f0560e01b815260006004820152602401610d88565b6117d2838383612286565b63ffffffff8216600081815260016020908152604091829020849055815192835282018390527f238399d427b947898edb290f5ff0f9109849b1c3ba196a42e35f00c50a54b98b91016110c9565b6060806000611bf98560200135611bb286612428565b611bbf60a089018961335c565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061245492505050565b9093509050600081611c0c576001611c0f565b60025b9050611c2f611c216020880188612ea6565b8261094060808a018a61335c565b6004549093506001600160a01b03168015611cb55760405163043a78eb60e01b81526001600160a01b0382169063043a78eb90611c7290889088906004016134f8565b602060405180830381865afa158015611c8f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cb391906130c3565b505b5050509250929050565b60408051808201909152600080825260208201527f0000000000000000000000001a44076050125825900e736c501f859c50fe728c6001600160a01b031663ddc28c586040518060a001604052808863ffffffff168152602001611d2289611840565b8152602001878152602001868152602001851515815250306040518363ffffffff1660e01b8152600401611d5792919061351d565b6040805180830381865afa158015611d73573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d9791906135c6565b95945050505050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60005b8151811015611ec757611e22828281518110611e1157611e11613325565b602002602001015160400151611ef7565b818181518110611e3457611e34613325565b60200260200101516040015160036000848481518110611e5657611e56613325565b60200260200101516000015163ffffffff1663ffffffff1681526020019081526020016000206000848481518110611e9057611e90613325565b60200260200101516020015161ffff1661ffff1681526020019081526020016000209081611ebe9190613632565b50600101611df3565b507fbe4864a8e820971c0247f5992e2da559595f7bf076a21cb5928d443d2a13b67481604051610f1691906136f1565b600281015161ffff8116600314610f595781604051639a6d49cd60e01b8152600401610d8891906129f0565b611f2b612959565b6040805180820190915260008082526020820152600080611f6233604089013560608a0135611f5d60208c018c612ea6565b6124ce565b91509150600080611f738984611b9c565b9092509050611f9f611f8860208b018b612ea6565b8383611f99368d90038d018d61377c565b8b6124f4565b60408051808201909152858152602080820186905282519298509096503391907f85496b760a4b7f8d66384b9df21b381f5d1b1e79f229a47aaf4c232edc2fe59a90611fed908d018d612ea6565b6040805163ffffffff909216825260208201899052810187905260600160405180910390a350505050935093915050565b6001600160a01b0384166120485760405163e602df0560e01b815260006004820152602401610d88565b6001600160a01b03831661207257604051634a1406b160e11b815260006004820152602401610d88565b6001600160a01b0380851660009081526006602090815260408083209387168352929052208290558015610e0457826001600160a01b0316846001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040516120e591815260200190565b60405180910390a350505050565b60007f000000000000000000000000000000000000000000000000000000e8d4a5100061212081846137c4565b610b9791906137e6565b60006121396020828486613296565b610f40916137fd565b6000612152602860208486613296565b61215b9161381b565b60c01c9392505050565b6000610b977f000000000000000000000000000000000000000000000000000000e8d4a510006001600160401b0384166137e6565b60006001600160a01b0384166121b05761dead93505b6121ba84846125ff565b509092915050565b60606121d18260288186613296565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929695505050505050565b606084848484604051602001612226949392919061384b565b6040516020818303038152906040529050949350505050565b600a5460ff161561113d5760405163d93c066560e01b815260040160405180910390fd5b600a5460ff1661113d57604051638dfc202b60e01b815260040160405180910390fd5b61228e61223f565b6001600b54036122e05760405162461bcd60e51b815260206004820152601d60248201527f546f6b656e3a205472616e7366657220697320726573747269637465640000006044820152606401610d88565b6002600b540361235f57600c546001600160a01b03848116911614806123135750600c546001600160a01b038381169116145b61235f5760405162461bcd60e51b815260206004820152601760248201527f546f6b656e3a20496e76616c6964207472616e736665720000000000000000006044820152606401610d88565b6001600160a01b0383166000908152600d602052604090205460ff16156123bf5760405162461bcd60e51b8152602060048201526014602482015273199c9bdb481a5cc81a5b88189b1858dad31a5cdd60621b6044820152606401610d88565b6001600160a01b0382166000908152600d602052604090205460ff161561241d5760405162461bcd60e51b81526020600482015260126024820152711d1bc81a5cc81a5b88189b1858dad31a5cdd60721b6044820152606401610d88565b6117d2838383612635565b6000610b977f000000000000000000000000000000000000000000000000000000e8d4a51000836137c4565b805160609015158061249d57848460405160200161248992919091825260c01b6001600160c01b031916602082015260280190565b6040516020818303038152906040526124c4565b848433856040516020016124b4949392919061389a565b6040516020818303038152906040525b9150935093915050565b6000806124dc8585856117d7565b90925090506124eb868361275f565b94509492505050565b6124fc612959565b600061250b8460000151612795565b6020850151909150156125255761252584602001516127bd565b7f0000000000000000000000001a44076050125825900e736c501f859c50fe728c6001600160a01b0316632637a450826040518060a001604052808b63ffffffff1681526020016125758c611840565b81526020018a815260200189815260200160008960200151111515815250866040518463ffffffff1660e01b81526004016125b192919061351d565b60806040518083038185885af11580156125cf573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052508101906125f491906138dd565b979650505050505050565b6001600160a01b0382166126295760405163ec442f0560e01b815260006004820152602401610d88565b610f5960008383612286565b6001600160a01b0383166126605780600760008282546126559190613927565b909155506126d29050565b6001600160a01b038316600090815260056020526040902054818110156126b35760405163391434e360e21b81526001600160a01b03851660048201526024810182905260448101839052606401610d88565b6001600160a01b03841660009081526005602052604090209082900390555b6001600160a01b0382166126ee5760078054829003905561270d565b6001600160a01b03821660009081526005602052604090208054820190555b816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8360405161275291815260200190565b60405180910390a3505050565b6001600160a01b03821661278957604051634b637e8f60e11b815260006004820152602401610d88565b610f5982600083612286565b60008134146127b9576040516304fb820960e51b8152346004820152602401610d88565b5090565b60007f0000000000000000000000001a44076050125825900e736c501f859c50fe728c6001600160a01b031663e4fe1d946040518163ffffffff1660e01b8152600401602060405180830381865afa15801561281d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128419190613077565b90506001600160a01b03811661286a576040516329b99a9560e11b815260040160405180910390fd5b6040805133602482018190527f0000000000000000000000001a44076050125825900e736c501f859c50fe728c6001600160a01b0381811660448501526064808501889052855180860390910181526084909401909452602080840180516001600160e01b03166323b872dd60e01b1781528451610f59968816958993610e0493889360009283929091839182885af18061290b576040513d6000823e3d81fd5b50506000513d91508115612923578060011415612930565b6001600160a01b0384163b155b15610e0457604051635274afe760e01b81526001600160a01b0385166004820152602401610d88565b60405180606001604052806000801916815260200160006001600160401b0316815260200161299b604051806040016040528060008152602001600081525090565b905290565b60005b838110156129bb5781810151838201526020016129a3565b50506000910152565b600081518084526129dc8160208601602086016129a0565b601f01601f19169290920160200192915050565b602081526000610f4060208301846129c4565b6001600160a01b038116811461178c57600080fd5b60008060408385031215612a2b57600080fd5b8235612a3681612a03565b946020939093013593505050565b600060e08284031215612a5657600080fd5b50919050565b600060208284031215612a6e57600080fd5b81356001600160401b03811115612a8457600080fd5b61114c84828501612a44565b8351815260208085015190820152600060a08201604060a0604085015281865180845260c08601915060c08160051b8701019350602080890160005b83811015612b0b5788870360bf19018552815180518852830151838801879052612af8878901826129c4565b9750509382019390820190600101612acc565b5050875160608801525050506020850151608085015250905061114c565b600080600060608486031215612b3e57600080fd5b8335612b4981612a03565b92506020840135612b5981612a03565b929592945050506040919091013590565b600060608284031215612a5657600080fd5b60008083601f840112612b8e57600080fd5b5081356001600160401b03811115612ba557600080fd5b602083019150836020828501011115612bbd57600080fd5b9250929050565b600080600080600080600060e0888a031215612bdf57600080fd5b612be98989612b6a565b96506060880135955060808801356001600160401b0380821115612c0c57600080fd5b612c188b838c01612b7c565b909750955060a08a01359150612c2d82612a03565b90935060c08901359080821115612c4357600080fd5b50612c508a828b01612b7c565b989b979a50959850939692959293505050565b801515811461178c57600080fd5b600060208284031215612c8357600080fd5b8135610f4081612c63565b803563ffffffff81168114612ca257600080fd5b919050565b60008060408385031215612cba57600080fd5b612a3683612c8e565b60008060408385031215612cd657600080fd5b82356001600160401b03811115612cec57600080fd5b612cf885828601612a44565b9250506020830135612d0981612c63565b809150509250929050565b815181526020808301519082015260408101610b97565b803561ffff81168114612ca257600080fd5b60008060408385031215612d5057600080fd5b612d5983612c8e565b9150612d6760208401612d2b565b90509250929050565b60008060408385031215612d8357600080fd5b8235612d8e81612a03565b91506020830135612d0981612c63565b600060208284031215612db057600080fd5b8135610f4081612a03565b60008060008060a08587031215612dd157600080fd5b612ddb8686612b6a565b935060608501356001600160401b03811115612df657600080fd5b612e0287828801612b7c565b9094509250506080850135612e1681612a03565b939692955090935050565b60008083601f840112612e3357600080fd5b5081356001600160401b03811115612e4a57600080fd5b6020830191508360208260051b8501011115612bbd57600080fd5b60008060208385031215612e7857600080fd5b82356001600160401b03811115612e8e57600080fd5b612e9a85828601612e21565b90969095509350505050565b600060208284031215612eb857600080fd5b610f4082612c8e565b60008060008060608587031215612ed757600080fd5b612ee085612c8e565b9350612eee60208601612d2b565b925060408501356001600160401b03811115612f0957600080fd5b612f1587828801612b7c565b95989497509550505050565b600060208284031215612f3357600080fd5b5035919050565b60008060008385036080811215612f5057600080fd5b84356001600160401b03811115612f6657600080fd5b612f7287828801612a44565b9450506040601f1982011215612f8757600080fd5b506020840191506060840135612f9c81612a03565b809150509250925092565b600060c082019050835182526001600160401b0360208501511660208301526040840151612fe2604084018280518252602090810151910152565b5082516080830152602083015160a0830152610f40565b6000806040838503121561300c57600080fd5b823561301781612a03565b91506020830135612d0981612a03565b60006060828403121561303957600080fd5b610f408383612b6a565b600181811c9082168061305757607f821691505b602082108103612a5657634e487b7160e01b600052602260045260246000fd5b60006020828403121561308957600080fd5b8151610f4081612a03565b6000602082840312156130a657600080fd5b5051919050565b634e487b7160e01b600052604160045260246000fd5b6000602082840312156130d557600080fd5b8151610f4081612c63565b604051606081016001600160401b0381118282101715613102576131026130ad565b60405290565b604080519081016001600160401b0381118282101715613102576131026130ad565b604051601f8201601f191681016001600160401b0381118282101715613152576131526130ad565b604052919050565b60006001600160401b03821115613173576131736130ad565b50601f01601f191660200190565b60006001600160401b038084111561319b5761319b6130ad565b8360051b60206131ac81830161312a565b8681529185019181810190368411156131c457600080fd5b865b8481101561328a578035868111156131de5760008081fd5b880160603682900312156131f25760008081fd5b6131fa6130e0565b61320382612c8e565b8152613210868301612d2b565b86820152604080830135898111156132285760008081fd5b929092019136601f84011261323d5760008081fd5b823561325061324b8261315a565b61312a565b81815236898387010111156132655760008081fd5b818986018a8301376000918101890191909152908201528452509183019183016131c6565b50979650505050505050565b600080858511156132a657600080fd5b838611156132b357600080fd5b5050820193919092039150565b600084516132d28184602089016129a0565b8201838582376000930192835250909392505050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b60208152600061114c6020830184866132e8565b634e487b7160e01b600052603260045260246000fd5b6000823561013e1983360301811261335257600080fd5b9190910192915050565b6000808335601e1984360301811261337357600080fd5b8301803591506001600160401b0382111561338d57600080fd5b602001915036819003821315612bbd57600080fd5b6001600160401b038116811461178c57600080fd5b63ffffffff6133c589612c8e565b16815260208801356020820152600060408901356133e2816133a2565b6001600160401b03811660408401525087606083015260e0608083015261340d60e0830187896132e8565b6001600160a01b03861660a084015282810360c084015261342f8185876132e8565b9a9950505050505050505050565b60006020828403121561344f57600080fd5b81516001600160401b0381111561346557600080fd5b8201601f8101841361347657600080fd5b805161348461324b8261315a565b81815285602083850101111561349957600080fd5b611d978260208301602086016129a0565b6000602082840312156134bc57600080fd5b8135610f40816133a2565b60018060a01b038516815283602082015261ffff83166040820152608060608201526000610fba60808301846129c4565b60408152600061350b60408301856129c4565b8281036020840152611d9781856129c4565b6040815263ffffffff8351166040820152602083015160608201526000604084015160a0608084015261355360e08401826129c4565b90506060850151603f198483030160a085015261357082826129c4565b60809690960151151560c08501525050506001600160a01b039190911660209091015290565b6000604082840312156135a857600080fd5b6135b0613108565b9050815181526020820151602082015292915050565b6000604082840312156135d857600080fd5b610f408383613596565b601f8211156117d2576000816000526020600020601f850160051c8101602086101561360b5750805b601f850160051c820191505b8181101561362a57828155600101613617565b505050505050565b81516001600160401b0381111561364b5761364b6130ad565b61365f816136598454613043565b846135e2565b602080601f831160018114613694576000841561367c5750858301515b600019600386901b1c1916600185901b17855561362a565b600085815260208120601f198616915b828110156136c3578886015182559484019460019091019084016136a4565b50858210156136e15787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b600060208083018184528085518083526040925060408601915060408160051b87010184880160005b8381101561376e57888303603f190185528151805163ffffffff1684528781015161ffff1688850152860151606087850181905261375a818601836129c4565b96890196945050509086019060010161371a565b509098975050505050505050565b60006040828403121561378e57600080fd5b613796613108565b82358152602083013560208201528091505092915050565b634e487b7160e01b600052601160045260246000fd5b6000826137e157634e487b7160e01b600052601260045260246000fd5b500490565b8082028115828204841417610b9757610b976137ae565b80356020831015610b9757600019602084900360031b1b1692915050565b6001600160c01b031981358181169160088510156138435780818660080360031b1b83161692505b505092915050565b6001600160401b0360c01b8560c01b16815263ffffffff60e01b8460e01b16600882015282600c8201526000825161388a81602c8501602087016129a0565b91909101602c0195945050505050565b8481526001600160401b0360c01b8460c01b166020820152826028820152600082516138cd8160488501602087016129a0565b9190910160480195945050505050565b6000608082840312156138ef57600080fd5b6138f76130e0565b825181526020830151613909816133a2565b602082015261391b8460408501613596565b60408201529392505050565b80820180821115610b9757610b976137ae56fea26469706673582212208cdcc1c04c9f55e5e452b377a7de41cb0bff8330b3a792e337650d60bf202d8564736f6c63430008160033

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

000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000001a44076050125825900e736c501f859c50fe728c000000000000000000000000b839a86a29c18c10999c131d68bf9f736775151200000000000000000000000000000000000000000000000000000000000000084879706572696f6e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000452494f4e00000000000000000000000000000000000000000000000000000000

-----Decoded View---------------
Arg [0] : _name (string): Hyperion
Arg [1] : _symbol (string): RION
Arg [2] : _lzEndpoint (address): 0x1a44076050125825900e736c501f859c50fE728c
Arg [3] : _delegate (address): 0xb839a86a29C18C10999c131D68BF9f7367751512

-----Encoded View---------------
8 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000080
Arg [1] : 00000000000000000000000000000000000000000000000000000000000000c0
Arg [2] : 0000000000000000000000001a44076050125825900e736c501f859c50fe728c
Arg [3] : 000000000000000000000000b839a86a29c18c10999c131d68bf9f7367751512
Arg [4] : 0000000000000000000000000000000000000000000000000000000000000008
Arg [5] : 4879706572696f6e000000000000000000000000000000000000000000000000
Arg [6] : 0000000000000000000000000000000000000000000000000000000000000004
Arg [7] : 52494f4e00000000000000000000000000000000000000000000000000000000


Deployed Bytecode Sourcemap

342:2761:40:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1760:89:33;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;427:38:40;;;;;;;;;;;;464:1;427:38;;;;;916:25:41;;;904:2;889:18;427:38:40;770:177:41;3979:186:33;;;;;;;;;;-1:-1:-1;3979:186:33;;;;;:::i;:::-;;:::i;:::-;;;1573:14:41;;1566:22;1548:41;;1536:2;1521:18;3979:186:33;1408:187:41;5176:1276:24;;;;;;;;;;-1:-1:-1;5176:1276:24;;;;;:::i;:::-;;:::i;:::-;;;;;;;;;:::i;2330:27::-;;;;;;;;;;-1:-1:-1;2330:27:24;;;;-1:-1:-1;;;;;2330:27:24;;;;;;-1:-1:-1;;;;;3787:32:41;;;3769:51;;3757:2;3742:18;2330:27:24;3623:203:41;2896:201:40;;;;;;;;;;-1:-1:-1;2896:201:40;;;;;:::i;:::-;;:::i;:::-;;4368:708:12;;;;;;:::i;:::-;;:::i;2204:40:24:-;;;;;;;;;;;;2243:1;2204:40;;;;;6028:6:41;6016:19;;;5998:38;;5986:2;5971:18;2204:40:24;5854:188:41;3475:140:24;;;;;;;;;;-1:-1:-1;3475:140:24;;;-1:-1:-1;;;6217:52:41;;3606:1:24;6300:2:41;6285:18;;6278:59;6190:18;3475:140:24;6047:296:41;2573:190:40;;;;;;;;;;-1:-1:-1;2573:190:40;;;;;:::i;:::-;;:::i;1287:235:10:-;;;;;;;;;;-1:-1:-1;1287:235:10;;;843:1:13;6924:34:41;;678:1:12;6989:2:41;6974:18;;6967:43;6860:18;1287:235:10;6717:299:41;2830:97:33;;;;;;;;;;-1:-1:-1;2908:12:33;;2830:97;;2167:31:24;;;;;;;;;;;;2197:1;2167:31;;4757:244:33;;;;;;;;;;-1:-1:-1;4757:244:33;;;;;:::i;:::-;;:::i;541:25:40:-;;;;;;;;;;-1:-1:-1;541:25:40;;;;-1:-1:-1;;;;;541:25:40;;;2688:82:33;;;;;;;;;;-1:-1:-1;2761:2:33;2688:82;;;7193:4:41;7181:17;;;7163:36;;7151:2;7136:18;2688:82:33;7021:184:41;1724:108:11;;;;;;;;;;-1:-1:-1;1724:108:11;;;;;:::i;:::-;;:::i;6903:774:24:-;;;;;;;;;;-1:-1:-1;6903:774:24;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;875:93:19:-;;;;;;;;;;-1:-1:-1;956:4:19;875:93;;538::18;;;;;;;;;;-1:-1:-1;538:93:18;;;;;:::i;:::-;;:::i;16151:132:24:-;;;;;;;;;;-1:-1:-1;16151:132:24;;;;;:::i;:::-;16256:11;;;;;16233:4;16256:11;;;:5;:11;;;;;;:20;;16151:132;1726:84:38;;;;;;;;;;-1:-1:-1;1796:7:38;;;;1726:84;;446:46:11;;;;;;;;;;;;;;;1950:158:40;;;;;;;;;;-1:-1:-1;1950:158:40;;;;;:::i;:::-;;:::i;471:38::-;;;;;;;;;;;;508:1;471:38;;4657:163:24;;;;;;;;;;-1:-1:-1;4657:163:24;;;;;:::i;:::-;;:::i;2985:116:33:-;;;;;;;;;;-1:-1:-1;2985:116:33;;;;;:::i;:::-;-1:-1:-1;;;;;3076:18:33;3050:7;3076:18;;;:9;:18;;;;;;;2985:116;2293:101:28;;;;;;;;;;;;;:::i;3507:128:12:-;;;;;;;;;;-1:-1:-1;3507:128:12;;;;;:::i;:::-;3596:12;3507:128;;;;;;;;-1:-1:-1;;;;;10072:31:41;;;10054:50;;10042:2;10027:18;3507:128:12;9910:200:41;2013:216:12;;;;;;;;;;-1:-1:-1;2013:216:12;;;;;:::i;:::-;;:::i;4222:87:24:-;;;;;;;;;;-1:-1:-1;4301:1:24;4222:87;;1638:85:28;;;;;;;;;;-1:-1:-1;1684:7:28;1710:6;-1:-1:-1;;;;;1710:6:28;1638:85;;1962:93:33;;;;;;;;;;;;;:::i;1861:46:24:-;;;;;;;;;;;;;;;2228:213:40;;;;;;;;;;-1:-1:-1;2228:213:40;;;;;:::i;:::-;;:::i;1460:94:23:-;;;;;;;;;;-1:-1:-1;1519:4:23;1460:94;;3296:178:33;;;;;;;;;;-1:-1:-1;3296:178:33;;;;;:::i;:::-;;:::i;387:34:40:-;;;;;;;;;;;;420:1;387:34;;2769:121;;;;;;;;;;-1:-1:-1;2769:121:40;;;;;:::i;:::-;2873:10;;-1:-1:-1;;;;;2862:21:40;;;2873:10;;2862:21;;2769:121;559:23:19;;;;;;;;;;-1:-1:-1;559:23:19;;;;-1:-1:-1;;;;;559:23:19;;;1391:156:18;;;;;;;;;;-1:-1:-1;1391:156:18;;;;;:::i;:::-;;:::i;569:48:11:-;;;;;;;;;;-1:-1:-1;569:48:11;;;;;:::i;:::-;;;;;;;;;;;;;;3510:981:18;;;;;;;;;;-1:-1:-1;3510:981:18;;;;;:::i;:::-;;:::i;1640:304:40:-;;;;;;;;;;-1:-1:-1;1640:304:40;;;;;:::i;:::-;;:::i;1698:1333:19:-;;;;;;:::i;:::-;;:::i;515:20:40:-;;;;;;;;;;;;;;;;8365:290:24;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;:::i;3252:105:11:-;;;;;;;;;;-1:-1:-1;3252:105:11;;;;;:::i;:::-;;:::i;3679:409:19:-;;;;;;:::i;:::-;;:::i;1100:139::-;;;;;;;;;;-1:-1:-1;1100:139:19;;;;;:::i;:::-;;:::i;3532:140:33:-;;;;;;;;;;-1:-1:-1;3532:140:33;;;;;:::i;:::-;-1:-1:-1;;;;;3638:18:33;;;3612:7;3638:18;;;:11;:18;;;;;;;;:27;;;;;;;;;;;;;3532:140;590:45:40;;;;;;;;;;-1:-1:-1;590:45:40;;;;;:::i;:::-;;;;;;;;;;;;;;;;2543:215:28;;;;;;;;;;-1:-1:-1;2543:215:28;;;;;:::i;:::-;;:::i;2114:108:40:-;;;;;;;;;;-1:-1:-1;2114:108:40;;;;;:::i;:::-;-1:-1:-1;;;;;2193:22:40;2170:4;2193:22;;;:13;:22;;;;;;;;;2114:108;2771:149:12;;;;;;;;;;-1:-1:-1;2771:149:12;;;;;:::i;:::-;;:::i;1760:89:33:-;1805:13;1837:5;1830:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1760:89;:::o;3979:186::-;4052:4;735:10:37;4106:31:33;735:10:37;4122:7:33;4131:5;4106:8;:31::i;:::-;4154:4;4147:11;;;3979:186;;;;;:::o;5176:1276:24:-;-1:-1:-1;;;;;;;;;;;;;;;;;5328:35:24;5365:28;-1:-1:-1;;;;;;;;;;;;;;;;;;;5365:28:24;5409:19;5483;5512:4;-1:-1:-1;;;;;5512:10:24;;:12;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;5505:32:24;;:34;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;5601;;;;;;;;;;;;;;;;;;5752:21;;-1:-1:-1;5752:21:24;;;;;;;;;5601:34;;-1:-1:-1;5601:34:24;;-1:-1:-1;5752:21:24;;;;-1:-1:-1;;;;;;;;;;;;;;;;;5752:21:24;;;;;;;;;;;;;;;-1:-1:-1;5736:37:24;-1:-1:-1;6210:20:24;;6260:120;6284:19;;;;6317:22;;;;6353:17;;;;6284:10;6353:17;:::i;:::-;6260:10;:120::i;:::-;6403:42;;;;;;;;;;;;;;;;5176:1276;;;;-1:-1:-1;;;;;;5176:1276:24:o;2896:201:40:-;1531:13:28;:11;:13::i;:::-;-1:-1:-1;;;;;2998:16:40;::::1;2990:56;;;::::0;-1:-1:-1;;;2990:56:40;;16384:2:41;2990:56:40::1;::::0;::::1;16366:21:41::0;16423:2;16403:18;;;16396:30;16462:29;16442:18;;;16435:57;16509:18;;2990:56:40::1;;;;;;;;;3056:34;::::0;-1:-1:-1;;;3056:34:40;;-1:-1:-1;;;;;16730:32:41;;;3056:34:40::1;::::0;::::1;16712:51:41::0;16779:18;;;16772:34;;;3056:22:40;::::1;::::0;::::1;::::0;16685:18:41;;3056:34:40::1;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;2896:201:::0;;;:::o;4368:708:12:-;4681:8;-1:-1:-1;;;;;4673:31:12;4694:10;4673:31;4669:68;;4713:24;;-1:-1:-1;;;4713:24:12;;4726:10;4713:24;;;3769:51:41;3742:18;;4713:24:12;3623:203:41;4669:68:12;4873:14;;;;;;4837:32;;4854:14;;4873:7;4854:14;:::i;:::-;4837:16;:32::i;:::-;:50;4833:103;;4905:14;;;;:7;:14;:::i;:::-;4896:40;;-1:-1:-1;;;4896:40:12;;17269:10:41;17257:23;;;4896:40:12;;;17239:42:41;4921:14:12;;;;17297:18:41;;;17290:34;17212:18;;4896:40:12;17067:263:41;4833:103:12;5010:59;5021:7;5030:5;5037:8;;5047:9;5058:10;;5010;:59::i;:::-;4368:708;;;;;;;:::o;2573:190:40:-;1531:13:28;:11;:13::i;:::-;2639:7:40::1;2635:87;;;2662:8;:6;:8::i;:::-;2635:87;;;2701:10;:8;:10::i;:::-;2736:20;::::0;1573:14:41;;1566:22;1548:41;;2736:20:40::1;::::0;1536:2:41;1521:18;2736:20:40::1;;;;;;;;2573:190:::0;:::o;4757:244:33:-;4844:4;735:10:37;4900:37:33;4916:4;735:10:37;4931:5:33;4900:15;:37::i;:::-;4947:26;4957:4;4963:2;4967:5;4947:9;:26::i;:::-;4990:4;4983:11;;;4757:244;;;;;;:::o;1724:108:11:-;1531:13:28;:11;:13::i;:::-;1804:21:11::1;1813:4;1819:5;1804:8;:21::i;:::-;1724:108:::0;;:::o;6903:774:24:-;-1:-1:-1;;;;;;;;;;;;;;;;;7237:24:24;7265:74;7276:19;;;;7297:22;;;;7321:17;;;;7276:10;7321:17;:::i;7265:74::-;7234:105;;;7428:20;7450;7474:49;7494:10;7506:16;7474:19;:49::i;:::-;7427:96;;-1:-1:-1;7427:96:24;-1:-1:-1;7612:58:24;7619:17;;;;:10;:17;:::i;:::-;7638:7;7647;7656:13;7612:6;:58::i;:::-;7605:65;6903:774;-1:-1:-1;;;;;;6903:774:24:o;538:93:18:-;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;1950:158:40:-;1531:13:28;:11;:13::i;:::-;-1:-1:-1;;;;;2028:22:40;::::1;;::::0;;;:13:::1;:22;::::0;;;;;;;;:30;;-1:-1:-1;;2028:30:40::1;::::0;::::1;;::::0;;::::1;::::0;;;2073:28;;17503:51:41;;;17570:18;;;17563:50;2073:28:40::1;::::0;17476:18:41;2073:28:40::1;;;;;;;;1950:158:::0;;:::o;4657:163:24:-;1531:13:28;:11;:13::i;:::-;4740:12:24::1;:28:::0;;-1:-1:-1;;;;;;4740:28:24::1;-1:-1:-1::0;;;;;4740:28:24;::::1;::::0;;::::1;::::0;;;4783:30:::1;::::0;3769:51:41;;;4783:30:24::1;::::0;3757:2:41;3742:18;4783:30:24::1;3623:203:41::0;2293:101:28;1531:13;:11;:13::i;:::-;2357:30:::1;2384:1;2357:18;:30::i;:::-;2293:101::o:0;2013:216:12:-;-1:-1:-1;;;;;2198:24:12;;2217:4;2198:24;2013:216;;;;;;;:::o;1962:93:33:-;2009:13;2041:7;2034:14;;;;;:::i;2228:213:40:-;1531:13:28;:11;:13::i;:::-;2330:10:40::1;::::0;;-1:-1:-1;;;;;2350:25:40;;::::1;-1:-1:-1::0;;;;;;2350:25:40;::::1;::::0;::::1;::::0;;;2390:44:::1;::::0;;2330:10;;;::::1;17836:34:41::0;;;17901:2;17886:18;;17879:43;;;;2390:44:40::1;::::0;17771:18:41;2390:44:40::1;17624:304:41::0;3296:178:33;3365:4;735:10:37;3419:27:33;735:10:37;3436:2:33;3440:5;3419:9;:27::i;1391:156:18:-;1531:13:28;:11;:13::i;:::-;1503:37:18::1;;1523:16:::0;;1503:37:::1;:::i;:::-;:19;:37::i;3510:981::-:0;3701:21;;;3677;3701;;;:15;:21;;;;;;;;:31;;;;;;;;;;3677:55;;3653:12;;3677:21;3701:31;3677:55;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3861:8;:15;3880:1;3861:20;3857:46;;3890:13;;3883:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;3883:20:18;;-1:-1:-1;3883:20:18;;-1:-1:-1;;;;3883:20:18;3857:46;3988:1;3964:25;;;3960:46;;3998:8;-1:-1:-1;3991:15:18;;3960:46;4153:1;4129:25;;4125:267;;4170:34;4190:13;;4170:34;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;4170:19:18;;-1:-1:-1;;;4170:34:18:i;:::-;4353:8;4363:17;:13;4377:1;4363:13;;:17;:::i;:::-;4340:41;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;4333:48;;;;;4125:267;4470:13;;4455:29;;-1:-1:-1;;;4455:29:18;;;;;;;;;:::i;1640:304:40:-;2490:10;;-1:-1:-1;;;;;2490:10:40;735::37;2490:26:40;2482:67;;;;-1:-1:-1;;;2482:67:40;;22585:2:41;2482:67:40;;;22567:21:41;22624:2;22604:18;;;22597:30;22663;22643:18;;;22636:58;22711:18;;2482:67:40;22383:352:41;2482:67:40;1730:5:::1;::::0;1753:11;;;:30:::1;;;464:1;1768;:15;1753:30;:49;;;;508:1;1787;:15;1753:49;1745:74;;;::::0;-1:-1:-1;;;1745:74:40;;22942:2:41;1745:74:40::1;::::0;::::1;22924:21:41::0;22981:2;22961:18;;;22954:30;-1:-1:-1;;;23000:18:41;;;22993:42;23052:18;;1745:74:40::1;22740:336:41::0;1745:74:40::1;1833:5;::::0;:15;1829:109:::1;;1864:5;:9:::0;;;1892:35:::1;::::0;;23255:25:41;;;23311:2;23296:18;;23289:34;;;1892:35:40::1;::::0;23228:18:41;1892:35:40::1;23081:248:41::0;1698:1333:19;1799:9;1794:1037;1814:19;;;1794:1037;;;1854:29;1886:8;;1895:1;1886:11;;;;;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;1854:43;-1:-1:-1;1980:50:19;1987:20;;;;1854:43;1987:20;:::i;:::-;2009;;;;16256:11:24;;;;;16233:4;16256:11;;;:5;:11;;;;;;:20;;16151:132;1980:50:19;1975:65;;2032:8;;;1975:65;2602:4;:22;2633:12;;;;:6;2696:11;;;;2725:14;;;;2633:6;2725:14;:::i;:::-;2757:15;;;;;;;;:::i;:::-;2790:16;;;;:6;:16;:::i;:::-;2602:218;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1840:991;1794:1037;1835:3;;1794:1037;;;;2988:10;-1:-1:-1;;;;;2978:43:19;;:45;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;2978:45:19;;;;;;;;;;;;:::i;:::-;2961:63;;-1:-1:-1;;;2961:63:19;;;;;;;;:::i;8365:290:24:-;8526:34;;:::i;:::-;-1:-1:-1;;;;;;;;;;;;;;;;;8609:39:24;8615:10;8627:4;8633:14;8609:5;:39::i;:::-;8602:46;;;;8365:290;;;;;;;:::o;3252:105:11:-;1531:13:28;:11;:13::i;:::-;3319:31:11::1;::::0;-1:-1:-1;;;3319:31:11;;-1:-1:-1;;;;;3787:32:41;;;3319:31:11::1;::::0;::::1;3769:51:41::0;3319:8:11::1;:20;::::0;::::1;::::0;3742:18:41;;3319:31:11::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;3252:105:::0;:::o;3679:409:19:-;3958:10;3980:4;3958:27;3954:50;;3994:10;;-1:-1:-1;;;3994:10:19;;;;;;;;;;;3954:50;4014:67;4033:7;4042:5;4049:8;;4059:9;4070:10;;4014:18;:67::i;1100:139::-;1531:13:28;:11;:13::i;:::-;1175:8:19::1;:20:::0;;-1:-1:-1;;;;;;1175:20:19::1;-1:-1:-1::0;;;;;1175:20:19;::::1;::::0;;::::1;::::0;;;1210:22:::1;::::0;3769:51:41;;;1210:22:19::1;::::0;3757:2:41;3742:18;1210:22:19::1;3623:203:41::0;2543:215:28;1531:13;:11;:13::i;:::-;-1:-1:-1;;;;;2627:22:28;::::1;2623:91;;2672:31;::::0;-1:-1:-1;;;2672:31:28;;2700:1:::1;2672:31;::::0;::::1;3769:51:41::0;3742:18;;2672:31:28::1;3623:203:41::0;2623:91:28::1;2723:28;2742:8;2723:18;:28::i;:::-;2543:215:::0;:::o;2771:149:12:-;2853:4;2900:13;;;;;;2876:5;;2853:4;;2882:13;;2900:6;2882:13;:::i;:::-;2876:20;;;;;;;;;;;;;-1:-1:-1;2876:20:12;;:37;;2771:149;-1:-1:-1;;2771:149:12:o;8707:128:33:-;8791:37;8800:5;8807:7;8816:5;8823:4;8791:8;:37::i;:::-;8707:128;;;:::o;18168:668:24:-;18310:20;18332:24;18506:22;18518:9;18506:11;:22::i;:::-;18491:37;;18654:12;18635:31;;18736:12;18717:16;:31;18713:117;;;18771:48;;-1:-1:-1;;;18771:48:24;;;;;23255:25:41;;;23296:18;;;23289:34;;;23228:18;;18771:48:24;23081:248:41;1796:162:28;1684:7;1710:6;-1:-1:-1;;;;;1710:6:28;735:10:37;1855:23:28;1851:101;;1901:40;;-1:-1:-1;;;1901:40:28;;735:10:37;1901:40:28;;;3769:51:41;3742:18;;1901:40:28;3623:203:41;2718:196:11;2822:11;;;2788:7;2822:11;;;:5;:11;;;;;;;2843:43;;2874:12;;-1:-1:-1;;;2874:12:11;;26281:10:41;26269:23;;2874:12:11;;;26251:42:41;26224:18;;2874:12:11;26107:192:41;12944:1806:24;13421:17;13441:36;:17;:8;;:15;:17::i;:::-;2891:2:27;2780:123;13441:36:24;13421:56;;13610:24;13637:62;13645:9;13656:26;13662:19;:8;;:17;:19::i;:::-;13656:5;:26::i;:::-;13684:14;;;;:7;:14;:::i;:::-;13637:7;:62::i;:::-;13610:89;-1:-1:-1;243:2:27;-1:-1:-1;;13710:955:24;;;13814:23;13840:175;13883:13;;;;;;;;:::i;:::-;13914:14;;;;:7;:14;:::i;:::-;13946:16;13980:21;:8;;:19;:21::i;:::-;13840:25;:175::i;:::-;14562:92;;-1:-1:-1;;;14562:92:24;;13814:201;;-1:-1:-1;;;;;;14562:8:24;:20;;;;:92;;14583:9;;14594:5;;14601:1;;13814:201;;14562:92;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;13737:928;13710:955;-1:-1:-1;;;;;14680:63:24;;14692:5;14680:63;14699:14;;;;:7;:14;:::i;:::-;14680:63;;;17269:10:41;17257:23;;;17239:42;;17312:2;17297:18;;17290:34;;;17212:18;14680:63:24;;;;;;;13247:1503;;12944:1806;;;;;;;:::o;2339:115:38:-;1350:19;:17;:19::i;:::-;2398:7:::1;:14:::0;;-1:-1:-1;;2398:14:38::1;2408:4;2398:14;::::0;;2427:20:::1;2434:12;735:10:37::0;;656:96;2434:12:38::1;2427:20;::::0;-1:-1:-1;;;;;3787:32:41;;;3769:51;;3757:2;3742:18;2427:20:38::1;;;;;;;2339:115::o:0;2586:117::-;1597:16;:14;:16::i;:::-;2644:7:::1;:15:::0;;-1:-1:-1;;2644:15:38::1;::::0;;2674:22:::1;735:10:37::0;2683:12:38::1;656:96:37::0;10396:476:33;-1:-1:-1;;;;;3638:18:33;;;10495:24;3638:18;;;:11;:18;;;;;;;;:27;;;;;;;;;;-1:-1:-1;;10561:36:33;;10557:309;;;10636:5;10617:16;:24;10613:130;;;10668:60;;-1:-1:-1;;;10668:60:33;;-1:-1:-1;;;;;27526:32:41;;10668:60:33;;;27508:51:41;27575:18;;;27568:34;;;27618:18;;;27611:34;;;27481:18;;10668:60:33;27306:345:41;10613:130:33;10784:57;10793:5;10800:7;10828:5;10809:16;:24;10835:5;10784:8;:57::i;5374:300::-;-1:-1:-1;;;;;5457:18:33;;5453:86;;5498:30;;-1:-1:-1;;;5498:30:33;;5525:1;5498:30;;;3769:51:41;3742:18;;5498:30:33;3623:203:41;5453:86:33;-1:-1:-1;;;;;5552:16:33;;5548:86;;5591:32;;-1:-1:-1;;;5591:32:33;;5620:1;5591:32;;;3769:51:41;3742:18;;5591:32:33;3623:203:41;5548:86:33;5643:24;5651:4;5657:2;5661:5;5643:7;:24::i;2286:134:11:-;2359:11;;;;;;;:5;:11;;;;;;;;;:19;;;2393:20;;17239:42:41;;;17297:18;;17290:34;;;2393:20:11;;17212:18:41;2393:20:11;17067:263:41;10990:1436:24;11122:20;11144;11176:15;11347:324;11379:10;:13;;;11406:16;11412:9;11406:5;:16::i;:::-;11640:21;;;;:10;:21;:::i;:::-;11347:324;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;11347:18:24;;-1:-1:-1;;;11347:324:24:i;:::-;11323:348;;-1:-1:-1;11323:348:24;-1:-1:-1;11751:14:24;11323:348;11768:33;;2197:1;11768:33;;;2243:1;11768:33;11751:50;-1:-1:-1;11923:67:24;11938:17;;;;:10;:17;:::i;:::-;11957:7;11966:23;;;;:10;:23;:::i;11923:67::-;12248:12;;11913:77;;-1:-1:-1;;;;;;12248:12:24;12340:23;;12336:83;;12365:54;;-1:-1:-1;;;12365:54:24;;-1:-1:-1;;;;;12365:36:24;;;;;:54;;12402:7;;12411;;12365:54;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;12336:83;11166:1260;;;10990:1436;;;;;:::o;2038:391:13:-;-1:-1:-1;;;;;;;;;;;;;;;;;2259:8:13;-1:-1:-1;;;;;2259:14:13;;2291:86;;;;;;;;2307:7;2291:86;;;;;;2316:25;2333:7;2316:16;:25::i;:::-;2291:86;;;;2343:8;2291:86;;;;2353:8;2291:86;;;;2363:13;2291:86;;;;;2403:4;2259:163;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;2240:182;2038:391;-1:-1:-1;;;;;2038:391:13:o;2912:187:28:-;2985:16;3004:6;;-1:-1:-1;;;;;3020:17:28;;;-1:-1:-1;;;;;;3020:17:28;;;;;;3052:40;;3004:6;;;;;;;3052:40;;2985:16;3052:40;2975:124;2912:187;:::o;2237:514:18:-;2345:9;2340:354;2364:16;:23;2360:1;:27;2340:354;;;2522:48;2542:16;2559:1;2542:19;;;;;;;;:::i;:::-;;;;;;;:27;;;2522:19;:48::i;:::-;2656:16;2673:1;2656:19;;;;;;;;:::i;:::-;;;;;;;:27;;;2584:15;:40;2600:16;2617:1;2600:19;;;;;;;;:::i;:::-;;;;;;;:23;;;2584:40;;;;;;;;;;;;;;;:69;2625:16;2642:1;2625:19;;;;;;;;:::i;:::-;;;;;;;:27;;;2584:69;;;;;;;;;;;;;;;:99;;;;;;:::i;:::-;-1:-1:-1;2389:3:18;;2340:354;;;;2709:35;2727:16;2709:35;;;;;;:::i;4631:264::-;4801:1;4787:16;;4781:23;4827:28;;;463:1;4827:28;4823:65;;4879:8;4864:24;;-1:-1:-1;;;4864:24:18;;;;;;;;:::i;9363:1333:24:-;9517:34;;:::i;:::-;-1:-1:-1;;;;;;;;;;;;;;;;;9915:20:24;;9965:140;9985:10;10009:19;;;;10042:22;;;;10078:17;;;;10009:10;10078:17;:::i;:::-;9965:6;:140::i;:::-;9914:191;;;;10194:20;10216;10240:49;10260:10;10272:16;10240:19;:49::i;:::-;10193:96;;-1:-1:-1;10193:96:24;-1:-1:-1;10412:66:24;10420:17;;;;:10;:17;:::i;:::-;10439:7;10448;10412:66;;;;;;;10457:4;10412:66;:::i;:::-;10463:14;10412:7;:66::i;:::-;10544:42;;;;;;;;;;;;;;;;;;;10610:15;;10399:79;;-1:-1:-1;10544:42:24;;-1:-1:-1;10646:10:24;;10610:15;10602:87;;10627:17;;;;:10;:17;:::i;:::-;10602:87;;;33422:10:41;33410:23;;;33392:42;;33465:2;33450:18;;33443:34;;;33493:18;;33486:34;;;33380:2;33365:18;10602:87:24;;;;;;;9583:1113;;;;9363:1333;;;;;;:::o;9682:432:33:-;-1:-1:-1;;;;;9794:19:33;;9790:89;;9836:32;;-1:-1:-1;;;9836:32:33;;9865:1;9836:32;;;3769:51:41;3742:18;;9836:32:33;3623:203:41;9790:89:33;-1:-1:-1;;;;;9892:21:33;;9888:90;;9936:31;;-1:-1:-1;;;9936:31:33;;9964:1;9936:31;;;3769:51:41;3742:18;;9936:31:33;3623:203:41;9888:90:33;-1:-1:-1;;;;;9987:18:33;;;;;;;:11;:18;;;;;;;;:27;;;;;;;;;:35;;;10032:76;;;;10082:7;-1:-1:-1;;;;;10066:31:33;10075:5;-1:-1:-1;;;;;10066:31:33;;10091:5;10066:31;;;;916:25:41;;904:2;889:18;;770:177;10066:31:33;;;;;;;;9682:432;;;;:::o;16677:172:24:-;16748:16;16821:21;16784:33;16821:21;16784:9;:33;:::i;:::-;16783:59;;;;:::i;1573:123:27:-;1633:7;1667:21;188:2;1633:7;1667:4;;:21;:::i;:::-;1659:30;;;:::i;1874:152::-;1936:6;1975:42;243:2;188;1975:4;;:42;:::i;:::-;1968:50;;;:::i;:::-;1961:58;;;1874:152;-1:-1:-1;;;1874:152:27:o;17073:139:24:-;17137:16;17172:33;17184:21;-1:-1:-1;;;;;17172:33:24;;;:::i;2939:462:23:-;3073:24;-1:-1:-1;;;;;3113:19:23;;3109:46;;3148:6;3134:21;;3109:46;3251:21;3257:3;3262:9;3251:5;:21::i;:::-;-1:-1:-1;3385:9:23;;2939:462;-1:-1:-1;;2939:462:23:o;2186:130:27:-;2250:12;2281:28;:4;243:2;2281:4;;:28;:::i;:::-;2274:35;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;2274:35:27;;2186:130;-1:-1:-1;;;;;;2186:130:27:o;640:284:26:-;824:17;877:6;885:7;894:9;905:11;860:57;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;853:64;;640:284;;;;;;:::o;1878:128:38:-;1796:7;;;;1939:61;;;1974:15;;-1:-1:-1;;;1974:15:38;;;;;;;;;;;2078:126;1796:7;;;;2136:62;;2172:15;;-1:-1:-1;;;2172:15:38;;;;;;;;;;;1144:490:40;1350:19:38;:17;:19::i;:::-;464:1:40::1;1248:5;;:19:::0;1244:89:::1;;1283:39;::::0;-1:-1:-1;;;1283:39:40;;35429:2:41;1283:39:40::1;::::0;::::1;35411:21:41::0;35468:2;35448:18;;;35441:30;35507:31;35487:18;;;35480:59;35556:18;;1283:39:40::1;35227:353:41::0;1244:89:40::1;508:1;1346:5;;:19:::0;1342:124:::1;;1397:10;::::0;-1:-1:-1;;;;;1389:18:40;;::::1;1397:10:::0;::::1;1389:18;::::0;:38:::1;;-1:-1:-1::0;1417:10:40::1;::::0;-1:-1:-1;;;;;1411:16:40;;::::1;1417:10:::0;::::1;1411:16;1389:38;1381:74;;;::::0;-1:-1:-1;;;1381:74:40;;35787:2:41;1381:74:40::1;::::0;::::1;35769:21:41::0;35826:2;35806:18;;;35799:30;35865:25;35845:18;;;35838:53;35908:18;;1381:74:40::1;35585:347:41::0;1381:74:40::1;-1:-1:-1::0;;;;;1484:19:40;::::1;;::::0;;;:13:::1;:19;::::0;;;;;::::1;;1483:20;1475:53;;;::::0;-1:-1:-1;;;1475:53:40;;36139:2:41;1475:53:40::1;::::0;::::1;36121:21:41::0;36178:2;36158:18;;;36151:30;-1:-1:-1;;;36197:18:41;;;36190:50;36257:18;;1475:53:40::1;35937:344:41::0;1475:53:40::1;-1:-1:-1::0;;;;;1547:17:40;::::1;;::::0;;;:13:::1;:17;::::0;;;;;::::1;;1546:18;1538:49;;;::::0;-1:-1:-1;;;1538:49:40;;36488:2:41;1538:49:40::1;::::0;::::1;36470:21:41::0;36527:2;36507:18;;;36500:30;-1:-1:-1;;;36546:18:41;;;36539:48;36604:18;;1538:49:40::1;36286:342:41::0;1538:49:40::1;1597:30;1611:4;1617:2;1621:5;1597:13;:30::i;17436:147:24:-:0;17501:15;17542:33;17554:21;17542:9;:33;:::i;598:506:27:-;791:18;;732:17;;791:22;;;934:163;;1074:7;1083:13;1057:40;;;;;;;;36788:19:41;;;36863:3;36841:16;-1:-1:-1;;;;;;36837:51:41;36832:2;36823:12;;36816:73;36914:2;36905:12;;36633:290;1057:40:27;;;;;;;;;;;;;934:163;;;976:7;985:13;1017:10;1030:11;959:83;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;934:163;927:170;;598:506;;;;;;:::o;2037:567:23:-;2198:20;2220:24;2291:44;2302:9;2313:12;2327:7;2291:10;:44::i;:::-;2256:79;;-1:-1:-1;2256:79:23;-1:-1:-1;2571:26:23;2577:5;2256:79;2571:5;:26::i;:::-;2037:567;;;;;;;:::o;3188:766:13:-;3389:31;;:::i;:::-;3554:20;3577:26;3588:4;:14;;;3577:10;:26::i;:::-;3617:15;;;;3554:49;;-1:-1:-1;3617:19:13;3613:53;;3638:28;3650:4;:15;;;3638:11;:28::i;:::-;3755:8;-1:-1:-1;;;;;3755:13:13;;3777:12;3809:92;;;;;;;;3825:7;3809:92;;;;;;3834:25;3851:7;3834:16;:25::i;:::-;3809:92;;;;3861:8;3809:92;;;;3871:8;3809:92;;;;3899:1;3881:4;:15;;;:19;3809:92;;;;;3919:14;3755:192;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;3677:270;3188:766;-1:-1:-1;;;;;;;3188:766:13:o;7439:208:33:-;-1:-1:-1;;;;;7509:21:33;;7505:91;;7553:32;;-1:-1:-1;;;7553:32:33;;7582:1;7553:32;;;3769:51:41;3742:18;;7553:32:33;3623:203:41;7505:91:33;7605:35;7621:1;7625:7;7634:5;7605:7;:35::i;5989:1107::-;-1:-1:-1;;;;;6078:18:33;;6074:540;;6230:5;6214:12;;:21;;;;;;;:::i;:::-;;;;-1:-1:-1;6074:540:33;;-1:-1:-1;6074:540:33;;-1:-1:-1;;;;;6288:15:33;;6266:19;6288:15;;;:9;:15;;;;;;6321:19;;;6317:115;;;6367:50;;-1:-1:-1;;;6367:50:33;;-1:-1:-1;;;;;27526:32:41;;6367:50:33;;;27508:51:41;27575:18;;;27568:34;;;27618:18;;;27611:34;;;27481:18;;6367:50:33;27306:345:41;6317:115:33;-1:-1:-1;;;;;6552:15:33;;;;;;:9;:15;;;;;6570:19;;;;6552:37;;6074:540;-1:-1:-1;;;;;6628:16:33;;6624:425;;6791:12;:21;;;;;;;6624:425;;;-1:-1:-1;;;;;7002:13:33;;;;;;:9;:13;;;;;:22;;;;;;6624:425;7079:2;-1:-1:-1;;;;;7064:25:33;7073:4;-1:-1:-1;;;;;7064:25:33;;7083:5;7064:25;;;;916::41;;904:2;889:18;;770:177;7064:25:33;;;;;;;;5989:1107;;;:::o;7965:206::-;-1:-1:-1;;;;;8035:21:33;;8031:89;;8079:30;;-1:-1:-1;;;8079:30:33;;8106:1;8079:30;;;3769:51:41;3742:18;;8079:30:33;3623:203:41;8031:89:33;8129:35;8137:7;8154:1;8158:5;8129:7;:35::i;4650:191:13:-;4716:17;4762:10;4749:9;:23;4745:62;;4781:26;;-1:-1:-1;;;4781:26:13;;4797:9;4781:26;;;916:25:41;889:18;;4781:26:13;770:177:41;4745:62:13;-1:-1:-1;4824:10:13;4650:191::o;5218:410::-;5371:15;5389:8;-1:-1:-1;;;;;5389:16:13;;:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;5371:36;-1:-1:-1;;;;;;5421:21:13;;5417:54;;5451:20;;-1:-1:-1;;;5451:20:13;;;;;;;;;;;5417:54;1745:53:36;;;5578:10:13;1745:53:36;;;38363:34:41;;;5598:8:13;-1:-1:-1;;;;;38433:15:41;;;38413:18;;;38406:43;38465:18;;;;38458:34;;;1745:53:36;;;;;;;;;;38298:18:41;;;;1745:53:36;;;;;;;;;-1:-1:-1;;;;;1745:53:36;-1:-1:-1;;;1745:53:36;;;8600:11;;5545:76:13;;:32;;;5609:11;;1718:81:36;;5545:32:13;;-1:-1:-1;;;;1745:53:36;;-1:-1:-1;;;5545:32:13;8566:5:36;8561:60;8673:7;8663:176;;8717:4;8711:11;8762:16;8759:1;8754:3;8739:40;8808:16;8803:3;8796:29;8663:176;-1:-1:-1;;8916:1:36;8910:8;8866:16;;-1:-1:-1;8942:15:36;;:68;;8994:11;9009:1;8994:16;;8942:68;;;-1:-1:-1;;;;;8960:26:36;;;:31;8942:68;8938:146;;;9033:40;;-1:-1:-1;;;9033:40:36;;-1:-1:-1;;;;;3787:32:41;;9033:40:36;;;3769:51:41;3742:18;;9033:40:36;3623:203:41;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;14:250:41:-;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:41;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:41;488:39;;;;529:4;484:50;;269:271;-1:-1:-1;;269:271:41:o;545:220::-;694:2;683:9;676:21;657:4;714:45;755:2;744:9;740:18;732:6;714:45;:::i;952:131::-;-1:-1:-1;;;;;1027:31:41;;1017:42;;1007:70;;1073:1;1070;1063:12;1088:315;1156:6;1164;1217:2;1205:9;1196:7;1192:23;1188:32;1185:52;;;1233:1;1230;1223:12;1185:52;1272:9;1259:23;1291:31;1316:5;1291:31;:::i;:::-;1341:5;1393:2;1378:18;;;;1365:32;;-1:-1:-1;;;1088:315:41:o;1600:158::-;1662:5;1707:3;1698:6;1693:3;1689:16;1685:26;1682:46;;;1724:1;1721;1714:12;1682:46;-1:-1:-1;1746:6:41;1600:158;-1:-1:-1;1600:158:41:o;1763:360::-;1851:6;1904:2;1892:9;1883:7;1879:23;1875:32;1872:52;;;1920:1;1917;1910:12;1872:52;1960:9;1947:23;-1:-1:-1;;;;;1985:6:41;1982:30;1979:50;;;2025:1;2022;2015:12;1979:50;2048:69;2109:7;2100:6;2089:9;2085:22;2048:69;:::i;2282:1336::-;2202:12;;2190:25;;2264:4;2253:16;;;2247:23;2231:14;;;2224:47;2648:4;2696:3;2681:19;;2773:2;2811:3;2806:2;2795:9;2791:18;2784:31;2835:6;2870;2864:13;2901:6;2893;2886:22;2939:3;2928:9;2924:19;2917:26;;3002:3;2992:6;2989:1;2985:14;2974:9;2970:30;2966:40;2952:54;;3025:4;3064;3056:6;3052:17;3087:1;3097:429;3111:6;3108:1;3105:13;3097:429;;;3176:22;;;-1:-1:-1;;3172:37:41;3160:50;;3233:13;;3274:9;;3259:25;;3323:11;;3317:18;3355:15;;;3348:27;;;3398:48;3430:15;;;3317:18;3398:48;:::i;:::-;3388:58;-1:-1:-1;;3504:12:41;;;;3469:15;;;;3133:1;3126:9;3097:429;;;-1:-1:-1;;2202:12:41;;3608:2;3593:18;;2190:25;-1:-1:-1;;;2264:4:41;2253:16;;2247:23;2231:14;;;2224:47;-1:-1:-1;3543:6:41;-1:-1:-1;3558:54:41;2128:149;3831:456;3908:6;3916;3924;3977:2;3965:9;3956:7;3952:23;3948:32;3945:52;;;3993:1;3990;3983:12;3945:52;4032:9;4019:23;4051:31;4076:5;4051:31;:::i;:::-;4101:5;-1:-1:-1;4158:2:41;4143:18;;4130:32;4171:33;4130:32;4171:33;:::i;:::-;3831:456;;4223:7;;-1:-1:-1;;;4277:2:41;4262:18;;;;4249:32;;3831:456::o;4292:154::-;4351:5;4396:2;4387:6;4382:3;4378:16;4374:25;4371:45;;;4412:1;4409;4402:12;4451:347;4502:8;4512:6;4566:3;4559:4;4551:6;4547:17;4543:27;4533:55;;4584:1;4581;4574:12;4533:55;-1:-1:-1;4607:20:41;;-1:-1:-1;;;;;4639:30:41;;4636:50;;;4682:1;4679;4672:12;4636:50;4719:4;4711:6;4707:17;4695:29;;4771:3;4764:4;4755:6;4747;4743:19;4739:30;4736:39;4733:59;;;4788:1;4785;4778:12;4733:59;4451:347;;;;;:::o;4803:1046::-;4944:6;4952;4960;4968;4976;4984;4992;5045:3;5033:9;5024:7;5020:23;5016:33;5013:53;;;5062:1;5059;5052:12;5013:53;5085;5130:7;5119:9;5085:53;:::i;:::-;5075:63;;5185:2;5174:9;5170:18;5157:32;5147:42;;5240:3;5229:9;5225:19;5212:33;-1:-1:-1;;;;;5305:2:41;5297:6;5294:14;5291:34;;;5321:1;5318;5311:12;5291:34;5360:58;5410:7;5401:6;5390:9;5386:22;5360:58;:::i;:::-;5437:8;;-1:-1:-1;5334:84:41;-1:-1:-1;5522:3:41;5507:19;;5494:33;;-1:-1:-1;5536:31:41;5494:33;5536:31;:::i;:::-;5586:5;;-1:-1:-1;5644:3:41;5629:19;;5616:33;;5661:16;;;5658:36;;;5690:1;5687;5680:12;5658:36;;5729:60;5781:7;5770:8;5759:9;5755:24;5729:60;:::i;:::-;4803:1046;;;;-1:-1:-1;4803:1046:41;;-1:-1:-1;4803:1046:41;;;;5703:86;;-1:-1:-1;;;4803:1046:41:o;6348:118::-;6434:5;6427:13;6420:21;6413:5;6410:32;6400:60;;6456:1;6453;6446:12;6471:241;6527:6;6580:2;6568:9;6559:7;6555:23;6551:32;6548:52;;;6596:1;6593;6586:12;6548:52;6635:9;6622:23;6654:28;6676:5;6654:28;:::i;7210:163::-;7277:20;;7337:10;7326:22;;7316:33;;7306:61;;7363:1;7360;7353:12;7306:61;7210:163;;;:::o;7378:252::-;7445:6;7453;7506:2;7494:9;7485:7;7481:23;7477:32;7474:52;;;7522:1;7519;7512:12;7474:52;7545:28;7563:9;7545:28;:::i;7635:489::-;7729:6;7737;7790:2;7778:9;7769:7;7765:23;7761:32;7758:52;;;7806:1;7803;7796:12;7758:52;7846:9;7833:23;-1:-1:-1;;;;;7871:6:41;7868:30;7865:50;;;7911:1;7908;7901:12;7865:50;7934:69;7995:7;7986:6;7975:9;7971:22;7934:69;:::i;:::-;7924:79;;;8053:2;8042:9;8038:18;8025:32;8066:28;8088:5;8066:28;:::i;:::-;8113:5;8103:15;;;7635:489;;;;;:::o;8129:253::-;2202:12;;2190:25;;2264:4;2253:16;;;2247:23;2231:14;;;2224:47;8319:2;8304:18;;8331:45;2128:149;8387:159;8454:20;;8514:6;8503:18;;8493:29;;8483:57;;8536:1;8533;8526:12;8551:256;8617:6;8625;8678:2;8666:9;8657:7;8653:23;8649:32;8646:52;;;8694:1;8691;8684:12;8646:52;8717:28;8735:9;8717:28;:::i;:::-;8707:38;;8764:37;8797:2;8786:9;8782:18;8764:37;:::i;:::-;8754:47;;8551:256;;;;;:::o;9271:382::-;9336:6;9344;9397:2;9385:9;9376:7;9372:23;9368:32;9365:52;;;9413:1;9410;9403:12;9365:52;9452:9;9439:23;9471:31;9496:5;9471:31;:::i;:::-;9521:5;-1:-1:-1;9578:2:41;9563:18;;9550:32;9591:30;9550:32;9591:30;:::i;9658:247::-;9717:6;9770:2;9758:9;9749:7;9745:23;9741:32;9738:52;;;9786:1;9783;9776:12;9738:52;9825:9;9812:23;9844:31;9869:5;9844:31;:::i;10115:668::-;10227:6;10235;10243;10251;10304:3;10292:9;10283:7;10279:23;10275:33;10272:53;;;10321:1;10318;10311:12;10272:53;10344;10389:7;10378:9;10344:53;:::i;:::-;10334:63;;10448:2;10437:9;10433:18;10420:32;-1:-1:-1;;;;;10467:6:41;10464:30;10461:50;;;10507:1;10504;10497:12;10461:50;10546:58;10596:7;10587:6;10576:9;10572:22;10546:58;:::i;:::-;10623:8;;-1:-1:-1;10520:84:41;-1:-1:-1;;10708:3:41;10693:19;;10680:33;10722:31;10680:33;10722:31;:::i;:::-;10115:668;;;;-1:-1:-1;10115:668:41;;-1:-1:-1;;10115:668:41:o;10788:395::-;10879:8;10889:6;10943:3;10936:4;10928:6;10924:17;10920:27;10910:55;;10961:1;10958;10951:12;10910:55;-1:-1:-1;10984:20:41;;-1:-1:-1;;;;;11016:30:41;;11013:50;;;11059:1;11056;11049:12;11013:50;11096:4;11088:6;11084:17;11072:29;;11156:3;11149:4;11139:6;11136:1;11132:14;11124:6;11120:27;11116:38;11113:47;11110:67;;;11173:1;11170;11163:12;11188:504;11313:6;11321;11374:2;11362:9;11353:7;11349:23;11345:32;11342:52;;;11390:1;11387;11380:12;11342:52;11430:9;11417:23;-1:-1:-1;;;;;11455:6:41;11452:30;11449:50;;;11495:1;11492;11485:12;11449:50;11534:98;11624:7;11615:6;11604:9;11600:22;11534:98;:::i;:::-;11651:8;;11508:124;;-1:-1:-1;11188:504:41;-1:-1:-1;;;;11188:504:41:o;11697:184::-;11755:6;11808:2;11796:9;11787:7;11783:23;11779:32;11776:52;;;11824:1;11821;11814:12;11776:52;11847:28;11865:9;11847:28;:::i;12068:553::-;12154:6;12162;12170;12178;12231:2;12219:9;12210:7;12206:23;12202:32;12199:52;;;12247:1;12244;12237:12;12199:52;12270:28;12288:9;12270:28;:::i;:::-;12260:38;;12317:37;12350:2;12339:9;12335:18;12317:37;:::i;:::-;12307:47;;12405:2;12394:9;12390:18;12377:32;-1:-1:-1;;;;;12424:6:41;12421:30;12418:50;;;12464:1;12461;12454:12;12418:50;12503:58;12553:7;12544:6;12533:9;12529:22;12503:58;:::i;:::-;12068:553;;;;-1:-1:-1;12580:8:41;-1:-1:-1;;;;12068:553:41:o;12626:180::-;12685:6;12738:2;12726:9;12717:7;12713:23;12709:32;12706:52;;;12754:1;12751;12744:12;12706:52;-1:-1:-1;12777:23:41;;12626:180;-1:-1:-1;12626:180:41:o;13314:655::-;13450:6;13458;13466;13510:9;13501:7;13497:23;13540:3;13536:2;13532:12;13529:32;;;13557:1;13554;13547:12;13529:32;13597:9;13584:23;-1:-1:-1;;;;;13622:6:41;13619:30;13616:50;;;13662:1;13659;13652:12;13616:50;13685:69;13746:7;13737:6;13726:9;13722:22;13685:69;:::i;:::-;13675:79;-1:-1:-1;;13788:2:41;-1:-1:-1;;13770:16:41;;13766:25;13763:45;;;13804:1;13801;13794:12;13763:45;;13842:2;13831:9;13827:18;13817:28;;13895:2;13884:9;13880:18;13867:32;13908:31;13933:5;13908:31;:::i;:::-;13958:5;13948:15;;;13314:655;;;;;:::o;13974:609::-;14214:4;14256:3;14245:9;14241:19;14233:27;;14293:6;14287:13;14276:9;14269:32;-1:-1:-1;;;;;14361:4:41;14353:6;14349:17;14343:24;14339:49;14332:4;14321:9;14317:20;14310:79;14436:4;14428:6;14424:17;14418:24;14451:62;14507:4;14496:9;14492:20;14478:12;2202;;2190:25;;2264:4;2253:16;;;2247:23;2231:14;;2224:47;2128:149;14451:62;-1:-1:-1;2202:12:41;;14572:3;14557:19;;2190:25;2264:4;2253:16;;2247:23;2231:14;;;2224:47;14522:55;2128:149;14588:388;14656:6;14664;14717:2;14705:9;14696:7;14692:23;14688:32;14685:52;;;14733:1;14730;14723:12;14685:52;14772:9;14759:23;14791:31;14816:5;14791:31;:::i;:::-;14841:5;-1:-1:-1;14898:2:41;14883:18;;14870:32;14911:33;14870:32;14911:33;:::i;14981:234::-;15064:6;15117:2;15105:9;15096:7;15092:23;15088:32;15085:52;;;15133:1;15130;15123:12;15085:52;15156:53;15201:7;15190:9;15156:53;:::i;15220:380::-;15299:1;15295:12;;;;15342;;;15363:61;;15417:4;15409:6;15405:17;15395:27;;15363:61;15470:2;15462:6;15459:14;15439:18;15436:38;15433:161;;15516:10;15511:3;15507:20;15504:1;15497:31;15551:4;15548:1;15541:15;15579:4;15576:1;15569:15;15605:251;15675:6;15728:2;15716:9;15707:7;15703:23;15699:32;15696:52;;;15744:1;15741;15734:12;15696:52;15776:9;15770:16;15795:31;15820:5;15795:31;:::i;15861:184::-;15931:6;15984:2;15972:9;15963:7;15959:23;15955:32;15952:52;;;16000:1;15997;15990:12;15952:52;-1:-1:-1;16023:16:41;;15861:184;-1:-1:-1;15861:184:41:o;16050:127::-;16111:10;16106:3;16102:20;16099:1;16092:31;16142:4;16139:1;16132:15;16166:4;16163:1;16156:15;16817:245;16884:6;16937:2;16925:9;16916:7;16912:23;16908:32;16905:52;;;16953:1;16950;16943:12;16905:52;16985:9;16979:16;17004:28;17026:5;17004:28;:::i;17933:253::-;18005:2;17999:9;18047:4;18035:17;;-1:-1:-1;;;;;18067:34:41;;18103:22;;;18064:62;18061:88;;;18129:18;;:::i;:::-;18165:2;18158:22;17933:253;:::o;18191:257::-;18263:4;18257:11;;;18295:17;;-1:-1:-1;;;;;18327:34:41;;18363:22;;;18324:62;18321:88;;;18389:18;;:::i;18453:275::-;18524:2;18518:9;18589:2;18570:13;;-1:-1:-1;;18566:27:41;18554:40;;-1:-1:-1;;;;;18609:34:41;;18645:22;;;18606:62;18603:88;;;18671:18;;:::i;:::-;18707:2;18700:22;18453:275;;-1:-1:-1;18453:275:41:o;18733:186::-;18781:4;-1:-1:-1;;;;;18806:6:41;18803:30;18800:56;;;18836:18;;:::i;:::-;-1:-1:-1;18902:2:41;18881:15;-1:-1:-1;;18877:29:41;18908:4;18873:40;;18733:186::o;18924:2117::-;19116:9;-1:-1:-1;;;;;19191:2:41;19183:6;19180:14;19177:40;;;19197:18;;:::i;:::-;19243:6;19240:1;19236:14;19269:4;19293:28;19317:2;19313;19309:11;19293:28;:::i;:::-;19355:19;;;19425:14;;;;19390:12;;;;19462:14;19451:26;;19448:46;;;19490:1;19487;19480:12;19448:46;19514:5;19528:1480;19544:6;19539:3;19536:15;19528:1480;;;19630:3;19617:17;19666:2;19653:11;19650:19;19647:109;;;19710:1;19739:2;19735;19728:14;19647:109;19779:23;;19847:4;19826:14;19822:23;;;19818:34;19815:124;;;19893:1;19922:2;19918;19911:14;19815:124;19967:22;;:::i;:::-;20018:21;20036:2;20018:21;:::i;:::-;20009:7;20002:38;20078:30;20104:2;20100;20096:11;20078:30;:::i;:::-;20073:2;20064:7;20060:16;20053:56;20132:2;20182;20178;20174:11;20161:25;20213:2;20205:6;20202:14;20199:104;;;20257:1;20286:2;20282;20275:14;20199:104;20326:15;;;;;20383:14;20376:4;20368:13;;20364:34;20354:135;;20441:1;20471:3;20466;20459:16;20354:135;20526:2;20513:16;20555:49;20571:32;20599:3;20571:32;:::i;:::-;20555:49;:::i;:::-;20631:3;20624:5;20617:18;20677:14;20672:2;20666:3;20662:2;20658:12;20654:21;20651:41;20648:134;;;20734:1;20764:3;20759;20752:16;20648:134;20837:3;20832:2;20828;20824:11;20819:2;20812:5;20808:14;20795:46;20887:1;20865:15;;;20861:24;;20854:35;;;;20909:16;;;20902:31;20946:20;;-1:-1:-1;20986:12:41;;;;19561;;19528:1480;;;-1:-1:-1;21030:5:41;18924:2117;-1:-1:-1;;;;;;;18924:2117:41:o;21046:331::-;21151:9;21162;21204:8;21192:10;21189:24;21186:44;;;21226:1;21223;21216:12;21186:44;21255:6;21245:8;21242:20;21239:40;;;21275:1;21272;21265:12;21239:40;-1:-1:-1;;21301:23:41;;;21346:25;;;;;-1:-1:-1;21046:331:41:o;21382:476::-;21573:3;21611:6;21605:13;21627:66;21686:6;21681:3;21674:4;21666:6;21662:17;21627:66;:::i;:::-;21715:16;;21768:6;21760;21715:16;21740:35;21832:1;21794:18;;21821:13;;;-1:-1:-1;21794:18:41;;21382:476;-1:-1:-1;;;21382:476:41:o;21863:266::-;21951:6;21946:3;21939:19;22003:6;21996:5;21989:4;21984:3;21980:14;21967:43;-1:-1:-1;22055:1:41;22030:16;;;22048:4;22026:27;;;22019:38;;;;22111:2;22090:15;;;-1:-1:-1;;22086:29:41;22077:39;;;22073:50;;21863:266::o;22134:244::-;22291:2;22280:9;22273:21;22254:4;22311:61;22368:2;22357:9;22353:18;22345:6;22337;22311:61;:::i;23334:127::-;23395:10;23390:3;23386:20;23383:1;23376:31;23426:4;23423:1;23416:15;23450:4;23447:1;23440:15;23466:331;23565:4;23623:11;23610:25;23717:3;23713:8;23702;23686:14;23682:29;23678:44;23658:18;23654:69;23644:97;;23737:1;23734;23727:12;23644:97;23758:33;;;;;23466:331;-1:-1:-1;;23466:331:41:o;23802:521::-;23879:4;23885:6;23945:11;23932:25;24039:2;24035:7;24024:8;24008:14;24004:29;24000:43;23980:18;23976:68;23966:96;;24058:1;24055;24048:12;23966:96;24085:33;;24137:20;;;-1:-1:-1;;;;;;24169:30:41;;24166:50;;;24212:1;24209;24202:12;24166:50;24245:4;24233:17;;-1:-1:-1;24276:14:41;24272:27;;;24262:38;;24259:58;;;24313:1;24310;24303:12;24328:129;-1:-1:-1;;;;;24406:5:41;24402:30;24395:5;24392:41;24382:69;;24447:1;24444;24437:12;24462:988;24836:10;24809:25;24827:6;24809:25;:::i;:::-;24805:42;24794:9;24787:61;24911:4;24903:6;24899:17;24886:31;24879:4;24868:9;24864:20;24857:61;24768:4;24965;24957:6;24953:17;24940:31;24980:30;25004:5;24980:30;:::i;:::-;-1:-1:-1;;;;;25052:5:41;25048:30;25041:4;25030:9;25026:20;25019:60;;25115:6;25110:2;25099:9;25095:18;25088:34;25159:3;25153;25142:9;25138:19;25131:32;25186:62;25243:3;25232:9;25228:19;25220:6;25212;25186:62;:::i;:::-;-1:-1:-1;;;;;25285:32:41;;25305:3;25264:19;;25257:61;25355:22;;;25349:3;25334:19;;25327:51;25395:49;25359:6;25429;25421;25395:49;:::i;:::-;25387:57;24462:988;-1:-1:-1;;;;;;;;;;24462:988:41:o;25455:647::-;25534:6;25587:2;25575:9;25566:7;25562:23;25558:32;25555:52;;;25603:1;25600;25593:12;25555:52;25636:9;25630:16;-1:-1:-1;;;;;25661:6:41;25658:30;25655:50;;;25701:1;25698;25691:12;25655:50;25724:22;;25777:4;25769:13;;25765:27;-1:-1:-1;25755:55:41;;25806:1;25803;25796:12;25755:55;25835:2;25829:9;25860:48;25876:31;25904:2;25876:31;:::i;25860:48::-;25931:2;25924:5;25917:17;25971:7;25966:2;25961;25957;25953:11;25949:20;25946:33;25943:53;;;25992:1;25989;25982:12;25943:53;26005:67;26069:2;26064;26057:5;26053:14;26048:2;26044;26040:11;26005:67;:::i;26304:245::-;26362:6;26415:2;26403:9;26394:7;26390:23;26386:32;26383:52;;;26431:1;26428;26421:12;26383:52;26470:9;26457:23;26489:30;26513:5;26489:30;:::i;26554:479::-;26821:1;26817;26812:3;26808:11;26804:19;26796:6;26792:32;26781:9;26774:51;26861:6;26856:2;26845:9;26841:18;26834:34;26916:6;26908;26904:19;26899:2;26888:9;26884:18;26877:47;26960:3;26955:2;26944:9;26940:18;26933:31;26755:4;26981:46;27022:3;27011:9;27007:19;26999:6;26981:46;:::i;27656:379::-;27849:2;27838:9;27831:21;27812:4;27875:45;27916:2;27905:9;27901:18;27893:6;27875:45;:::i;:::-;27968:9;27960:6;27956:22;27951:2;27940:9;27936:18;27929:50;27996:33;28022:6;28014;27996:33;:::i;28040:887::-;28259:2;28248:9;28241:21;28317:10;28308:6;28302:13;28298:30;28293:2;28282:9;28278:18;28271:58;28383:4;28375:6;28371:17;28365:24;28360:2;28349:9;28345:18;28338:52;28222:4;28437:2;28429:6;28425:15;28419:22;28478:4;28472:3;28461:9;28457:19;28450:33;28506:52;28553:3;28542:9;28538:19;28524:12;28506:52;:::i;:::-;28492:66;;28607:2;28599:6;28595:15;28589:22;28681:2;28677:7;28665:9;28657:6;28653:22;28649:36;28642:4;28631:9;28627:20;28620:66;28709:41;28743:6;28727:14;28709:41;:::i;:::-;28819:3;28807:16;;;;28801:23;28794:31;28787:39;28781:3;28766:19;;28759:68;-1:-1:-1;;;;;;;;28888:32:41;;;;28881:4;28866:20;;;28859:62;28695:55;28040:887::o;28932:284::-;29002:5;29050:4;29038:9;29033:3;29029:19;29025:30;29022:50;;;29068:1;29065;29058:12;29022:50;29090:22;;:::i;:::-;29081:31;;29141:9;29135:16;29128:5;29121:31;29205:2;29194:9;29190:18;29184:25;29179:2;29172:5;29168:14;29161:49;28932:284;;;;:::o;29221:257::-;29319:6;29372:2;29360:9;29351:7;29347:23;29343:32;29340:52;;;29388:1;29385;29378:12;29340:52;29411:61;29464:7;29453:9;29411:61;:::i;29608:542::-;29709:2;29704:3;29701:11;29698:446;;;29745:1;29769:5;29766:1;29759:16;29813:4;29810:1;29800:18;29883:2;29871:10;29867:19;29864:1;29860:27;29854:4;29850:38;29919:4;29907:10;29904:20;29901:47;;;-1:-1:-1;29942:4:41;29901:47;29997:2;29992:3;29988:12;29985:1;29981:20;29975:4;29971:31;29961:41;;30052:82;30070:2;30063:5;30060:13;30052:82;;;30115:17;;;30096:1;30085:13;30052:82;;;30056:3;;;29608:542;;;:::o;30326:1341::-;30450:3;30444:10;-1:-1:-1;;;;;30469:6:41;30466:30;30463:56;;;30499:18;;:::i;:::-;30528:96;30617:6;30577:38;30609:4;30603:11;30577:38;:::i;:::-;30571:4;30528:96;:::i;:::-;30679:4;;30736:2;30725:14;;30753:1;30748:662;;;;31454:1;31471:6;31468:89;;;-1:-1:-1;31523:19:41;;;31517:26;31468:89;-1:-1:-1;;30283:1:41;30279:11;;;30275:24;30271:29;30261:40;30307:1;30303:11;;;30258:57;31570:81;;30718:943;;30748:662;29555:1;29548:14;;;29592:4;29579:18;;-1:-1:-1;;30784:20:41;;;30901:236;30915:7;30912:1;30909:14;30901:236;;;31004:19;;;30998:26;30983:42;;31096:27;;;;31064:1;31052:14;;;;30931:19;;30901:236;;;30905:3;31165:6;31156:7;31153:19;31150:201;;;31226:19;;;31220:26;-1:-1:-1;;31309:1:41;31305:14;;;31321:3;31301:24;31297:37;31293:42;31278:58;31263:74;;31150:201;-1:-1:-1;;;;;31397:1:41;31381:14;;;31377:22;31364:36;;-1:-1:-1;30326:1341:41:o;31672:1164::-;31888:4;31917:2;31957;31946:9;31942:18;31987:2;31976:9;31969:21;32010:6;32045;32039:13;32076:6;32068;32061:22;32102:2;32092:12;;32135:2;32124:9;32120:18;32113:25;;32197:2;32187:6;32184:1;32180:14;32169:9;32165:30;32161:39;32235:2;32227:6;32223:15;32256:1;32266:541;32280:6;32277:1;32274:13;32266:541;;;32345:22;;;-1:-1:-1;;32341:36:41;32329:49;;32401:13;;32473:9;;32484:10;32469:26;32454:42;;32543:11;;;32537:18;32557:6;32533:31;32516:15;;;32509:56;32604:11;;32598:18;32437:4;32636:15;;;32629:27;;;32679:48;32711:15;;;32598:18;32679:48;:::i;:::-;32785:12;;;;32669:58;-1:-1:-1;;;32750:15:41;;;;32302:1;32295:9;32266:541;;;-1:-1:-1;32824:6:41;;31672:1164;-1:-1:-1;;;;;;;;31672:1164:41:o;32841:346::-;32928:6;32981:2;32969:9;32960:7;32956:23;32952:32;32949:52;;;32997:1;32994;32987:12;32949:52;33023:22;;:::i;:::-;33081:9;33068:23;33061:5;33054:38;33152:2;33141:9;33137:18;33124:32;33119:2;33112:5;33108:14;33101:56;33176:5;33166:15;;;32841:346;;;;:::o;33531:127::-;33592:10;33587:3;33583:20;33580:1;33573:31;33623:4;33620:1;33613:15;33647:4;33644:1;33637:15;33663:217;33703:1;33729;33719:132;;33773:10;33768:3;33764:20;33761:1;33754:31;33808:4;33805:1;33798:15;33836:4;33833:1;33826:15;33719:132;-1:-1:-1;33865:9:41;;33663:217::o;33885:168::-;33958:9;;;33989;;34006:15;;;34000:22;;33986:37;33976:71;;34027:18;;:::i;34058:255::-;34178:19;;34217:2;34209:11;;34206:101;;;-1:-1:-1;;34278:2:41;34274:12;;;34271:1;34267:20;34263:33;34252:45;34058:255;;;;:::o;34318:331::-;-1:-1:-1;;;;;;34438:19:41;;34522:11;;;;34553:1;34545:10;;34542:101;;;34630:2;34624;34617:3;34614:1;34610:11;34607:1;34603:19;34599:28;34595:2;34591:37;34587:46;34578:55;;34542:101;;;34318:331;;;;:::o;34654:568::-;-1:-1:-1;;;;;34919:3:41;34915:28;34906:6;34901:3;34897:16;34893:51;34888:3;34881:64;35005:10;35000:3;34996:20;34987:6;34982:3;34978:16;34974:43;34970:1;34965:3;34961:11;34954:64;35048:6;35043:2;35038:3;35034:12;35027:28;34863:3;35084:6;35078:13;35100:75;35168:6;35163:2;35158:3;35154:12;35147:4;35139:6;35135:17;35100:75;:::i;:::-;35195:16;;;;35213:2;35191:25;;34654:568;-1:-1:-1;;;;;34654:568:41:o;36928:532::-;37169:6;37164:3;37157:19;-1:-1:-1;;;;;37232:3:41;37228:28;37219:6;37214:3;37210:16;37206:51;37201:2;37196:3;37192:12;37185:73;37288:6;37283:2;37278:3;37274:12;37267:28;37139:3;37324:6;37318:13;37340:73;37406:6;37401:2;37396:3;37392:12;37387:2;37379:6;37375:15;37340:73;:::i;:::-;37433:16;;;;37451:2;37429:25;;36928:532;-1:-1:-1;;;;;36928:532:41:o;37465:523::-;37567:6;37620:3;37608:9;37599:7;37595:23;37591:33;37588:53;;;37637:1;37634;37627:12;37588:53;37663:22;;:::i;:::-;37714:9;37708:16;37701:5;37694:31;37770:2;37759:9;37755:18;37749:25;37783:32;37807:7;37783:32;:::i;:::-;37842:2;37831:14;;37824:31;37887:70;37949:7;37944:2;37929:18;;37887:70;:::i;:::-;37882:2;37871:14;;37864:94;37875:5;37465:523;-1:-1:-1;;;37465:523:41:o;37993:125::-;38058:9;;;38079:10;;;38076:36;;;38092:18;;:::i

Swarm Source

ipfs://8cdcc1c04c9f55e5e452b377a7de41cb0bff8330b3a792e337650d60bf202d85
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.