Overview
ETH Balance
ETH Value
$0.00Multichain Info
Latest 1 from a total of 1 transactions
| Transaction Hash | 
                                         
                                            
                                                Method 
                                            
                                            
                                         
                                     | 
                                    
                                         
                                            
                                                Block
                                            
                                            
                                         
                                     | 
                                    
                                         
                                            
                                                From
                                            
                                            
                                         
                                     | 
                                    
                                         
                                            
                                                To
                                            
                                            
                                         
                                     | 
                                    |||||
|---|---|---|---|---|---|---|---|---|---|
| Endpoint | 13797065 | 19 days ago | IN | 0 ETH | 0.00000137 | 
View more zero value Internal Transactions in Advanced View mode
Cross-Chain Transactions
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.22;
import "@layerzerolabs/oft-evm/contracts/interfaces/IOFT.sol";
import {OFTFeeUpgradeable} from "@layerzerolabs/oft-evm-upgradeable/contracts/oft/OFTFeeUpgradeable.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
contract GGUSDOFT is OFTFeeUpgradeable {
    address private feeAddress;
    mapping(address => bool) private whitelist;
    uint256 private nonce;
    event FeeAddress(address feeAddress);
    event WhitelistUpdated(address indexed account, bool isWhitelisted);
    event TransferEx(address indexed from, address indexed to, uint256 indexed nonce, uint256 value, uint256 fromBalanceAfterTransfer, uint256 toBalanceAfterTransfer);
    constructor(address _lzEndpoint) OFTFeeUpgradeable(_lzEndpoint) {
        _disableInitializers();
    }
    function initialize(
        string memory _name,
        string memory _symbol,
        address _delegate
    ) public initializer {
        __OFT_init(_name, _symbol, _delegate);
        __Ownable_init(_delegate);
        feeAddress = address(0);
    }
    
    function initialize2(
        string memory _name,
        string memory _symbol
    ) public  reinitializer(2) {
        __ERC20_init(_name, _symbol);
    }
    function setFeeAddress(address _feeAddress) external onlyOwner {
        feeAddress = _feeAddress;
        emit FeeAddress(feeAddress);
    }
    function getFeeAddress() public view virtual returns (address) {
        return feeAddress;
    }
    function addToWhitelist(address _account) external onlyOwner {
        require(!whitelist[_account], "Already whitelisted");
        whitelist[_account] = true;
        emit WhitelistUpdated(_account, true);
    }
    function removeFromWhitelist(address _account) external onlyOwner {
        require(whitelist[_account], "Not whitelisted");
        whitelist[_account] = false;
        emit WhitelistUpdated(_account, false);
    }
    function isWhitelisted(address _account) public view returns (bool) {
        return whitelist[_account];
    }
    function _debit(
        address _from,
        uint256 _amountLD,
        uint256 _minAmountLD,
        uint32 _dstEid
    ) internal override virtual returns (uint256 amountSentLD, uint256 amountReceivedLD) {
        (amountSentLD, amountReceivedLD) = whitelist[_from]
            ? _debitViewNoFee(_amountLD, _minAmountLD)
            : _debitView(_amountLD, _minAmountLD, _dstEid);
        if (amountReceivedLD > amountSentLD) {
            revert("Amount received cannot be greater than amount sent");
        }
        uint256 fee = amountSentLD - amountReceivedLD;
        if (fee > 0) {
            if (feeAddress == address(0)) {
                OFTFeeStorage storage $ = _getOFTFeeStorage();
                unchecked {
                    $.feeBalance += fee;
                }
                _transfer(_from, address(this), fee);
            } else {
                // transfer fee to special account
                _transfer(_from, feeAddress, fee);
            }
        }
        _burn(_from, amountReceivedLD);
    }
    function _debitViewNoFee(
        uint256 _amountLD,
        uint256 _minAmountLD
    ) internal view virtual returns (uint256 amountSentLD, uint256 amountReceivedLD) {
        amountSentLD = _amountLD;
        unchecked {
            amountReceivedLD = _removeDust(_amountLD);
        }
        if (amountReceivedLD < _minAmountLD) {
            revert SlippageExceeded(amountReceivedLD, _minAmountLD);
        }
    }
    function decimals() public override view virtual returns (uint8){
        return 6;
    }
    function _update(address from, address to, uint256 value) internal override virtual {
        super._update(from, to, value);
        nonce++;
        emit TransferEx(from, to, nonce, value, balanceOf(from), balanceOf(to));
    }
}// 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 { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import { IOAppOptionsType3, EnforcedOptionParam } from "@layerzerolabs/oapp-evm/contracts/oapp/interfaces/IOAppOptionsType3.sol";
/**
 * @title OAppOptionsType3
 * @dev Abstract contract implementing the IOAppOptionsType3 interface with type 3 options.
 */
abstract contract OAppOptionsType3Upgradeable is IOAppOptionsType3, OwnableUpgradeable {
    struct OAppOptionsType3Storage {
        // @dev The "msgType" should be defined in the child contract.
        mapping(uint32 => mapping(uint16 => bytes)) enforcedOptions;
    }
    // keccak256(abi.encode(uint256(keccak256("layerzerov2.storage.oappoptionstype3")) - 1)) & ~bytes32(uint256(0xff))
    bytes32 private constant OAPP_OPTIONS_TYPE_3_STORAGE_LOCATION =
        0x8d2bda5d9f6ffb5796910376005392955773acee5548d0fcdb10e7c264ea0000;
    uint16 internal constant OPTION_TYPE_3 = 3;
    function _getOAppOptionsType3Storage() internal pure returns (OAppOptionsType3Storage storage $) {
        assembly {
            $.slot := OAPP_OPTIONS_TYPE_3_STORAGE_LOCATION
        }
    }
    /**
     * @dev Ownable is not initialized here on purpose. It should be initialized in the child contract to
     * accommodate the different version of Ownable.
     */
    function __OAppOptionsType3_init() internal onlyInitializing {}
    function __OAppOptionsType3_init_unchained() internal onlyInitializing {}
    function enforcedOptions(uint32 _eid, uint16 _msgType) public view returns (bytes memory) {
        OAppOptionsType3Storage storage $ = _getOAppOptionsType3Storage();
        return $.enforcedOptions[_eid][_msgType];
    }
    /**
     * @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 {
        OAppOptionsType3Storage storage $ = _getOAppOptionsType3Storage();
        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) {
        OAppOptionsType3Storage storage $ = _getOAppOptionsType3Storage();
        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 calldata _options) internal pure virtual {
        uint16 optionsType = uint16(bytes2(_options[0:2]));
        if (optionsType != OPTION_TYPE_3) revert InvalidOptions(_options);
    }
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import { IOAppCore, ILayerZeroEndpointV2 } from "@layerzerolabs/oapp-evm/contracts/oapp/interfaces/IOAppCore.sol";
/**
 * @title OAppCore
 * @dev Abstract contract implementing the IOAppCore interface with basic OApp configurations.
 */
abstract contract OAppCoreUpgradeable is IOAppCore, OwnableUpgradeable {
    struct OAppCoreStorage {
        mapping(uint32 => bytes32) peers;
    }
    // keccak256(abi.encode(uint256(keccak256("layerzerov2.storage.oappcore")) - 1)) & ~bytes32(uint256(0xff))
    bytes32 private constant OAPP_CORE_STORAGE_LOCATION =
        0x72ab1bc1039b79dc4724ffca13de82c96834302d3c7e0d4252232d4b2dd8f900;
    function _getOAppCoreStorage() internal pure returns (OAppCoreStorage storage $) {
        assembly {
            $.slot := OAPP_CORE_STORAGE_LOCATION
        }
    }
    // The LayerZero endpoint associated with the given OApp
    ILayerZeroEndpointV2 public immutable endpoint;
    /**
     * @dev Constructor to initialize the OAppCore with the provided endpoint and delegate.
     * @param _endpoint The address of the LOCAL Layer Zero endpoint.
     */
    constructor(address _endpoint) {
        endpoint = ILayerZeroEndpointV2(_endpoint);
    }
    /**
     * @dev Initializes the OAppCore with the provided delegate.
     * @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.
     * @dev Ownable is not initialized here on purpose. It should be initialized in the child contract to
     * accommodate the different version of Ownable.
     */
    function __OAppCore_init(address _delegate) internal onlyInitializing {
        __OAppCore_init_unchained(_delegate);
    }
    function __OAppCore_init_unchained(address _delegate) internal onlyInitializing {
        if (_delegate == address(0)) revert InvalidDelegate();
        endpoint.setDelegate(_delegate);
    }
    /**
     * @notice Returns the peer address (OApp instance) associated with a specific endpoint.
     * @param _eid The endpoint ID.
     * @return peer The address of the peer associated with the specified endpoint.
     */
    function peers(uint32 _eid) public view override returns (bytes32) {
        OAppCoreStorage storage $ = _getOAppCoreStorage();
        return $.peers[_eid];
    }
    /**
     * @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 {
        OAppCoreStorage storage $ = _getOAppCoreStorage();
        $.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) {
        OAppCoreStorage storage $ = _getOAppCoreStorage();
        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 "@layerzerolabs/oapp-evm/contracts/oapp/interfaces/IOAppReceiver.sol";
import { OAppCoreUpgradeable } from "./OAppCoreUpgradeable.sol";
/**
 * @title OAppReceiver
 * @dev Abstract contract implementing the ILayerZeroReceiver interface and extending OAppCore for OApp receivers.
 */
abstract contract OAppReceiverUpgradeable is IOAppReceiver, OAppCoreUpgradeable {
    // 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;
    /**
     * @param _delegate The delegate capable of making OApp configurations inside of the endpoint.
     * @dev Ownable is not initialized here on purpose. It should be initialized in the child contract to
     * accommodate the different version of Ownable.
     */
    function __OAppReceiver_init(address _delegate) internal onlyInitializing {
        __OAppCore_init(_delegate);
    }
    function __OAppReceiver_init_unchained() internal onlyInitializing {}
    /**
     * @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 { OAppCoreUpgradeable } from "./OAppCoreUpgradeable.sol";
/**
 * @title OAppSender
 * @dev Abstract contract implementing the OAppSender functionality for sending messages to a LayerZero endpoint.
 */
abstract contract OAppSenderUpgradeable is OAppCoreUpgradeable {
    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;
    /**
     * @param _delegate The delegate capable of making OApp configurations inside of the endpoint.
     * @dev Ownable is not initialized here on purpose. It should be initialized in the child contract to
     * accommodate the different version of Ownable.
     */
    function __OAppSender_init(address _delegate) internal onlyInitializing {
        __OAppCore_init(_delegate);
    }
    function __OAppSender_init_unchained() internal onlyInitializing {}
    /**
     * @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 'MessagingFee' and 'MessagingReceipt' so it's exposed to OApp implementers
// solhint-disable-next-line no-unused-import
import { OAppSenderUpgradeable, MessagingFee, MessagingReceipt } from "./OAppSenderUpgradeable.sol";
// @dev Import the 'Origin' so it's exposed to OApp implementers
// solhint-disable-next-line no-unused-import
import { OAppReceiverUpgradeable, Origin } from "./OAppReceiverUpgradeable.sol";
import { OAppCoreUpgradeable } from "./OAppCoreUpgradeable.sol";
/**
 * @title OApp
 * @dev Abstract contract serving as the base for OApp implementation, combining OAppSender and OAppReceiver functionality.
 */
abstract contract OAppUpgradeable is OAppSenderUpgradeable, OAppReceiverUpgradeable {
    /**
     * @dev Constructor to initialize the OApp with the provided endpoint and owner.
     * @param _endpoint The address of the LOCAL LayerZero endpoint.
     */
    constructor(address _endpoint) OAppCoreUpgradeable(_endpoint) {}
    /**
     * @dev Initializes the OApp with the provided delegate.
     * @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.
     * @dev Ownable is not initialized here on purpose. It should be initialized in the child contract to
     * accommodate the different version of Ownable.
     */
    function __OApp_init(address _delegate) internal onlyInitializing {
        __OAppCore_init(_delegate);
        __OAppReceiver_init_unchained();
        __OAppSender_init_unchained();
    }
    function __OApp_init_unchained() internal onlyInitializing {}
    /**
     * @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(OAppSenderUpgradeable, OAppReceiverUpgradeable)
        returns (uint64 senderVersion, uint64 receiverVersion)
    {
        return (SENDER_VERSION, RECEIVER_VERSION);
    }
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import { IPreCrime } from "@layerzerolabs/oapp-evm/contracts/precrime/interfaces/IPreCrime.sol";
import { IOAppPreCrimeSimulator, InboundPacket, Origin } from "@layerzerolabs/oapp-evm/contracts/precrime/interfaces/IOAppPreCrimeSimulator.sol";
/**
 * @title OAppPreCrimeSimulator
 * @dev Abstract contract serving as the base for preCrime simulation functionality in an OApp.
 */
abstract contract OAppPreCrimeSimulatorUpgradeable is IOAppPreCrimeSimulator, OwnableUpgradeable {
    struct OAppPreCrimeSimulatorStorage {
        // The address of the preCrime implementation.
        address preCrime;
    }
    // keccak256(abi.encode(uint256(keccak256("layerzerov2.storage.oappprecrimesimulator")) - 1)) & ~bytes32(uint256(0xff))
    bytes32 private constant OAPP_PRE_CRIME_SIMULATOR_STORAGE_LOCATION =
        0xefb041d771d6daaa55702fff6eb740d63ba559a75d2d1d3e151c78ff2480b600;
    function _getOAppPreCrimeSimulatorStorage() internal pure returns (OAppPreCrimeSimulatorStorage storage $) {
        assembly {
            $.slot := OAPP_PRE_CRIME_SIMULATOR_STORAGE_LOCATION
        }
    }
    /**
     * @dev Ownable is not initialized here on purpose. It should be initialized in the child contract to
     * accommodate the different version of Ownable.
     */
    function __OAppPreCrimeSimulator_init() internal onlyInitializing {}
    function __OAppPreCrimeSimulator_init_unchained() internal onlyInitializing {}
    function preCrime() external view override returns (address) {
        OAppPreCrimeSimulatorStorage storage $ = _getOAppPreCrimeSimulatorStorage();
        return $.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 {
        OAppPreCrimeSimulatorStorage storage $ = _getOAppPreCrimeSimulatorStorage();
        $.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 { 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 { 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 { 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: UNLICENSED
pragma solidity ^0.8.20;
import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import { Initializable } from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import { FeeConfig, IFee } from "@layerzerolabs/oft-evm/contracts/interfaces/IFee.sol";
/**
 * @title FeeUpgradeable
 * @notice Implements fee configuration and calculation.
 */
abstract contract FeeUpgradeable is IFee, Initializable, OwnableUpgradeable {
    uint16 public constant BPS_DENOMINATOR = 10_000;
    struct FeeStorage {
        uint16 defaultFeeBps;
        mapping(uint32 => FeeConfig) feeBps;
    }
    // keccak256(abi.encode(uint256(keccak256("layerzerov2.storage.fee")) - 1)) & ~bytes32(uint256(0xff))
    bytes32 private constant FEE_STORAGE_LOCATION = 0x0cb173d183337e25fab6cb85705c15aad6a58cb1d552ed71b9bc628c8a3de800;
    /**
     * @dev The init function is intentionally left empty and does not initialize Ownable.
     * This is to ensure that Ownable can be initialized in the child contract to accommodate
     * potential different versions of Ownable that might be used.
     */
    function __Fee_init() internal onlyInitializing {}
    function __Fee_init_unchained() internal onlyInitializing {}
    function _getFeeStorage() internal pure returns (FeeStorage storage $) {
        assembly {
            $.slot := FEE_STORAGE_LOCATION
        }
    }
    /**
     * @dev Sets the default fee basis points (BPS) for all destinations.
     */
    function setDefaultFeeBps(uint16 _feeBps) external onlyOwner {
        if (_feeBps > BPS_DENOMINATOR) revert IFee.InvalidBps();
        FeeStorage storage $ = _getFeeStorage();
        $.defaultFeeBps = _feeBps;
        emit DefaultFeeBpsSet(_feeBps);
    }
    /**
     * @dev Sets the fee basis points (BPS) for a specific destination LayerZero EndpointV2 ID.
     */
    function setFeeBps(uint32 _dstEid, uint16 _feeBps, bool _enabled) external onlyOwner {
        if (_feeBps > BPS_DENOMINATOR) revert IFee.InvalidBps();
        FeeStorage storage $ = _getFeeStorage();
        $.feeBps[_dstEid] = FeeConfig(_feeBps, _enabled);
        emit FeeBpsSet(_dstEid, _feeBps, _enabled);
    }
    /**
     * @dev Returns the fee for a specific destination LayerZero EndpointV2 ID.
     */
    function getFee(uint32 _dstEid, uint256 _amount) public view virtual returns (uint256) {
        uint16 bps = _getFeeBps(_dstEid);
        //  @note If amount * bps < BPS_DENOMINATOR, there is no fee
        return bps == 0 ? 0 : (_amount * bps) / BPS_DENOMINATOR;
    }
    function _getFeeBps(uint32 _dstEid) internal view returns (uint16) {
        FeeStorage storage $ = _getFeeStorage();
        FeeConfig memory config = $.feeBps[_dstEid];
        return config.enabled ? config.feeBps : $.defaultFeeBps;
    }
    /**
     * @dev Returns the default fee.
     */
    function defaultFeeBps() public view virtual returns (uint16) {
        FeeStorage storage $ = _getFeeStorage();
        return $.defaultFeeBps;
    }
    /**
     * @dev Returns the configured fee for a given eid.
     */
    function feeBps(uint32 _dstEid) public view virtual returns (FeeConfig memory) {
        FeeStorage storage $ = _getFeeStorage();
        FeeConfig memory config = $.feeBps[_dstEid];
        return config;
    }
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import { OAppUpgradeable, Origin } from "@layerzerolabs/oapp-evm-upgradeable/contracts/oapp/OAppUpgradeable.sol";
import { OAppOptionsType3Upgradeable } from "@layerzerolabs/oapp-evm-upgradeable/contracts/oapp/libs/OAppOptionsType3Upgradeable.sol";
import { IOAppMsgInspector } from "@layerzerolabs/oapp-evm/contracts/oapp/interfaces/IOAppMsgInspector.sol";
import { OAppPreCrimeSimulatorUpgradeable } from "@layerzerolabs/oapp-evm-upgradeable/contracts/precrime/OAppPreCrimeSimulatorUpgradeable.sol";
import { IOFT, SendParam, OFTLimit, OFTReceipt, OFTFeeDetail, MessagingReceipt, MessagingFee } from "@layerzerolabs/oft-evm/contracts/interfaces/IOFT.sol";
import { OFTMsgCodec } from "@layerzerolabs/oft-evm/contracts/libs/OFTMsgCodec.sol";
import { OFTComposeMsgCodec } from "@layerzerolabs/oft-evm/contracts/libs/OFTComposeMsgCodec.sol";
/**
 * @title OFTCore
 * @dev Abstract contract for the OftChain (OFT) token.
 */
abstract contract OFTCoreUpgradeable is
    IOFT,
    OAppUpgradeable,
    OAppPreCrimeSimulatorUpgradeable,
    OAppOptionsType3Upgradeable
{
    using OFTMsgCodec for bytes;
    using OFTMsgCodec for bytes32;
    struct OFTCoreStorage {
        // Address of an optional contract to inspect both 'message' and 'options'
        address msgInspector;
    }
    // keccak256(abi.encode(uint256(keccak256("layerzerov2.storage.oftcore")) - 1)) & ~bytes32(uint256(0xff))
    bytes32 private constant OFT_CORE_STORAGE_LOCATION =
        0x41db8a78b0206aba5c54bcbfc2bda0d84082a84eb88e680379a57b9e9f653c00;
    // @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;
    event MsgInspectorSet(address inspector);
    function _getOFTCoreStorage() internal pure returns (OFTCoreStorage storage $) {
        assembly {
            $.slot := OFT_CORE_STORAGE_LOCATION
        }
    }
    /**
     * @dev Constructor.
     * @param _localDecimals The decimals of the token on the local chain (this chain).
     * @param _endpoint The address of the LayerZero endpoint.
     */
    constructor(uint8 _localDecimals, address _endpoint) OAppUpgradeable(_endpoint) {
        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 Initializes the OFTCore contract.
     * @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.
     * @dev Ownable is not initialized here on purpose. It should be initialized in the child contract to
     * accommodate the different version of Ownable.
     */
    function __OFTCore_init(address _delegate) internal onlyInitializing {
        __OApp_init(_delegate);
        __OAppPreCrimeSimulator_init();
        __OAppOptionsType3_init();
    }
    function __OFTCore_init_unchained() internal onlyInitializing {}
    function msgInspector() public view returns (address) {
        OFTCoreStorage storage $ = _getOFTCoreStorage();
        return $.msgInspector;
    }
    /**
     * @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 pure 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 {
        OFTCoreStorage storage $ = _getOFTCoreStorage();
        $.msgInspector = _msgInspector;
        emit MsgInspectorSet(_msgInspector);
    }
    /**
     * @notice Provides a quote for OFT-related operations.
     * @param _sendParam The parameters for the send operation.
     * @return oftLimit The OFT limit information.
     * @return oftFeeDetails The details of OFT fees.
     * @return oftReceipt The OFT receipt information.
     */
    function quoteOFT(
        SendParam calldata _sendParam
    )
        external
        view
        virtual
        returns (OFTLimit memory oftLimit, OFTFeeDetail[] memory oftFeeDetails, OFTReceipt memory oftReceipt)
    {
        uint256 minAmountLD = 0; // Unused in the default implementation.
        uint256 maxAmountLD = type(uint256).max; // Unused in the default implementation.
        oftLimit = OFTLimit(minAmountLD, maxAmountLD);
        // Unused in the default implementation; reserved for future complex fee details.
        oftFeeDetails = new OFTFeeDetail[](0);
        // @dev This is the same as the send() operation, but without the actual send.
        // - amountSentLD is the amount in local decimals that would be sent from the sender.
        // - amountReceivedLD is the amount in local decimals that will be credited to the recipient on the remote OFT instance.
        // @dev The amountSentLD MIGHT not equal the amount the user actually receives. HOWEVER, the default does.
        (uint256 amountSentLD, uint256 amountReceivedLD) = _debitView(
            _sendParam.amountLD,
            _sendParam.minAmountLD,
            _sendParam.dstEid
        );
        oftReceipt = OFTReceipt(amountSentLD, amountReceivedLD);
    }
    /**
     * @notice Provides a quote for the send() operation.
     * @param _sendParam The parameters for the send() operation.
     * @param _payInLzToken Flag indicating whether the caller is paying in the LZ token.
     * @return msgFee The calculated LayerZero messaging fee from the send() operation.
     *
     * @dev MessagingFee: LayerZero msg fee
     *  - nativeFee: The native fee.
     *  - lzTokenFee: The lzToken fee.
     */
    function quoteSend(
        SendParam calldata _sendParam,
        bool _payInLzToken
    ) external view virtual returns (MessagingFee memory msgFee) {
        // @dev mock the amount to receive, this is the same operation used in the send().
        // The quote is as similar as possible to the actual send() operation.
        (, uint256 amountReceivedLD) = _debitView(_sendParam.amountLD, _sendParam.minAmountLD, _sendParam.dstEid);
        // @dev Builds the options and OFT message to quote in the endpoint.
        (bytes memory message, bytes memory options) = _buildMsgAndOptions(_sendParam, amountReceivedLD);
        // @dev Calculates the LayerZero fee for the send() operation.
        return _quote(_sendParam.dstEid, message, options, _payInLzToken);
    }
    /**
     * @dev Executes the send operation.
     * @param _sendParam The parameters for the send operation.
     * @param _fee The calculated fee for the send() operation.
     *      - nativeFee: The native fee.
     *      - lzTokenFee: The lzToken fee.
     * @param _refundAddress The address to receive any excess funds.
     * @return msgReceipt The receipt for the send operation.
     * @return oftReceipt The OFT receipt information.
     *
     * @dev MessagingReceipt: LayerZero msg receipt
     *  - guid: The unique identifier for the sent message.
     *  - nonce: The nonce of the sent message.
     *  - fee: The LayerZero fee incurred for the message.
     */
    function send(
        SendParam calldata _sendParam,
        MessagingFee calldata _fee,
        address _refundAddress
    ) external payable virtual returns (MessagingReceipt memory msgReceipt, OFTReceipt memory oftReceipt) {
        return _send(_sendParam, _fee, _refundAddress);
    }
    /**
     * @dev Internal function to execute send operations.
     * @param _sendParam The parameters for the send operation.
     * @param _fee The calculated LayerZero messaging fee from the send() operation.
     * @param _refundAddress The address to receive any excess funds from LayerZero fees.
     * @return msgReceipt The receipt from the LayerZero messaging library.
     * @return oftReceipt The OFT receipt information.
     */
    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);
        OFTCoreStorage storage $ = _getOFTCoreStorage();
        // @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.
     *
     * @dev Reverts if the _amountLD in shared decimals overflows uint64.
     * @dev eg. uint(2**64 + 123) with a conversion rate of 1 wraps around 2**64 to uint(123).
     */
    function _toSD(uint256 _amountLD) internal view virtual returns (uint64 amountSD) {
        uint256 _amountSD = _amountLD / decimalConversionRate;
        if (_amountSD > type(uint64).max) revert AmountSDOverflowed(_amountSD);
        return uint64(_amountSD);
    }
    /**
     * @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 from.
     * @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
pragma solidity ^0.8.20;
import { FeeUpgradeable } from "./FeeUpgradeable.sol";
import { OFTUpgradeable } from "./OFTUpgradeable.sol";
/**
 * @title OFTFeeUpgradeable Contract
 * @notice Upgradeable OFT with fees.
 */
abstract contract OFTFeeUpgradeable is OFTUpgradeable, FeeUpgradeable {
    struct OFTFeeStorage {
        uint256 feeBalance;
    }
    // keccak256(abi.encode(uint256(keccak256("layerzerov2.storage.oftfee")) - 1)) & ~bytes32(uint256(0xff))
    bytes32 private constant OFT_FEE_STORAGE_LOCATION =
        0x68f1d0d99488c60d21eadee2cca13b58661d56fbcb4e4464d6fc8def1b342200;
    function _getOFTFeeStorage() internal pure returns (OFTFeeStorage storage $) {
        assembly {
            $.slot := OFT_FEE_STORAGE_LOCATION
        }
    }
    function feeBalance() public view returns (uint256) {
        OFTFeeStorage storage $ = _getOFTFeeStorage();
        return $.feeBalance;
    }
    event FeeWithdrawn(address indexed to, uint256 amountLD);
    error NoFeesToWithdraw();
    /**
     * @dev Constructor for initializing the contract with LayerZero endpoint address.
     * @param _lzEndpoint The address of the LayerZero endpoint.
     */
    constructor(address _lzEndpoint) OFTUpgradeable(_lzEndpoint) {}
    /**
     * @dev Initializes the OFTFeeUpgradeable contract.
     * @param _name The name of the OFT.
     * @param _symbol The symbol of the OFT.
     * @param _delegate The address of the LayerZero delegate.
     */
    function __OFTFee_init(
        string memory _name,
        string memory _symbol,
        address _delegate
    ) internal onlyInitializing {
        __OFT_init(_name, _symbol, _delegate);
        __Fee_init();
    }
    /**
     * @dev Unchained initialization function for the contract.
     */
    function __OFTFee_init_unchained() internal onlyInitializing {}
    /**
     * @dev Calculates the amount to be sent and received after applying fees and checking for slippage.
     * @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 _debitView(
        uint256 _amountLD,
        uint256 _minAmountLD,
        uint32 _dstEid
    ) internal view virtual override returns (uint256 amountSentLD, uint256 amountReceivedLD) {
        amountSentLD = _amountLD;
        // @dev Apply the fee, then de-dust the amount afterwards.
        // This means the fee is taken from the amount before the dust is removed.
        uint256 fee = getFee(_dstEid, _amountLD);
        unchecked {
            amountReceivedLD = _removeDust(_amountLD - fee);
        }
        // @dev Check for slippage.
        if (amountReceivedLD < _minAmountLD) {
            revert SlippageExceeded(amountReceivedLD, _minAmountLD);
        }
    }
    /**
     * @dev Debits the sender's account for the full amount with fees and burns amount minus fees.
     * @param _from The address of the sender.
     * @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 endpoint ID.
     * @return amountSentLD The amount sent in local decimals.
     * @return amountReceivedLD The amount received in local decimals on the destination chain.
     */
    function _debit(
        address _from,
        uint256 _amountLD,
        uint256 _minAmountLD,
        uint32 _dstEid
    ) internal virtual override returns (uint256 amountSentLD, uint256 amountReceivedLD) {
        (amountSentLD, amountReceivedLD) = _debitView(_amountLD, _minAmountLD, _dstEid);
        if (amountSentLD > amountReceivedLD) {
            // @dev Increment the total fees that can be withdrawn.
            //      Fees include the dust resulting from the de-dust operation.
            OFTFeeStorage storage $ = _getOFTFeeStorage();
            unchecked {
                uint256 fee = amountSentLD - amountReceivedLD;
                $.feeBalance += fee;
                _transfer(_from, address(this), fee);
            }
        }
        _burn(_from, amountReceivedLD);
    }
    /**
     * @notice Withdraws accumulated fees to a specified address.
     * @param _to The address to which the fees will be withdrawn.
     */
    function withdrawFees(address _to) external onlyOwner {
        OFTFeeStorage storage $ = _getOFTFeeStorage();
        uint256 balance = $.feeBalance;
        if (balance == 0) revert NoFeesToWithdraw();
        $.feeBalance = 0;
        _transfer(address(this), _to, balance);
        emit FeeWithdrawn(_to, balance);
    }
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import { ERC20Upgradeable } from "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol";
import { IOFT, OFTCoreUpgradeable } from "./OFTCoreUpgradeable.sol";
/**
 * @title OFT Contract
 * @dev OFT is an ERC-20 token that extends the functionality of the OFTCore contract.
 */
abstract contract OFTUpgradeable is OFTCoreUpgradeable, ERC20Upgradeable {
    /**
     * @dev Constructor for the OFT contract.
     * @param _lzEndpoint The LayerZero endpoint address.
     */
    constructor(address _lzEndpoint) OFTCoreUpgradeable(decimals(), _lzEndpoint) {}
    /**
     * @dev Initializes the OFT with the provided name, symbol, and delegate.
     * @param _name The name of the OFT.
     * @param _symbol The symbol of the OFT.
     * @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.
     * @dev Ownable is not initialized here on purpose. It should be initialized in the child contract to
     * accommodate the different version of Ownable.
     */
    function __OFT_init(string memory _name, string memory _symbol, address _delegate) internal onlyInitializing {
        __ERC20_init(_name, _symbol);
        __OFTCore_init(_delegate);
    }
    function __OFT_init_unchained() internal onlyInitializing {}
    /**
     * @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.0;
struct FeeConfig {
    uint16 feeBps;
    bool enabled;
}
/**
 * @title Fee interface.
 * @notice A generic interface for collecting fees.
 */
interface IFee {
    // errors
    error InvalidBps();
    error InvalidFeeOwner();
    // events
    event FeeBpsSet(uint32 dstEid, uint16 feeBps, bool enabled);
    event DefaultFeeBpsSet(uint16 feeBps);
    // setters
    /**
     * @dev Sets the default fee basis points (BPS) for all destinations.
     */
    function setDefaultFeeBps(uint16 _feeBps) external;
    /**
     * @dev Sets the fee basis points (BPS) for a specific destination LayerZero EndpointV2 ID.
     */
    function setFeeBps(uint32 _dstEid, uint16 _feeBps, bool _enabled) external;
}// 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);
    error AmountSDOverflowed(uint256 amountSD);
    // 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
// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)
pragma solidity ^0.8.20;
import {ContextUpgradeable} from "../utils/ContextUpgradeable.sol";
import {Initializable} from "../proxy/utils/Initializable.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 OwnableUpgradeable is Initializable, ContextUpgradeable {
    /// @custom:storage-location erc7201:openzeppelin.storage.Ownable
    struct OwnableStorage {
        address _owner;
    }
    // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Ownable")) - 1)) & ~bytes32(uint256(0xff))
    bytes32 private constant OwnableStorageLocation = 0x9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300;
    function _getOwnableStorage() private pure returns (OwnableStorage storage $) {
        assembly {
            $.slot := OwnableStorageLocation
        }
    }
    /**
     * @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.
     */
    function __Ownable_init(address initialOwner) internal onlyInitializing {
        __Ownable_init_unchained(initialOwner);
    }
    function __Ownable_init_unchained(address initialOwner) internal onlyInitializing {
        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) {
        OwnableStorage storage $ = _getOwnableStorage();
        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 {
        OwnableStorage storage $ = _getOwnableStorage();
        address oldOwner = $._owner;
        $._owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.3.0) (proxy/utils/Initializable.sol)
pragma solidity ^0.8.20;
/**
 * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
 * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an
 * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
 * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
 *
 * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be
 * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in
 * case an upgrade adds a module that needs to be initialized.
 *
 * For example:
 *
 * [.hljs-theme-light.nopadding]
 * ```solidity
 * contract MyToken is ERC20Upgradeable {
 *     function initialize() initializer public {
 *         __ERC20_init("MyToken", "MTK");
 *     }
 * }
 *
 * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {
 *     function initializeV2() reinitializer(2) public {
 *         __ERC20Permit_init("MyToken");
 *     }
 * }
 * ```
 *
 * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
 * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.
 *
 * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
 * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
 *
 * [CAUTION]
 * ====
 * Avoid leaving a contract uninitialized.
 *
 * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation
 * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke
 * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:
 *
 * [.hljs-theme-light.nopadding]
 * ```
 * /// @custom:oz-upgrades-unsafe-allow constructor
 * constructor() {
 *     _disableInitializers();
 * }
 * ```
 * ====
 */
abstract contract Initializable {
    /**
     * @dev Storage of the initializable contract.
     *
     * It's implemented on a custom ERC-7201 namespace to reduce the risk of storage collisions
     * when using with upgradeable contracts.
     *
     * @custom:storage-location erc7201:openzeppelin.storage.Initializable
     */
    struct InitializableStorage {
        /**
         * @dev Indicates that the contract has been initialized.
         */
        uint64 _initialized;
        /**
         * @dev Indicates that the contract is in the process of being initialized.
         */
        bool _initializing;
    }
    // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Initializable")) - 1)) & ~bytes32(uint256(0xff))
    bytes32 private constant INITIALIZABLE_STORAGE = 0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00;
    /**
     * @dev The contract is already initialized.
     */
    error InvalidInitialization();
    /**
     * @dev The contract is not initializing.
     */
    error NotInitializing();
    /**
     * @dev Triggered when the contract has been initialized or reinitialized.
     */
    event Initialized(uint64 version);
    /**
     * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,
     * `onlyInitializing` functions can be used to initialize parent contracts.
     *
     * Similar to `reinitializer(1)`, except that in the context of a constructor an `initializer` may be invoked any
     * number of times. This behavior in the constructor can be useful during testing and is not expected to be used in
     * production.
     *
     * Emits an {Initialized} event.
     */
    modifier initializer() {
        // solhint-disable-next-line var-name-mixedcase
        InitializableStorage storage $ = _getInitializableStorage();
        // Cache values to avoid duplicated sloads
        bool isTopLevelCall = !$._initializing;
        uint64 initialized = $._initialized;
        // Allowed calls:
        // - initialSetup: the contract is not in the initializing state and no previous version was
        //                 initialized
        // - construction: the contract is initialized at version 1 (no reinitialization) and the
        //                 current contract is just being deployed
        bool initialSetup = initialized == 0 && isTopLevelCall;
        bool construction = initialized == 1 && address(this).code.length == 0;
        if (!initialSetup && !construction) {
            revert InvalidInitialization();
        }
        $._initialized = 1;
        if (isTopLevelCall) {
            $._initializing = true;
        }
        _;
        if (isTopLevelCall) {
            $._initializing = false;
            emit Initialized(1);
        }
    }
    /**
     * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the
     * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be
     * used to initialize parent contracts.
     *
     * A reinitializer may be used after the original initialization step. This is essential to configure modules that
     * are added through upgrades and that require initialization.
     *
     * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`
     * cannot be nested. If one is invoked in the context of another, execution will revert.
     *
     * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in
     * a contract, executing them in the right order is up to the developer or operator.
     *
     * WARNING: Setting the version to 2**64 - 1 will prevent any future reinitialization.
     *
     * Emits an {Initialized} event.
     */
    modifier reinitializer(uint64 version) {
        // solhint-disable-next-line var-name-mixedcase
        InitializableStorage storage $ = _getInitializableStorage();
        if ($._initializing || $._initialized >= version) {
            revert InvalidInitialization();
        }
        $._initialized = version;
        $._initializing = true;
        _;
        $._initializing = false;
        emit Initialized(version);
    }
    /**
     * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the
     * {initializer} and {reinitializer} modifiers, directly or indirectly.
     */
    modifier onlyInitializing() {
        _checkInitializing();
        _;
    }
    /**
     * @dev Reverts if the contract is not in an initializing state. See {onlyInitializing}.
     */
    function _checkInitializing() internal view virtual {
        if (!_isInitializing()) {
            revert NotInitializing();
        }
    }
    /**
     * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.
     * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized
     * to any version. It is recommended to use this to lock implementation contracts that are designed to be called
     * through proxies.
     *
     * Emits an {Initialized} event the first time it is successfully executed.
     */
    function _disableInitializers() internal virtual {
        // solhint-disable-next-line var-name-mixedcase
        InitializableStorage storage $ = _getInitializableStorage();
        if ($._initializing) {
            revert InvalidInitialization();
        }
        if ($._initialized != type(uint64).max) {
            $._initialized = type(uint64).max;
            emit Initialized(type(uint64).max);
        }
    }
    /**
     * @dev Returns the highest version that has been initialized. See {reinitializer}.
     */
    function _getInitializedVersion() internal view returns (uint64) {
        return _getInitializableStorage()._initialized;
    }
    /**
     * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.
     */
    function _isInitializing() internal view returns (bool) {
        return _getInitializableStorage()._initializing;
    }
    /**
     * @dev Pointer to storage slot. Allows integrators to override it with a custom storage location.
     *
     * NOTE: Consider following the ERC-7201 formula to derive storage locations.
     */
    function _initializableStorageSlot() internal pure virtual returns (bytes32) {
        return INITIALIZABLE_STORAGE;
    }
    /**
     * @dev Returns a pointer to the storage namespace.
     */
    // solhint-disable-next-line var-name-mixedcase
    function _getInitializableStorage() private pure returns (InitializableStorage storage $) {
        bytes32 slot = _initializableStorageSlot();
        assembly {
            $.slot := slot
        }
    }
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC20/ERC20.sol)
pragma solidity ^0.8.20;
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {IERC20Metadata} from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
import {ContextUpgradeable} from "../../utils/ContextUpgradeable.sol";
import {IERC20Errors} from "@openzeppelin/contracts/interfaces/draft-IERC6093.sol";
import {Initializable} from "../../proxy/utils/Initializable.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 ERC20Upgradeable is Initializable, ContextUpgradeable, IERC20, IERC20Metadata, IERC20Errors {
    /// @custom:storage-location erc7201:openzeppelin.storage.ERC20
    struct ERC20Storage {
        mapping(address account => uint256) _balances;
        mapping(address account => mapping(address spender => uint256)) _allowances;
        uint256 _totalSupply;
        string _name;
        string _symbol;
    }
    // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.ERC20")) - 1)) & ~bytes32(uint256(0xff))
    bytes32 private constant ERC20StorageLocation = 0x52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace00;
    function _getERC20Storage() private pure returns (ERC20Storage storage $) {
        assembly {
            $.slot := ERC20StorageLocation
        }
    }
    /**
     * @dev Sets the values for {name} and {symbol}.
     *
     * Both values are immutable: they can only be set once during construction.
     */
    function __ERC20_init(string memory name_, string memory symbol_) internal onlyInitializing {
        __ERC20_init_unchained(name_, symbol_);
    }
    function __ERC20_init_unchained(string memory name_, string memory symbol_) internal onlyInitializing {
        ERC20Storage storage $ = _getERC20Storage();
        $._name = name_;
        $._symbol = symbol_;
    }
    /**
     * @dev Returns the name of the token.
     */
    function name() public view virtual returns (string memory) {
        ERC20Storage storage $ = _getERC20Storage();
        return $._name;
    }
    /**
     * @dev Returns the symbol of the token, usually a shorter version of the
     * name.
     */
    function symbol() public view virtual returns (string memory) {
        ERC20Storage storage $ = _getERC20Storage();
        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;
    }
    /// @inheritdoc IERC20
    function totalSupply() public view virtual returns (uint256) {
        ERC20Storage storage $ = _getERC20Storage();
        return $._totalSupply;
    }
    /// @inheritdoc IERC20
    function balanceOf(address account) public view virtual returns (uint256) {
        ERC20Storage storage $ = _getERC20Storage();
        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;
    }
    /// @inheritdoc IERC20
    function allowance(address owner, address spender) public view virtual returns (uint256) {
        ERC20Storage storage $ = _getERC20Storage();
        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 {
        ERC20Storage storage $ = _getERC20Storage();
        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 {
        ERC20Storage storage $ = _getERC20Storage();
        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.0.1) (utils/Context.sol)
pragma solidity ^0.8.20;
import {Initializable} from "../proxy/utils/Initializable.sol";
/**
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
abstract contract ContextUpgradeable is Initializable {
    function __Context_init() internal onlyInitializing {
    }
    function __Context_init_unchained() internal onlyInitializing {
    }
    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.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.4.0) (interfaces/draft-IERC6093.sol)
pragma solidity >=0.8.4;
/**
 * @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.4.0) (interfaces/IERC1363.sol)
pragma solidity >=0.6.2;
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);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC165.sol)
pragma solidity >=0.4.16;
import {IERC165} from "../utils/introspection/IERC165.sol";// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC20.sol)
pragma solidity >=0.4.16;
import {IERC20} from "../token/ERC20/IERC20.sol";// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC20/extensions/IERC20Metadata.sol)
pragma solidity >=0.6.2;
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.4.0) (token/ERC20/IERC20.sol)
pragma solidity >=0.4.16;
/**
 * @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.4.0) (utils/introspection/IERC165.sol)
pragma solidity >=0.4.16;
/**
 * @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);
}{
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "evmVersion": "paris",
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "abi"
      ]
    }
  },
  "metadata": {
    "useLiteralContent": true
  }
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
 
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_lzEndpoint","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint256","name":"amountSD","type":"uint256"}],"name":"AmountSDOverflowed","type":"error"},{"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":"InvalidBps","type":"error"},{"inputs":[],"name":"InvalidDelegate","type":"error"},{"inputs":[],"name":"InvalidEndpointCall","type":"error"},{"inputs":[],"name":"InvalidFeeOwner","type":"error"},{"inputs":[],"name":"InvalidInitialization","type":"error"},{"inputs":[],"name":"InvalidLocalDecimals","type":"error"},{"inputs":[{"internalType":"bytes","name":"options","type":"bytes"}],"name":"InvalidOptions","type":"error"},{"inputs":[],"name":"LzTokenUnavailable","type":"error"},{"inputs":[],"name":"NoFeesToWithdraw","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":[],"name":"NotInitializing","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":"uint16","name":"feeBps","type":"uint16"}],"name":"DefaultFeeBpsSet","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":"feeAddress","type":"address"}],"name":"FeeAddress","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"dstEid","type":"uint32"},{"indexed":false,"internalType":"uint16","name":"feeBps","type":"uint16"},{"indexed":false,"internalType":"bool","name":"enabled","type":"bool"}],"name":"FeeBpsSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountLD","type":"uint256"}],"name":"FeeWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"version","type":"uint64"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"inspector","type":"address"}],"name":"MsgInspectorSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"guid","type":"bytes32"},{"indexed":false,"internalType":"uint32","name":"srcEid","type":"uint32"},{"indexed":true,"internalType":"address","name":"toAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountReceivedLD","type":"uint256"}],"name":"OFTReceived","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"guid","type":"bytes32"},{"indexed":false,"internalType":"uint32","name":"dstEid","type":"uint32"},{"indexed":true,"internalType":"address","name":"fromAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountSentLD","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountReceivedLD","type":"uint256"}],"name":"OFTSent","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"eid","type":"uint32"},{"indexed":false,"internalType":"bytes32","name":"peer","type":"bytes32"}],"name":"PeerSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"preCrimeAddress","type":"address"}],"name":"PreCrimeSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"nonce","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"fromBalanceAfterTransfer","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"toBalanceAfterTransfer","type":"uint256"}],"name":"TransferEx","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"bool","name":"isWhitelisted","type":"bool"}],"name":"WhitelistUpdated","type":"event"},{"inputs":[],"name":"BPS_DENOMINATOR","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"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":[{"internalType":"address","name":"_account","type":"address"}],"name":"addToWhitelist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint32","name":"srcEid","type":"uint32"},{"internalType":"bytes32","name":"sender","type":"bytes32"},{"internalType":"uint64","name":"nonce","type":"uint64"}],"internalType":"struct Origin","name":"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":"defaultFeeBps","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"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":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feeBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"_dstEid","type":"uint32"}],"name":"feeBps","outputs":[{"components":[{"internalType":"uint16","name":"feeBps","type":"uint16"},{"internalType":"bool","name":"enabled","type":"bool"}],"internalType":"struct FeeConfig","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"_dstEid","type":"uint32"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"getFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFeeAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"_name","type":"string"},{"internalType":"string","name":"_symbol","type":"string"},{"internalType":"address","name":"_delegate","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_name","type":"string"},{"internalType":"string","name":"_symbol","type":"string"}],"name":"initialize2","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint32","name":"srcEid","type":"uint32"},{"internalType":"bytes32","name":"sender","type":"bytes32"},{"internalType":"uint64","name":"nonce","type":"uint64"}],"internalType":"struct Origin","name":"","type":"tuple"},{"internalType":"bytes","name":"","type":"bytes"},{"internalType":"address","name":"_sender","type":"address"}],"name":"isComposeMsgSender","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"_eid","type":"uint32"},{"internalType":"bytes32","name":"_peer","type":"bytes32"}],"name":"isPeer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"isWhitelisted","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":[{"internalType":"uint32","name":"_eid","type":"uint32"}],"name":"peers","outputs":[{"internalType":"bytes32","name":"","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":"_account","type":"address"}],"name":"removeFromWhitelist","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":"uint16","name":"_feeBps","type":"uint16"}],"name":"setDefaultFeeBps","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":"_feeAddress","type":"address"}],"name":"setFeeAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"_dstEid","type":"uint32"},{"internalType":"uint16","name":"_feeBps","type":"uint16"},{"internalType":"bool","name":"_enabled","type":"bool"}],"name":"setFeeBps","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_msgInspector","type":"address"}],"name":"setMsgInspector","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"_eid","type":"uint32"},{"internalType":"bytes32","name":"_peer","type":"bytes32"}],"name":"setPeer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_preCrime","type":"address"}],"name":"setPreCrime","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"sharedDecimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"pure","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":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"}],"name":"withdrawFees","outputs":[],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
60c06040523480156200001157600080fd5b506040516200456838038062004568833981016040819052620000349162000147565b6001600160a01b0381166080528080600681620000536006836200018f565b6200006090600a620002a8565b60a05250620000739250506200007a9050565b50620002b9565b6000620000866200011c565b805490915068010000000000000000900460ff1615620000b95760405163f92ee8a960e01b815260040160405180910390fd5b80546001600160401b0390811614620001195780546001600160401b0319166001600160401b0390811782556040519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50565b6000807ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005b92915050565b6000602082840312156200015a57600080fd5b81516001600160a01b03811681146200017257600080fd5b9392505050565b634e487b7160e01b600052601160045260246000fd5b60ff828116828216039081111562000141576200014162000179565b600181815b80851115620001ec578160001904821115620001d057620001d062000179565b80851615620001de57918102915b93841c9390800290620001b0565b509250929050565b600082620002055750600162000141565b81620002145750600062000141565b81600181146200022d5760028114620002385762000258565b600191505062000141565b60ff8411156200024c576200024c62000179565b50506001821b62000141565b5060208310610133831016604e8410600b84101617156200027d575081810a62000141565b620002898383620001ab565b8060001904821115620002a057620002a062000179565b029392505050565b60006200017260ff841683620001f4565b60805160a051614243620003256000396000818161096e015281816126fa0152818161276f01526128d80152600081816107bd01528181610e9301528181611b9401528181611f8e015281816122b301528181612b5c01528181612e7d0152612f3601526142436000f3fe6080604052600436106103765760003560e01c80636fc1b31e116101d1578063b98bd07011610102578063d045a0dc116100a0578063e43252d71161006f578063e43252d714610b3c578063f2fde38b14610b5c578063fc0c546a14610714578063ff7bd03d14610b7c57600080fd5b8063d045a0dc14610ad3578063d424388514610ae6578063dd62ed3e14610b06578063e1a4521814610b2657600080fd5b8063bcae25a4116100dc578063bcae25a414610a59578063bd815db014610a7f578063c7c7f5b314610a92578063ca5eb5e114610ab357600080fd5b8063b98bd070146109d9578063bb0b6a53146109f9578063bc70b35414610a3957600080fd5b80638ab1d6811161016f578063963efcaa11610149578063963efcaa1461095c5780639f68b96414610990578063a9059cbb146109a4578063b731ea0a146109c457600080fd5b80638ab1d681146109125780638da5cb5b1461093257806395d89b411461094757600080fd5b80637d25a05e116101ab5780637d25a05e1461088857806382413eac146108c3578063857749b01461056b5780638705fcd4146108f257600080fd5b80636fc1b31e1461083357806370a0823114610853578063715018a61461087357600080fd5b80633194c180116102ab57806352ae2879116102495780635bf9c226116102235780635bf9c2261461078b5780635e280f11146107ab57806360b71d4e146107df5780636db7bcdb1461081357600080fd5b806352ae2879146107145780635535d461146107275780635a0dfe4d1461074757600080fd5b80633b6f743b116102855780633b6f743b146106895780633b7d72b4146106b65780634488b652146106d65780634e7ceacb146106f657600080fd5b80633194c180146105875780633400288b146106305780633af32abf1461065057600080fd5b8063156a0d0f1161031857806318160ddd116102f257806318160ddd146104f85780631f5e13341461053657806323b872dd1461054b578063313ce5671461056b57600080fd5b8063156a0d0f1461048f578063164e68de146104b657806317442b70146104d657600080fd5b80630d35b415116103545780630d35b415146103f8578063111ecdad1461042757806313137d6514610454578063134d4f251461046757600080fd5b806306fdde031461037b578063077f224a146103a6578063095ea7b3146103c8575b600080fd5b34801561038757600080fd5b50610390610b9c565b60405161039d91906130fd565b60405180910390f35b3480156103b257600080fd5b506103c66103c1366004613210565b610c5f565b005b3480156103d457600080fd5b506103e86103e3366004613287565b610d76565b604051901515815260200161039d565b34801561040457600080fd5b506104186104133660046132cb565b610d90565b60405161039d939291906132ff565b34801561043357600080fd5b5061043c610e5c565b6040516001600160a01b03909116815260200161039d565b6103c66104623660046133eb565b610e91565b34801561047357600080fd5b5061047c600281565b60405161ffff909116815260200161039d565b34801561049b57600080fd5b506040805162b9270b60e21b8152600160208201520161039d565b3480156104c257600080fd5b506103c66104d136600461348a565b610f51565b3480156104e257600080fd5b506040805160018152600260208201520161039d565b34801561050457600080fd5b507f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace02545b60405190815260200161039d565b34801561054257600080fd5b5061047c600181565b34801561055757600080fd5b506103e86105663660046134a7565b610ff5565b34801561057757600080fd5b506040516006815260200161039d565b34801561059357600080fd5b5061060f6105a2366004613501565b6040805180820182526000808252602091820181905263ffffffff9390931683527f0cb173d183337e25fab6cb85705c15aad6a58cb1d552ed71b9bc628c8a3de80181529181902081518083019092525461ffff8116825262010000900460ff1615159181019190915290565b60408051825161ffff1681526020928301511515928101929092520161039d565b34801561063c57600080fd5b506103c661064b36600461351c565b61101b565b34801561065c57600080fd5b506103e861066b36600461348a565b6001600160a01b031660009081526001602052604090205460ff1690565b34801561069557600080fd5b506106a96106a4366004613546565b611088565b60405161039d9190613597565b3480156106c257600080fd5b506103c66106d13660046135ae565b6110ef565b3480156106e257600080fd5b506103c66106f1366004613623565b6111b9565b34801561070257600080fd5b506000546001600160a01b031661043c565b34801561072057600080fd5b503061043c565b34801561073357600080fd5b5061039061074236600461363e565b611240565b34801561075357600080fd5b506103e861076236600461351c565b63ffffffff9190911660009081526000805160206141ee83398151915260205260409020541490565b34801561079757600080fd5b506105286107a636600461351c565b61131b565b3480156107b757600080fd5b5061043c7f000000000000000000000000000000000000000000000000000000000000000081565b3480156107eb57600080fd5b507f68f1d0d99488c60d21eadee2cca13b58661d56fbcb4e4464d6fc8def1b34220054610528565b34801561081f57600080fd5b506103c661082e366004613671565b61135e565b34801561083f57600080fd5b506103c661084e36600461348a565b611429565b34801561085f57600080fd5b5061052861086e36600461348a565b61149d565b34801561087f57600080fd5b506103c66114c5565b34801561089457600080fd5b506108ab6108a336600461351c565b600092915050565b6040516001600160401b03909116815260200161039d565b3480156108cf57600080fd5b506103e86108de3660046136ad565b6001600160a01b0381163014949350505050565b3480156108fe57600080fd5b506103c661090d36600461348a565b6114d9565b34801561091e57600080fd5b506103c661092d36600461348a565b611535565b34801561093e57600080fd5b5061043c6115ed565b34801561095357600080fd5b50610390611616565b34801561096857600080fd5b506105287f000000000000000000000000000000000000000000000000000000000000000081565b34801561099c57600080fd5b5060006103e8565b3480156109b057600080fd5b506103e86109bf366004613287565b611655565b3480156109d057600080fd5b5061043c611663565b3480156109e557600080fd5b506103c66109f4366004613757565b61168c565b348015610a0557600080fd5b50610528610a14366004613501565b63ffffffff1660009081526000805160206141ee833981519152602052604090205490565b348015610a4557600080fd5b50610390610a54366004613798565b61180d565b348015610a6557600080fd5b506000805160206141ce8339815191525461ffff1661047c565b6103c6610a8d366004613757565b6119a3565b610aa5610aa03660046137f8565b611b3a565b60405161039d92919061385a565b348015610abf57600080fd5b506103c6610ace36600461348a565b611b6d565b6103c6610ae13660046133eb565b611bf3565b348015610af257600080fd5b506103c6610b0136600461348a565b611c22565b348015610b1257600080fd5b50610528610b213660046138ac565b611c96565b348015610b3257600080fd5b5061047c61271081565b348015610b4857600080fd5b506103c6610b5736600461348a565b611ce0565b348015610b6857600080fd5b506103c6610b7736600461348a565b611d9a565b348015610b8857600080fd5b506103e8610b973660046138da565b611dd8565b7f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace0380546060916000805160206141ae83398151915291610bdb906138f6565b80601f0160208091040260200160405190810160405280929190818152602001828054610c07906138f6565b8015610c545780601f10610c2957610100808354040283529160200191610c54565b820191906000526020600020905b815481529060010190602001808311610c3757829003601f168201915b505050505091505090565b6000610c69611df6565b805490915060ff600160401b82041615906001600160401b0316600081158015610c905750825b90506000826001600160401b03166001148015610cac5750303b155b905081158015610cba575080155b15610cd85760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff191660011785558315610d0257845460ff60401b1916600160401b1785555b610d0d888888611e1f565b610d1686611e3f565b600080546001600160a01b03191690558315610d6c57845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b5050505050505050565b600033610d84818585611e50565b60019150505b92915050565b60408051808201909152600080825260208201526060610dc3604051806040016040528060008152602001600081525090565b6040805180820182526000808252600019602080840182905284518381529081019094529195509182610e19565b604080518082019091526000815260606020820152815260200190600190039081610df15790505b509350600080610e3e604089013560608a0135610e3960208c018c613501565b611e5d565b60408051808201909152918252602082015296989597505050505050565b6000807f41db8a78b0206aba5c54bcbfc2bda0d84082a84eb88e680379a57b9e9f653c005b546001600160a01b031692915050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03163314610ee1576040516391ac5e4f60e01b81523360048201526024015b60405180910390fd5b60208701803590610efb90610ef6908a613501565b611eae565b14610f3957610f0d6020880188613501565b60405163309afaf360e21b815263ffffffff909116600482015260208801356024820152604401610ed8565b610f4887878787878787611ef9565b50505050505050565b610f59612060565b7f68f1d0d99488c60d21eadee2cca13b58661d56fbcb4e4464d6fc8def1b34220080546000819003610f9e57604051630d00db4d60e31b815260040160405180910390fd5b60008255610fad308483612092565b826001600160a01b03167f78473f3f373f7673597f4f0fa5873cb4d375fea6d4339ad6b56dbd411513cb3f82604051610fe891815260200190565b60405180910390a2505050565b6000336110038582856120f1565b61100e858585612092565b60019150505b9392505050565b611023612060565b63ffffffff821660008181526000805160206141ee833981519152602081815260409283902085905582519384528301849052917f238399d427b947898edb290f5ff0f9109849b1c3ba196a42e35f00c50a54b98b91015b60405180910390a1505050565b604080518082019091526000808252602082015260006110b860408501356060860135610e396020880188613501565b9150506000806110c88684612158565b90925090506110e56110dd6020880188613501565b83838861229d565b9695505050505050565b600260006110fb611df6565b8054909150600160401b900460ff1680611122575080546001600160401b03808416911610155b156111405760405163f92ee8a960e01b815260040160405180910390fd5b805468ffffffffffffffffff19166001600160401b03831617600160401b17815561116b848461237e565b805460ff60401b191681556040516001600160401b03831681527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2906020015b60405180910390a150505050565b6111c1612060565b61271061ffff821611156111e85760405163c6cc5d7f60e01b815260040160405180910390fd5b6000805160206141ce833981519152805461ffff191661ffff831690811782556040519081527f9283ddc0c2b59320e00b0ae4a992b110df098c38e3b6ea1d92fe7a6d3504be9b906020015b60405180910390a15050565b63ffffffff821660009081527f8d2bda5d9f6ffb5796910376005392955773acee5548d0fcdb10e7c264ea00006020818152604080842061ffff8616855290915290912080546060929190611294906138f6565b80601f01602080910402602001604051908101604052809291908181526020018280546112c0906138f6565b801561130d5780601f106112e25761010080835404028352916020019161130d565b820191906000526020600020905b8154815290600101906020018083116112f057829003601f168201915b505050505091505092915050565b60008061132784612394565b905061ffff8116156113535761271061134461ffff831685613940565b61134e9190613957565b611356565b60005b949350505050565b611366612060565b61271061ffff8316111561138d5760405163c6cc5d7f60e01b815260040160405180910390fd5b60006000805160206141ce83398151915260408051808201825261ffff868116808352861515602080850182815263ffffffff8c16600081815260018a0184528890209651875492511515620100000262ffffff1990931696169590951717909455845192835292820152918201529091507f56f0bca120766dba5aeeb89a1cf629c3495dc497c82f426d4e4d58c54b72764c906060016111ab565b611431612060565b7f41db8a78b0206aba5c54bcbfc2bda0d84082a84eb88e680379a57b9e9f653c0080546001600160a01b0319166001600160a01b03831690811782556040519081527ff0be4f1e87349231d80c36b33f9e8639658eeaf474014dee15a3e6a4d441419790602001611234565b6001600160a01b031660009081526000805160206141ae833981519152602052604090205490565b6114cd612060565b6114d76000612413565b565b6114e1612060565b600080546001600160a01b0319166001600160a01b0383169081179091556040519081527f0cc4d0c9af0c184a6ba4203a2d8f4a6843759ea43f751b50f516f6fb4241d9df9060200160405180910390a150565b61153d612060565b6001600160a01b03811660009081526001602052604090205460ff166115975760405162461bcd60e51b815260206004820152600f60248201526e139bdd081dda1a5d195b1a5cdd1959608a1b6044820152606401610ed8565b6001600160a01b0381166000818152600160209081526040808320805460ff19169055519182527ff93f9a76c1bf3444d22400a00cb9fe990e6abe9dbb333fda48859cfee864543d91015b60405180910390a250565b6000807f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300610e81565b7f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace0480546060916000805160206141ae83398151915291610bdb906138f6565b600033610d84818585612092565b6000807fefb041d771d6daaa55702fff6eb740d63ba559a75d2d1d3e151c78ff2480b600610e81565b611694612060565b7f8d2bda5d9f6ffb5796910376005392955773acee5548d0fcdb10e7c264ea000060005b828110156117db576116fa8484838181106116d5576116d5613979565b90506020028101906116e7919061398f565b6116f59060408101906139af565b612484565b83838281811061170c5761170c613979565b905060200281019061171e919061398f565b61172c9060408101906139af565b83600087878681811061174157611741613979565b9050602002810190611753919061398f565b611761906020810190613501565b63ffffffff1663ffffffff168152602001908152602001600020600087878681811061178f5761178f613979565b90506020028101906117a1919061398f565b6117b2906040810190602001613623565b61ffff1681526020810191909152604001600020916117d2919083613a45565b506001016116b8565b507fbe4864a8e820971c0247f5992e2da559595f7bf076a21cb5928d443d2a13b674838360405161107b929190613b2d565b63ffffffff841660009081527f8d2bda5d9f6ffb5796910376005392955773acee5548d0fcdb10e7c264ea00006020818152604080842061ffff88168552909152822080546060939190611860906138f6565b80601f016020809104026020016040519081016040528092919081815260200182805461188c906138f6565b80156118d95780601f106118ae576101008083540402835291602001916118d9565b820191906000526020600020905b8154815290600101906020018083116118bc57829003601f168201915b50505050509050805160000361192a5784848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550611356945050505050565b600084900361193c5791506113569050565b600284106119865761194e8585612484565b8061195c8560028189613c11565b60405160200161196e93929190613c3b565b60405160208183030381529060405292505050611356565b8484604051639a6d49cd60e01b8152600401610ed8929190613c63565b60005b81811015611ab957368383838181106119c1576119c1613979565b90506020028101906119d39190613c77565b9050611a136119e56020830183613501565b602083013563ffffffff9190911660009081526000805160206141ee83398151915260205260409020541490565b611a1d5750611ab1565b3063d045a0dc60c08301358360a0810135611a3c6101008301836139af565b611a4d610100890160e08a0161348a565b611a5b6101208a018a6139af565b6040518963ffffffff1660e01b8152600401611a7d9796959493929190613ca3565b6000604051808303818588803b158015611a9657600080fd5b505af1158015611aaa573d6000803e3d6000fd5b5050505050505b6001016119a6565b50336001600160a01b0316638e9e70996040518163ffffffff1660e01b8152600401600060405180830381865afa158015611af8573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611b209190810190613d29565b604051638351eea760e01b8152600401610ed891906130fd565b611b42613066565b6040805180820190915260008082526020820152611b618585856124c6565b91509150935093915050565b611b75612060565b60405163ca5eb5e160e01b81526001600160a01b0382811660048301527f0000000000000000000000000000000000000000000000000000000000000000169063ca5eb5e190602401600060405180830381600087803b158015611bd857600080fd5b505af1158015611bec573d6000803e3d6000fd5b5050505050565b333014611c135760405163029a949d60e31b815260040160405180910390fd5b610f4887878787878787610f39565b611c2a612060565b7fefb041d771d6daaa55702fff6eb740d63ba559a75d2d1d3e151c78ff2480b60080546001600160a01b0319166001600160a01b03831690811782556040519081527fd48d879cef83a1c0bdda516f27b13ddb1b3f8bbac1c9e1511bb2a659c242776090602001611234565b6001600160a01b0391821660009081527f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace016020908152604080832093909416825291909152205490565b611ce8612060565b6001600160a01b03811660009081526001602052604090205460ff1615611d475760405162461bcd60e51b8152602060048201526013602482015272105b1c9958591e481dda1a5d195b1a5cdd1959606a1b6044820152606401610ed8565b6001600160a01b038116600081815260016020818152604092839020805460ff19168317905591519081527ff93f9a76c1bf3444d22400a00cb9fe990e6abe9dbb333fda48859cfee864543d91016115e2565b611da2612060565b6001600160a01b038116611dcc57604051631e4fbdf760e01b815260006004820152602401610ed8565b611dd581612413565b50565b600060208201803590611def90610a149085613501565b1492915050565b6000807ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00610d8a565b611e276125c1565b611e31838361237e565b611e3a816125e6565b505050565b611e476125c1565b611dd581612607565b611e3a838383600161260f565b82600080611e6b848461131b565b9050611e788187036126f6565b915084821015611ea5576040516371c4efed60e01b81526004810183905260248101869052604401610ed8565b50935093915050565b63ffffffff811660009081526000805160206141ee83398151915260208190526040822054806110145760405163f6ff4fb760e01b815263ffffffff85166004820152602401610ed8565b6000611f0b611f08878761272d565b90565b90506000611f3782611f25611f208a8a612745565b612768565b611f3260208d018d613501565b61279d565b90506028861115611ffe576000611f74611f5760608c0160408d01613d96565b611f6460208d018d613501565b84611f6f8c8c6127c5565b612810565b604051633e5ac80960e11b81529091506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690637cb5901290611fca9086908d906000908790600401613db3565b600060405180830381600087803b158015611fe457600080fd5b505af1158015611ff8573d6000803e3d6000fd5b50505050505b6001600160a01b038216887fefed6d3500546b29533b128a29e3a94d70788727f0507505ac12eaf2e578fd9c61203760208d018d613501565b6040805163ffffffff9092168252602082018690520160405180910390a3505050505050505050565b336120696115ed565b6001600160a01b0316146114d75760405163118cdaa760e01b8152336004820152602401610ed8565b6001600160a01b0383166120bc57604051634b637e8f60e11b815260006004820152602401610ed8565b6001600160a01b0382166120e65760405163ec442f0560e01b815260006004820152602401610ed8565b611e3a838383612842565b60006120fd8484611c96565b9050600019811015612152578181101561214357604051637dc7a0d960e11b81526001600160a01b03841660048201526024810182905260448101839052606401610ed8565b6121528484848403600061260f565b50505050565b60608060006121b5856020013561216e866128d0565b61217b60a08901896139af565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061292a92505050565b90935090506000816121c85760016121cb565b60025b90506121eb6121dd6020880188613501565b82610a5460808a018a6139af565b7f41db8a78b0206aba5c54bcbfc2bda0d84082a84eb88e680379a57b9e9f653c008054919450906001600160a01b031680156122925760405163043a78eb60e01b81526001600160a01b0382169063043a78eb9061224f9089908990600401613de4565b602060405180830381865afa15801561226c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122909190613e09565b505b505050509250929050565b60408051808201909152600080825260208201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663ddc28c586040518060a001604052808863ffffffff16815260200161230089611eae565b8152602001878152602001868152602001851515815250306040518363ffffffff1660e01b8152600401612335929190613e26565b6040805180830381865afa158015612351573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123759190613ecf565b95945050505050565b6123866125c1565b61239082826129a4565b5050565b63ffffffff811660009081527f0cb173d183337e25fab6cb85705c15aad6a58cb1d552ed71b9bc628c8a3de8016020908152604080832081518083019092525461ffff8116825262010000900460ff1615159181018290526000805160206141ce8339815191529161240b57815461ffff16611356565b519392505050565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930080546001600160a01b031981166001600160a01b03848116918217845560405192169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3505050565b60006124936002828486613c11565b61249c91613eeb565b60f01c905060038114611e3a578282604051639a6d49cd60e01b8152600401610ed8929190613c63565b6124ce613066565b604080518082019091526000808252602082015260008061250533604089013560608a013561250060208c018c613501565b6129f5565b915091506000806125168984612158565b909250905061254261252b60208b018b613501565b838361253c368d90038d018d613f1b565b8b612b29565b60408051808201909152858152602080820186905282519298509096503391907f85496b760a4b7f8d66384b9df21b381f5d1b1e79f229a47aaf4c232edc2fe59a90612590908d018d613501565b6040805163ffffffff909216825260208201899052810187905260600160405180910390a350505050935093915050565b6125c9612c34565b6114d757604051631afcd79f60e31b815260040160405180910390fd5b6125ee6125c1565b6125f781612c4e565b6125ff612c5f565b611dd5612c5f565b611da26125c1565b6000805160206141ae8339815191526001600160a01b0385166126485760405163e602df0560e01b815260006004820152602401610ed8565b6001600160a01b03841661267257604051634a1406b160e11b815260006004820152602401610ed8565b6001600160a01b03808616600090815260018301602090815260408083209388168352929052208390558115611bec57836001600160a01b0316856001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925856040516126e791815260200190565b60405180910390a35050505050565b60007f00000000000000000000000000000000000000000000000000000000000000006127238184613957565b610d8a9190613940565b600061273c6020828486613c11565b61101491613f4d565b6000612755602860208486613c11565b61275e91613f6b565b60c01c9392505050565b6000610d8a7f00000000000000000000000000000000000000000000000000000000000000006001600160401b038416613940565b60006001600160a01b0384166127b35761dead93505b6127bd8484612c67565b509092915050565b60606127d48260288186613c11565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929695505050505050565b6060848484846040516020016128299493929190613f99565b6040516020818303038152906040529050949350505050565b61284d838383612c9d565b6002805490600061285d83613fe8565b9190505550600254826001600160a01b0316846001600160a01b03167f6d16356255ebed8e5918262476684aaa5f8054befd93154494221a6026157aa5846128a48861149d565b6128ad8861149d565b6040805193845260208401929092529082015260600160405180910390a4505050565b6000806128fd7f000000000000000000000000000000000000000000000000000000000000000084613957565b90506001600160401b03811115610d8a5760405163e2ce941360e01b815260048101829052602401610ed8565b805160609015158061297357848460405160200161295f92919091825260c01b6001600160c01b031916602082015260280190565b60405160208183030381529060405261299a565b8484338560405160200161298a9493929190614001565b6040516020818303038152906040525b9150935093915050565b6129ac6125c1565b6000805160206141ae8339815191527f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace036129e68482614044565b50600481016121528382614044565b6001600160a01b038416600090815260016020526040812054819060ff16612a2757612a22858585611e5d565b612a31565b612a318585612ddb565b909250905081811115612aa15760405162461bcd60e51b815260206004820152603260248201527f416d6f756e742072656365697665642063616e6e6f74206265206772656174656044820152711c881d1a185b88185b5bdd5b9d081cd95b9d60721b6064820152608401610ed8565b6000612aad8284614103565b90508015612b15576000546001600160a01b0316612afd577f68f1d0d99488c60d21eadee2cca13b58661d56fbcb4e4464d6fc8def1b342200805482018155612af7883084612092565b50612b15565b600054612b159088906001600160a01b031683612092565b612b1f8783612e1b565b5094509492505050565b612b31613066565b6000612b408460000151612e51565b602085015190915015612b5a57612b5a8460200151612e79565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632637a450826040518060a001604052808b63ffffffff168152602001612baa8c611eae565b81526020018a815260200189815260200160008960200151111515815250866040518463ffffffff1660e01b8152600401612be6929190613e26565b60806040518083038185885af1158015612c04573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190612c299190614116565b979650505050505050565b6000612c3e611df6565b54600160401b900460ff16919050565b612c566125c1565b6125f781612f5b565b6114d76125c1565b6001600160a01b038216612c915760405163ec442f0560e01b815260006004820152602401610ed8565b61239060008383612842565b6000805160206141ae8339815191526001600160a01b038416612cd95781816002016000828254612cce919061417d565b90915550612d4b9050565b6001600160a01b03841660009081526020829052604090205482811015612d2c5760405163391434e360e21b81526001600160a01b03861660048201526024810182905260448101849052606401610ed8565b6001600160a01b03851660009081526020839052604090209083900390555b6001600160a01b038316612d69576002810180548390039055612d88565b6001600160a01b03831660009081526020829052604090208054830190555b826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051612dcd91815260200190565b60405180910390a350505050565b816000612de7826126f6565b905082811015612e14576040516371c4efed60e01b81526004810182905260248101849052604401610ed8565b9250929050565b6001600160a01b038216612e4557604051634b637e8f60e11b815260006004820152602401610ed8565b61239082600083612842565b6000813414612e75576040516304fb820960e51b8152346004820152602401610ed8565b5090565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663e4fe1d946040518163ffffffff1660e01b8152600401602060405180830381865afa158015612ed9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612efd9190614190565b90506001600160a01b038116612f26576040516329b99a9560e11b815260040160405180910390fd5b6123906001600160a01b038216337f000000000000000000000000000000000000000000000000000000000000000085612f6c565b612f636125c1565b611dd581612fc6565b604080516001600160a01b0385811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b179052612152908590612ff5565b612fce6125c1565b6001600160a01b038116611b7557604051632d618d8160e21b815260040160405180910390fd5b600080602060008451602086016000885af180613018576040513d6000823e3d81fd5b50506000513d9150811561303057806001141561303d565b6001600160a01b0384163b155b1561215257604051635274afe760e01b81526001600160a01b0385166004820152602401610ed8565b60405180606001604052806000801916815260200160006001600160401b031681526020016130a8604051806040016040528060008152602001600081525090565b905290565b60005b838110156130c85781810151838201526020016130b0565b50506000910152565b600081518084526130e98160208601602086016130ad565b601f01601f19169290920160200192915050565b60208152600061101460208301846130d1565b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b038111828210171561314857613148613110565b60405290565b604051601f8201601f191681016001600160401b038111828210171561317657613176613110565b604052919050565b60006001600160401b0382111561319757613197613110565b50601f01601f191660200190565b600082601f8301126131b657600080fd5b81356131c96131c48261317e565b61314e565b8181528460208386010111156131de57600080fd5b816020850160208301376000918101602001919091529392505050565b6001600160a01b0381168114611dd557600080fd5b60008060006060848603121561322557600080fd5b83356001600160401b038082111561323c57600080fd5b613248878388016131a5565b9450602086013591508082111561325e57600080fd5b5061326b868287016131a5565b925050604084013561327c816131fb565b809150509250925092565b6000806040838503121561329a57600080fd5b82356132a5816131fb565b946020939093013593505050565b600060e082840312156132c557600080fd5b50919050565b6000602082840312156132dd57600080fd5b81356001600160401b038111156132f357600080fd5b611356848285016132b3565b8351815260208085015190820152600060a08201604060a0604085015281865180845260c08601915060c08160051b8701019350602080890160005b8381101561337a5788870360bf19018552815180518852830151838801879052613367878901826130d1565b975050938201939082019060010161333b565b50508751606088015250505060208501516080850152509050611356565b6000606082840312156132c557600080fd5b60008083601f8401126133bc57600080fd5b5081356001600160401b038111156133d357600080fd5b602083019150836020828501011115612e1457600080fd5b600080600080600080600060e0888a03121561340657600080fd5b6134108989613398565b96506060880135955060808801356001600160401b038082111561343357600080fd5b61343f8b838c016133aa565b909750955060a08a01359150613454826131fb565b90935060c0890135908082111561346a57600080fd5b506134778a828b016133aa565b989b979a50959850939692959293505050565b60006020828403121561349c57600080fd5b8135611014816131fb565b6000806000606084860312156134bc57600080fd5b83356134c7816131fb565b925060208401356134d7816131fb565b929592945050506040919091013590565b803563ffffffff811681146134fc57600080fd5b919050565b60006020828403121561351357600080fd5b611014826134e8565b6000806040838503121561352f57600080fd5b6132a5836134e8565b8015158114611dd557600080fd5b6000806040838503121561355957600080fd5b82356001600160401b0381111561356f57600080fd5b61357b858286016132b3565b925050602083013561358c81613538565b809150509250929050565b815181526020808301519082015260408101610d8a565b600080604083850312156135c157600080fd5b82356001600160401b03808211156135d857600080fd5b6135e4868387016131a5565b935060208501359150808211156135fa57600080fd5b50613607858286016131a5565b9150509250929050565b803561ffff811681146134fc57600080fd5b60006020828403121561363557600080fd5b61101482613611565b6000806040838503121561365157600080fd5b61365a836134e8565b915061366860208401613611565b90509250929050565b60008060006060848603121561368657600080fd5b61368f846134e8565b925061369d60208501613611565b9150604084013561327c81613538565b60008060008060a085870312156136c357600080fd5b6136cd8686613398565b935060608501356001600160401b038111156136e857600080fd5b6136f4878288016133aa565b9094509250506080850135613708816131fb565b939692955090935050565b60008083601f84011261372557600080fd5b5081356001600160401b0381111561373c57600080fd5b6020830191508360208260051b8501011115612e1457600080fd5b6000806020838503121561376a57600080fd5b82356001600160401b0381111561378057600080fd5b61378c85828601613713565b90969095509350505050565b600080600080606085870312156137ae57600080fd5b6137b7856134e8565b93506137c560208601613611565b925060408501356001600160401b038111156137e057600080fd5b6137ec878288016133aa565b95989497509550505050565b6000806000838503608081121561380e57600080fd5b84356001600160401b0381111561382457600080fd5b613830878288016132b3565b9450506040601f198201121561384557600080fd5b50602084019150606084013561327c816131fb565b600060c082019050835182526001600160401b0360208501511660208301526040840151613895604084018280518252602090810151910152565b5082516080830152602083015160a0830152611014565b600080604083850312156138bf57600080fd5b82356138ca816131fb565b9150602083013561358c816131fb565b6000606082840312156138ec57600080fd5b6110148383613398565b600181811c9082168061390a57607f821691505b6020821081036132c557634e487b7160e01b600052602260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b8082028115828204841417610d8a57610d8a61392a565b60008261397457634e487b7160e01b600052601260045260246000fd5b500490565b634e487b7160e01b600052603260045260246000fd5b60008235605e198336030181126139a557600080fd5b9190910192915050565b6000808335601e198436030181126139c657600080fd5b8301803591506001600160401b038211156139e057600080fd5b602001915036819003821315612e1457600080fd5b601f821115611e3a576000816000526020600020601f850160051c81016020861015613a1e5750805b601f850160051c820191505b81811015613a3d57828155600101613a2a565b505050505050565b6001600160401b03831115613a5c57613a5c613110565b613a7083613a6a83546138f6565b836139f5565b6000601f841160018114613aa45760008515613a8c5750838201355b600019600387901b1c1916600186901b178355611bec565b600083815260209020601f19861690835b82811015613ad55786850135825560209485019460019092019101613ab5565b5086821015613af25760001960f88860031b161c19848701351681555b505060018560011b0183555050505050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b60208082528181018390526000906040808401600586901b8501820187855b88811015613c0357878303603f190184528135368b9003605e19018112613b7257600080fd5b8a01606063ffffffff613b84836134e8565b16855261ffff613b95898401613611565b168886015286820135601e19833603018112613bb057600080fd5b9091018781019190356001600160401b03811115613bcd57600080fd5b803603831315613bdc57600080fd5b8188870152613bee8287018285613b04565b96890196955050509186019150600101613b4c565b509098975050505050505050565b60008085851115613c2157600080fd5b83861115613c2e57600080fd5b5050820193919092039150565b60008451613c4d8184602089016130ad565b8201838582376000930192835250909392505050565b602081526000611356602083018486613b04565b6000823561013e198336030181126139a557600080fd5b6001600160401b0381168114611dd557600080fd5b63ffffffff613cb1896134e8565b1681526020880135602082015260006040890135613cce81613c8e565b6001600160401b03811660408401525087606083015260e06080830152613cf960e083018789613b04565b6001600160a01b03861660a084015282810360c0840152613d1b818587613b04565b9a9950505050505050505050565b600060208284031215613d3b57600080fd5b81516001600160401b03811115613d5157600080fd5b8201601f81018413613d6257600080fd5b8051613d706131c48261317e565b818152856020838501011115613d8557600080fd5b6123758260208301602086016130ad565b600060208284031215613da857600080fd5b813561101481613c8e565b60018060a01b038516815283602082015261ffff831660408201526080606082015260006110e560808301846130d1565b604081526000613df760408301856130d1565b828103602084015261237581856130d1565b600060208284031215613e1b57600080fd5b815161101481613538565b6040815263ffffffff8351166040820152602083015160608201526000604084015160a06080840152613e5c60e08401826130d1565b90506060850151603f198483030160a0850152613e7982826130d1565b60809690960151151560c08501525050506001600160a01b039190911660209091015290565b600060408284031215613eb157600080fd5b613eb9613126565b9050815181526020820151602082015292915050565b600060408284031215613ee157600080fd5b6110148383613e9f565b6001600160f01b03198135818116916002851015613f135780818660020360031b1b83161692505b505092915050565b600060408284031215613f2d57600080fd5b613f35613126565b82358152602083013560208201528091505092915050565b80356020831015610d8a57600019602084900360031b1b1692915050565b6001600160c01b03198135818116916008851015613f135760089490940360031b84901b1690921692915050565b6001600160401b0360c01b8560c01b16815263ffffffff60e01b8460e01b16600882015282600c82015260008251613fd881602c8501602087016130ad565b91909101602c0195945050505050565b600060018201613ffa57613ffa61392a565b5060010190565b8481526001600160401b0360c01b8460c01b166020820152826028820152600082516140348160488501602087016130ad565b9190910160480195945050505050565b81516001600160401b0381111561405d5761405d613110565b6140718161406b84546138f6565b846139f5565b602080601f8311600181146140a6576000841561408e5750858301515b600019600386901b1c1916600185901b178555613a3d565b600085815260208120601f198616915b828110156140d5578886015182559484019460019091019084016140b6565b50858210156140f35787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b81810381811115610d8a57610d8a61392a565b60006080828403121561412857600080fd5b604051606081018181106001600160401b038211171561414a5761414a613110565b60405282518152602083015161415f81613c8e565b60208201526141718460408501613e9f565b60408201529392505050565b80820180821115610d8a57610d8a61392a565b6000602082840312156141a257600080fd5b8151611014816131fb56fe52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace000cb173d183337e25fab6cb85705c15aad6a58cb1d552ed71b9bc628c8a3de80072ab1bc1039b79dc4724ffca13de82c96834302d3c7e0d4252232d4b2dd8f900a26469706673582212201f248ed02b808c1ae29a9f9f54f2f17eb576e8abbaff0b6b42bafc474f592bed64736f6c634300081600330000000000000000000000006f475642a6e85809b1c36fa62763669b1b48dd5b
Deployed Bytecode
0x6080604052600436106103765760003560e01c80636fc1b31e116101d1578063b98bd07011610102578063d045a0dc116100a0578063e43252d71161006f578063e43252d714610b3c578063f2fde38b14610b5c578063fc0c546a14610714578063ff7bd03d14610b7c57600080fd5b8063d045a0dc14610ad3578063d424388514610ae6578063dd62ed3e14610b06578063e1a4521814610b2657600080fd5b8063bcae25a4116100dc578063bcae25a414610a59578063bd815db014610a7f578063c7c7f5b314610a92578063ca5eb5e114610ab357600080fd5b8063b98bd070146109d9578063bb0b6a53146109f9578063bc70b35414610a3957600080fd5b80638ab1d6811161016f578063963efcaa11610149578063963efcaa1461095c5780639f68b96414610990578063a9059cbb146109a4578063b731ea0a146109c457600080fd5b80638ab1d681146109125780638da5cb5b1461093257806395d89b411461094757600080fd5b80637d25a05e116101ab5780637d25a05e1461088857806382413eac146108c3578063857749b01461056b5780638705fcd4146108f257600080fd5b80636fc1b31e1461083357806370a0823114610853578063715018a61461087357600080fd5b80633194c180116102ab57806352ae2879116102495780635bf9c226116102235780635bf9c2261461078b5780635e280f11146107ab57806360b71d4e146107df5780636db7bcdb1461081357600080fd5b806352ae2879146107145780635535d461146107275780635a0dfe4d1461074757600080fd5b80633b6f743b116102855780633b6f743b146106895780633b7d72b4146106b65780634488b652146106d65780634e7ceacb146106f657600080fd5b80633194c180146105875780633400288b146106305780633af32abf1461065057600080fd5b8063156a0d0f1161031857806318160ddd116102f257806318160ddd146104f85780631f5e13341461053657806323b872dd1461054b578063313ce5671461056b57600080fd5b8063156a0d0f1461048f578063164e68de146104b657806317442b70146104d657600080fd5b80630d35b415116103545780630d35b415146103f8578063111ecdad1461042757806313137d6514610454578063134d4f251461046757600080fd5b806306fdde031461037b578063077f224a146103a6578063095ea7b3146103c8575b600080fd5b34801561038757600080fd5b50610390610b9c565b60405161039d91906130fd565b60405180910390f35b3480156103b257600080fd5b506103c66103c1366004613210565b610c5f565b005b3480156103d457600080fd5b506103e86103e3366004613287565b610d76565b604051901515815260200161039d565b34801561040457600080fd5b506104186104133660046132cb565b610d90565b60405161039d939291906132ff565b34801561043357600080fd5b5061043c610e5c565b6040516001600160a01b03909116815260200161039d565b6103c66104623660046133eb565b610e91565b34801561047357600080fd5b5061047c600281565b60405161ffff909116815260200161039d565b34801561049b57600080fd5b506040805162b9270b60e21b8152600160208201520161039d565b3480156104c257600080fd5b506103c66104d136600461348a565b610f51565b3480156104e257600080fd5b506040805160018152600260208201520161039d565b34801561050457600080fd5b507f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace02545b60405190815260200161039d565b34801561054257600080fd5b5061047c600181565b34801561055757600080fd5b506103e86105663660046134a7565b610ff5565b34801561057757600080fd5b506040516006815260200161039d565b34801561059357600080fd5b5061060f6105a2366004613501565b6040805180820182526000808252602091820181905263ffffffff9390931683527f0cb173d183337e25fab6cb85705c15aad6a58cb1d552ed71b9bc628c8a3de80181529181902081518083019092525461ffff8116825262010000900460ff1615159181019190915290565b60408051825161ffff1681526020928301511515928101929092520161039d565b34801561063c57600080fd5b506103c661064b36600461351c565b61101b565b34801561065c57600080fd5b506103e861066b36600461348a565b6001600160a01b031660009081526001602052604090205460ff1690565b34801561069557600080fd5b506106a96106a4366004613546565b611088565b60405161039d9190613597565b3480156106c257600080fd5b506103c66106d13660046135ae565b6110ef565b3480156106e257600080fd5b506103c66106f1366004613623565b6111b9565b34801561070257600080fd5b506000546001600160a01b031661043c565b34801561072057600080fd5b503061043c565b34801561073357600080fd5b5061039061074236600461363e565b611240565b34801561075357600080fd5b506103e861076236600461351c565b63ffffffff9190911660009081526000805160206141ee83398151915260205260409020541490565b34801561079757600080fd5b506105286107a636600461351c565b61131b565b3480156107b757600080fd5b5061043c7f0000000000000000000000006f475642a6e85809b1c36fa62763669b1b48dd5b81565b3480156107eb57600080fd5b507f68f1d0d99488c60d21eadee2cca13b58661d56fbcb4e4464d6fc8def1b34220054610528565b34801561081f57600080fd5b506103c661082e366004613671565b61135e565b34801561083f57600080fd5b506103c661084e36600461348a565b611429565b34801561085f57600080fd5b5061052861086e36600461348a565b61149d565b34801561087f57600080fd5b506103c66114c5565b34801561089457600080fd5b506108ab6108a336600461351c565b600092915050565b6040516001600160401b03909116815260200161039d565b3480156108cf57600080fd5b506103e86108de3660046136ad565b6001600160a01b0381163014949350505050565b3480156108fe57600080fd5b506103c661090d36600461348a565b6114d9565b34801561091e57600080fd5b506103c661092d36600461348a565b611535565b34801561093e57600080fd5b5061043c6115ed565b34801561095357600080fd5b50610390611616565b34801561096857600080fd5b506105287f000000000000000000000000000000000000000000000000000000000000000181565b34801561099c57600080fd5b5060006103e8565b3480156109b057600080fd5b506103e86109bf366004613287565b611655565b3480156109d057600080fd5b5061043c611663565b3480156109e557600080fd5b506103c66109f4366004613757565b61168c565b348015610a0557600080fd5b50610528610a14366004613501565b63ffffffff1660009081526000805160206141ee833981519152602052604090205490565b348015610a4557600080fd5b50610390610a54366004613798565b61180d565b348015610a6557600080fd5b506000805160206141ce8339815191525461ffff1661047c565b6103c6610a8d366004613757565b6119a3565b610aa5610aa03660046137f8565b611b3a565b60405161039d92919061385a565b348015610abf57600080fd5b506103c6610ace36600461348a565b611b6d565b6103c6610ae13660046133eb565b611bf3565b348015610af257600080fd5b506103c6610b0136600461348a565b611c22565b348015610b1257600080fd5b50610528610b213660046138ac565b611c96565b348015610b3257600080fd5b5061047c61271081565b348015610b4857600080fd5b506103c6610b5736600461348a565b611ce0565b348015610b6857600080fd5b506103c6610b7736600461348a565b611d9a565b348015610b8857600080fd5b506103e8610b973660046138da565b611dd8565b7f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace0380546060916000805160206141ae83398151915291610bdb906138f6565b80601f0160208091040260200160405190810160405280929190818152602001828054610c07906138f6565b8015610c545780601f10610c2957610100808354040283529160200191610c54565b820191906000526020600020905b815481529060010190602001808311610c3757829003601f168201915b505050505091505090565b6000610c69611df6565b805490915060ff600160401b82041615906001600160401b0316600081158015610c905750825b90506000826001600160401b03166001148015610cac5750303b155b905081158015610cba575080155b15610cd85760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff191660011785558315610d0257845460ff60401b1916600160401b1785555b610d0d888888611e1f565b610d1686611e3f565b600080546001600160a01b03191690558315610d6c57845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b5050505050505050565b600033610d84818585611e50565b60019150505b92915050565b60408051808201909152600080825260208201526060610dc3604051806040016040528060008152602001600081525090565b6040805180820182526000808252600019602080840182905284518381529081019094529195509182610e19565b604080518082019091526000815260606020820152815260200190600190039081610df15790505b509350600080610e3e604089013560608a0135610e3960208c018c613501565b611e5d565b60408051808201909152918252602082015296989597505050505050565b6000807f41db8a78b0206aba5c54bcbfc2bda0d84082a84eb88e680379a57b9e9f653c005b546001600160a01b031692915050565b7f0000000000000000000000006f475642a6e85809b1c36fa62763669b1b48dd5b6001600160a01b03163314610ee1576040516391ac5e4f60e01b81523360048201526024015b60405180910390fd5b60208701803590610efb90610ef6908a613501565b611eae565b14610f3957610f0d6020880188613501565b60405163309afaf360e21b815263ffffffff909116600482015260208801356024820152604401610ed8565b610f4887878787878787611ef9565b50505050505050565b610f59612060565b7f68f1d0d99488c60d21eadee2cca13b58661d56fbcb4e4464d6fc8def1b34220080546000819003610f9e57604051630d00db4d60e31b815260040160405180910390fd5b60008255610fad308483612092565b826001600160a01b03167f78473f3f373f7673597f4f0fa5873cb4d375fea6d4339ad6b56dbd411513cb3f82604051610fe891815260200190565b60405180910390a2505050565b6000336110038582856120f1565b61100e858585612092565b60019150505b9392505050565b611023612060565b63ffffffff821660008181526000805160206141ee833981519152602081815260409283902085905582519384528301849052917f238399d427b947898edb290f5ff0f9109849b1c3ba196a42e35f00c50a54b98b91015b60405180910390a1505050565b604080518082019091526000808252602082015260006110b860408501356060860135610e396020880188613501565b9150506000806110c88684612158565b90925090506110e56110dd6020880188613501565b83838861229d565b9695505050505050565b600260006110fb611df6565b8054909150600160401b900460ff1680611122575080546001600160401b03808416911610155b156111405760405163f92ee8a960e01b815260040160405180910390fd5b805468ffffffffffffffffff19166001600160401b03831617600160401b17815561116b848461237e565b805460ff60401b191681556040516001600160401b03831681527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2906020015b60405180910390a150505050565b6111c1612060565b61271061ffff821611156111e85760405163c6cc5d7f60e01b815260040160405180910390fd5b6000805160206141ce833981519152805461ffff191661ffff831690811782556040519081527f9283ddc0c2b59320e00b0ae4a992b110df098c38e3b6ea1d92fe7a6d3504be9b906020015b60405180910390a15050565b63ffffffff821660009081527f8d2bda5d9f6ffb5796910376005392955773acee5548d0fcdb10e7c264ea00006020818152604080842061ffff8616855290915290912080546060929190611294906138f6565b80601f01602080910402602001604051908101604052809291908181526020018280546112c0906138f6565b801561130d5780601f106112e25761010080835404028352916020019161130d565b820191906000526020600020905b8154815290600101906020018083116112f057829003601f168201915b505050505091505092915050565b60008061132784612394565b905061ffff8116156113535761271061134461ffff831685613940565b61134e9190613957565b611356565b60005b949350505050565b611366612060565b61271061ffff8316111561138d5760405163c6cc5d7f60e01b815260040160405180910390fd5b60006000805160206141ce83398151915260408051808201825261ffff868116808352861515602080850182815263ffffffff8c16600081815260018a0184528890209651875492511515620100000262ffffff1990931696169590951717909455845192835292820152918201529091507f56f0bca120766dba5aeeb89a1cf629c3495dc497c82f426d4e4d58c54b72764c906060016111ab565b611431612060565b7f41db8a78b0206aba5c54bcbfc2bda0d84082a84eb88e680379a57b9e9f653c0080546001600160a01b0319166001600160a01b03831690811782556040519081527ff0be4f1e87349231d80c36b33f9e8639658eeaf474014dee15a3e6a4d441419790602001611234565b6001600160a01b031660009081526000805160206141ae833981519152602052604090205490565b6114cd612060565b6114d76000612413565b565b6114e1612060565b600080546001600160a01b0319166001600160a01b0383169081179091556040519081527f0cc4d0c9af0c184a6ba4203a2d8f4a6843759ea43f751b50f516f6fb4241d9df9060200160405180910390a150565b61153d612060565b6001600160a01b03811660009081526001602052604090205460ff166115975760405162461bcd60e51b815260206004820152600f60248201526e139bdd081dda1a5d195b1a5cdd1959608a1b6044820152606401610ed8565b6001600160a01b0381166000818152600160209081526040808320805460ff19169055519182527ff93f9a76c1bf3444d22400a00cb9fe990e6abe9dbb333fda48859cfee864543d91015b60405180910390a250565b6000807f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300610e81565b7f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace0480546060916000805160206141ae83398151915291610bdb906138f6565b600033610d84818585612092565b6000807fefb041d771d6daaa55702fff6eb740d63ba559a75d2d1d3e151c78ff2480b600610e81565b611694612060565b7f8d2bda5d9f6ffb5796910376005392955773acee5548d0fcdb10e7c264ea000060005b828110156117db576116fa8484838181106116d5576116d5613979565b90506020028101906116e7919061398f565b6116f59060408101906139af565b612484565b83838281811061170c5761170c613979565b905060200281019061171e919061398f565b61172c9060408101906139af565b83600087878681811061174157611741613979565b9050602002810190611753919061398f565b611761906020810190613501565b63ffffffff1663ffffffff168152602001908152602001600020600087878681811061178f5761178f613979565b90506020028101906117a1919061398f565b6117b2906040810190602001613623565b61ffff1681526020810191909152604001600020916117d2919083613a45565b506001016116b8565b507fbe4864a8e820971c0247f5992e2da559595f7bf076a21cb5928d443d2a13b674838360405161107b929190613b2d565b63ffffffff841660009081527f8d2bda5d9f6ffb5796910376005392955773acee5548d0fcdb10e7c264ea00006020818152604080842061ffff88168552909152822080546060939190611860906138f6565b80601f016020809104026020016040519081016040528092919081815260200182805461188c906138f6565b80156118d95780601f106118ae576101008083540402835291602001916118d9565b820191906000526020600020905b8154815290600101906020018083116118bc57829003601f168201915b50505050509050805160000361192a5784848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550611356945050505050565b600084900361193c5791506113569050565b600284106119865761194e8585612484565b8061195c8560028189613c11565b60405160200161196e93929190613c3b565b60405160208183030381529060405292505050611356565b8484604051639a6d49cd60e01b8152600401610ed8929190613c63565b60005b81811015611ab957368383838181106119c1576119c1613979565b90506020028101906119d39190613c77565b9050611a136119e56020830183613501565b602083013563ffffffff9190911660009081526000805160206141ee83398151915260205260409020541490565b611a1d5750611ab1565b3063d045a0dc60c08301358360a0810135611a3c6101008301836139af565b611a4d610100890160e08a0161348a565b611a5b6101208a018a6139af565b6040518963ffffffff1660e01b8152600401611a7d9796959493929190613ca3565b6000604051808303818588803b158015611a9657600080fd5b505af1158015611aaa573d6000803e3d6000fd5b5050505050505b6001016119a6565b50336001600160a01b0316638e9e70996040518163ffffffff1660e01b8152600401600060405180830381865afa158015611af8573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611b209190810190613d29565b604051638351eea760e01b8152600401610ed891906130fd565b611b42613066565b6040805180820190915260008082526020820152611b618585856124c6565b91509150935093915050565b611b75612060565b60405163ca5eb5e160e01b81526001600160a01b0382811660048301527f0000000000000000000000006f475642a6e85809b1c36fa62763669b1b48dd5b169063ca5eb5e190602401600060405180830381600087803b158015611bd857600080fd5b505af1158015611bec573d6000803e3d6000fd5b5050505050565b333014611c135760405163029a949d60e31b815260040160405180910390fd5b610f4887878787878787610f39565b611c2a612060565b7fefb041d771d6daaa55702fff6eb740d63ba559a75d2d1d3e151c78ff2480b60080546001600160a01b0319166001600160a01b03831690811782556040519081527fd48d879cef83a1c0bdda516f27b13ddb1b3f8bbac1c9e1511bb2a659c242776090602001611234565b6001600160a01b0391821660009081527f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace016020908152604080832093909416825291909152205490565b611ce8612060565b6001600160a01b03811660009081526001602052604090205460ff1615611d475760405162461bcd60e51b8152602060048201526013602482015272105b1c9958591e481dda1a5d195b1a5cdd1959606a1b6044820152606401610ed8565b6001600160a01b038116600081815260016020818152604092839020805460ff19168317905591519081527ff93f9a76c1bf3444d22400a00cb9fe990e6abe9dbb333fda48859cfee864543d91016115e2565b611da2612060565b6001600160a01b038116611dcc57604051631e4fbdf760e01b815260006004820152602401610ed8565b611dd581612413565b50565b600060208201803590611def90610a149085613501565b1492915050565b6000807ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00610d8a565b611e276125c1565b611e31838361237e565b611e3a816125e6565b505050565b611e476125c1565b611dd581612607565b611e3a838383600161260f565b82600080611e6b848461131b565b9050611e788187036126f6565b915084821015611ea5576040516371c4efed60e01b81526004810183905260248101869052604401610ed8565b50935093915050565b63ffffffff811660009081526000805160206141ee83398151915260208190526040822054806110145760405163f6ff4fb760e01b815263ffffffff85166004820152602401610ed8565b6000611f0b611f08878761272d565b90565b90506000611f3782611f25611f208a8a612745565b612768565b611f3260208d018d613501565b61279d565b90506028861115611ffe576000611f74611f5760608c0160408d01613d96565b611f6460208d018d613501565b84611f6f8c8c6127c5565b612810565b604051633e5ac80960e11b81529091506001600160a01b037f0000000000000000000000006f475642a6e85809b1c36fa62763669b1b48dd5b1690637cb5901290611fca9086908d906000908790600401613db3565b600060405180830381600087803b158015611fe457600080fd5b505af1158015611ff8573d6000803e3d6000fd5b50505050505b6001600160a01b038216887fefed6d3500546b29533b128a29e3a94d70788727f0507505ac12eaf2e578fd9c61203760208d018d613501565b6040805163ffffffff9092168252602082018690520160405180910390a3505050505050505050565b336120696115ed565b6001600160a01b0316146114d75760405163118cdaa760e01b8152336004820152602401610ed8565b6001600160a01b0383166120bc57604051634b637e8f60e11b815260006004820152602401610ed8565b6001600160a01b0382166120e65760405163ec442f0560e01b815260006004820152602401610ed8565b611e3a838383612842565b60006120fd8484611c96565b9050600019811015612152578181101561214357604051637dc7a0d960e11b81526001600160a01b03841660048201526024810182905260448101839052606401610ed8565b6121528484848403600061260f565b50505050565b60608060006121b5856020013561216e866128d0565b61217b60a08901896139af565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061292a92505050565b90935090506000816121c85760016121cb565b60025b90506121eb6121dd6020880188613501565b82610a5460808a018a6139af565b7f41db8a78b0206aba5c54bcbfc2bda0d84082a84eb88e680379a57b9e9f653c008054919450906001600160a01b031680156122925760405163043a78eb60e01b81526001600160a01b0382169063043a78eb9061224f9089908990600401613de4565b602060405180830381865afa15801561226c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122909190613e09565b505b505050509250929050565b60408051808201909152600080825260208201527f0000000000000000000000006f475642a6e85809b1c36fa62763669b1b48dd5b6001600160a01b031663ddc28c586040518060a001604052808863ffffffff16815260200161230089611eae565b8152602001878152602001868152602001851515815250306040518363ffffffff1660e01b8152600401612335929190613e26565b6040805180830381865afa158015612351573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123759190613ecf565b95945050505050565b6123866125c1565b61239082826129a4565b5050565b63ffffffff811660009081527f0cb173d183337e25fab6cb85705c15aad6a58cb1d552ed71b9bc628c8a3de8016020908152604080832081518083019092525461ffff8116825262010000900460ff1615159181018290526000805160206141ce8339815191529161240b57815461ffff16611356565b519392505050565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930080546001600160a01b031981166001600160a01b03848116918217845560405192169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3505050565b60006124936002828486613c11565b61249c91613eeb565b60f01c905060038114611e3a578282604051639a6d49cd60e01b8152600401610ed8929190613c63565b6124ce613066565b604080518082019091526000808252602082015260008061250533604089013560608a013561250060208c018c613501565b6129f5565b915091506000806125168984612158565b909250905061254261252b60208b018b613501565b838361253c368d90038d018d613f1b565b8b612b29565b60408051808201909152858152602080820186905282519298509096503391907f85496b760a4b7f8d66384b9df21b381f5d1b1e79f229a47aaf4c232edc2fe59a90612590908d018d613501565b6040805163ffffffff909216825260208201899052810187905260600160405180910390a350505050935093915050565b6125c9612c34565b6114d757604051631afcd79f60e31b815260040160405180910390fd5b6125ee6125c1565b6125f781612c4e565b6125ff612c5f565b611dd5612c5f565b611da26125c1565b6000805160206141ae8339815191526001600160a01b0385166126485760405163e602df0560e01b815260006004820152602401610ed8565b6001600160a01b03841661267257604051634a1406b160e11b815260006004820152602401610ed8565b6001600160a01b03808616600090815260018301602090815260408083209388168352929052208390558115611bec57836001600160a01b0316856001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925856040516126e791815260200190565b60405180910390a35050505050565b60007f00000000000000000000000000000000000000000000000000000000000000016127238184613957565b610d8a9190613940565b600061273c6020828486613c11565b61101491613f4d565b6000612755602860208486613c11565b61275e91613f6b565b60c01c9392505050565b6000610d8a7f00000000000000000000000000000000000000000000000000000000000000016001600160401b038416613940565b60006001600160a01b0384166127b35761dead93505b6127bd8484612c67565b509092915050565b60606127d48260288186613c11565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929695505050505050565b6060848484846040516020016128299493929190613f99565b6040516020818303038152906040529050949350505050565b61284d838383612c9d565b6002805490600061285d83613fe8565b9190505550600254826001600160a01b0316846001600160a01b03167f6d16356255ebed8e5918262476684aaa5f8054befd93154494221a6026157aa5846128a48861149d565b6128ad8861149d565b6040805193845260208401929092529082015260600160405180910390a4505050565b6000806128fd7f000000000000000000000000000000000000000000000000000000000000000184613957565b90506001600160401b03811115610d8a5760405163e2ce941360e01b815260048101829052602401610ed8565b805160609015158061297357848460405160200161295f92919091825260c01b6001600160c01b031916602082015260280190565b60405160208183030381529060405261299a565b8484338560405160200161298a9493929190614001565b6040516020818303038152906040525b9150935093915050565b6129ac6125c1565b6000805160206141ae8339815191527f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace036129e68482614044565b50600481016121528382614044565b6001600160a01b038416600090815260016020526040812054819060ff16612a2757612a22858585611e5d565b612a31565b612a318585612ddb565b909250905081811115612aa15760405162461bcd60e51b815260206004820152603260248201527f416d6f756e742072656365697665642063616e6e6f74206265206772656174656044820152711c881d1a185b88185b5bdd5b9d081cd95b9d60721b6064820152608401610ed8565b6000612aad8284614103565b90508015612b15576000546001600160a01b0316612afd577f68f1d0d99488c60d21eadee2cca13b58661d56fbcb4e4464d6fc8def1b342200805482018155612af7883084612092565b50612b15565b600054612b159088906001600160a01b031683612092565b612b1f8783612e1b565b5094509492505050565b612b31613066565b6000612b408460000151612e51565b602085015190915015612b5a57612b5a8460200151612e79565b7f0000000000000000000000006f475642a6e85809b1c36fa62763669b1b48dd5b6001600160a01b0316632637a450826040518060a001604052808b63ffffffff168152602001612baa8c611eae565b81526020018a815260200189815260200160008960200151111515815250866040518463ffffffff1660e01b8152600401612be6929190613e26565b60806040518083038185885af1158015612c04573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190612c299190614116565b979650505050505050565b6000612c3e611df6565b54600160401b900460ff16919050565b612c566125c1565b6125f781612f5b565b6114d76125c1565b6001600160a01b038216612c915760405163ec442f0560e01b815260006004820152602401610ed8565b61239060008383612842565b6000805160206141ae8339815191526001600160a01b038416612cd95781816002016000828254612cce919061417d565b90915550612d4b9050565b6001600160a01b03841660009081526020829052604090205482811015612d2c5760405163391434e360e21b81526001600160a01b03861660048201526024810182905260448101849052606401610ed8565b6001600160a01b03851660009081526020839052604090209083900390555b6001600160a01b038316612d69576002810180548390039055612d88565b6001600160a01b03831660009081526020829052604090208054830190555b826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051612dcd91815260200190565b60405180910390a350505050565b816000612de7826126f6565b905082811015612e14576040516371c4efed60e01b81526004810182905260248101849052604401610ed8565b9250929050565b6001600160a01b038216612e4557604051634b637e8f60e11b815260006004820152602401610ed8565b61239082600083612842565b6000813414612e75576040516304fb820960e51b8152346004820152602401610ed8565b5090565b60007f0000000000000000000000006f475642a6e85809b1c36fa62763669b1b48dd5b6001600160a01b031663e4fe1d946040518163ffffffff1660e01b8152600401602060405180830381865afa158015612ed9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612efd9190614190565b90506001600160a01b038116612f26576040516329b99a9560e11b815260040160405180910390fd5b6123906001600160a01b038216337f0000000000000000000000006f475642a6e85809b1c36fa62763669b1b48dd5b85612f6c565b612f636125c1565b611dd581612fc6565b604080516001600160a01b0385811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b179052612152908590612ff5565b612fce6125c1565b6001600160a01b038116611b7557604051632d618d8160e21b815260040160405180910390fd5b600080602060008451602086016000885af180613018576040513d6000823e3d81fd5b50506000513d9150811561303057806001141561303d565b6001600160a01b0384163b155b1561215257604051635274afe760e01b81526001600160a01b0385166004820152602401610ed8565b60405180606001604052806000801916815260200160006001600160401b031681526020016130a8604051806040016040528060008152602001600081525090565b905290565b60005b838110156130c85781810151838201526020016130b0565b50506000910152565b600081518084526130e98160208601602086016130ad565b601f01601f19169290920160200192915050565b60208152600061101460208301846130d1565b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b038111828210171561314857613148613110565b60405290565b604051601f8201601f191681016001600160401b038111828210171561317657613176613110565b604052919050565b60006001600160401b0382111561319757613197613110565b50601f01601f191660200190565b600082601f8301126131b657600080fd5b81356131c96131c48261317e565b61314e565b8181528460208386010111156131de57600080fd5b816020850160208301376000918101602001919091529392505050565b6001600160a01b0381168114611dd557600080fd5b60008060006060848603121561322557600080fd5b83356001600160401b038082111561323c57600080fd5b613248878388016131a5565b9450602086013591508082111561325e57600080fd5b5061326b868287016131a5565b925050604084013561327c816131fb565b809150509250925092565b6000806040838503121561329a57600080fd5b82356132a5816131fb565b946020939093013593505050565b600060e082840312156132c557600080fd5b50919050565b6000602082840312156132dd57600080fd5b81356001600160401b038111156132f357600080fd5b611356848285016132b3565b8351815260208085015190820152600060a08201604060a0604085015281865180845260c08601915060c08160051b8701019350602080890160005b8381101561337a5788870360bf19018552815180518852830151838801879052613367878901826130d1565b975050938201939082019060010161333b565b50508751606088015250505060208501516080850152509050611356565b6000606082840312156132c557600080fd5b60008083601f8401126133bc57600080fd5b5081356001600160401b038111156133d357600080fd5b602083019150836020828501011115612e1457600080fd5b600080600080600080600060e0888a03121561340657600080fd5b6134108989613398565b96506060880135955060808801356001600160401b038082111561343357600080fd5b61343f8b838c016133aa565b909750955060a08a01359150613454826131fb565b90935060c0890135908082111561346a57600080fd5b506134778a828b016133aa565b989b979a50959850939692959293505050565b60006020828403121561349c57600080fd5b8135611014816131fb565b6000806000606084860312156134bc57600080fd5b83356134c7816131fb565b925060208401356134d7816131fb565b929592945050506040919091013590565b803563ffffffff811681146134fc57600080fd5b919050565b60006020828403121561351357600080fd5b611014826134e8565b6000806040838503121561352f57600080fd5b6132a5836134e8565b8015158114611dd557600080fd5b6000806040838503121561355957600080fd5b82356001600160401b0381111561356f57600080fd5b61357b858286016132b3565b925050602083013561358c81613538565b809150509250929050565b815181526020808301519082015260408101610d8a565b600080604083850312156135c157600080fd5b82356001600160401b03808211156135d857600080fd5b6135e4868387016131a5565b935060208501359150808211156135fa57600080fd5b50613607858286016131a5565b9150509250929050565b803561ffff811681146134fc57600080fd5b60006020828403121561363557600080fd5b61101482613611565b6000806040838503121561365157600080fd5b61365a836134e8565b915061366860208401613611565b90509250929050565b60008060006060848603121561368657600080fd5b61368f846134e8565b925061369d60208501613611565b9150604084013561327c81613538565b60008060008060a085870312156136c357600080fd5b6136cd8686613398565b935060608501356001600160401b038111156136e857600080fd5b6136f4878288016133aa565b9094509250506080850135613708816131fb565b939692955090935050565b60008083601f84011261372557600080fd5b5081356001600160401b0381111561373c57600080fd5b6020830191508360208260051b8501011115612e1457600080fd5b6000806020838503121561376a57600080fd5b82356001600160401b0381111561378057600080fd5b61378c85828601613713565b90969095509350505050565b600080600080606085870312156137ae57600080fd5b6137b7856134e8565b93506137c560208601613611565b925060408501356001600160401b038111156137e057600080fd5b6137ec878288016133aa565b95989497509550505050565b6000806000838503608081121561380e57600080fd5b84356001600160401b0381111561382457600080fd5b613830878288016132b3565b9450506040601f198201121561384557600080fd5b50602084019150606084013561327c816131fb565b600060c082019050835182526001600160401b0360208501511660208301526040840151613895604084018280518252602090810151910152565b5082516080830152602083015160a0830152611014565b600080604083850312156138bf57600080fd5b82356138ca816131fb565b9150602083013561358c816131fb565b6000606082840312156138ec57600080fd5b6110148383613398565b600181811c9082168061390a57607f821691505b6020821081036132c557634e487b7160e01b600052602260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b8082028115828204841417610d8a57610d8a61392a565b60008261397457634e487b7160e01b600052601260045260246000fd5b500490565b634e487b7160e01b600052603260045260246000fd5b60008235605e198336030181126139a557600080fd5b9190910192915050565b6000808335601e198436030181126139c657600080fd5b8301803591506001600160401b038211156139e057600080fd5b602001915036819003821315612e1457600080fd5b601f821115611e3a576000816000526020600020601f850160051c81016020861015613a1e5750805b601f850160051c820191505b81811015613a3d57828155600101613a2a565b505050505050565b6001600160401b03831115613a5c57613a5c613110565b613a7083613a6a83546138f6565b836139f5565b6000601f841160018114613aa45760008515613a8c5750838201355b600019600387901b1c1916600186901b178355611bec565b600083815260209020601f19861690835b82811015613ad55786850135825560209485019460019092019101613ab5565b5086821015613af25760001960f88860031b161c19848701351681555b505060018560011b0183555050505050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b60208082528181018390526000906040808401600586901b8501820187855b88811015613c0357878303603f190184528135368b9003605e19018112613b7257600080fd5b8a01606063ffffffff613b84836134e8565b16855261ffff613b95898401613611565b168886015286820135601e19833603018112613bb057600080fd5b9091018781019190356001600160401b03811115613bcd57600080fd5b803603831315613bdc57600080fd5b8188870152613bee8287018285613b04565b96890196955050509186019150600101613b4c565b509098975050505050505050565b60008085851115613c2157600080fd5b83861115613c2e57600080fd5b5050820193919092039150565b60008451613c4d8184602089016130ad565b8201838582376000930192835250909392505050565b602081526000611356602083018486613b04565b6000823561013e198336030181126139a557600080fd5b6001600160401b0381168114611dd557600080fd5b63ffffffff613cb1896134e8565b1681526020880135602082015260006040890135613cce81613c8e565b6001600160401b03811660408401525087606083015260e06080830152613cf960e083018789613b04565b6001600160a01b03861660a084015282810360c0840152613d1b818587613b04565b9a9950505050505050505050565b600060208284031215613d3b57600080fd5b81516001600160401b03811115613d5157600080fd5b8201601f81018413613d6257600080fd5b8051613d706131c48261317e565b818152856020838501011115613d8557600080fd5b6123758260208301602086016130ad565b600060208284031215613da857600080fd5b813561101481613c8e565b60018060a01b038516815283602082015261ffff831660408201526080606082015260006110e560808301846130d1565b604081526000613df760408301856130d1565b828103602084015261237581856130d1565b600060208284031215613e1b57600080fd5b815161101481613538565b6040815263ffffffff8351166040820152602083015160608201526000604084015160a06080840152613e5c60e08401826130d1565b90506060850151603f198483030160a0850152613e7982826130d1565b60809690960151151560c08501525050506001600160a01b039190911660209091015290565b600060408284031215613eb157600080fd5b613eb9613126565b9050815181526020820151602082015292915050565b600060408284031215613ee157600080fd5b6110148383613e9f565b6001600160f01b03198135818116916002851015613f135780818660020360031b1b83161692505b505092915050565b600060408284031215613f2d57600080fd5b613f35613126565b82358152602083013560208201528091505092915050565b80356020831015610d8a57600019602084900360031b1b1692915050565b6001600160c01b03198135818116916008851015613f135760089490940360031b84901b1690921692915050565b6001600160401b0360c01b8560c01b16815263ffffffff60e01b8460e01b16600882015282600c82015260008251613fd881602c8501602087016130ad565b91909101602c0195945050505050565b600060018201613ffa57613ffa61392a565b5060010190565b8481526001600160401b0360c01b8460c01b166020820152826028820152600082516140348160488501602087016130ad565b9190910160480195945050505050565b81516001600160401b0381111561405d5761405d613110565b6140718161406b84546138f6565b846139f5565b602080601f8311600181146140a6576000841561408e5750858301515b600019600386901b1c1916600185901b178555613a3d565b600085815260208120601f198616915b828110156140d5578886015182559484019460019091019084016140b6565b50858210156140f35787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b81810381811115610d8a57610d8a61392a565b60006080828403121561412857600080fd5b604051606081018181106001600160401b038211171561414a5761414a613110565b60405282518152602083015161415f81613c8e565b60208201526141718460408501613e9f565b60408201529392505050565b80820180821115610d8a57610d8a61392a565b6000602082840312156141a257600080fd5b8151611014816131fb56fe52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace000cb173d183337e25fab6cb85705c15aad6a58cb1d552ed71b9bc628c8a3de80072ab1bc1039b79dc4724ffca13de82c96834302d3c7e0d4252232d4b2dd8f900a26469706673582212201f248ed02b808c1ae29a9f9f54f2f17eb576e8abbaff0b6b42bafc474f592bed64736f6c63430008160033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000006f475642a6e85809b1c36fa62763669b1b48dd5b
-----Decoded View---------------
Arg [0] : _lzEndpoint (address): 0x6F475642a6e85809B1c36Fa62763669b1b48DD5B
-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 0000000000000000000000006f475642a6e85809b1c36fa62763669b1b48dd5b
Deployed Bytecode Sourcemap
318:3573:47:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2697:144:35;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;864:254:47;;;;;;;;;;-1:-1:-1;864:254:47;;;;;:::i;:::-;;:::i;:::-;;5114:186:35;;;;;;;;;;-1:-1:-1;5114:186:35;;;;;:::i;:::-;;:::i;:::-;;;3409:14:48;;3402:22;3384:41;;3372:2;3357:18;5114:186:35;3244:187:48;6517:1259:26;;;;;;;;;;-1:-1:-1;6517:1259:26;;;;;:::i;:::-;;:::i;:::-;;;;;;;;;:::i;4798:149::-;;;;;;;;;;;;;:::i;:::-;;;-1:-1:-1;;;;;5623:32:48;;;5605:51;;5593:2;5578:18;4798:149:26;5459:203:48;4921:708:11;;;;;;:::i;:::-;;:::i;2777:40:26:-;;;;;;;;;;;;2816:1;2777:40;;;;;7403:6:48;7391:19;;;7373:38;;7361:2;7346:18;2777:40:26;7229:188:48;3987:140:26;;;;;;;;;;-1:-1:-1;3987:140:26;;;-1:-1:-1;;;7592:52:48;;4118:1:26;7675:2:48;7660:18;;7653:59;7565:18;3987:140:26;7422:296:48;4512:325:27;;;;;;;;;;-1:-1:-1;4512:325:27;;;;;:::i;:::-;;:::i;1951:257:13:-;;;;;;;;;;-1:-1:-1;1951:257:13;;;887:1:12;8182:34:48;;759:1:11;8247:2:48;8232:18;;8225:43;8118:18;1951:257:13;7975:299:48;3850:152:35;;;;;;;;;;-1:-1:-1;3981:14:35;;3850:152;;;8425:25:48;;;8413:2;8398:18;3850:152:35;8279:177:48;2740:31:26;;;;;;;;;;;;2770:1;2740:31;;5892:244:35;;;;;;;;;;-1:-1:-1;5892:244:35;;;;;:::i;:::-;;:::i;3565:89:47:-;;;;;;;;;;-1:-1:-1;3565:89:47;;3646:1;9064:36:48;;9052:2;9037:18;3565:89:47;8922:184:48;3150:211:25;;;;;;;;;;-1:-1:-1;3150:211:25;;;;;:::i;:::-;-1:-1:-1;;;;;;;;;;;;;;;;;;;3314:17:25;;;;;;;:8;:17;;;;;;3288:43;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3150:211;;;;;9690:13:48;;9705:6;9686:26;9668:45;;9783:4;9771:17;;;9765:24;9758:32;9751:40;9729:20;;;9722:70;;;;9641:18;3150:211:25;9468:330:48;3028:202:10;;;;;;;;;;-1:-1:-1;3028:202:10;;;;;:::i;:::-;;:::i;1981:111:47:-;;;;;;;;;;-1:-1:-1;1981:111:47;;;;;:::i;:::-;-1:-1:-1;;;;;2066:19:47;2043:4;2066:19;;;:9;:19;;;;;;;;;1981:111;8227:774:26;;;;;;;;;;-1:-1:-1;8227:774:26;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;1128:157:47:-;;;;;;;;;;-1:-1:-1;1128:157:47;;;;;:::i;:::-;;:::i;1553:257:25:-;;;;;;;;;;-1:-1:-1;1553:257:25;;;;;:::i;:::-;;:::i;1438:97:47:-;;;;;;;;;;-1:-1:-1;1492:7:47;1518:10;-1:-1:-1;;;;;1518:10:47;1438:97;;2068:93:15;;;;;;;;;;-1:-1:-1;2149:4:15;2068:93;;1532:222:14;;;;;;;;;;-1:-1:-1;1532:222:14;;;;;:::i;:::-;;:::i;17277:132:26:-;;;;;;;;;;-1:-1:-1;17277:132:26;;;;;:::i;:::-;2485:13:10;;;;;17359:4:26;2485:13:10;;;-1:-1:-1;;;;;;;;;;;2485:13:10;;;;;;17382:20:26;;17277:132;2346:270:25;;;;;;;;;;-1:-1:-1;2346:270:25;;;;;:::i;:::-;;:::i;1035:46:10:-;;;;;;;;;;;;;;;799:143:27;;;;;;;;;;-1:-1:-1;753:24:27;923:12;799:143;;1928:316:25;;;;;;;;;;-1:-1:-1;1928:316:25;;;;;:::i;:::-;;:::i;5989:222:26:-;;;;;;;;;;-1:-1:-1;5989:222:26;;;;;:::i;:::-;;:::i;4035:171:35:-;;;;;;;;;;-1:-1:-1;4035:171:35;;;;;:::i;:::-;;:::i;3155:101:33:-;;;;;;;;;;;;;:::i;4060:128:11:-;;;;;;;;;;-1:-1:-1;4060:128:11;;;;;:::i;:::-;4149:12;4060:128;;;;;;;;-1:-1:-1;;;;;13365:31:48;;;13347:50;;13335:2;13320:18;4060:128:11;13203:200:48;2566:216:11;;;;;;;;;;-1:-1:-1;2566:216:11;;;;;:::i;:::-;-1:-1:-1;;;;;2751:24:11;;2770:4;2751:24;2566:216;;;;;;;1291:141:47;;;;;;;;;;-1:-1:-1;1291:141:47;;;;;:::i;:::-;;:::i;1760:215::-;;;;;;;;;;-1:-1:-1;1760:215:47;;;;;:::i;:::-;;:::i;2441:144:33:-;;;;;;;;;;;;;:::i;2954:148:35:-;;;;;;;;;;;;;:::i;2434:46:26:-;;;;;;;;;;;;;;;2026:94:28;;;;;;;;;;-1:-1:-1;2085:4:28;2026:94;;4401:178:35;;;;;;;;;;-1:-1:-1;4401:178:35;;;;;:::i;:::-;;:::i;1596:180:15:-;;;;;;;;;;;;;:::i;2513:600:14:-;;;;;;;;;;-1:-1:-1;2513:600:14;;;;;:::i;:::-;;:::i;2342:163:10:-;;;;;;;;;;-1:-1:-1;2342:163:10;;;;;:::i;:::-;2485:13;;2400:7;2485:13;;;-1:-1:-1;;;;;;;;;;;2485:13:10;;;;;;;2342:163;3872:1058:14;;;;;;;;;;-1:-1:-1;3872:1058:14;;;;;:::i;:::-;;:::i;2922:150:25:-;;;;;;;;;;-1:-1:-1;;;;;;;;;;;;3050:15:25;;;2922:150;;2978:1333:15;;;;;;:::i;:::-;;:::i;9689:290:26:-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;:::i;4123:105:10:-;;;;;;;;;;-1:-1:-1;4123:105:10;;;;;:::i;:::-;;:::i;4959:409:15:-;;;;;;:::i;:::-;;:::i;2293:226::-;;;;;;;;;;-1:-1:-1;2293:226:15;;;;;:::i;:::-;;:::i;4612:195:35:-;;;;;;;;;;-1:-1:-1;4612:195:35;;;;;:::i;:::-;;:::i;530:47:25:-;;;;;;;;;;;;571:6;530:47;;1541:213:47;;;;;;;;;;-1:-1:-1;1541:213:47;;;;;:::i;:::-;;:::i;3405:215:33:-;;;;;;;;;;-1:-1:-1;3405:215:33;;;;;:::i;:::-;;:::i;3324:149:11:-;;;;;;;;;;-1:-1:-1;3324:149:11;;;;;:::i;:::-;;:::i;2697:144:35:-;2827:7;2820:14;;2742:13;;-1:-1:-1;;;;;;;;;;;2064:20:35;2820:14;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2697:144;:::o;864:254:47:-;4158:30:34;4191:26;:24;:26::i;:::-;4302:15;;4158:59;;-1:-1:-1;4302:15:34;-1:-1:-1;;;4302:15:34;;;4301:16;;-1:-1:-1;;;;;4348:14:34;4279:19;4724:16;;:34;;;;;4744:14;4724:34;4704:54;;4768:17;4788:11;-1:-1:-1;;;;;4788:16:34;4803:1;4788:16;:50;;;;-1:-1:-1;4816:4:34;4808:25;:30;4788:50;4768:70;;4854:12;4853:13;:30;;;;;4871:12;4870:13;4853:30;4849:91;;;4906:23;;-1:-1:-1;;;4906:23:34;;;;;;;;;;;4849:91;4949:18;;-1:-1:-1;;4949:18:34;4966:1;4949:18;;;4977:67;;;;5011:22;;-1:-1:-1;;;;5011:22:34;-1:-1:-1;;;5011:22:34;;;4977:67;1006:37:47::1;1017:5;1024:7;1033:9;1006:10;:37::i;:::-;1053:25;1068:9;1053:14;:25::i;:::-;1109:1;1088:23:::0;;-1:-1:-1;;;;;;1088:23:47::1;::::0;;5064:101:34;;;;5098:23;;-1:-1:-1;;;;5098:23:34;;;5140:14;;-1:-1:-1;13347:50:48;;5140:14:34;;13335:2:48;13320:18;5140:14:34;;;;;;;5064:101;4092:1079;;;;;864:254:47;;;:::o;5114:186:35:-;5187:4;966:10:36;5241:31:35;966:10:36;5257:7:35;5266:5;5241:8;:31::i;:::-;5289:4;5282:11;;;5114:186;;;;;:::o;6517:1259:26:-;-1:-1:-1;;;;;;;;;;;;;;;;;6669:35:26;6706:28;-1:-1:-1;;;;;;;;;;;;;;;;;;;6706:28:26;6925:34;;;;;;;;-1:-1:-1;6925:34:26;;;-1:-1:-1;;6925:34:26;;;;;;;7076:21;;;;;;;;;;;6925:34;;-1:-1:-1;;;7076:21:26;;;-1:-1:-1;;;;;;;;;;;;;;;;;7076:21:26;;;;;;;;;;;;;;;-1:-1:-1;7060:37:26;-1:-1:-1;7534:20:26;;7584:120;7608:19;;;;7641:22;;;;7677:17;;;;7608:10;7677:17;:::i;:::-;7584:10;:120::i;:::-;7727:42;;;;;;;;;;;;;;;;6517:1259;;;;-1:-1:-1;;;;;;6517:1259:26:o;4798:149::-;4843:7;;2993:25;4889:20;4926:14;-1:-1:-1;;;;;4926:14:26;;4798:149;-1:-1:-1;;4798:149:26:o;4921:708:11:-;5234:8;-1:-1:-1;;;;;5226:31:11;5247:10;5226:31;5222:68;;5266:24;;-1:-1:-1;;;5266:24:11;;5279:10;5266:24;;;5605:51:48;5578:18;;5266:24:11;;;;;;;;5222:68;5426:14;;;;;;5390:32;;5407:14;;5426:7;5407:14;:::i;:::-;5390:16;:32::i;:::-;:50;5386:103;;5458:14;;;;:7;:14;:::i;:::-;5449:40;;-1:-1:-1;;;5449:40:11;;18940:10:48;18928:23;;;5449:40:11;;;18910:42:48;5474:14:11;;;;18968:18:48;;;18961:34;18883:18;;5449:40:11;18738:263:48;5386:103:11;5563:59;5574:7;5583:5;5590:8;;5600:9;5611:10;;5563;:59::i;:::-;4921:708;;;;;;;:::o;4512:325:27:-;2334:13:33;:11;:13::i;:::-;753:24:27;4649:12;;4576:23:::1;4675:12:::0;;;4671:43:::1;;4696:18;;-1:-1:-1::0;;;4696:18:27::1;;;;;;;;;;;4671:43;4740:1;4725:16:::0;;4751:38:::1;4769:4;4776:3:::0;4781:7;4751:9:::1;:38::i;:::-;4817:3;-1:-1:-1::0;;;;;4804:26:27::1;;4822:7;4804:26;;;;8425:25:48::0;;8413:2;8398:18;;8279:177;4804:26:27::1;;;;;;;;4566:271;;4512:325:::0;:::o;5892:244:35:-;5979:4;966:10:36;6035:37:35;6051:4;966:10:36;6066:5:35;6035:15;:37::i;:::-;6082:26;6092:4;6098:2;6102:5;6082:9;:26::i;:::-;6125:4;6118:11;;;5892:244;;;;;;:::o;3028:202:10:-;2334:13:33;:11;:13::i;:::-;3167::10::1;::::0;::::1;3108:25;3167:13:::0;;;-1:-1:-1;;;;;;;;;;;3167:13:10::1;::::0;;;;;;;;:21;;;3203:20;;18910:42:48;;;18968:18;;18961:34;;;926:26:10;3203:20:::1;::::0;18883:18:48;3203:20:10::1;;;;;;;;3098:132;3028:202:::0;;:::o;8227:774:26:-;-1:-1:-1;;;;;;;;;;;;;;;;;8561:24:26;8589:74;8600:19;;;;8621:22;;;;8645:17;;;;8600:10;8645:17;:::i;8589:74::-;8558:105;;;8752:20;8774;8798:49;8818:10;8830:16;8798:19;:49::i;:::-;8751:96;;-1:-1:-1;8751:96:26;-1:-1:-1;8936:58:26;8943:17;;;;:10;:17;:::i;:::-;8962:7;8971;8980:13;8936:6;:58::i;:::-;8929:65;8227:774;-1:-1:-1;;;;;;8227:774:26:o;1128:157:47:-;1237:1;6355:30:34;6388:26;:24;:26::i;:::-;6429:15;;;;-1:-1:-1;;;;6429:15:34;;;;;:44;;-1:-1:-1;6448:14:34;;-1:-1:-1;;;;;6448:25:34;;;:14;;:25;;6429:44;6425:105;;;6496:23;;-1:-1:-1;;;6496:23:34;;;;;;;;;;;6425:105;6539:24;;-1:-1:-1;;6573:22:34;-1:-1:-1;;;;;6539:24:34;;6573:22;-1:-1:-1;;;6573:22:34;;;1250:28:47::1;1263:5:::0;1270:7;1250:12:::1;:28::i;:::-;6616:23:34::0;;-1:-1:-1;;;;6616:23:34;;;6654:20;;-1:-1:-1;;;;;13365:31:48;;13347:50;;6654:20:34;;13335:2:48;13320:18;6654:20:34;;;;;;;;6289:392;1128:157:47;;;:::o;1553:257:25:-;2334:13:33;:11;:13::i;:::-;571:6:25::1;1628:25;::::0;::::1;;1624:55;;;1662:17;;-1:-1:-1::0;;;1662:17:25::1;;;;;;;;;;;1624:55;-1:-1:-1::0;;;;;;;;;;;1738:25:25;;-1:-1:-1;;1738:25:25::1;;::::0;::::1;::::0;;::::1;::::0;;1778::::1;::::0;7373:38:48;;;1778:25:25::1;::::0;7361:2:48;7346:18;1778:25:25::1;;;;;;;;1614:196;1553:257:::0;:::o;1532:222:14:-;1714:23;;;1632:33;1714:23;;;1151:36;1714:23;;;;;;;;:33;;;;;;;;;;;1707:40;;1608:12;;1151:36;1714:33;1707:40;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1532:222;;;;:::o;2346:270:25:-;2424:7;2443:10;2456:19;2467:7;2456:10;:19::i;:::-;2443:32;-1:-1:-1;2561:8:25;;;;:48;;571:6;2577:13;2576:33;2577:13;;:7;:13;:::i;:::-;2576:33;;;;:::i;:::-;2561:48;;;2572:1;2561:48;2554:55;2346:270;-1:-1:-1;;;;2346:270:25:o;1928:316::-;2334:13:33;:11;:13::i;:::-;571:6:25::1;2027:25;::::0;::::1;;2023:55;;;2061:17;;-1:-1:-1::0;;;2061:17:25::1;;;;;;;;;;;2023:55;2088:20;-1:-1:-1::0;;;;;;;;;;;2157:28:25::1;::::0;;;;::::1;::::0;;::::1;::::0;;::::1;::::0;;;;::::1;;;::::0;;::::1;::::0;;;2137:17:::1;::::0;::::1;-1:-1:-1::0;2137:17:25;;;:8:::1;::::0;::::1;:17:::0;;;;;:48;;;;;;::::1;;::::0;::::1;-1:-1:-1::0;;2137:48:25;;;;::::1;::::0;;;;::::1;::::0;;;2200:37;;19725:42:48;;;19783:18;;;19776:47;19839:18;;;19832:50;2137:8:25;;-1:-1:-1;2200:37:25::1;::::0;19713:2:48;19698:18;2200:37:25::1;19533:355:48::0;5989:222:26;2334:13:33;:11;:13::i;:::-;2993:25:26;6129:30;;-1:-1:-1;;;;;;6129:30:26::1;-1:-1:-1::0;;;;;6129:30:26;::::1;::::0;;::::1;::::0;;6174::::1;::::0;5605:51:48;;;6174:30:26::1;::::0;5593:2:48;5578:18;6174:30:26::1;5459:203:48::0;4035:171:35;-1:-1:-1;;;;;4179:20:35;4100:7;4179:20;;;-1:-1:-1;;;;;;;;;;;4179:20:35;;;;;;;4035:171::o;3155:101:33:-;2334:13;:11;:13::i;:::-;3219:30:::1;3246:1;3219:18;:30::i;:::-;3155:101::o:0;1291:141:47:-;2334:13:33;:11;:13::i;:::-;1364:10:47::1;:24:::0;;-1:-1:-1;;;;;;1364:24:47::1;-1:-1:-1::0;;;;;1364:24:47;::::1;::::0;;::::1;::::0;;;1403:22:::1;::::0;5605:51:48;;;1403:22:47::1;::::0;5593:2:48;5578:18;1403:22:47::1;;;;;;;1291:141:::0;:::o;1760:215::-;2334:13:33;:11;:13::i;:::-;-1:-1:-1;;;;;1844:19:47;::::1;;::::0;;;:9:::1;:19;::::0;;;;;::::1;;1836:47;;;::::0;-1:-1:-1;;;1836:47:47;;20095:2:48;1836:47:47::1;::::0;::::1;20077:21:48::0;20134:2;20114:18;;;20107:30;-1:-1:-1;;;20153:18:48;;;20146:45;20208:18;;1836:47:47::1;19893:339:48::0;1836:47:47::1;-1:-1:-1::0;;;;;1893:19:47;::::1;1915:5;1893:19:::0;;;:9:::1;:19;::::0;;;;;;;:27;;-1:-1:-1;;1893:27:47::1;::::0;;1935:33;3384:41:48;;;1935:33:47::1;::::0;3357:18:48;1935:33:47::1;;;;;;;;1760:215:::0;:::o;2441:144:33:-;2487:7;;1313:22;2533:20;1192:159;2954:148:35;3086:9;3079:16;;3001:13;;-1:-1:-1;;;;;;;;;;;2064:20:35;3079:16;;;:::i;4401:178::-;4470:4;966:10:36;4524:27:35;966:10:36;4541:2:35;4545:5;4524:9;:27::i;1596:180:15:-;1648:7;;1200:41;1708:34;1050:207;2513:600:14;2334:13:33;:11;:13::i;:::-;1151:36:14;2625:33:::1;2700:356;2720:27:::0;;::::1;2700:356;;;2882:48;2902:16;;2919:1;2902:19;;;;;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;:27;::::0;::::1;::::0;::::1;::::0;::::1;:::i;:::-;2882:19;:48::i;:::-;3018:16;;3035:1;3018:19;;;;;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;:27;::::0;::::1;::::0;::::1;::::0;::::1;:::i;:::-;2944:1:::0;:17:::1;2962:16:::0;;2979:1;2962:19;;::::1;;;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;:23;::::0;::::1;::::0;::::1;::::0;::::1;:::i;:::-;2944:42;;;;;;;;;;;;;;;:71;2987:16;;3004:1;2987:19;;;;;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;:27;::::0;;;;;::::1;;;:::i;:::-;2944:71;;::::0;;::::1;::::0;::::1;::::0;;;;;;-1:-1:-1;2944:71:14;;:101:::1;::::0;;:71;:101:::1;:::i;:::-;-1:-1:-1::0;2749:3:14::1;;2700:356;;;;3071:35;3089:16;;3071:35;;;;;;;:::i;3872:1058::-:0;4138:23;;;4039:33;4138:23;;;1151:36;4138:23;;;;;;;;:33;;;;;;;;;;4114:57;;4015:12;;4039:33;4138;4114:57;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4300:8;:15;4319:1;4300:20;4296:46;;4329:13;;4322:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;4322:20:14;;-1:-1:-1;4322:20:14;;-1:-1:-1;;;;;4322:20:14;4296:46;4427:1;4403:25;;;4399:46;;4437:8;-1:-1:-1;4430:15:14;;-1:-1:-1;4430:15:14;4399:46;4592:1;4568:25;;4564:267;;4609:34;4629:13;;4609:19;:34::i;:::-;4792:8;4802:17;:13;4816:1;4802:13;;:17;:::i;:::-;4779:41;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;4772:48;;;;;;4564:267;4909:13;;4894:29;;-1:-1:-1;;;4894:29:14;;;;;;;;;:::i;2978:1333:15:-;3079:9;3074:1037;3094:19;;;3074:1037;;;3134:29;3166:8;;3175:1;3166:11;;;;;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;3134:43;-1:-1:-1;3260:50:15;3267:20;;;;3134:43;3267:20;:::i;:::-;3289;;;;2485:13:10;;;;;17359:4:26;2485:13:10;;;-1:-1:-1;;;;;;;;;;;2485:13:10;;;;;;17382:20:26;;17277:132;3260:50:15;3255:65;;3312:8;;;3255:65;3882:4;:22;3913:12;;;;:6;3976:11;;;;4005:14;;;;3913:6;4005:14;:::i;:::-;4037:15;;;;;;;;:::i;:::-;4070:16;;;;:6;:16;:::i;:::-;3882:218;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3120:991;3074:1037;3115:3;;3074:1037;;;;4268:10;-1:-1:-1;;;;;4258:43:15;;:45;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;4258:45:15;;;;;;;;;;;;:::i;:::-;4241:63;;-1:-1:-1;;;4241:63:15;;;;;;;;:::i;9689:290:26:-;9850:34;;:::i;:::-;-1:-1:-1;;;;;;;;;;;;;;;;;9933:39:26;9939:10;9951:4;9957:14;9933:5;:39::i;:::-;9926:46;;;;9689:290;;;;;;:::o;4123:105:10:-;2334:13:33;:11;:13::i;:::-;4190:31:10::1;::::0;-1:-1:-1;;;4190:31:10;;-1:-1:-1;;;;;5623:32:48;;;4190:31:10::1;::::0;::::1;5605:51:48::0;4190:8:10::1;:20;::::0;::::1;::::0;5578:18:48;;4190:31:10::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;4123:105:::0;:::o;4959:409:15:-;5238:10;5260:4;5238:27;5234:50;;5274:10;;-1:-1:-1;;;5274:10:15;;;;;;;;;;;5234:50;5294:67;5313:7;5322:5;5329:8;;5339:9;5350:10;;5294:18;:67::i;2293:226::-;2334:13:33;:11;:13::i;:::-;1200:41:15;2453:22;;-1:-1:-1;;;;;;2453:22:15::1;-1:-1:-1::0;;;;;2453:22:15;::::1;::::0;;::::1;::::0;;2490::::1;::::0;5605:51:48;;;2490:22:15::1;::::0;5593:2:48;5578:18;2490:22:15::1;5459:203:48::0;4612:195:35;-1:-1:-1;;;;;4771:20:35;;;4692:7;4771:20;;;:13;:20;;;;;;;;:29;;;;;;;;;;;;;4612:195::o;1541:213:47:-;2334:13:33;:11;:13::i;:::-;-1:-1:-1;;;;;1621:19:47;::::1;;::::0;;;:9:::1;:19;::::0;;;;;::::1;;1620:20;1612:52;;;::::0;-1:-1:-1;;;1612:52:47;;28720:2:48;1612:52:47::1;::::0;::::1;28702:21:48::0;28759:2;28739:18;;;28732:30;-1:-1:-1;;;28778:18:48;;;28771:49;28837:18;;1612:52:47::1;28518:343:48::0;1612:52:47::1;-1:-1:-1::0;;;;;1674:19:47;::::1;;::::0;;;1696:4:::1;1674:19;::::0;;;;;;;;:26;;-1:-1:-1;;1674:26:47::1;::::0;::::1;::::0;;1715:32;;3384:41:48;;;1715:32:47::1;::::0;3357:18:48;1715:32:47::1;3244:187:48::0;3405:215:33;2334:13;:11;:13::i;:::-;-1:-1:-1;;;;;3489:22:33;::::1;3485:91;;3534:31;::::0;-1:-1:-1;;;3534:31:33;;3562:1:::1;3534:31;::::0;::::1;5605:51:48::0;5578:18;;3534:31:33::1;5459:203:48::0;3485:91:33::1;3585:28;3604:8;3585:18;:28::i;:::-;3405:215:::0;:::o;3324:149:11:-;3406:4;3453:13;;;;;;3429:20;;3435:13;;3453:6;3435:13;:::i;3429:20::-;:37;;3324:149;-1:-1:-1;;3324:149:11:o;9071:205:34:-;9129:30;;3147:66;9186:27;8819:122;1160:189:28;6929:20:34;:18;:20::i;:::-;1279:28:28::1;1292:5;1299:7;1279:12;:28::i;:::-;1317:25;1332:9;1317:14;:25::i;:::-;1160:189:::0;;;:::o;1847:127:33:-;6929:20:34;:18;:20::i;:::-;1929:38:33::1;1954:12;1929:24;:38::i;9905:128:35:-:0;9989:37;9998:5;10005:7;10014:5;10021:4;9989:8;:37::i;2335:691:27:-;2555:9;2482:20;;2739:26;2746:7;2555:9;2739:6;:26::i;:::-;2725:40;;2818:28;2842:3;2830:9;:15;2818:11;:28::i;:::-;2799:47;;2926:12;2907:16;:31;2903:117;;;2961:48;;-1:-1:-1;;;2961:48:27;;;;;29040:25:48;;;29081:18;;;29074:34;;;29013:18;;2961:48:27;28866:248:48;2903:117:27;2530:496;2335:691;;;;;;:::o;3528:257:10:-;3691:13;;;3598:7;3691:13;;;-1:-1:-1;;;;;;;;;;;3691:13:10;;;;;;;;;3714:43;;3745:12;;-1:-1:-1;;;3745:12:10;;29293:10:48;29281:23;;3745:12:10;;;29263:42:48;29236:18;;3745:12:10;29119:192:48;14070:1806:26;14547:17;14567:36;:17;:8;;:15;:17::i;:::-;2891:2:32;2780:123;14567:36:26;14547:56;;14736:24;14763:62;14771:9;14782:26;14788:19;:8;;:17;:19::i;:::-;14782:5;:26::i;:::-;14810:14;;;;:7;:14;:::i;:::-;14763:7;:62::i;:::-;14736:89;-1:-1:-1;243:2:32;-1:-1:-1;;14836:955:26;;;14940:23;14966:175;15009:13;;;;;;;;:::i;:::-;15040:14;;;;:7;:14;:::i;:::-;15072:16;15106:21;:8;;:19;:21::i;:::-;14966:25;:175::i;:::-;15688:92;;-1:-1:-1;;;15688:92:26;;14940:201;;-1:-1:-1;;;;;;15688:8:26;:20;;;;:92;;15709:9;;15720:5;;15727:1;;14940:201;;15688:92;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;14863:928;14836:955;-1:-1:-1;;;;;15806:63:26;;15818:5;15806:63;15825:14;;;;:7;:14;:::i;:::-;15806:63;;;18940:10:48;18928:23;;;18910:42;;18983:2;18968:18;;18961:34;;;18883:18;15806:63:26;;;;;;;14373:1503;;14070:1806;;;;;;;:::o;2658:162:33:-;966:10:36;2717:7:33;:5;:7::i;:::-;-1:-1:-1;;;;;2717:23:33;;2713:101;;2763:40;;-1:-1:-1;;;2763:40:33;;966:10:36;2763:40:33;;;5605:51:48;5578:18;;2763:40:33;5459:203:48;6509:300:35;-1:-1:-1;;;;;6592:18:35;;6588:86;;6633:30;;-1:-1:-1;;;6633:30:35;;6660:1;6633:30;;;5605:51:48;5578:18;;6633:30:35;5459:203:48;6588:86:35;-1:-1:-1;;;;;6687:16:35;;6683:86;;6726:32;;-1:-1:-1;;;6726:32:35;;6755:1;6726:32;;;5605:51:48;5578:18;;6726:32:35;5459:203:48;6683:86:35;6778:24;6786:4;6792:2;6796:5;6778:7;:24::i;11649:476::-;11748:24;11775:25;11785:5;11792:7;11775:9;:25::i;:::-;11748:52;;-1:-1:-1;;11814:16:35;:36;11810:309;;;11889:5;11870:16;:24;11866:130;;;11921:60;;-1:-1:-1;;;11921:60:35;;-1:-1:-1;;;;;30538:32:48;;11921:60:35;;;30520:51:48;30587:18;;;30580:34;;;30630:18;;;30623:34;;;30493:18;;11921:60:35;30318:345:48;11866:130:35;12037:57;12046:5;12053:7;12081:5;12062:16;:24;12088:5;12037:8;:57::i;:::-;11738:387;11649:476;;;:::o;12056:1496:26:-;12188:20;12210;12242:15;12413:324;12445:10;:13;;;12472:16;12478:9;12472:5;:16::i;:::-;12706:21;;;;:10;:21;:::i;:::-;12413:324;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;12413:18:26;;-1:-1:-1;;;12413:324:26:i;:::-;12389:348;;-1:-1:-1;12389:348:26;-1:-1:-1;12817:14:26;12389:348;12834:33;;2770:1;12834:33;;;2816:1;12834:33;12817:50;-1:-1:-1;12989:67:26;13004:17;;;;:10;:17;:::i;:::-;13023:7;13032:23;;;;:10;:23;:::i;12989:67::-;2993:25;13372:14;;12979:77;;-1:-1:-1;2993:25:26;-1:-1:-1;;;;;13372:14:26;13466:23;;13462:83;;13491:54;;-1:-1:-1;;;13491:54:26;;-1:-1:-1;;;;;13491:36:26;;;;;:54;;13528:7;;13537;;13491:54;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;13462:83;12232:1320;;;;12056:1496;;;;;:::o;2550:391:12:-;-1:-1:-1;;;;;;;;;;;;;;;;;2771:8:12;-1:-1:-1;;;;;2771:14:12;;2803:86;;;;;;;;2819:7;2803:86;;;;;;2828:25;2845:7;2828:16;:25::i;:::-;2803:86;;;;2855:8;2803:86;;;;2865:8;2803:86;;;;2875:13;2803:86;;;;;2915:4;2771:163;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;2752:182;2550:391;-1:-1:-1;;;;;2550:391:12:o;2263:147:35:-;6929:20:34;:18;:20::i;:::-;2365:38:35::1;2388:5;2395:7;2365:22;:38::i;:::-;2263:147:::0;;:::o;2622:241:25:-;2774:17;;;2681:6;2774:17;;;:8;:17;;;;;;;;2748:43;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;1421:20:25;2808:48;;2841:15;;;;2808:48;;;2825:13;;2801:55;-1:-1:-1;;;2622:241:25:o;3774:248:33:-;1313:22;3923:8;;-1:-1:-1;;;;;;3941:19:33;;-1:-1:-1;;;;;3941:19:33;;;;;;;;3975:40;;3923:8;;;;;3975:40;;3847:24;;3975:40;3837:185;;3774:248;:::o;5070:218:14:-;5156:18;5191:13;5202:1;5156:18;5191:8;;:13;:::i;:::-;5184:21;;;:::i;:::-;5177:29;;;-1:-1:-1;1003:1:14;5220:28;;5216:65;;5272:8;;5257:24;;-1:-1:-1;;;5257:24:14;;;;;;;;;:::i;10429:1333:26:-;10583:34;;:::i;:::-;-1:-1:-1;;;;;;;;;;;;;;;;;10981:20:26;;11031:140;11051:10;11075:19;;;;11108:22;;;;11144:17;;;;11075:10;11144:17;:::i;:::-;11031:6;:140::i;:::-;10980:191;;;;11260:20;11282;11306:49;11326:10;11338:16;11306:19;:49::i;:::-;11259:96;;-1:-1:-1;11259:96:26;-1:-1:-1;11478:66:26;11486:17;;;;:10;:17;:::i;:::-;11505:7;11514;11478:66;;;;;;;11523:4;11478:66;:::i;:::-;11529:14;11478:7;:66::i;:::-;11610:42;;;;;;;;;;;;;;;;;;;11676:15;;11465:79;;-1:-1:-1;11610:42:26;;-1:-1:-1;11712:10:26;;11676:15;11668:87;;11693:17;;;;:10;:17;:::i;:::-;11668:87;;;33649:10:48;33637:23;;;33619:42;;33692:2;33677:18;;33670:34;;;33720:18;;33713:34;;;33607:2;33592:18;11668:87:26;;;;;;;10649:1113;;;;10429:1333;;;;;;:::o;7082:141:34:-;7149:17;:15;:17::i;:::-;7144:73;;7189:17;;-1:-1:-1;;;7189:17:34;;;;;;;;;;;4539:183:26;6929:20:34;:18;:20::i;:::-;4618:22:26::1;4630:9;4618:11;:22::i;:::-;4650:30;:28;:30::i;:::-;4690:25;:23;:25::i;1980:235:33:-:0;6929:20:34;:18;:20::i;10880:487:35:-;-1:-1:-1;;;;;;;;;;;;;;;;11045:19:35;;11041:89;;11087:32;;-1:-1:-1;;;11087:32:35;;11116:1;11087:32;;;5605:51:48;5578:18;;11087:32:35;5459:203:48;11041:89:35;-1:-1:-1;;;;;11143:21:35;;11139:90;;11187:31;;-1:-1:-1;;;11187:31:35;;11215:1;11187:31;;;5605:51:48;5578:18;;11187:31:35;5459:203:48;11139:90:35;-1:-1:-1;;;;;11238:20:35;;;;;;;:13;;;:20;;;;;;;;:29;;;;;;;;;:37;;;11285:76;;;;11335:7;-1:-1:-1;;;;;11319:31:35;11328:5;-1:-1:-1;;;;;11319:31:35;;11344:5;11319:31;;;;8425:25:48;;8413:2;8398:18;;8279:177;11319:31:35;;;;;;;;10978:389;10880:487;;;;:::o;17803:172:26:-;17874:16;17947:21;17910:33;17947:21;17910:9;:33;:::i;:::-;17909:59;;;;:::i;1573:123:32:-;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:32:o;18199:139:26:-;18263:16;18298:33;18310:21;-1:-1:-1;;;;;18298:33:26;;;:::i;3505:462:28:-;3639:24;-1:-1:-1;;;;;3679:19:28;;3675:46;;3714:6;3700:21;;3675:46;3817:21;3823:3;3828:9;3817:5;:21::i;:::-;-1:-1:-1;3951:9:28;;3505:462;-1:-1:-1;;3505:462:28:o;2186:130:32:-;2250:12;2281:28;:4;243:2;2281:4;;:28;:::i;:::-;2274:35;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;2274:35:32;;2186:130;-1:-1:-1;;;;;;2186:130:32:o;640:284:31:-;824:17;877:6;885:7;894:9;905:11;860:57;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;853:64;;640:284;;;;;;:::o;3660:229:47:-;3754:30;3768:4;3774:2;3778:5;3754:13;:30::i;:::-;3794:5;:7;;;:5;:7;;;:::i;:::-;;;;;;3837:5;;3833:2;-1:-1:-1;;;;;3816:66:47;3827:4;-1:-1:-1;;;;;3816:66:47;;3844:5;3851:15;3861:4;3851:9;:15::i;:::-;3868:13;3878:2;3868:9;:13::i;:::-;3816:66;;;35269:25:48;;;35325:2;35310:18;;35303:34;;;;35353:18;;;35346:34;35257:2;35242:18;3816:66:47;;;;;;;3660:229;;;:::o;18738:266:26:-;18803:15;;18850:33;18862:21;18850:9;:33;:::i;:::-;18830:53;-1:-1:-1;;;;;;18897:28:26;;18893:70;;;18934:29;;-1:-1:-1;;;18934:29:26;;;;;8425:25:48;;;8398:18;;18934:29:26;8279:177:48;598:506:32;791:18;;732:17;;791:22;;;934:163;;1074:7;1083:13;1057:40;;;;;;;;35546:19:48;;;35621:3;35599:16;-1:-1:-1;;;;;;35595:51:48;35590:2;35581:12;;35574:73;35672:2;35663:12;;35391:290;1057:40:32;;;;;;;;;;;;;934:163;;;976:7;985:13;1017:10;1030:11;959:83;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;934:163;927:170;;598:506;;;;;;:::o;2416:216:35:-;6929:20:34;:18;:20::i;:::-;-1:-1:-1;;;;;;;;;;;2581:7:35;:15:::1;2591:5:::0;2581:7;:15:::1;:::i;:::-;-1:-1:-1::0;2606:9:35::1;::::0;::::1;:19;2618:7:::0;2606:9;:19:::1;:::i;2098:1036:47:-:0;-1:-1:-1;;;;;2352:16:47;;2259:20;2352:16;;;:9;:16;;;;;;2259:20;;2352:16;;:130;;2438:44;2449:9;2460:12;2474:7;2438:10;:44::i;:::-;2352:130;;;2383:40;2399:9;2410:12;2383:15;:40::i;:::-;2317:165;;-1:-1:-1;2317:165:47;-1:-1:-1;2496:31:47;;;2492:122;;;2543:60;;-1:-1:-1;;;2543:60:47;;37773:2:48;2543:60:47;;;37755:21:48;37812:2;37792:18;;;37785:30;37851:34;37831:18;;;37824:62;-1:-1:-1;;;37902:18:48;;;37895:48;37960:19;;2543:60:47;37571:414:48;2492:122:47;2623:11;2637:31;2652:16;2637:12;:31;:::i;:::-;2623:45;-1:-1:-1;2683:7:47;;2679:409;;2732:1;2710:10;-1:-1:-1;;;;;2710:10:47;2706:372;;753:24:27;2849:19:47;;;;;;2904:36;2914:5;2929:4;2849:19;2904:9;:36::i;:::-;2736:219;2706:372;;;3047:10;;3030:33;;3040:5;;-1:-1:-1;;;;;3047:10:47;3059:3;3030:9;:33::i;:::-;3097:30;3103:5;3110:16;3097:5;:30::i;:::-;2307:827;2098:1036;;;;;;;:::o;3700:766:12:-;3901:31;;:::i;:::-;4066:20;4089:26;4100:4;:14;;;4089:10;:26::i;:::-;4129:15;;;;4066:49;;-1:-1:-1;4129:19:12;4125:53;;4150:28;4162:4;:15;;;4150:11;:28::i;:::-;4267:8;-1:-1:-1;;;;;4267:13:12;;4289:12;4321:92;;;;;;;;4337:7;4321:92;;;;;;4346:25;4363:7;4346:16;:25::i;:::-;4321:92;;;;4373:8;4321:92;;;;4383:8;4321:92;;;;4411:1;4393:4;:15;;;:19;4321:92;;;;;4431:14;4267:192;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;4189:270;3700:766;-1:-1:-1;;;;;;;3700:766:12:o;8485:120:34:-;8535:4;8558:26;:24;:26::i;:::-;:40;-1:-1:-1;;;8558:40:34;;;;;;-1:-1:-1;8485:120:34:o;1456:189:13:-;6929:20:34;:18;:20::i;:::-;1532:26:13::1;1548:9;1532:15;:26::i;1438:68:15:-:0;6929:20:34;:18;:20::i;8637:208:35:-;-1:-1:-1;;;;;8707:21:35;;8703:91;;8751:32;;-1:-1:-1;;;8751:32:35;;8780:1;8751:32;;;5605:51:48;5578:18;;8751:32:35;5459:203:48;8703:91:35;8803:35;8819:1;8823:7;8832:5;8803:7;:35::i;7124:1170::-;-1:-1:-1;;;;;;;;;;;;;;;;7266:18:35;;7262:546;;7420:5;7402:1;:14;;;:23;;;;;;;:::i;:::-;;;;-1:-1:-1;7262:546:35;;-1:-1:-1;7262:546:35;;-1:-1:-1;;;;;7478:17:35;;7456:19;7478:17;;;;;;;;;;;7513:19;;;7509:115;;;7559:50;;-1:-1:-1;;;7559:50:35;;-1:-1:-1;;;;;30538:32:48;;7559:50:35;;;30520:51:48;30587:18;;;30580:34;;;30630:18;;;30623:34;;;30493:18;;7559:50:35;30318:345:48;7509:115:35;-1:-1:-1;;;;;7744:17:35;;:11;:17;;;;;;;;;;7764:19;;;;7744:39;;7262:546;-1:-1:-1;;;;;7822:16:35;;7818:429;;7985:14;;;:23;;;;;;;7818:429;;;-1:-1:-1;;;;;8198:15:35;;:11;:15;;;;;;;;;;:24;;;;;;7818:429;8277:2;-1:-1:-1;;;;;8262:25:35;8271:4;-1:-1:-1;;;;;8262:25:35;;8281:5;8262:25;;;;8425::48;;8413:2;8398:18;;8279:177;8262:25:35;;;;;;;;7199:1095;7124:1170;;;:::o;3140:419:47:-;3332:9;3259:20;3394:22;3332:9;3394:11;:22::i;:::-;3375:41;;3459:12;3440:16;:31;3436:117;;;3494:48;;-1:-1:-1;;;3494:48:47;;;;;29040:25:48;;;29081:18;;;29074:34;;;29013:18;;3494:48:47;28866:248:48;3436:117:47;3140:419;;;;;:::o;9163:206:35:-;-1:-1:-1;;;;;9233:21:35;;9229:89;;9277:30;;-1:-1:-1;;;9277:30:35;;9304:1;9277:30;;;5605:51:48;5578:18;;9277:30:35;5459:203:48;9229:89:35;9327:35;9335:7;9352:1;9356:5;9327:7;:35::i;5162:191:12:-;5228:17;5274:10;5261:9;:23;5257:62;;5293:26;;-1:-1:-1;;;5293:26:12;;5309:9;5293:26;;;8425:25:48;8398:18;;5293:26:12;8279:177:48;5257:62:12;-1:-1:-1;5336:10:12;5162:191::o;5730:410::-;5883:15;5901:8;-1:-1:-1;;;;;5901:16:12;;:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;5883:36;-1:-1:-1;;;;;;5933:21:12;;5929:54;;5963:20;;-1:-1:-1;;;5963:20:12;;;;;;;;;;;5929:54;6057:76;-1:-1:-1;;;;;6057:32:12;;6090:10;6110:8;6121:11;6057:32;:76::i;1787:123:10:-;6929:20:34;:18;:20::i;:::-;1867:36:10::1;1893:9;1867:25;:36::i;1618:188:44:-:0;1745:53;;;-1:-1:-1;;;;;39453:15:48;;;1745:53:44;;;39435:34:48;39505:15;;39485:18;;;39478:43;39537:18;;;;39530:34;;;1745:53:44;;;;;;;;;;39370:18:48;;;;1745:53:44;;;;;;;;-1:-1:-1;;;;;1745:53:44;-1:-1:-1;;;1745:53:44;;;1718:81;;1738:5;;1718:19;:81::i;1916:191:10:-;6929:20:34;:18;:20::i;:::-;-1:-1:-1;;;;;2010:23:10;::::1;2006:53;;2042:17;;-1:-1:-1::0;;;2042:17:10::1;;;;;;;;;;;8370:720:44::0;8450:18;8478:19;8616:4;8613:1;8606:4;8600:11;8593:4;8587;8583:15;8580:1;8573:5;8566;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:44;8910:8;8866:16;;-1:-1:-1;8942:15:44;;:68;;8994:11;9009:1;8994:16;;8942:68;;;-1:-1:-1;;;;;8960:26:44;;;:31;8942:68;8938:146;;;9033:40;;-1:-1:-1;;;9033:40:44;;-1:-1:-1;;;;;5623:32:48;;9033:40:44;;;5605:51:48;5578:18;;9033:40:44;5459:203:48;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;14:250:48:-;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:48;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:48;488:39;;;;529:4;484:50;;269:271;-1:-1:-1;;269:271:48:o;545:220::-;694:2;683:9;676:21;657:4;714:45;755:2;744:9;740:18;732:6;714:45;:::i;770:127::-;831:10;826:3;822:20;819:1;812:31;862:4;859:1;852:15;886:4;883:1;876:15;902:257;974:4;968:11;;;1006:17;;-1:-1:-1;;;;;1038:34:48;;1074:22;;;1035:62;1032:88;;;1100:18;;:::i;:::-;1136:4;1129:24;902:257;:::o;1164:275::-;1235:2;1229:9;1300:2;1281:13;;-1:-1:-1;;1277:27:48;1265:40;;-1:-1:-1;;;;;1320:34:48;;1356:22;;;1317:62;1314:88;;;1382:18;;:::i;:::-;1418:2;1411:22;1164:275;;-1:-1:-1;1164:275:48:o;1444:187::-;1493:4;-1:-1:-1;;;;;1518:6:48;1515:30;1512:56;;;1548:18;;:::i;:::-;-1:-1:-1;1614:2:48;1593:15;-1:-1:-1;;1589:29:48;1620:4;1585:40;;1444:187::o;1636:464::-;1679:5;1732:3;1725:4;1717:6;1713:17;1709:27;1699:55;;1750:1;1747;1740:12;1699:55;1786:6;1773:20;1817:49;1833:32;1862:2;1833:32;:::i;:::-;1817:49;:::i;:::-;1891:2;1882:7;1875:19;1937:3;1930:4;1925:2;1917:6;1913:15;1909:26;1906:35;1903:55;;;1954:1;1951;1944:12;1903:55;2019:2;2012:4;2004:6;2000:17;1993:4;1984:7;1980:18;1967:55;2067:1;2042:16;;;2060:4;2038:27;2031:38;;;;2046:7;1636:464;-1:-1:-1;;;1636:464:48:o;2105:131::-;-1:-1:-1;;;;;2180:31:48;;2170:42;;2160:70;;2226:1;2223;2216:12;2241:678;2338:6;2346;2354;2407:2;2395:9;2386:7;2382:23;2378:32;2375:52;;;2423:1;2420;2413:12;2375:52;2463:9;2450:23;-1:-1:-1;;;;;2533:2:48;2525:6;2522:14;2519:34;;;2549:1;2546;2539:12;2519:34;2572:50;2614:7;2605:6;2594:9;2590:22;2572:50;:::i;:::-;2562:60;;2675:2;2664:9;2660:18;2647:32;2631:48;;2704:2;2694:8;2691:16;2688:36;;;2720:1;2717;2710:12;2688:36;;2743:52;2787:7;2776:8;2765:9;2761:24;2743:52;:::i;:::-;2733:62;;;2845:2;2834:9;2830:18;2817:32;2858:31;2883:5;2858:31;:::i;:::-;2908:5;2898:15;;;2241:678;;;;;:::o;2924:315::-;2992:6;3000;3053:2;3041:9;3032:7;3028:23;3024:32;3021:52;;;3069:1;3066;3059:12;3021:52;3108:9;3095:23;3127:31;3152:5;3127:31;:::i;:::-;3177:5;3229:2;3214:18;;;;3201:32;;-1:-1:-1;;;2924:315:48:o;3436:158::-;3498:5;3543:3;3534:6;3529:3;3525:16;3521:26;3518:46;;;3560:1;3557;3550:12;3518:46;-1:-1:-1;3582:6:48;3436:158;-1:-1:-1;3436:158:48:o;3599:360::-;3687:6;3740:2;3728:9;3719:7;3715:23;3711:32;3708:52;;;3756:1;3753;3746:12;3708:52;3796:9;3783:23;-1:-1:-1;;;;;3821:6:48;3818:30;3815:50;;;3861:1;3858;3851:12;3815:50;3884:69;3945:7;3936:6;3925:9;3921:22;3884:69;:::i;4118:1336::-;4038:12;;4026:25;;4100:4;4089:16;;;4083:23;4067:14;;;4060:47;4484:4;4532:3;4517:19;;4609:2;4647:3;4642:2;4631:9;4627:18;4620:31;4671:6;4706;4700:13;4737:6;4729;4722:22;4775:3;4764:9;4760:19;4753:26;;4838:3;4828:6;4825:1;4821:14;4810:9;4806:30;4802:40;4788:54;;4861:4;4900;4892:6;4888:17;4923:1;4933:429;4947:6;4944:1;4941:13;4933:429;;;5012:22;;;-1:-1:-1;;5008:37:48;4996:50;;5069:13;;5110:9;;5095:25;;5159:11;;5153:18;5191:15;;;5184:27;;;5234:48;5266:15;;;5153:18;5234:48;:::i;:::-;5224:58;-1:-1:-1;;5340:12:48;;;;5305:15;;;;4969:1;4962:9;4933:429;;;-1:-1:-1;;4038:12:48;;5444:2;5429:18;;4026:25;-1:-1:-1;;;4100:4:48;4089:16;;4083:23;4067:14;;;4060:47;-1:-1:-1;5379:6:48;-1:-1:-1;5394:54:48;3964:149;5667:154;5726:5;5771:2;5762:6;5757:3;5753:16;5749:25;5746:45;;;5787:1;5784;5777:12;5826:347;5877:8;5887:6;5941:3;5934:4;5926:6;5922:17;5918:27;5908:55;;5959:1;5956;5949:12;5908:55;-1:-1:-1;5982:20:48;;-1:-1:-1;;;;;6014:30:48;;6011:50;;;6057:1;6054;6047:12;6011:50;6094:4;6086:6;6082:17;6070:29;;6146:3;6139:4;6130:6;6122;6118:19;6114:30;6111:39;6108:59;;;6163:1;6160;6153:12;6178:1046;6319:6;6327;6335;6343;6351;6359;6367;6420:3;6408:9;6399:7;6395:23;6391:33;6388:53;;;6437:1;6434;6427:12;6388:53;6460;6505:7;6494:9;6460:53;:::i;:::-;6450:63;;6560:2;6549:9;6545:18;6532:32;6522:42;;6615:3;6604:9;6600:19;6587:33;-1:-1:-1;;;;;6680:2:48;6672:6;6669:14;6666:34;;;6696:1;6693;6686:12;6666:34;6735:58;6785:7;6776:6;6765:9;6761:22;6735:58;:::i;:::-;6812:8;;-1:-1:-1;6709:84:48;-1:-1:-1;6897:3:48;6882:19;;6869:33;;-1:-1:-1;6911:31:48;6869:33;6911:31;:::i;:::-;6961:5;;-1:-1:-1;7019:3:48;7004:19;;6991:33;;7036:16;;;7033:36;;;7065:1;7062;7055:12;7033:36;;7104:60;7156:7;7145:8;7134:9;7130:24;7104:60;:::i;:::-;6178:1046;;;;-1:-1:-1;6178:1046:48;;-1:-1:-1;6178:1046:48;;;;7078:86;;-1:-1:-1;;;6178:1046:48:o;7723:247::-;7782:6;7835:2;7823:9;7814:7;7810:23;7806:32;7803:52;;;7851:1;7848;7841:12;7803:52;7890:9;7877:23;7909:31;7934:5;7909:31;:::i;8461:456::-;8538:6;8546;8554;8607:2;8595:9;8586:7;8582:23;8578:32;8575:52;;;8623:1;8620;8613:12;8575:52;8662:9;8649:23;8681:31;8706:5;8681:31;:::i;:::-;8731:5;-1:-1:-1;8788:2:48;8773:18;;8760:32;8801:33;8760:32;8801:33;:::i;:::-;8461:456;;8853:7;;-1:-1:-1;;;8907:2:48;8892:18;;;;8879:32;;8461:456::o;9111:163::-;9178:20;;9238:10;9227:22;;9217:33;;9207:61;;9264:1;9261;9254:12;9207:61;9111:163;;;:::o;9279:184::-;9337:6;9390:2;9378:9;9369:7;9365:23;9361:32;9358:52;;;9406:1;9403;9396:12;9358:52;9429:28;9447:9;9429:28;:::i;9803:252::-;9870:6;9878;9931:2;9919:9;9910:7;9906:23;9902:32;9899:52;;;9947:1;9944;9937:12;9899:52;9970:28;9988:9;9970:28;:::i;10060:118::-;10146:5;10139:13;10132:21;10125:5;10122:32;10112:60;;10168:1;10165;10158:12;10183:489;10277:6;10285;10338:2;10326:9;10317:7;10313:23;10309:32;10306:52;;;10354:1;10351;10344:12;10306:52;10394:9;10381:23;-1:-1:-1;;;;;10419:6:48;10416:30;10413:50;;;10459:1;10456;10449:12;10413:50;10482:69;10543:7;10534:6;10523:9;10519:22;10482:69;:::i;:::-;10472:79;;;10601:2;10590:9;10586:18;10573:32;10614:28;10636:5;10614:28;:::i;:::-;10661:5;10651:15;;;10183:489;;;;;:::o;10677:253::-;4038:12;;4026:25;;4100:4;4089:16;;;4083:23;4067:14;;;4060:47;10867:2;10852:18;;10879:45;3964:149;10935:543;11023:6;11031;11084:2;11072:9;11063:7;11059:23;11055:32;11052:52;;;11100:1;11097;11090:12;11052:52;11140:9;11127:23;-1:-1:-1;;;;;11210:2:48;11202:6;11199:14;11196:34;;;11226:1;11223;11216:12;11196:34;11249:50;11291:7;11282:6;11271:9;11267:22;11249:50;:::i;:::-;11239:60;;11352:2;11341:9;11337:18;11324:32;11308:48;;11381:2;11371:8;11368:16;11365:36;;;11397:1;11394;11387:12;11365:36;;11420:52;11464:7;11453:8;11442:9;11438:24;11420:52;:::i;:::-;11410:62;;;10935:543;;;;;:::o;11483:159::-;11550:20;;11610:6;11599:18;;11589:29;;11579:57;;11632:1;11629;11622:12;11647:184;11705:6;11758:2;11746:9;11737:7;11733:23;11729:32;11726:52;;;11774:1;11771;11764:12;11726:52;11797:28;11815:9;11797:28;:::i;11836:256::-;11902:6;11910;11963:2;11951:9;11942:7;11938:23;11934:32;11931:52;;;11979:1;11976;11969:12;11931:52;12002:28;12020:9;12002:28;:::i;:::-;11992:38;;12049:37;12082:2;12071:9;12067:18;12049:37;:::i;:::-;12039:47;;11836:256;;;;;:::o;12813:385::-;12885:6;12893;12901;12954:2;12942:9;12933:7;12929:23;12925:32;12922:52;;;12970:1;12967;12960:12;12922:52;12993:28;13011:9;12993:28;:::i;:::-;12983:38;;13040:37;13073:2;13062:9;13058:18;13040:37;:::i;:::-;13030:47;;13127:2;13116:9;13112:18;13099:32;13140:28;13162:5;13140:28;:::i;13408:668::-;13520:6;13528;13536;13544;13597:3;13585:9;13576:7;13572:23;13568:33;13565:53;;;13614:1;13611;13604:12;13565:53;13637;13682:7;13671:9;13637:53;:::i;:::-;13627:63;;13741:2;13730:9;13726:18;13713:32;-1:-1:-1;;;;;13760:6:48;13757:30;13754:50;;;13800:1;13797;13790:12;13754:50;13839:58;13889:7;13880:6;13869:9;13865:22;13839:58;:::i;:::-;13916:8;;-1:-1:-1;13813:84:48;-1:-1:-1;;14001:3:48;13986:19;;13973:33;14015:31;13973:33;14015:31;:::i;:::-;13408:668;;;;-1:-1:-1;13408:668:48;;-1:-1:-1;;13408:668:48:o;14081:395::-;14172:8;14182:6;14236:3;14229:4;14221:6;14217:17;14213:27;14203:55;;14254:1;14251;14244:12;14203:55;-1:-1:-1;14277:20:48;;-1:-1:-1;;;;;14309:30:48;;14306:50;;;14352:1;14349;14342:12;14306:50;14389:4;14381:6;14377:17;14365:29;;14449:3;14442:4;14432:6;14429:1;14425:14;14417:6;14413:27;14409:38;14406:47;14403:67;;;14466:1;14463;14456:12;14481:504;14606:6;14614;14667:2;14655:9;14646:7;14642:23;14638:32;14635:52;;;14683:1;14680;14673:12;14635:52;14723:9;14710:23;-1:-1:-1;;;;;14748:6:48;14745:30;14742:50;;;14788:1;14785;14778:12;14742:50;14827:98;14917:7;14908:6;14897:9;14893:22;14827:98;:::i;:::-;14944:8;;14801:124;;-1:-1:-1;14481:504:48;-1:-1:-1;;;;14481:504:48:o;15172:553::-;15258:6;15266;15274;15282;15335:2;15323:9;15314:7;15310:23;15306:32;15303:52;;;15351:1;15348;15341:12;15303:52;15374:28;15392:9;15374:28;:::i;:::-;15364:38;;15421:37;15454:2;15443:9;15439:18;15421:37;:::i;:::-;15411:47;;15509:2;15498:9;15494:18;15481:32;-1:-1:-1;;;;;15528:6:48;15525:30;15522:50;;;15568:1;15565;15558:12;15522:50;15607:58;15657:7;15648:6;15637:9;15633:22;15607:58;:::i;:::-;15172:553;;;;-1:-1:-1;15684:8:48;-1:-1:-1;;;;15172:553:48:o;16233:655::-;16369:6;16377;16385;16429:9;16420:7;16416:23;16459:3;16455:2;16451:12;16448:32;;;16476:1;16473;16466:12;16448:32;16516:9;16503:23;-1:-1:-1;;;;;16541:6:48;16538:30;16535:50;;;16581:1;16578;16571:12;16535:50;16604:69;16665:7;16656:6;16645:9;16641:22;16604:69;:::i;:::-;16594:79;-1:-1:-1;;16707:2:48;-1:-1:-1;;16689:16:48;;16685:25;16682:45;;;16723:1;16720;16713:12;16682:45;;16761:2;16750:9;16746:18;16736:28;;16814:2;16803:9;16799:18;16786:32;16827:31;16852:5;16827:31;:::i;16893:609::-;17133:4;17175:3;17164:9;17160:19;17152:27;;17212:6;17206:13;17195:9;17188:32;-1:-1:-1;;;;;17280:4:48;17272:6;17268:17;17262:24;17258:49;17251:4;17240:9;17236:20;17229:79;17355:4;17347:6;17343:17;17337:24;17370:62;17426:4;17415:9;17411:20;17397:12;4038;;4026:25;;4100:4;4089:16;;;4083:23;4067:14;;4060:47;3964:149;17370:62;-1:-1:-1;4038:12:48;;17491:3;17476:19;;4026:25;4100:4;4089:16;;4083:23;4067:14;;;4060:47;17441:55;3964:149;17507:388;17575:6;17583;17636:2;17624:9;17615:7;17611:23;17607:32;17604:52;;;17652:1;17649;17642:12;17604:52;17691:9;17678:23;17710:31;17735:5;17710:31;:::i;:::-;17760:5;-1:-1:-1;17817:2:48;17802:18;;17789:32;17830:33;17789:32;17830:33;:::i;17900:234::-;17983:6;18036:2;18024:9;18015:7;18011:23;18007:32;18004:52;;;18052:1;18049;18042:12;18004:52;18075:53;18120:7;18109:9;18075:53;:::i;18139:380::-;18218:1;18214:12;;;;18261;;;18282:61;;18336:4;18328:6;18324:17;18314:27;;18282:61;18389:2;18381:6;18378:14;18358:18;18355:38;18352:161;;18435:10;18430:3;18426:20;18423:1;18416:31;18470:4;18467:1;18460:15;18498:4;18495:1;18488:15;19006:127;19067:10;19062:3;19058:20;19055:1;19048:31;19098:4;19095:1;19088:15;19122:4;19119:1;19112:15;19138:168;19211:9;;;19242;;19259:15;;;19253:22;;19239:37;19229:71;;19280:18;;:::i;19311:217::-;19351:1;19377;19367:132;;19421:10;19416:3;19412:20;19409:1;19402:31;19456:4;19453:1;19446:15;19484:4;19481:1;19474:15;19367:132;-1:-1:-1;19513:9:48;;19311:217::o;20237:127::-;20298:10;20293:3;20289:20;20286:1;20279:31;20329:4;20326:1;20319:15;20353:4;20350:1;20343:15;20369:336;20474:4;20532:11;20519:25;20626:2;20622:7;20611:8;20595:14;20591:29;20587:43;20567:18;20563:68;20553:96;;20645:1;20642;20635:12;20553:96;20666:33;;;;;20369:336;-1:-1:-1;;20369:336:48:o;20710:521::-;20787:4;20793:6;20853:11;20840:25;20947:2;20943:7;20932:8;20916:14;20912:29;20908:43;20888:18;20884:68;20874:96;;20966:1;20963;20956:12;20874:96;20993:33;;21045:20;;;-1:-1:-1;;;;;;21077:30:48;;21074:50;;;21120:1;21117;21110:12;21074:50;21153:4;21141:17;;-1:-1:-1;21184:14:48;21180:27;;;21170:38;;21167:58;;;21221:1;21218;21211:12;21361:542;21462:2;21457:3;21454:11;21451:446;;;21498:1;21522:5;21519:1;21512:16;21566:4;21563:1;21553:18;21636:2;21624:10;21620:19;21617:1;21613:27;21607:4;21603:38;21672:4;21660:10;21657:20;21654:47;;;-1:-1:-1;21695:4:48;21654:47;21750:2;21745:3;21741:12;21738:1;21734:20;21728:4;21724:31;21714:41;;21805:82;21823:2;21816:5;21813:13;21805:82;;;21868:17;;;21849:1;21838:13;21805:82;;;21809:3;;;21361:542;;;:::o;22079:1202::-;-1:-1:-1;;;;;22196:3:48;22193:27;22190:53;;;22223:18;;:::i;:::-;22252:93;22341:3;22301:38;22333:4;22327:11;22301:38;:::i;:::-;22295:4;22252:93;:::i;:::-;22371:1;22396:2;22391:3;22388:11;22413:1;22408:615;;;;23067:1;23084:3;23081:93;;;-1:-1:-1;23140:19:48;;;23127:33;23081:93;-1:-1:-1;;22036:1:48;22032:11;;;22028:24;22024:29;22014:40;22060:1;22056:11;;;22011:57;23187:78;;22381:894;;22408:615;21308:1;21301:14;;;21345:4;21332:18;;-1:-1:-1;;22444:17:48;;;22544:9;22566:229;22580:7;22577:1;22574:14;22566:229;;;22669:19;;;22656:33;22641:49;;22776:4;22761:20;;;;22729:1;22717:14;;;;22596:12;22566:229;;;22570:3;22823;22814:7;22811:16;22808:159;;;22947:1;22943:6;22937:3;22931;22928:1;22924:11;22920:21;22916:34;22912:39;22899:9;22894:3;22890:19;22877:33;22873:79;22865:6;22858:95;22808:159;;;23010:1;23004:3;23001:1;22997:11;22993:19;22987:4;22980:33;22381:894;;22079:1202;;;:::o;23286:266::-;23374:6;23369:3;23362:19;23426:6;23419:5;23412:4;23407:3;23403:14;23390:43;-1:-1:-1;23478:1:48;23453:16;;;23471:4;23449:27;;;23442:38;;;;23534:2;23513:15;;;-1:-1:-1;;23509:29:48;23500:39;;;23496:50;;23286:266::o;23557:1774::-;23814:2;23866:21;;;23839:18;;;23922:22;;;23785:4;;23963:2;23981:18;;;24045:1;24041:14;;;24026:30;;24022:39;;24084:6;23785:4;24118:1184;24132:6;24129:1;24126:13;24118:1184;;;24197:22;;;-1:-1:-1;;24193:36:48;24181:49;;24269:20;;24344:14;24340:27;;;-1:-1:-1;;24336:41:48;24312:66;;24302:94;;24392:1;24389;24382:12;24302:94;24422:31;;24476:4;24538:10;24512:24;24422:31;24512:24;:::i;:::-;24508:41;24500:6;24493:57;24626:6;24591:33;24620:2;24613:5;24609:14;24591:33;:::i;:::-;24587:46;24582:2;24574:6;24570:15;24563:71;24699:2;24692:5;24688:14;24675:28;24788:2;24784:7;24776:5;24760:14;24756:26;24752:40;24730:20;24726:67;24716:95;;24807:1;24804;24797:12;24716:95;24839:32;;;24947:16;;;;-1:-1:-1;24898:21:48;-1:-1:-1;;;;;24979:30:48;;24976:50;;;25022:1;25019;25012:12;24976:50;25075:6;25059:14;25055:27;25046:7;25042:41;25039:61;;;25096:1;25093;25086:12;25039:61;25137:2;25132;25124:6;25120:15;25113:27;25163:59;25218:2;25210:6;25206:15;25198:6;25189:7;25163:59;:::i;:::-;25280:12;;;;25153:69;-1:-1:-1;;;25245:15:48;;;;-1:-1:-1;24154:1:48;24147:9;24118:1184;;;-1:-1:-1;25319:6:48;;23557:1774;-1:-1:-1;;;;;;;;23557:1774:48:o;25336:331::-;25441:9;25452;25494:8;25482:10;25479:24;25476:44;;;25516:1;25513;25506:12;25476:44;25545:6;25535:8;25532:20;25529:40;;;25565:1;25562;25555:12;25529:40;-1:-1:-1;;25591:23:48;;;25636:25;;;;;-1:-1:-1;25336:331:48:o;25672:476::-;25863:3;25901:6;25895:13;25917:66;25976:6;25971:3;25964:4;25956:6;25952:17;25917:66;:::i;:::-;26005:16;;26058:6;26050;26005:16;26030:35;26122:1;26084:18;;26111:13;;;-1:-1:-1;26084:18:48;;25672:476;-1:-1:-1;;;25672:476:48:o;26153:244::-;26310:2;26299:9;26292:21;26273:4;26330:61;26387:2;26376:9;26372:18;26364:6;26356;26330:61;:::i;26402:331::-;26501:4;26559:11;26546:25;26653:3;26649:8;26638;26622:14;26618:29;26614:44;26594:18;26590:69;26580:97;;26673:1;26670;26663:12;26738:129;-1:-1:-1;;;;;26816:5:48;26812:30;26805:5;26802:41;26792:69;;26857:1;26854;26847:12;26872:988;27246:10;27219:25;27237:6;27219:25;:::i;:::-;27215:42;27204:9;27197:61;27321:4;27313:6;27309:17;27296:31;27289:4;27278:9;27274:20;27267:61;27178:4;27375;27367:6;27363:17;27350:31;27390:30;27414:5;27390:30;:::i;:::-;-1:-1:-1;;;;;27462:5:48;27458:30;27451:4;27440:9;27436:20;27429:60;;27525:6;27520:2;27509:9;27505:18;27498:34;27569:3;27563;27552:9;27548:19;27541:32;27596:62;27653:3;27642:9;27638:19;27630:6;27622;27596:62;:::i;:::-;-1:-1:-1;;;;;27695:32:48;;27715:3;27674:19;;27667:61;27765:22;;;27759:3;27744:19;;27737:51;27805:49;27769:6;27839;27831;27805:49;:::i;:::-;27797:57;26872:988;-1:-1:-1;;;;;;;;;;26872:988:48:o;27865:648::-;27944:6;27997:2;27985:9;27976:7;27972:23;27968:32;27965:52;;;28013:1;28010;28003:12;27965:52;28046:9;28040:16;-1:-1:-1;;;;;28071:6:48;28068:30;28065:50;;;28111:1;28108;28101:12;28065:50;28134:22;;28187:4;28179:13;;28175:27;-1:-1:-1;28165:55:48;;28216:1;28213;28206:12;28165:55;28245:2;28239:9;28270:49;28286:32;28315:2;28286:32;:::i;28270:49::-;28342:2;28335:5;28328:17;28382:7;28377:2;28372;28368;28364:11;28360:20;28357:33;28354:53;;;28403:1;28400;28393:12;28354:53;28416:67;28480:2;28475;28468:5;28464:14;28459:2;28455;28451:11;28416:67;:::i;29316:245::-;29374:6;29427:2;29415:9;29406:7;29402:23;29398:32;29395:52;;;29443:1;29440;29433:12;29395:52;29482:9;29469:23;29501:30;29525:5;29501:30;:::i;29566:479::-;29833:1;29829;29824:3;29820:11;29816:19;29808:6;29804:32;29793:9;29786:51;29873:6;29868:2;29857:9;29853:18;29846:34;29928:6;29920;29916:19;29911:2;29900:9;29896:18;29889:47;29972:3;29967:2;29956:9;29952:18;29945:31;29767:4;29993:46;30034:3;30023:9;30019:19;30011:6;29993:46;:::i;30668:379::-;30861:2;30850:9;30843:21;30824:4;30887:45;30928:2;30917:9;30913:18;30905:6;30887:45;:::i;:::-;30980:9;30972:6;30968:22;30963:2;30952:9;30948:18;30941:50;31008:33;31034:6;31026;31008:33;:::i;31052:245::-;31119:6;31172:2;31160:9;31151:7;31147:23;31143:32;31140:52;;;31188:1;31185;31178:12;31140:52;31220:9;31214:16;31239:28;31261:5;31239:28;:::i;31302:887::-;31521:2;31510:9;31503:21;31579:10;31570:6;31564:13;31560:30;31555:2;31544:9;31540:18;31533:58;31645:4;31637:6;31633:17;31627:24;31622:2;31611:9;31607:18;31600:52;31484:4;31699:2;31691:6;31687:15;31681:22;31740:4;31734:3;31723:9;31719:19;31712:33;31768:52;31815:3;31804:9;31800:19;31786:12;31768:52;:::i;:::-;31754:66;;31869:2;31861:6;31857:15;31851:22;31943:2;31939:7;31927:9;31919:6;31915:22;31911:36;31904:4;31893:9;31889:20;31882:66;31971:41;32005:6;31989:14;31971:41;:::i;:::-;32081:3;32069:16;;;;32063:23;32056:31;32049:39;32043:3;32028:19;;32021:68;-1:-1:-1;;;;;;;;32150:32:48;;;;32143:4;32128:20;;;32121:62;31957:55;31302:887::o;32194:284::-;32264:5;32312:4;32300:9;32295:3;32291:19;32287:30;32284:50;;;32330:1;32327;32320:12;32284:50;32352:22;;:::i;:::-;32343:31;;32403:9;32397:16;32390:5;32383:31;32467:2;32456:9;32452:18;32446:25;32441:2;32434:5;32430:14;32423:49;32194:284;;;;:::o;32483:257::-;32581:6;32634:2;32622:9;32613:7;32609:23;32605:32;32602:52;;;32650:1;32647;32640:12;32602:52;32673:61;32726:7;32715:9;32673:61;:::i;32745:318::-;-1:-1:-1;;;;;;32865:19:48;;32936:11;;;;32967:1;32959:10;;32956:101;;;33044:2;33038;33031:3;33028:1;33024:11;33021:1;33017:19;33013:28;33009:2;33005:37;33001:46;32992:55;;32956:101;;;32745:318;;;;:::o;33068:346::-;33155:6;33208:2;33196:9;33187:7;33183:23;33179:32;33176:52;;;33224:1;33221;33214:12;33176:52;33250:22;;:::i;:::-;33308:9;33295:23;33288:5;33281:38;33379:2;33368:9;33364:18;33351:32;33346:2;33339:5;33335:14;33328:56;33403:5;33393:15;;;33068:346;;;;:::o;33758:255::-;33878:19;;33917:2;33909:11;;33906:101;;;-1:-1:-1;;33978:2:48;33974:12;;;33971:1;33967:20;33963:33;33952:45;33758:255;;;;:::o;34018:331::-;-1:-1:-1;;;;;;34138:19:48;;34222:11;;;;34253:1;34245:10;;34242:101;;;34314:1;34310:11;;;;34307:1;34303:19;34299:28;;;34291:37;34287:46;;;;34018:331;-1:-1:-1;;34018:331:48:o;34354:568::-;-1:-1:-1;;;;;34619:3:48;34615:28;34606:6;34601:3;34597:16;34593:51;34588:3;34581:64;34705:10;34700:3;34696:20;34687:6;34682:3;34678:16;34674:43;34670:1;34665:3;34661:11;34654:64;34748:6;34743:2;34738:3;34734:12;34727:28;34563:3;34784:6;34778:13;34800:75;34868:6;34863:2;34858:3;34854:12;34847:4;34839:6;34835:17;34800:75;:::i;:::-;34895:16;;;;34913:2;34891:25;;34354:568;-1:-1:-1;;;;;34354:568:48:o;34927:135::-;34966:3;34987:17;;;34984:43;;35007:18;;:::i;:::-;-1:-1:-1;35054:1:48;35043:13;;34927:135::o;35686:532::-;35927:6;35922:3;35915:19;-1:-1:-1;;;;;35990:3:48;35986:28;35977:6;35972:3;35968:16;35964:51;35959:2;35954:3;35950:12;35943:73;36046:6;36041:2;36036:3;36032:12;36025:28;35897:3;36082:6;36076:13;36098:73;36164:6;36159:2;36154:3;36150:12;36145:2;36137:6;36133:15;36098:73;:::i;:::-;36191:16;;;;36209:2;36187:25;;35686:532;-1:-1:-1;;;;;35686:532:48:o;36223:1343::-;36349:3;36343:10;-1:-1:-1;;;;;36368:6:48;36365:30;36362:56;;;36398:18;;:::i;:::-;36427:96;36516:6;36476:38;36508:4;36502:11;36476:38;:::i;:::-;36470:4;36427:96;:::i;:::-;36578:4;;36635:2;36624:14;;36652:1;36647:662;;;;37353:1;37370:6;37367:89;;;-1:-1:-1;37422:19:48;;;37416:26;37367:89;-1:-1:-1;;22036:1:48;22032:11;;;22028:24;22024:29;22014:40;22060:1;22056:11;;;22011:57;37469:81;;36617:943;;36647:662;21308:1;21301:14;;;21345:4;21332:18;;-1:-1:-1;;36683:20:48;;;36800:236;36814:7;36811:1;36808:14;36800:236;;;36903:19;;;36897:26;36882:42;;36995:27;;;;36963:1;36951:14;;;;36830:19;;36800:236;;;36804:3;37064:6;37055:7;37052:19;37049:201;;;37125:19;;;37119:26;-1:-1:-1;;37208:1:48;37204:14;;;37220:3;37200:24;37196:37;37192:42;37177:58;37162:74;;37049:201;-1:-1:-1;;;;;37296:1:48;37280:14;;;37276:22;37263:36;;-1:-1:-1;36223:1343:48:o;37990:128::-;38057:9;;;38078:11;;;38075:37;;;38092:18;;:::i;38123:681::-;38225:6;38278:3;38266:9;38257:7;38253:23;38249:33;38246:53;;;38295:1;38292;38285:12;38246:53;38328:2;38322:9;38370:4;38362:6;38358:17;38441:6;38429:10;38426:22;-1:-1:-1;;;;;38393:10:48;38390:34;38387:62;38384:88;;;38452:18;;:::i;:::-;38488:2;38481:22;38527:16;;38512:32;;38587:2;38572:18;;38566:25;38600:30;38566:25;38600:30;:::i;:::-;38658:2;38646:15;;38639:30;38702:70;38764:7;38759:2;38744:18;;38702:70;:::i;:::-;38697:2;38685:15;;38678:95;38689:6;38123:681;-1:-1:-1;;;38123:681:48:o;38809:125::-;38874:9;;;38895:10;;;38892:36;;;38908:18;;:::i;38939:251::-;39009:6;39062:2;39050:9;39041:7;39037:23;39033:32;39030:52;;;39078:1;39075;39068:12;39030:52;39110:9;39104:16;39129:31;39154:5;39129:31;:::i
Swarm Source
ipfs://1f248ed02b808c1ae29a9f9f54f2f17eb576e8abbaff0b6b42bafc474f592bed
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.