Source Code
                
                
                
                    
                
                
            
            
        Overview
ETH Balance
0 ETH
                            ETH Value
$0.00Multichain Info
                            
                            N/A
                            
                        
                        
                    View more zero value Internal Transactions in Advanced View mode
                                    
                                    
                                    
                                         Advanced mode:
                                    
                                    
                                    
                                        
                                    
                                    
                                
                            
Cross-Chain Transactions
Loading...
Loading
Contract Name:
                                        
                                            GGUSDOFT
                                        
                                    Compiler Version
                                        
                                            v0.8.22+commit.4fc1097e
                                        
                                    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 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 { IERC20Metadata, IERC20 } from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import { IOFT, OFTCoreUpgradeable } from "./OFTCoreUpgradeable.sol";
import { FeeUpgradeable } from "./FeeUpgradeable.sol";
import { OFTAdapterUpgradeable } from "./OFTAdapterUpgradeable.sol";
/**
 * @title OFTAdapterFeeUpgradeable Contract
 * @dev OFTAdapter is a contract that adapts an ERC-20 token to the OFT functionality.
 *
 * @dev For existing ERC20 tokens, this can be used to convert the token to crosschain compatibility.
 * @dev WARNING: ONLY 1 of these should exist for a given global mesh,
 * unless you make a NON-default implementation of OFT and needs to be done very carefully.
 * @dev WARNING: The default OFTAdapter implementation assumes LOSSLESS transfers, ie. 1 token in, 1 token out.
 * IF the 'innerToken' applies something like a transfer fee, the default will NOT work...
 * a pre/post balance check will need to be done to calculate the amountSentLD/amountReceivedLD.
 */
abstract contract OFTAdapterFeeUpgradeable is OFTAdapterUpgradeable, FeeUpgradeable {
    using SafeERC20 for IERC20;
    struct OFTAdapterFeeStorage {
        uint256 feeBalance;
    }
    // keccak256(abi.encode(uint256(keccak256("layerzerov2.storage.oftadapterfee")) - 1)) & ~bytes32(uint256(0xff))
    bytes32 private constant OFT_ADAPTER_FEE_STORAGE_LOCATION =
        0x75ae803fc5bc34bf9750128bd6622421186811a8566aa9e660cbc56033db8c00;
    function _getOFTAdapterFeeStorage() internal pure returns (OFTAdapterFeeStorage storage $) {
        assembly {
            $.slot := OFT_ADAPTER_FEE_STORAGE_LOCATION
        }
    }
    function feeBalance() public view returns (uint256) {
        OFTAdapterFeeStorage storage $ = _getOFTAdapterFeeStorage();
        return $.feeBalance;
    }
    event FeeWithdrawn(address indexed to, uint256 amountLD);
    
    error NoFeesToWithdraw();
    /**
     * @dev Constructor for initializing the contract with token and endpoint addresses.
     * @param _token The address of the token.
     * @param _lzEndpoint The address of the LayerZero endpoint.
     * @dev _token must implement the IERC20 interface, and include a decimals() function.
     */
    constructor(address _token, address _lzEndpoint) OFTAdapterUpgradeable(_token, _lzEndpoint) {}
    /**
     * @dev Initializes the OFTAdapter 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 __OFTAdapterFee_init(address _delegate) internal onlyInitializing {
        __OFTAdapter_init(_delegate);
        __Fee_init();
    }
    function __OFTAdapterFee_init_unchained() internal onlyInitializing {}
    /**
     * @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 {
        // @dev doesn't allow owner to pull from the locked assets of the contract,
        // only from accumulated fees
        OFTAdapterFeeStorage storage $ = _getOFTAdapterFeeStorage();
        uint256 balance = $.feeBalance;
        if (balance == 0) revert NoFeesToWithdraw();
        $.feeBalance = 0;
        innerToken.safeTransfer(_to, balance);
        emit FeeWithdrawn(_to, balance);
    }
    /**
     * @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 Transfers the full amount from the sender's balance to the contract,
     *      then burns the amount minus the fee from the contract leaving the fee locked in the contract.
     * @param _from The address to debit 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);
        if (amountSentLD > amountReceivedLD) {
            // @dev Increment the total fees that can be withdrawn.
            //      Fees include the dust resulting from the de-dust operation.
            OFTAdapterFeeStorage storage $ = _getOFTAdapterFeeStorage();
            unchecked {
                $.feeBalance += (amountSentLD - amountReceivedLD);
            }
        }
        // @dev Lock tokens by moving them into this contract from the caller.
        innerToken.safeTransferFrom(_from, address(this), amountSentLD);
    }
    /**
     * @dev Credits tokens to the specified address.
     * @param _to The address to credit the tokens to.
     * @param _amountLD The amount of tokens to credit in local decimals.
     * @dev _srcEid The source chain ID.
     * @return amountReceivedLD The amount of tokens ACTUALLY received in local decimals.
     */
    function _credit(
        address _to,
        uint256 _amountLD,
        uint32 // _srcEid
    ) internal virtual override returns (uint256 amountReceivedLD) {
        // @dev Unlock the tokens and transfer to the recipient.
        innerToken.safeTransfer(_to, _amountLD);
        // @dev In the case of NON-default OFTAdapter, the amountLD MIGHT not be == amountReceivedLD.
        return _amountLD;
    }
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import { IERC20Metadata, IERC20 } from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import { IOFT, OFTCoreUpgradeable } from "./OFTCoreUpgradeable.sol";
/**
 * @title OFTAdapter Contract
 * @dev OFTAdapter is a contract that adapts an ERC-20 token to the OFT functionality.
 *
 * @dev For existing ERC20 tokens, this can be used to convert the token to crosschain compatibility.
 * @dev WARNING: ONLY 1 of these should exist for a given global mesh,
 * unless you make a NON-default implementation of OFT and needs to be done very carefully.
 * @dev WARNING: The default OFTAdapter implementation assumes LOSSLESS transfers, ie. 1 token in, 1 token out.
 * IF the 'innerToken' applies something like a transfer fee, the default will NOT work...
 * a pre/post balance check will need to be done to calculate the amountSentLD/amountReceivedLD.
 */
abstract contract OFTAdapterUpgradeable is OFTCoreUpgradeable {
    using SafeERC20 for IERC20;
    IERC20 internal immutable innerToken;
    /**
     * @dev Constructor for the OFTAdapter contract.
     * @param _token The address of the ERC-20 token to be adapted.
     * @param _lzEndpoint The LayerZero endpoint address.
     * @dev _token must implement the IERC20 interface, and include a decimals() function.
     */
    constructor(
        address _token,
        address _lzEndpoint
    ) OFTCoreUpgradeable(IERC20Metadata(_token).decimals(), _lzEndpoint) {
        innerToken = IERC20(_token);
    }
    /**
     * @dev Initializes the OFTAdapter 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 __OFTAdapter_init(address _delegate) internal onlyInitializing {
        __OFTCore_init(_delegate);
    }
    function __OFTAdapter_init_unchained() internal onlyInitializing {}
    /**
     * @dev Retrieves the address of the underlying ERC20 implementation.
     * @return The address of the adapted ERC-20 token.
     *
     * @dev In the case of OFTAdapter, address(this) and erc20 are NOT the same contract.
     */
    function token() public view returns (address) {
        return address(innerToken);
    }
    /**
     * @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 default OFTAdapter, approval is required.
     * @dev In non-default OFTAdapter contracts with something like mint and burn privileges, it would NOT need approval.
     */
    function approvalRequired() external pure virtual returns (bool) {
        return true;
    }
    /**
     * @dev Burns tokens from the sender's specified balance, ie. pull method.
     * @param _from The address to debit 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.
     *
     * @dev msg.sender will need to approve this _amountLD of tokens to be locked inside of the contract.
     * @dev WARNING: The default OFTAdapter implementation assumes LOSSLESS transfers, ie. 1 token in, 1 token out.
     * IF the 'innerToken' applies something like a transfer fee, the default will NOT work...
     * a pre/post balance check will need to be done to calculate the amountReceivedLD.
     */
    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 Lock tokens by moving them into this contract from the caller.
        innerToken.safeTransferFrom(_from, address(this), 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.
     *
     * @dev WARNING: The default OFTAdapter implementation assumes LOSSLESS transfers, ie. 1 token in, 1 token out.
     * IF the 'innerToken' applies something like a transfer fee, the default will NOT work...
     * a pre/post balance check will need to be done to calculate the amountReceivedLD.
     */
    function _credit(
        address _to,
        uint256 _amountLD,
        uint32 /*_srcEid*/
    ) internal virtual override returns (uint256 amountReceivedLD) {
        // @dev Unlock the tokens and transfer to the recipient.
        innerToken.safeTransfer(_to, _amountLD);
        // @dev In the case of NON-default OFTAdapter, the amountLD MIGHT not be == amountReceivedLD.
        return _amountLD;
    }
}// 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/ERC20.sol)
pragma solidity ^0.8.20;
import {IERC20} from "./IERC20.sol";
import {IERC20Metadata} from "./extensions/IERC20Metadata.sol";
import {Context} from "../../utils/Context.sol";
import {IERC20Errors} from "../../interfaces/draft-IERC6093.sol";
/**
 * @dev Implementation of the {IERC20} interface.
 *
 * This implementation is agnostic to the way tokens are created. This means
 * that a supply mechanism has to be added in a derived contract using {_mint}.
 *
 * TIP: For a detailed writeup see our guide
 * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How
 * to implement supply mechanisms].
 *
 * The default value of {decimals} is 18. To change this, you should override
 * this function so it returns a different value.
 *
 * We have followed general OpenZeppelin Contracts guidelines: functions revert
 * instead returning `false` on failure. This behavior is nonetheless
 * conventional and does not conflict with the expectations of ERC-20
 * applications.
 */
abstract contract ERC20 is Context, IERC20, IERC20Metadata, IERC20Errors {
    mapping(address account => uint256) private _balances;
    mapping(address account => mapping(address spender => uint256)) private _allowances;
    uint256 private _totalSupply;
    string private _name;
    string private _symbol;
    /**
     * @dev Sets the values for {name} and {symbol}.
     *
     * Both values are immutable: they can only be set once during construction.
     */
    constructor(string memory name_, string memory symbol_) {
        _name = name_;
        _symbol = symbol_;
    }
    /**
     * @dev Returns the name of the token.
     */
    function name() public view virtual returns (string memory) {
        return _name;
    }
    /**
     * @dev Returns the symbol of the token, usually a shorter version of the
     * name.
     */
    function symbol() public view virtual returns (string memory) {
        return _symbol;
    }
    /**
     * @dev Returns the number of decimals used to get its user representation.
     * For example, if `decimals` equals `2`, a balance of `505` tokens should
     * be displayed to a user as `5.05` (`505 / 10 ** 2`).
     *
     * Tokens usually opt for a value of 18, imitating the relationship between
     * Ether and Wei. This is the default value returned by this function, unless
     * it's overridden.
     *
     * NOTE: This information is only used for _display_ purposes: it in
     * no way affects any of the arithmetic of the contract, including
     * {IERC20-balanceOf} and {IERC20-transfer}.
     */
    function decimals() public view virtual returns (uint8) {
        return 18;
    }
    /// @inheritdoc IERC20
    function totalSupply() public view virtual returns (uint256) {
        return _totalSupply;
    }
    /// @inheritdoc IERC20
    function balanceOf(address account) public view virtual returns (uint256) {
        return _balances[account];
    }
    /**
     * @dev See {IERC20-transfer}.
     *
     * Requirements:
     *
     * - `to` cannot be the zero address.
     * - the caller must have a balance of at least `value`.
     */
    function transfer(address to, uint256 value) public virtual returns (bool) {
        address owner = _msgSender();
        _transfer(owner, to, value);
        return true;
    }
    /// @inheritdoc IERC20
    function allowance(address owner, address spender) public view virtual returns (uint256) {
        return _allowances[owner][spender];
    }
    /**
     * @dev See {IERC20-approve}.
     *
     * NOTE: If `value` is the maximum `uint256`, the allowance is not updated on
     * `transferFrom`. This is semantically equivalent to an infinite approval.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function approve(address spender, uint256 value) public virtual returns (bool) {
        address owner = _msgSender();
        _approve(owner, spender, value);
        return true;
    }
    /**
     * @dev See {IERC20-transferFrom}.
     *
     * Skips emitting an {Approval} event indicating an allowance update. This is not
     * required by the ERC. See {xref-ERC20-_approve-address-address-uint256-bool-}[_approve].
     *
     * NOTE: Does not update the allowance if the current allowance
     * is the maximum `uint256`.
     *
     * Requirements:
     *
     * - `from` and `to` cannot be the zero address.
     * - `from` must have a balance of at least `value`.
     * - the caller must have allowance for ``from``'s tokens of at least
     * `value`.
     */
    function transferFrom(address from, address to, uint256 value) public virtual returns (bool) {
        address spender = _msgSender();
        _spendAllowance(from, spender, value);
        _transfer(from, to, value);
        return true;
    }
    /**
     * @dev Moves a `value` amount of tokens from `from` to `to`.
     *
     * This internal function is equivalent to {transfer}, and can be used to
     * e.g. implement automatic token fees, slashing mechanisms, etc.
     *
     * Emits a {Transfer} event.
     *
     * NOTE: This function is not virtual, {_update} should be overridden instead.
     */
    function _transfer(address from, address to, uint256 value) internal {
        if (from == address(0)) {
            revert ERC20InvalidSender(address(0));
        }
        if (to == address(0)) {
            revert ERC20InvalidReceiver(address(0));
        }
        _update(from, to, value);
    }
    /**
     * @dev Transfers a `value` amount of tokens from `from` to `to`, or alternatively mints (or burns) if `from`
     * (or `to`) is the zero address. All customizations to transfers, mints, and burns should be done by overriding
     * this function.
     *
     * Emits a {Transfer} event.
     */
    function _update(address from, address to, uint256 value) internal virtual {
        if (from == address(0)) {
            // Overflow check required: The rest of the code assumes that totalSupply never overflows
            _totalSupply += value;
        } else {
            uint256 fromBalance = _balances[from];
            if (fromBalance < value) {
                revert ERC20InsufficientBalance(from, fromBalance, value);
            }
            unchecked {
                // Overflow not possible: value <= fromBalance <= totalSupply.
                _balances[from] = fromBalance - value;
            }
        }
        if (to == address(0)) {
            unchecked {
                // Overflow not possible: value <= totalSupply or value <= fromBalance <= totalSupply.
                _totalSupply -= value;
            }
        } else {
            unchecked {
                // Overflow not possible: balance + value is at most totalSupply, which we know fits into a uint256.
                _balances[to] += value;
            }
        }
        emit Transfer(from, to, value);
    }
    /**
     * @dev Creates a `value` amount of tokens and assigns them to `account`, by transferring it from address(0).
     * Relies on the `_update` mechanism
     *
     * Emits a {Transfer} event with `from` set to the zero address.
     *
     * NOTE: This function is not virtual, {_update} should be overridden instead.
     */
    function _mint(address account, uint256 value) internal {
        if (account == address(0)) {
            revert ERC20InvalidReceiver(address(0));
        }
        _update(address(0), account, value);
    }
    /**
     * @dev Destroys a `value` amount of tokens from `account`, lowering the total supply.
     * Relies on the `_update` mechanism.
     *
     * Emits a {Transfer} event with `to` set to the zero address.
     *
     * NOTE: This function is not virtual, {_update} should be overridden instead
     */
    function _burn(address account, uint256 value) internal {
        if (account == address(0)) {
            revert ERC20InvalidSender(address(0));
        }
        _update(account, address(0), value);
    }
    /**
     * @dev Sets `value` as the allowance of `spender` over the `owner`'s tokens.
     *
     * This internal function is equivalent to `approve`, and can be used to
     * e.g. set automatic allowances for certain subsystems, etc.
     *
     * Emits an {Approval} event.
     *
     * Requirements:
     *
     * - `owner` cannot be the zero address.
     * - `spender` cannot be the zero address.
     *
     * Overrides to this logic should be done to the variant with an additional `bool emitEvent` argument.
     */
    function _approve(address owner, address spender, uint256 value) internal {
        _approve(owner, spender, value, true);
    }
    /**
     * @dev Variant of {_approve} with an optional flag to enable or disable the {Approval} event.
     *
     * By default (when calling {_approve}) the flag is set to true. On the other hand, approval changes made by
     * `_spendAllowance` during the `transferFrom` operation set the flag to false. This saves gas by not emitting any
     * `Approval` event during `transferFrom` operations.
     *
     * Anyone who wishes to continue emitting `Approval` events on the`transferFrom` operation can force the flag to
     * true using the following override:
     *
     * ```solidity
     * function _approve(address owner, address spender, uint256 value, bool) internal virtual override {
     *     super._approve(owner, spender, value, true);
     * }
     * ```
     *
     * Requirements are the same as {_approve}.
     */
    function _approve(address owner, address spender, uint256 value, bool emitEvent) internal virtual {
        if (owner == address(0)) {
            revert ERC20InvalidApprover(address(0));
        }
        if (spender == address(0)) {
            revert ERC20InvalidSpender(address(0));
        }
        _allowances[owner][spender] = value;
        if (emitEvent) {
            emit Approval(owner, spender, value);
        }
    }
    /**
     * @dev Updates `owner`'s allowance for `spender` based on spent `value`.
     *
     * Does not update the allowance value in case of infinite allowance.
     * Revert if not enough allowance is available.
     *
     * Does not emit an {Approval} event.
     */
    function _spendAllowance(address owner, address spender, uint256 value) internal virtual {
        uint256 currentAllowance = allowance(owner, spender);
        if (currentAllowance < type(uint256).max) {
            if (currentAllowance < value) {
                revert ERC20InsufficientAllowance(spender, currentAllowance, value);
            }
            unchecked {
                _approve(owner, spender, currentAllowance - value, false);
            }
        }
    }
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.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);
}// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.9;
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
contract Empty is Initializable {
    /// @custom:oz-upgrades-unsafe-allow constructor
    constructor() {
        _disableInitializers();
    }
    function initialize() public initializer {
    }
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.22;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
contract GGUSD is ERC20 {
    address public minter; // 指定的mint权限账户
    constructor(address _minter) ERC20("GGUSD", "GGUSD") {
        minter = _minter;
    }
    function mint(address to, uint256 amount) public {
        require(msg.sender == minter, "Only minter can mint tokens");
        _mint(to, amount);
    }
    function decimals() public override view virtual returns (uint8) {
        return 6;
    }
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.22;
import "@layerzerolabs/oft-evm/contracts/interfaces/IOFT.sol";
import {OFTAdapterFeeUpgradeable} from "@layerzerolabs/oft-evm-upgradeable/contracts/oft/OFTAdapterFeeUpgradeable.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
contract GGUSDOFTAdapter is OFTAdapterFeeUpgradeable {
    using SafeERC20 for IERC20;
    address private feeAddress;
    mapping(address => bool) private whitelist;
    event FeeAddress(address feeAddress);
    event WhitelistUpdated(address indexed account, bool isWhitelisted);
    constructor(
        address _token,
        address _lzEndpoint
    ) OFTAdapterFeeUpgradeable(_token, _lzEndpoint){
        _disableInitializers();
    }
    function initialize(
        address _delegate
    ) public initializer {
        __OFTAdapter_init(_delegate);
        __Ownable_init(_delegate);
        feeAddress = address(0);
    }
    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 virtual override 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 (feeAddress == address(0)) {
            if (fee > 0) {
                OFTAdapterFeeStorage storage $ = _getOFTAdapterFeeStorage();
                unchecked {
                    $.feeBalance += fee;
                }
            }
            innerToken.safeTransferFrom(_from, address(this), amountSentLD);
        } else {
            // transfer fee to special account
            if (fee > 0) {
                innerToken.safeTransferFrom(_from, feeAddress, fee);
            }
            innerToken.safeTransferFrom(_from, address(this), 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 sharedDecimals() public pure override virtual returns (uint8) {
        return 6;
    }
}pragma solidity ^0.8.22; // optimization enabled, 99999 runs, evm: petersburg
/**
 * @title Immutable Create2 Contract Factory
 * @author 0age
 * @notice This contract provides a safeCreate2 function that takes a salt value
 * and a block of initialization code as arguments and passes them into inline
 * assembly. The contract prevents redeploys by maintaining a mapping of all
 * contracts that have already been deployed, and prevents frontrunning or other
 * collisions by requiring that the first 20 bytes of the salt are equal to the
 * address of the caller (this can be bypassed by setting the first 20 bytes to
 * the null address). There is also a view function that computes the address of
 * the contract that will be created when submitting a given salt or nonce along
 * with a given block of initialization code.
 * @dev This contract has not yet been fully tested or audited - proceed with
 * caution and please share any exploits or optimizations you discover.
 */
contract ImmutableCreate2Factory {
    // mapping to track which addresses have already been deployed.
    mapping(address => bool) private _deployed;
    /**
     * @dev Create a contract using CREATE2 by submitting a given salt or nonce
   * along with the initialization code for the contract. Note that the first 20
   * bytes of the salt must match those of the calling address, which prevents
   * contract creation events from being submitted by unintended parties.
   * @param salt bytes32 The nonce that will be passed into the CREATE2 call.
   * @param initializationCode bytes The initialization code that will be passed
   * into the CREATE2 call.
   * @return deploymentAddress Address of the contract that will be created, or the null address
   * if a contract already exists at that address.
   */
    function safeCreate2(
        bytes32 salt,
        bytes calldata initializationCode
    ) external payable containsCaller(salt) returns (address deploymentAddress) {
        // move the initialization code from calldata to memory.
        bytes memory initCode = initializationCode;
        // determine the target address for contract deployment.
        address targetDeploymentAddress = address(
            uint160(                    // downcast to match the address type.
                uint256(                  // convert to uint to truncate upper digits.
                    keccak256(              // compute the CREATE2 hash using 4 inputs.
                        abi.encodePacked(     // pack all inputs to the hash together.
                            hex"ff",            // start with 0xff to distinguish from RLP.
                            address(this),      // this contract will be the caller.
                            salt,               // pass in the supplied salt value.
                            keccak256(          // pass in the hash of initialization code.
                                abi.encodePacked(
                                    initCode
                                )
                            )
                        )
                    )
                )
            )
        );
        // ensure that a contract hasn't been previously deployed to target address.
        require(
            !_deployed[targetDeploymentAddress],
            "Invalid contract creation - contract has already been deployed."
        );
        // using inline assembly: load data and length of data, then call CREATE2.
        assembly {                                // solhint-disable-line
            let encoded_data := add(0x20, initCode) // load initialization code.
            let encoded_size := mload(initCode)     // load the init code's length.
            deploymentAddress := create2(           // call CREATE2 with 4 arguments.
                callvalue(),                            // forward any attached value.
                encoded_data,                         // pass in initialization code.
                encoded_size,                         // pass in init code's length.
                salt                                  // pass in the salt value.
            )
        }
        // check address against target to ensure that deployment was successful.
        require(
            deploymentAddress == targetDeploymentAddress,
            "Failed to deploy contract using provided salt and initialization code."
        );
        // record the deployment of the contract to prevent redeploys.
        _deployed[deploymentAddress] = true;
    }
    /**
     * @dev Compute the address of the contract that will be created when
   * submitting a given salt or nonce to the contract along with the contract's
   * initialization code. The CREATE2 address is computed in accordance with
   * EIP-1014, and adheres to the formula therein of
   * `keccak256( 0xff ++ address ++ salt ++ keccak256(init_code)))[12:]` when
   * performing the computation. The computed address is then checked for any
   * existing contract code - if so, the null address will be returned instead.
   * @param salt bytes32 The nonce passed into the CREATE2 address calculation.
   * @param initCode bytes The contract initialization code to be used.
   * that will be passed into the CREATE2 address calculation.
   * @return deploymentAddress Address of the contract that will be created, or the null address
   * if a contract has already been deployed to that address.
   */
    function findCreate2Address(
        bytes32 salt,
        bytes calldata initCode
    ) external view returns (address deploymentAddress) {
        // determine the address where the contract will be deployed.
        deploymentAddress = address(
            uint160(                      // downcast to match the address type.
                uint256(                    // convert to uint to truncate upper digits.
                    keccak256(                // compute the CREATE2 hash using 4 inputs.
                        abi.encodePacked(       // pack all inputs to the hash together.
                            hex"ff",              // start with 0xff to distinguish from RLP.
                            address(this),        // this contract will be the caller.
                            salt,                 // pass in the supplied salt value.
                            keccak256(            // pass in the hash of initialization code.
                                abi.encodePacked(
                                    initCode
                                )
                            )
                        )
                    )
                )
            )
        );
        // return null address to signify failure if contract has been deployed.
        if (_deployed[deploymentAddress]) {
            return address(0);
        }
    }
    /**
     * @dev Compute the address of the contract that will be created when
   * submitting a given salt or nonce to the contract along with the keccak256
   * hash of the contract's initialization code. The CREATE2 address is computed
   * in accordance with EIP-1014, and adheres to the formula therein of
   * `keccak256( 0xff ++ address ++ salt ++ keccak256(init_code)))[12:]` when
   * performing the computation. The computed address is then checked for any
   * existing contract code - if so, the null address will be returned instead.
   * @param salt bytes32 The nonce passed into the CREATE2 address calculation.
   * @param initCodeHash bytes32 The keccak256 hash of the initialization code
   * that will be passed into the CREATE2 address calculation.
   * @return deploymentAddress Address of the contract that will be created, or the null address
   * if a contract has already been deployed to that address.
   */
    function findCreate2AddressViaHash(
        bytes32 salt,
        bytes32 initCodeHash
    ) external view returns (address deploymentAddress) {
        // determine the address where the contract will be deployed.
        deploymentAddress = address(
            uint160(                      // downcast to match the address type.
                uint256(                    // convert to uint to truncate upper digits.
                    keccak256(                // compute the CREATE2 hash using 4 inputs.
                        abi.encodePacked(       // pack all inputs to the hash together.
                            hex"ff",              // start with 0xff to distinguish from RLP.
                            address(this),        // this contract will be the caller.
                            salt,                 // pass in the supplied salt value.
                            initCodeHash          // pass in the hash of initialization code.
                        )
                    )
                )
            )
        );
        // return null address to signify failure if contract has been deployed.
        if (_deployed[deploymentAddress]) {
            return address(0);
        }
    }
    /**
     * @dev Determine if a contract has already been deployed by the factory to a
   * given address.
   * @param deploymentAddress address The contract address to check.
   * @return True if the contract has been deployed, false otherwise.
   */
    function hasBeenDeployed(
        address deploymentAddress
    ) external view returns (bool) {
        // determine if a contract has been deployed to the provided address.
        return _deployed[deploymentAddress];
    }
    /**
     * @dev Modifier to ensure that the first 20 bytes of a submitted salt match
   * those of the calling account. This provides protection against the salt
   * being stolen by frontrunners or other attackers. The protection can also be
   * bypassed if desired by setting each of the first 20 bytes to zero.
   * @param salt bytes32 The salt value to check against the calling address.
   */
    modifier containsCaller(bytes32 salt) {
        // prevent contract submissions from being stolen from tx.pool by requiring
        // that the first 20 bytes of the submitted salt match msg.sender.
        require(
            (address(bytes20(salt)) == msg.sender) ||
            (bytes20(salt) == bytes20(0)),
            "Invalid salt - first 20 bytes of the salt must match calling address."
        );
        _;
    }
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (proxy/transparent/ProxyAdmin.sol)
pragma solidity ^0.8.0;
import {TransparentUpgradeableProxy} from "hardhat-deploy/solc_0.8/openzeppelin/proxy/transparent/TransparentUpgradeableProxy.sol";
import {Ownable} from "hardhat-deploy/solc_0.8/openzeppelin/access/Ownable.sol";
/**
 * @dev This is an auxiliary contract meant to be assigned as the admin of a {TransparentUpgradeableProxy}. For an
 * explanation of why you would want to use this see the documentation for {TransparentUpgradeableProxy}.
 */
contract ProxyAdmin is Ownable {
    constructor (address initialOwner) Ownable(initialOwner) {}
    /**
     * @dev Returns the current implementation of `proxy`.
     *
     * Requirements:
     *
     * - This contract must be the admin of `proxy`.
     */
    function getProxyImplementation(TransparentUpgradeableProxy proxy) public view virtual returns (address) {
        // We need to manually run the static call since the getter cannot be flagged as view
        // bytes4(keccak256("implementation()")) == 0x5c60da1b
        (bool success, bytes memory returndata) = address(proxy).staticcall(hex"5c60da1b");
        require(success);
        return abi.decode(returndata, (address));
    }
    /**
     * @dev Returns the current admin of `proxy`.
     *
     * Requirements:
     *
     * - This contract must be the admin of `proxy`.
     */
    function getProxyAdmin(TransparentUpgradeableProxy proxy) public view virtual returns (address) {
        // We need to manually run the static call since the getter cannot be flagged as view
        // bytes4(keccak256("admin()")) == 0xf851a440
        (bool success, bytes memory returndata) = address(proxy).staticcall(hex"f851a440");
        require(success);
        return abi.decode(returndata, (address));
    }
    /**
     * @dev Changes the admin of `proxy` to `newAdmin`.
     *
     * Requirements:
     *
     * - This contract must be the current admin of `proxy`.
     */
    function changeProxyAdmin(TransparentUpgradeableProxy proxy, address newAdmin) public virtual onlyOwner {
        proxy.changeAdmin(newAdmin);
    }
    /**
     * @dev Upgrades `proxy` to `implementation`. See {TransparentUpgradeableProxy-upgradeTo}.
     *
     * Requirements:
     *
     * - This contract must be the admin of `proxy`.
     */
    function upgrade(TransparentUpgradeableProxy proxy, address implementation) public virtual onlyOwner {
        proxy.upgradeTo(implementation);
    }
    /**
     * @dev Upgrades `proxy` to `implementation` and calls a function on the new implementation. See
     * {TransparentUpgradeableProxy-upgradeToAndCall}.
     *
     * Requirements:
     *
     * - This contract must be the admin of `proxy`.
     */
    function upgradeAndCall(
        TransparentUpgradeableProxy proxy,
        address implementation,
        bytes memory data
    ) public payable virtual onlyOwner {
        proxy.upgradeToAndCall{value: msg.value}(implementation, data);
    }
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.22;
interface IERC1967 {
    /**
     * @dev Emitted when the implementation is upgraded.
     */
    event Upgraded(address indexed implementation);
    /**
     * @dev Emitted when the admin account has changed.
     */
    event AdminChanged(address previousAdmin, address newAdmin);
    /**
     * @dev Emitted when the beacon is changed.
     */
    event BeaconUpgraded(address indexed beacon);
}
interface ITransparentUpgradeableProxy is IERC1967 {
    function upgradeToAndCall(address, bytes calldata) external payable;
}
contract ProxyAdminV5 {
    string public constant UPGRADE_INTERFACE_VERSION = "5.0.0";
    /**
     * @dev Sets the initial owner who can perform upgrades.
     */
    constructor(address initialOwner) {}
    /**
     * @dev Upgrades `proxy` to `implementation` and calls a function on the new implementation.
     * See {TransparentUpgradeableProxy-_dispatchUpgradeToAndCall}.
     *
     * Requirements:
     *
     * - This contract must be the admin of `proxy`.
     * - If `data` is empty, `msg.value` must be zero.
     */
    function upgradeAndCall(
        address proxy,
        address implementation,
        bytes memory data
    ) public payable virtual {
        // proxy.upgradeToAndCall{value: msg.value}(implementation, data);
    }
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (access/Ownable.sol)
pragma solidity ^0.8.0;
import "../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.
 *
 * By default, the owner account will be the one that deploys the contract. This
 * can later be changed with {transferOwnership}.
 *
 * This module is used through inheritance. It will make available the modifier
 * `onlyOwner`, which can be applied to your functions to restrict their use to
 * the owner.
 */
abstract contract Ownable is Context {
    address private _owner;
    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
    /**
     * @dev Initializes the contract setting the deployer as the initial owner.
     */
    constructor (address initialOwner) {
        _transferOwnership(initialOwner);
    }
    /**
     * @dev Returns the address of the current owner.
     */
    function owner() public view virtual returns (address) {
        return _owner;
    }
    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        require(owner() == _msgSender(), "Ownable: caller is not the owner");
        _;
    }
    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions anymore. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby removing any functionality that is only available to the owner.
     */
    function renounceOwnership() public virtual onlyOwner {
        _transferOwnership(address(0));
    }
    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        require(newOwner != address(0), "Ownable: new owner is the zero address");
        _transferOwnership(newOwner);
    }
    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Internal function without access restriction.
     */
    function _transferOwnership(address newOwner) internal virtual {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (interfaces/draft-IERC1822.sol)
pragma solidity ^0.8.0;
/**
 * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified
 * proxy whose upgrades are fully controlled by the current implementation.
 */
interface IERC1822Proxiable {
    /**
     * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation
     * address.
     *
     * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks
     * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this
     * function revert if invoked through a proxy.
     */
    function proxiableUUID() external view returns (bytes32);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol)
pragma solidity ^0.8.0;
/**
 * @dev This is the interface that {BeaconProxy} expects of its beacon.
 */
interface IBeacon {
    /**
     * @dev Must return an address that can be used as a delegate call target.
     *
     * {BeaconProxy} will check that this address is a contract.
     */
    function implementation() external view returns (address);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (proxy/ERC1967/ERC1967Proxy.sol)
pragma solidity ^0.8.0;
import "../Proxy.sol";
import "./ERC1967Upgrade.sol";
/**
 * @dev This contract implements an upgradeable proxy. It is upgradeable because calls are delegated to an
 * implementation address that can be changed. This address is stored in storage in the location specified by
 * https://eips.ethereum.org/EIPS/eip-1967[EIP1967], so that it doesn't conflict with the storage layout of the
 * implementation behind the proxy.
 */
contract ERC1967Proxy is Proxy, ERC1967Upgrade {
    /**
     * @dev Initializes the upgradeable proxy with an initial implementation specified by `_logic`.
     *
     * If `_data` is nonempty, it's used as data in a delegate call to `_logic`. This will typically be an encoded
     * function call, and allows initializating the storage of the proxy like a Solidity constructor.
     */
    constructor(address _logic, bytes memory _data) payable {
        assert(_IMPLEMENTATION_SLOT == bytes32(uint256(keccak256("eip1967.proxy.implementation")) - 1));
        _upgradeToAndCall(_logic, _data, false);
    }
    /**
     * @dev Returns the current implementation address.
     */
    function _implementation() internal view virtual override returns (address impl) {
        return ERC1967Upgrade._getImplementation();
    }
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (proxy/ERC1967/ERC1967Upgrade.sol)
pragma solidity ^0.8.2;
import "../beacon/IBeacon.sol";
import "../../interfaces/draft-IERC1822.sol";
import "../../utils/Address.sol";
import "../../utils/StorageSlot.sol";
/**
 * @dev This abstract contract provides getters and event emitting update functions for
 * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots.
 *
 * _Available since v4.1._
 *
 * @custom:oz-upgrades-unsafe-allow delegatecall
 */
abstract contract ERC1967Upgrade {
    // This is the keccak-256 hash of "eip1967.proxy.rollback" subtracted by 1
    bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143;
    /**
     * @dev Storage slot with the address of the current implementation.
     * This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1, and is
     * validated in the constructor.
     */
    bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
    /**
     * @dev Emitted when the implementation is upgraded.
     */
    event Upgraded(address indexed implementation);
    /**
     * @dev Returns the current implementation address.
     */
    function _getImplementation() internal view returns (address) {
        return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
    }
    /**
     * @dev Stores a new address in the EIP1967 implementation slot.
     */
    function _setImplementation(address newImplementation) private {
        require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract");
        StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
    }
    /**
     * @dev Perform implementation upgrade
     *
     * Emits an {Upgraded} event.
     */
    function _upgradeTo(address newImplementation) internal {
        _setImplementation(newImplementation);
        emit Upgraded(newImplementation);
    }
    /**
     * @dev Perform implementation upgrade with additional setup call.
     *
     * Emits an {Upgraded} event.
     */
    function _upgradeToAndCall(
        address newImplementation,
        bytes memory data,
        bool forceCall
    ) internal {
        _upgradeTo(newImplementation);
        if (data.length > 0 || forceCall) {
            Address.functionDelegateCall(newImplementation, data);
        }
    }
    /**
     * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call.
     *
     * Emits an {Upgraded} event.
     */
    function _upgradeToAndCallUUPS(
        address newImplementation,
        bytes memory data,
        bool forceCall
    ) internal {
        // Upgrades from old implementations will perform a rollback test. This test requires the new
        // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing
        // this special case will break upgrade paths from old UUPS implementation to new ones.
        if (StorageSlot.getBooleanSlot(_ROLLBACK_SLOT).value) {
            _setImplementation(newImplementation);
        } else {
            try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) {
                require(slot == _IMPLEMENTATION_SLOT, "ERC1967Upgrade: unsupported proxiableUUID");
            } catch {
                revert("ERC1967Upgrade: new implementation is not UUPS");
            }
            _upgradeToAndCall(newImplementation, data, forceCall);
        }
    }
    /**
     * @dev Storage slot with the admin of the contract.
     * This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1, and is
     * validated in the constructor.
     */
    bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;
    /**
     * @dev Emitted when the admin account has changed.
     */
    event AdminChanged(address previousAdmin, address newAdmin);
    /**
     * @dev Returns the current admin.
     */
    function _getAdmin() internal view virtual returns (address) {
        return StorageSlot.getAddressSlot(_ADMIN_SLOT).value;
    }
    /**
     * @dev Stores a new address in the EIP1967 admin slot.
     */
    function _setAdmin(address newAdmin) private {
        require(newAdmin != address(0), "ERC1967: new admin is the zero address");
        StorageSlot.getAddressSlot(_ADMIN_SLOT).value = newAdmin;
    }
    /**
     * @dev Changes the admin of the proxy.
     *
     * Emits an {AdminChanged} event.
     */
    function _changeAdmin(address newAdmin) internal {
        emit AdminChanged(_getAdmin(), newAdmin);
        _setAdmin(newAdmin);
    }
    /**
     * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.
     * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor.
     */
    bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;
    /**
     * @dev Emitted when the beacon is upgraded.
     */
    event BeaconUpgraded(address indexed beacon);
    /**
     * @dev Returns the current beacon.
     */
    function _getBeacon() internal view returns (address) {
        return StorageSlot.getAddressSlot(_BEACON_SLOT).value;
    }
    /**
     * @dev Stores a new beacon in the EIP1967 beacon slot.
     */
    function _setBeacon(address newBeacon) private {
        require(Address.isContract(newBeacon), "ERC1967: new beacon is not a contract");
        require(Address.isContract(IBeacon(newBeacon).implementation()), "ERC1967: beacon implementation is not a contract");
        StorageSlot.getAddressSlot(_BEACON_SLOT).value = newBeacon;
    }
    /**
     * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does
     * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that).
     *
     * Emits a {BeaconUpgraded} event.
     */
    function _upgradeBeaconToAndCall(
        address newBeacon,
        bytes memory data,
        bool forceCall
    ) internal {
        _setBeacon(newBeacon);
        emit BeaconUpgraded(newBeacon);
        if (data.length > 0 || forceCall) {
            Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data);
        }
    }
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (proxy/Proxy.sol)
pragma solidity ^0.8.0;
/**
 * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM
 * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to
 * be specified by overriding the virtual {_implementation} function.
 *
 * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a
 * different contract through the {_delegate} function.
 *
 * The success and return data of the delegated call will be returned back to the caller of the proxy.
 */
abstract contract Proxy {
    /**
     * @dev Delegates the current call to `implementation`.
     *
     * This function does not return to its internal call site, it will return directly to the external caller.
     */
    function _delegate(address implementation) internal virtual {
        assembly {
            // Copy msg.data. We take full control of memory in this inline assembly
            // block because it will not return to Solidity code. We overwrite the
            // Solidity scratch pad at memory position 0.
            calldatacopy(0, 0, calldatasize())
            // Call the implementation.
            // out and outsize are 0 because we don't know the size yet.
            let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)
            // Copy the returned data.
            returndatacopy(0, 0, returndatasize())
            switch result
            // delegatecall returns 0 on error.
            case 0 {
                revert(0, returndatasize())
            }
            default {
                return(0, returndatasize())
            }
        }
    }
    /**
     * @dev This is a virtual function that should be overriden so it returns the address to which the fallback function
     * and {_fallback} should delegate.
     */
    function _implementation() internal view virtual returns (address);
    /**
     * @dev Delegates the current call to the address returned by `_implementation()`.
     *
     * This function does not return to its internall call site, it will return directly to the external caller.
     */
    function _fallback() internal virtual {
        _beforeFallback();
        _delegate(_implementation());
    }
    /**
     * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other
     * function in the contract matches the call data.
     */
    fallback() external payable virtual {
        _fallback();
    }
    /**
     * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if call data
     * is empty.
     */
    receive() external payable virtual {
        _fallback();
    }
    /**
     * @dev Hook that is called before falling back to the implementation. Can happen as part of a manual `_fallback`
     * call, or as part of the Solidity `fallback` or `receive` functions.
     *
     * If overriden should call `super._beforeFallback()`.
     */
    function _beforeFallback() internal virtual {}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (proxy/transparent/TransparentUpgradeableProxy.sol)
pragma solidity ^0.8.0;
import "../ERC1967/ERC1967Proxy.sol";
/**
 * @dev This contract implements a proxy that is upgradeable by an admin.
 *
 * To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector
 * clashing], which can potentially be used in an attack, this contract uses the
 * https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two
 * things that go hand in hand:
 *
 * 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if
 * that call matches one of the admin functions exposed by the proxy itself.
 * 2. If the admin calls the proxy, it can access the admin functions, but its calls will never be forwarded to the
 * implementation. If the admin tries to call a function on the implementation it will fail with an error that says
 * "admin cannot fallback to proxy target".
 *
 * These properties mean that the admin account can only be used for admin actions like upgrading the proxy or changing
 * the admin, so it's best if it's a dedicated account that is not used for anything else. This will avoid headaches due
 * to sudden errors when trying to call a function from the proxy implementation.
 *
 * Our recommendation is for the dedicated account to be an instance of the {ProxyAdmin} contract. If set up this way,
 * you should think of the `ProxyAdmin` instance as the real administrative interface of your proxy.
 */
contract TransparentUpgradeableProxy is ERC1967Proxy {
    /**
     * @dev Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and
     * optionally initialized with `_data` as explained in {ERC1967Proxy-constructor}.
     */
    constructor(
        address _logic,
        address admin_,
        bytes memory _data
    ) payable ERC1967Proxy(_logic, _data) {
        assert(_ADMIN_SLOT == bytes32(uint256(keccak256("eip1967.proxy.admin")) - 1));
        _changeAdmin(admin_);
    }
    /**
     * @dev Modifier used internally that will delegate the call to the implementation unless the sender is the admin.
     */
    modifier ifAdmin() {
        if (msg.sender == _getAdmin()) {
            _;
        } else {
            _fallback();
        }
    }
    /**
     * @dev Returns the current admin.
     *
     * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyAdmin}.
     *
     * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the
     * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.
     * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`
     */
    function admin() external ifAdmin returns (address admin_) {
        admin_ = _getAdmin();
    }
    /**
     * @dev Returns the current implementation.
     *
     * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyImplementation}.
     *
     * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the
     * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.
     * `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`
     */
    function implementation() external ifAdmin returns (address implementation_) {
        implementation_ = _implementation();
    }
    /**
     * @dev Changes the admin of the proxy.
     *
     * Emits an {AdminChanged} event.
     *
     * NOTE: Only the admin can call this function. See {ProxyAdmin-changeProxyAdmin}.
     */
    function changeAdmin(address newAdmin) external virtual ifAdmin {
        _changeAdmin(newAdmin);
    }
    /**
     * @dev Upgrade the implementation of the proxy.
     *
     * NOTE: Only the admin can call this function. See {ProxyAdmin-upgrade}.
     */
    function upgradeTo(address newImplementation) external ifAdmin {
        _upgradeToAndCall(newImplementation, bytes(""), false);
    }
    /**
     * @dev Upgrade the implementation of the proxy, and then call a function from the new implementation as specified
     * by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the
     * proxied contract.
     *
     * NOTE: Only the admin can call this function. See {ProxyAdmin-upgradeAndCall}.
     */
    function upgradeToAndCall(address newImplementation, bytes calldata data) external payable ifAdmin {
        _upgradeToAndCall(newImplementation, data, true);
    }
    /**
     * @dev Returns the current admin.
     */
    function _admin() internal view virtual returns (address) {
        return _getAdmin();
    }
    /**
     * @dev Makes sure the admin cannot access the fallback function. See {Proxy-_beforeFallback}.
     */
    function _beforeFallback() internal virtual override {
        require(msg.sender != _getAdmin(), "TransparentUpgradeableProxy: admin cannot fallback to proxy target");
        super._beforeFallback();
    }
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (utils/Address.sol)
pragma solidity ^0.8.1;
/**
 * @dev Collection of functions related to the address type
 */
library Address {
    /**
     * @dev Returns true if `account` is a contract.
     *
     * [IMPORTANT]
     * ====
     * It is unsafe to assume that an address for which this function returns
     * false is an externally-owned account (EOA) and not a contract.
     *
     * Among others, `isContract` will return false for the following
     * types of addresses:
     *
     *  - an externally-owned account
     *  - a contract in construction
     *  - an address where a contract will be created
     *  - an address where a contract lived, but was destroyed
     * ====
     *
     * [IMPORTANT]
     * ====
     * You shouldn't rely on `isContract` to protect against flash loan attacks!
     *
     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
     * constructor.
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // This method relies on extcodesize/address.code.length, which returns 0
        // for contracts in construction, since the code is only stored at the end
        // of the constructor execution.
        return account.code.length > 0;
    }
    /**
     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
     * `recipient`, forwarding all available gas and reverting on errors.
     *
     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
     * of certain opcodes, possibly making contracts go over the 2300 gas limit
     * imposed by `transfer`, making them unable to receive funds via
     * `transfer`. {sendValue} removes this limitation.
     *
     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
     *
     * IMPORTANT: because control is transferred to `recipient`, care must be
     * taken to not create reentrancy vulnerabilities. Consider using
     * {ReentrancyGuard} or the
     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
     */
    function sendValue(address payable recipient, uint256 amount) internal {
        require(address(this).balance >= amount, "Address: insufficient balance");
        (bool success, ) = recipient.call{value: amount}("");
        require(success, "Address: unable to send value, recipient may have reverted");
    }
    /**
     * @dev Performs a Solidity function call using a low level `call`. A
     * plain `call` is an unsafe replacement for a function call: use this
     * function instead.
     *
     * If `target` reverts with a revert reason, it is bubbled up by this
     * function (like regular Solidity function calls).
     *
     * Returns the raw returned data. To convert to the expected return value,
     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
     *
     * Requirements:
     *
     * - `target` must be a contract.
     * - calling `target` with `data` must not revert.
     *
     * _Available since v3.1._
     */
    function functionCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionCall(target, data, "Address: low-level call failed");
    }
    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
     * `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        return functionCallWithValue(target, data, 0, errorMessage);
    }
    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but also transferring `value` wei to `target`.
     *
     * Requirements:
     *
     * - the calling contract must have an ETH balance of at least `value`.
     * - the called Solidity function must be `payable`.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value
    ) internal returns (bytes memory) {
        return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
    }
    /**
     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
     * with `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value,
        string memory errorMessage
    ) internal returns (bytes memory) {
        require(address(this).balance >= value, "Address: insufficient balance for call");
        require(isContract(target), "Address: call to non-contract");
        (bool success, bytes memory returndata) = target.call{value: value}(data);
        return verifyCallResult(success, returndata, errorMessage);
    }
    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
        return functionStaticCall(target, data, "Address: low-level static call failed");
    }
    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal view returns (bytes memory) {
        require(isContract(target), "Address: static call to non-contract");
        (bool success, bytes memory returndata) = target.staticcall(data);
        return verifyCallResult(success, returndata, errorMessage);
    }
    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionDelegateCall(target, data, "Address: low-level delegate call failed");
    }
    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        require(isContract(target), "Address: delegate call to non-contract");
        (bool success, bytes memory returndata) = target.delegatecall(data);
        return verifyCallResult(success, returndata, errorMessage);
    }
    /**
     * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
     * revert reason using the provided one.
     *
     * _Available since v4.3._
     */
    function verifyCallResult(
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal pure returns (bytes memory) {
        if (success) {
            return returndata;
        } else {
            // Look for revert reason and bubble it up if present
            if (returndata.length > 0) {
                // The easiest way to bubble the revert reason is using memory via assembly
                assembly {
                    let returndata_size := mload(returndata)
                    revert(add(32, returndata), returndata_size)
                }
            } else {
                revert(errorMessage);
            }
        }
    }
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)
pragma solidity ^0.8.0;
/**
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
abstract contract Context {
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }
    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/StorageSlot.sol)
pragma solidity ^0.8.0;
/**
 * @dev Library for reading and writing primitive types to specific storage slots.
 *
 * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.
 * This library helps with reading and writing to such slots without the need for inline assembly.
 *
 * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.
 *
 * Example usage to set ERC1967 implementation slot:
 * ```
 * contract ERC1967 {
 *     bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
 *
 *     function _getImplementation() internal view returns (address) {
 *         return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
 *     }
 *
 *     function _setImplementation(address newImplementation) internal {
 *         require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract");
 *         StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
 *     }
 * }
 * ```
 *
 * _Available since v4.1 for `address`, `bool`, `bytes32`, and `uint256`._
 */
library StorageSlot {
    struct AddressSlot {
        address value;
    }
    struct BooleanSlot {
        bool value;
    }
    struct Bytes32Slot {
        bytes32 value;
    }
    struct Uint256Slot {
        uint256 value;
    }
    /**
     * @dev Returns an `AddressSlot` with member `value` located at `slot`.
     */
    function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {
        assembly {
            r.slot := slot
        }
    }
    /**
     * @dev Returns an `BooleanSlot` with member `value` located at `slot`.
     */
    function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {
        assembly {
            r.slot := slot
        }
    }
    /**
     * @dev Returns an `Bytes32Slot` with member `value` located at `slot`.
     */
    function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {
        assembly {
            r.slot := slot
        }
    }
    /**
     * @dev Returns an `Uint256Slot` with member `value` located at `slot`.
     */
    function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {
        assembly {
            r.slot := slot
        }
    }
}{
  "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":[{"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
60c06040523480156200001157600080fd5b506040516200441938038062004419833981016040819052620000349162000147565b6001600160a01b0381166080528080600681620000536006836200018f565b6200006090600a620002a8565b60a05250620000739250506200007a9050565b50620002b9565b6000620000866200011c565b805490915068010000000000000000900460ff1615620000b95760405163f92ee8a960e01b815260040160405180910390fd5b80546001600160401b0390811614620001195780546001600160401b0319166001600160401b0390811782556040519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50565b6000807ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005b92915050565b6000602082840312156200015a57600080fd5b81516001600160a01b03811681146200017257600080fd5b9392505050565b634e487b7160e01b600052601160045260246000fd5b60ff828116828216039081111562000141576200014162000179565b600181815b80851115620001ec578160001904821115620001d057620001d062000179565b80851615620001de57918102915b93841c9390800290620001b0565b509250929050565b600082620002055750600162000141565b81620002145750600062000141565b81600181146200022d5760028114620002385762000258565b600191505062000141565b60ff8411156200024c576200024c62000179565b50506001821b62000141565b5060208310610133831016604e8410600b84101617156200027d575081810a62000141565b620002898383620001ab565b8060001904821115620002a057620002a062000179565b029392505050565b60006200017260ff841683620001f4565b60805160a0516140f462000325600039600081816109430152818161260e0152818161268301526127ec01526000818161079201528181610e6801528181611aa801528181611ea2015281816121c701528181612a1f01528181612d910152612e4a01526140f46000f3fe60806040526004361061036b5760003560e01c806370a08231116101c6578063bb0b6a53116100f7578063d424388511610095578063e43252d71161006f578063e43252d714610b11578063f2fde38b14610b31578063fc0c546a146106e9578063ff7bd03d14610b5157600080fd5b8063d424388514610abb578063dd62ed3e14610adb578063e1a4521814610afb57600080fd5b8063bd815db0116100d1578063bd815db014610a54578063c7c7f5b314610a67578063ca5eb5e114610a88578063d045a0dc14610aa857600080fd5b8063bb0b6a53146109ce578063bc70b35414610a0e578063bcae25a414610a2e57600080fd5b80638da5cb5b116101645780639f68b9641161013e5780639f68b96414610965578063a9059cbb14610979578063b731ea0a14610999578063b98bd070146109ae57600080fd5b80638da5cb5b1461090757806395d89b411461091c578063963efcaa1461093157600080fd5b806382413eac116101a057806382413eac14610898578063857749b0146105605780638705fcd4146108c75780638ab1d681146108e757600080fd5b806370a0823114610828578063715018a6146108485780637d25a05e1461085d57600080fd5b80633194c180116102a05780635535d4611161023e5780635e280f11116102185780635e280f111461078057806360b71d4e146107b45780636db7bcdb146107e85780636fc1b31e1461080857600080fd5b80635535d461146106fc5780635a0dfe4d1461071c5780635bf9c2261461076057600080fd5b80633b6f743b1161027a5780633b6f743b1461067e5780634488b652146106ab5780634e7ceacb146106cb57806352ae2879146106e957600080fd5b80633194c1801461057c5780633400288b146106255780633af32abf1461064557600080fd5b8063156a0d0f1161030d57806318160ddd116102e757806318160ddd146104ed5780631f5e13341461052b57806323b872dd14610540578063313ce5671461056057600080fd5b8063156a0d0f14610484578063164e68de146104ab57806317442b70146104cb57600080fd5b80630d35b415116103495780630d35b415146103ed578063111ecdad1461041c57806313137d6514610449578063134d4f251461045c57600080fd5b806306fdde0314610370578063077f224a1461039b578063095ea7b3146103bd575b600080fd5b34801561037c57600080fd5b50610385610b71565b6040516103929190613011565b60405180910390f35b3480156103a757600080fd5b506103bb6103b6366004613124565b610c34565b005b3480156103c957600080fd5b506103dd6103d836600461319b565b610d4b565b6040519015158152602001610392565b3480156103f957600080fd5b5061040d6104083660046131df565b610d65565b60405161039293929190613213565b34801561042857600080fd5b50610431610e31565b6040516001600160a01b039091168152602001610392565b6103bb6104573660046132ff565b610e66565b34801561046857600080fd5b50610471600281565b60405161ffff9091168152602001610392565b34801561049057600080fd5b506040805162b9270b60e21b81526001602082015201610392565b3480156104b757600080fd5b506103bb6104c636600461339e565b610f26565b3480156104d757600080fd5b5060408051600181526002602082015201610392565b3480156104f957600080fd5b507f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace02545b604051908152602001610392565b34801561053757600080fd5b50610471600181565b34801561054c57600080fd5b506103dd61055b3660046133bb565b610fca565b34801561056c57600080fd5b5060405160068152602001610392565b34801561058857600080fd5b50610604610597366004613415565b6040805180820182526000808252602091820181905263ffffffff9390931683527f0cb173d183337e25fab6cb85705c15aad6a58cb1d552ed71b9bc628c8a3de80181529181902081518083019092525461ffff8116825262010000900460ff1615159181019190915290565b60408051825161ffff16815260209283015115159281019290925201610392565b34801561063157600080fd5b506103bb610640366004613430565b610ff0565b34801561065157600080fd5b506103dd61066036600461339e565b6001600160a01b031660009081526001602052604090205460ff1690565b34801561068a57600080fd5b5061069e61069936600461345a565b61105d565b60405161039291906134ab565b3480156106b757600080fd5b506103bb6106c63660046134d4565b6110c4565b3480156106d757600080fd5b506000546001600160a01b0316610431565b3480156106f557600080fd5b5030610431565b34801561070857600080fd5b506103856107173660046134ef565b61114b565b34801561072857600080fd5b506103dd610737366004613430565b63ffffffff91909116600090815260008051602061409f83398151915260205260409020541490565b34801561076c57600080fd5b5061051d61077b366004613430565b611226565b34801561078c57600080fd5b506104317f000000000000000000000000000000000000000000000000000000000000000081565b3480156107c057600080fd5b507f68f1d0d99488c60d21eadee2cca13b58661d56fbcb4e4464d6fc8def1b3422005461051d565b3480156107f457600080fd5b506103bb610803366004613522565b611269565b34801561081457600080fd5b506103bb61082336600461339e565b61133d565b34801561083457600080fd5b5061051d61084336600461339e565b6113b1565b34801561085457600080fd5b506103bb6113d9565b34801561086957600080fd5b50610880610878366004613430565b600092915050565b6040516001600160401b039091168152602001610392565b3480156108a457600080fd5b506103dd6108b336600461355e565b6001600160a01b0381163014949350505050565b3480156108d357600080fd5b506103bb6108e236600461339e565b6113ed565b3480156108f357600080fd5b506103bb61090236600461339e565b611449565b34801561091357600080fd5b50610431611501565b34801561092857600080fd5b5061038561152a565b34801561093d57600080fd5b5061051d7f000000000000000000000000000000000000000000000000000000000000000081565b34801561097157600080fd5b5060006103dd565b34801561098557600080fd5b506103dd61099436600461319b565b611569565b3480156109a557600080fd5b50610431611577565b3480156109ba57600080fd5b506103bb6109c9366004613608565b6115a0565b3480156109da57600080fd5b5061051d6109e9366004613415565b63ffffffff16600090815260008051602061409f833981519152602052604090205490565b348015610a1a57600080fd5b50610385610a29366004613649565b611721565b348015610a3a57600080fd5b5060008051602061407f8339815191525461ffff16610471565b6103bb610a62366004613608565b6118b7565b610a7a610a753660046136a9565b611a4e565b60405161039292919061370b565b348015610a9457600080fd5b506103bb610aa336600461339e565b611a81565b6103bb610ab63660046132ff565b611b07565b348015610ac757600080fd5b506103bb610ad636600461339e565b611b36565b348015610ae757600080fd5b5061051d610af636600461375d565b611baa565b348015610b0757600080fd5b5061047161271081565b348015610b1d57600080fd5b506103bb610b2c36600461339e565b611bf4565b348015610b3d57600080fd5b506103bb610b4c36600461339e565b611cae565b348015610b5d57600080fd5b506103dd610b6c36600461378b565b611cec565b7f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace03805460609160008051602061405f83398151915291610bb0906137a7565b80601f0160208091040260200160405190810160405280929190818152602001828054610bdc906137a7565b8015610c295780601f10610bfe57610100808354040283529160200191610c29565b820191906000526020600020905b815481529060010190602001808311610c0c57829003601f168201915b505050505091505090565b6000610c3e611d0a565b805490915060ff600160401b82041615906001600160401b0316600081158015610c655750825b90506000826001600160401b03166001148015610c815750303b155b905081158015610c8f575080155b15610cad5760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff191660011785558315610cd757845460ff60401b1916600160401b1785555b610ce2888888611d33565b610ceb86611d53565b600080546001600160a01b03191690558315610d4157845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b5050505050505050565b600033610d59818585611d64565b60019150505b92915050565b60408051808201909152600080825260208201526060610d98604051806040016040528060008152602001600081525090565b6040805180820182526000808252600019602080840182905284518381529081019094529195509182610dee565b604080518082019091526000815260606020820152815260200190600190039081610dc65790505b509350600080610e13604089013560608a0135610e0e60208c018c613415565b611d71565b60408051808201909152918252602082015296989597505050505050565b6000807f41db8a78b0206aba5c54bcbfc2bda0d84082a84eb88e680379a57b9e9f653c005b546001600160a01b031692915050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03163314610eb6576040516391ac5e4f60e01b81523360048201526024015b60405180910390fd5b60208701803590610ed090610ecb908a613415565b611dc2565b14610f0e57610ee26020880188613415565b60405163309afaf360e21b815263ffffffff909116600482015260208801356024820152604401610ead565b610f1d87878787878787611e0d565b50505050505050565b610f2e611f74565b7f68f1d0d99488c60d21eadee2cca13b58661d56fbcb4e4464d6fc8def1b34220080546000819003610f7357604051630d00db4d60e31b815260040160405180910390fd5b60008255610f82308483611fa6565b826001600160a01b03167f78473f3f373f7673597f4f0fa5873cb4d375fea6d4339ad6b56dbd411513cb3f82604051610fbd91815260200190565b60405180910390a2505050565b600033610fd8858285612005565b610fe3858585611fa6565b60019150505b9392505050565b610ff8611f74565b63ffffffff8216600081815260008051602061409f833981519152602081815260409283902085905582519384528301849052917f238399d427b947898edb290f5ff0f9109849b1c3ba196a42e35f00c50a54b98b91015b60405180910390a1505050565b6040805180820190915260008082526020820152600061108d60408501356060860135610e0e6020880188613415565b91505060008061109d868461206c565b90925090506110ba6110b26020880188613415565b8383886121b1565b9695505050505050565b6110cc611f74565b61271061ffff821611156110f35760405163c6cc5d7f60e01b815260040160405180910390fd5b60008051602061407f833981519152805461ffff191661ffff831690811782556040519081527f9283ddc0c2b59320e00b0ae4a992b110df098c38e3b6ea1d92fe7a6d3504be9b906020015b60405180910390a15050565b63ffffffff821660009081527f8d2bda5d9f6ffb5796910376005392955773acee5548d0fcdb10e7c264ea00006020818152604080842061ffff861685529091529091208054606092919061119f906137a7565b80601f01602080910402602001604051908101604052809291908181526020018280546111cb906137a7565b80156112185780601f106111ed57610100808354040283529160200191611218565b820191906000526020600020905b8154815290600101906020018083116111fb57829003601f168201915b505050505091505092915050565b60008061123284612292565b905061ffff81161561125e5761271061124f61ffff8316856137f1565b6112599190613808565b611261565b60005b949350505050565b611271611f74565b61271061ffff831611156112985760405163c6cc5d7f60e01b815260040160405180910390fd5b600060008051602061407f83398151915260408051808201825261ffff868116808352861515602080850182815263ffffffff8c16600081815260018a0184528890209651875492511515620100000262ffffff1990931696169590951717909455845192835292820152918201529091507f56f0bca120766dba5aeeb89a1cf629c3495dc497c82f426d4e4d58c54b72764c9060600160405180910390a150505050565b611345611f74565b7f41db8a78b0206aba5c54bcbfc2bda0d84082a84eb88e680379a57b9e9f653c0080546001600160a01b0319166001600160a01b03831690811782556040519081527ff0be4f1e87349231d80c36b33f9e8639658eeaf474014dee15a3e6a4d44141979060200161113f565b6001600160a01b0316600090815260008051602061405f833981519152602052604090205490565b6113e1611f74565b6113eb6000612311565b565b6113f5611f74565b600080546001600160a01b0319166001600160a01b0383169081179091556040519081527f0cc4d0c9af0c184a6ba4203a2d8f4a6843759ea43f751b50f516f6fb4241d9df9060200160405180910390a150565b611451611f74565b6001600160a01b03811660009081526001602052604090205460ff166114ab5760405162461bcd60e51b815260206004820152600f60248201526e139bdd081dda1a5d195b1a5cdd1959608a1b6044820152606401610ead565b6001600160a01b0381166000818152600160209081526040808320805460ff19169055519182527ff93f9a76c1bf3444d22400a00cb9fe990e6abe9dbb333fda48859cfee864543d91015b60405180910390a250565b6000807f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300610e56565b7f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace04805460609160008051602061405f83398151915291610bb0906137a7565b600033610d59818585611fa6565b6000807fefb041d771d6daaa55702fff6eb740d63ba559a75d2d1d3e151c78ff2480b600610e56565b6115a8611f74565b7f8d2bda5d9f6ffb5796910376005392955773acee5548d0fcdb10e7c264ea000060005b828110156116ef5761160e8484838181106115e9576115e961382a565b90506020028101906115fb9190613840565b611609906040810190613860565b612382565b8383828181106116205761162061382a565b90506020028101906116329190613840565b611640906040810190613860565b8360008787868181106116555761165561382a565b90506020028101906116679190613840565b611675906020810190613415565b63ffffffff1663ffffffff16815260200190815260200160002060008787868181106116a3576116a361382a565b90506020028101906116b59190613840565b6116c69060408101906020016134d4565b61ffff1681526020810191909152604001600020916116e69190836138f6565b506001016115cc565b507fbe4864a8e820971c0247f5992e2da559595f7bf076a21cb5928d443d2a13b67483836040516110509291906139de565b63ffffffff841660009081527f8d2bda5d9f6ffb5796910376005392955773acee5548d0fcdb10e7c264ea00006020818152604080842061ffff88168552909152822080546060939190611774906137a7565b80601f01602080910402602001604051908101604052809291908181526020018280546117a0906137a7565b80156117ed5780601f106117c2576101008083540402835291602001916117ed565b820191906000526020600020905b8154815290600101906020018083116117d057829003601f168201915b50505050509050805160000361183e5784848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550611261945050505050565b60008490036118505791506112619050565b6002841061189a576118628585612382565b806118708560028189613ac2565b60405160200161188293929190613aec565b60405160208183030381529060405292505050611261565b8484604051639a6d49cd60e01b8152600401610ead929190613b14565b60005b818110156119cd57368383838181106118d5576118d561382a565b90506020028101906118e79190613b28565b90506119276118f96020830183613415565b602083013563ffffffff91909116600090815260008051602061409f83398151915260205260409020541490565b61193157506119c5565b3063d045a0dc60c08301358360a0810135611950610100830183613860565b611961610100890160e08a0161339e565b61196f6101208a018a613860565b6040518963ffffffff1660e01b81526004016119919796959493929190613b54565b6000604051808303818588803b1580156119aa57600080fd5b505af11580156119be573d6000803e3d6000fd5b5050505050505b6001016118ba565b50336001600160a01b0316638e9e70996040518163ffffffff1660e01b8152600401600060405180830381865afa158015611a0c573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611a349190810190613bda565b604051638351eea760e01b8152600401610ead9190613011565b611a56612f7a565b6040805180820190915260008082526020820152611a758585856123c4565b91509150935093915050565b611a89611f74565b60405163ca5eb5e160e01b81526001600160a01b0382811660048301527f0000000000000000000000000000000000000000000000000000000000000000169063ca5eb5e190602401600060405180830381600087803b158015611aec57600080fd5b505af1158015611b00573d6000803e3d6000fd5b5050505050565b333014611b275760405163029a949d60e31b815260040160405180910390fd5b610f1d87878787878787610f0e565b611b3e611f74565b7fefb041d771d6daaa55702fff6eb740d63ba559a75d2d1d3e151c78ff2480b60080546001600160a01b0319166001600160a01b03831690811782556040519081527fd48d879cef83a1c0bdda516f27b13ddb1b3f8bbac1c9e1511bb2a659c24277609060200161113f565b6001600160a01b0391821660009081527f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace016020908152604080832093909416825291909152205490565b611bfc611f74565b6001600160a01b03811660009081526001602052604090205460ff1615611c5b5760405162461bcd60e51b8152602060048201526013602482015272105b1c9958591e481dda1a5d195b1a5cdd1959606a1b6044820152606401610ead565b6001600160a01b038116600081815260016020818152604092839020805460ff19168317905591519081527ff93f9a76c1bf3444d22400a00cb9fe990e6abe9dbb333fda48859cfee864543d91016114f6565b611cb6611f74565b6001600160a01b038116611ce057604051631e4fbdf760e01b815260006004820152602401610ead565b611ce981612311565b50565b600060208201803590611d03906109e99085613415565b1492915050565b6000807ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00610d5f565b611d3b6124bf565b611d4583836124e4565b611d4e816124fa565b505050565b611d5b6124bf565b611ce98161251b565b611d4e8383836001612523565b82600080611d7f8484611226565b9050611d8c81870361260a565b915084821015611db9576040516371c4efed60e01b81526004810183905260248101869052604401610ead565b50935093915050565b63ffffffff8116600090815260008051602061409f8339815191526020819052604082205480610fe95760405163f6ff4fb760e01b815263ffffffff85166004820152602401610ead565b6000611e1f611e1c8787612641565b90565b90506000611e4b82611e39611e348a8a612659565b61267c565b611e4660208d018d613415565b6126b1565b90506028861115611f12576000611e88611e6b60608c0160408d01613c47565b611e7860208d018d613415565b84611e838c8c6126d9565b612724565b604051633e5ac80960e11b81529091506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690637cb5901290611ede9086908d906000908790600401613c64565b600060405180830381600087803b158015611ef857600080fd5b505af1158015611f0c573d6000803e3d6000fd5b50505050505b6001600160a01b038216887fefed6d3500546b29533b128a29e3a94d70788727f0507505ac12eaf2e578fd9c611f4b60208d018d613415565b6040805163ffffffff9092168252602082018690520160405180910390a3505050505050505050565b33611f7d611501565b6001600160a01b0316146113eb5760405163118cdaa760e01b8152336004820152602401610ead565b6001600160a01b038316611fd057604051634b637e8f60e11b815260006004820152602401610ead565b6001600160a01b038216611ffa5760405163ec442f0560e01b815260006004820152602401610ead565b611d4e838383612756565b60006120118484611baa565b9050600019811015612066578181101561205757604051637dc7a0d960e11b81526001600160a01b03841660048201526024810182905260448101839052606401610ead565b61206684848484036000612523565b50505050565b60608060006120c98560200135612082866127e4565b61208f60a0890189613860565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061283e92505050565b90935090506000816120dc5760016120df565b60025b90506120ff6120f16020880188613415565b82610a2960808a018a613860565b7f41db8a78b0206aba5c54bcbfc2bda0d84082a84eb88e680379a57b9e9f653c008054919450906001600160a01b031680156121a65760405163043a78eb60e01b81526001600160a01b0382169063043a78eb906121639089908990600401613c95565b602060405180830381865afa158015612180573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121a49190613cba565b505b505050509250929050565b60408051808201909152600080825260208201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663ddc28c586040518060a001604052808863ffffffff16815260200161221489611dc2565b8152602001878152602001868152602001851515815250306040518363ffffffff1660e01b8152600401612249929190613cd7565b6040805180830381865afa158015612265573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122899190613d80565b95945050505050565b63ffffffff811660009081527f0cb173d183337e25fab6cb85705c15aad6a58cb1d552ed71b9bc628c8a3de8016020908152604080832081518083019092525461ffff8116825262010000900460ff16151591810182905260008051602061407f8339815191529161230957815461ffff16611261565b519392505050565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930080546001600160a01b031981166001600160a01b03848116918217845560405192169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3505050565b60006123916002828486613ac2565b61239a91613d9c565b60f01c905060038114611d4e578282604051639a6d49cd60e01b8152600401610ead929190613b14565b6123cc612f7a565b604080518082019091526000808252602082015260008061240333604089013560608a01356123fe60208c018c613415565b6128b8565b91509150600080612414898461206c565b909250905061244061242960208b018b613415565b838361243a368d90038d018d613dcc565b8b6129ec565b60408051808201909152858152602080820186905282519298509096503391907f85496b760a4b7f8d66384b9df21b381f5d1b1e79f229a47aaf4c232edc2fe59a9061248e908d018d613415565b6040805163ffffffff909216825260208201899052810187905260600160405180910390a350505050935093915050565b6124c7612af7565b6113eb57604051631afcd79f60e31b815260040160405180910390fd5b6124ec6124bf565b6124f68282612b11565b5050565b6125026124bf565b61250b81612b62565b612513612b73565b611ce9612b73565b611cb66124bf565b60008051602061405f8339815191526001600160a01b03851661255c5760405163e602df0560e01b815260006004820152602401610ead565b6001600160a01b03841661258657604051634a1406b160e11b815260006004820152602401610ead565b6001600160a01b03808616600090815260018301602090815260408083209388168352929052208390558115611b0057836001600160a01b0316856001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925856040516125fb91815260200190565b60405180910390a35050505050565b60007f00000000000000000000000000000000000000000000000000000000000000006126378184613808565b610d5f91906137f1565b60006126506020828486613ac2565b610fe991613dfe565b6000612669602860208486613ac2565b61267291613e1c565b60c01c9392505050565b6000610d5f7f00000000000000000000000000000000000000000000000000000000000000006001600160401b0384166137f1565b60006001600160a01b0384166126c75761dead93505b6126d18484612b7b565b509092915050565b60606126e88260288186613ac2565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929695505050505050565b60608484848460405160200161273d9493929190613e4a565b6040516020818303038152906040529050949350505050565b612761838383612bb1565b6002805490600061277183613e99565b9190505550600254826001600160a01b0316846001600160a01b03167f6d16356255ebed8e5918262476684aaa5f8054befd93154494221a6026157aa5846127b8886113b1565b6127c1886113b1565b6040805193845260208401929092529082015260600160405180910390a4505050565b6000806128117f000000000000000000000000000000000000000000000000000000000000000084613808565b90506001600160401b03811115610d5f5760405163e2ce941360e01b815260048101829052602401610ead565b805160609015158061288757848460405160200161287392919091825260c01b6001600160c01b031916602082015260280190565b6040516020818303038152906040526128ae565b8484338560405160200161289e9493929190613eb2565b6040516020818303038152906040525b9150935093915050565b6001600160a01b038416600090815260016020526040812054819060ff166128ea576128e5858585611d71565b6128f4565b6128f48585612cef565b9092509050818111156129645760405162461bcd60e51b815260206004820152603260248201527f416d6f756e742072656365697665642063616e6e6f74206265206772656174656044820152711c881d1a185b88185b5bdd5b9d081cd95b9d60721b6064820152608401610ead565b60006129708284613ef5565b905080156129d8576000546001600160a01b03166129c0577f68f1d0d99488c60d21eadee2cca13b58661d56fbcb4e4464d6fc8def1b3422008054820181556129ba883084611fa6565b506129d8565b6000546129d89088906001600160a01b031683611fa6565b6129e28783612d2f565b5094509492505050565b6129f4612f7a565b6000612a038460000151612d65565b602085015190915015612a1d57612a1d8460200151612d8d565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632637a450826040518060a001604052808b63ffffffff168152602001612a6d8c611dc2565b81526020018a815260200189815260200160008960200151111515815250866040518463ffffffff1660e01b8152600401612aa9929190613cd7565b60806040518083038185885af1158015612ac7573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190612aec9190613f08565b979650505050505050565b6000612b01611d0a565b54600160401b900460ff16919050565b612b196124bf565b60008051602061405f8339815191527f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace03612b538482613f6f565b50600481016120668382613f6f565b612b6a6124bf565b61250b81612e6f565b6113eb6124bf565b6001600160a01b038216612ba55760405163ec442f0560e01b815260006004820152602401610ead565b6124f660008383612756565b60008051602061405f8339815191526001600160a01b038416612bed5781816002016000828254612be2919061402e565b90915550612c5f9050565b6001600160a01b03841660009081526020829052604090205482811015612c405760405163391434e360e21b81526001600160a01b03861660048201526024810182905260448101849052606401610ead565b6001600160a01b03851660009081526020839052604090209083900390555b6001600160a01b038316612c7d576002810180548390039055612c9c565b6001600160a01b03831660009081526020829052604090208054830190555b826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051612ce191815260200190565b60405180910390a350505050565b816000612cfb8261260a565b905082811015612d28576040516371c4efed60e01b81526004810182905260248101849052604401610ead565b9250929050565b6001600160a01b038216612d5957604051634b637e8f60e11b815260006004820152602401610ead565b6124f682600083612756565b6000813414612d89576040516304fb820960e51b8152346004820152602401610ead565b5090565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663e4fe1d946040518163ffffffff1660e01b8152600401602060405180830381865afa158015612ded573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e119190614041565b90506001600160a01b038116612e3a576040516329b99a9560e11b815260040160405180910390fd5b6124f66001600160a01b038216337f000000000000000000000000000000000000000000000000000000000000000085612e80565b612e776124bf565b611ce981612eda565b604080516001600160a01b0385811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b179052612066908590612f09565b612ee26124bf565b6001600160a01b038116611a8957604051632d618d8160e21b815260040160405180910390fd5b600080602060008451602086016000885af180612f2c576040513d6000823e3d81fd5b50506000513d91508115612f44578060011415612f51565b6001600160a01b0384163b155b1561206657604051635274afe760e01b81526001600160a01b0385166004820152602401610ead565b60405180606001604052806000801916815260200160006001600160401b03168152602001612fbc604051806040016040528060008152602001600081525090565b905290565b60005b83811015612fdc578181015183820152602001612fc4565b50506000910152565b60008151808452612ffd816020860160208601612fc1565b601f01601f19169290920160200192915050565b602081526000610fe96020830184612fe5565b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b038111828210171561305c5761305c613024565b60405290565b604051601f8201601f191681016001600160401b038111828210171561308a5761308a613024565b604052919050565b60006001600160401b038211156130ab576130ab613024565b50601f01601f191660200190565b600082601f8301126130ca57600080fd5b81356130dd6130d882613092565b613062565b8181528460208386010111156130f257600080fd5b816020850160208301376000918101602001919091529392505050565b6001600160a01b0381168114611ce957600080fd5b60008060006060848603121561313957600080fd5b83356001600160401b038082111561315057600080fd5b61315c878388016130b9565b9450602086013591508082111561317257600080fd5b5061317f868287016130b9565b92505060408401356131908161310f565b809150509250925092565b600080604083850312156131ae57600080fd5b82356131b98161310f565b946020939093013593505050565b600060e082840312156131d957600080fd5b50919050565b6000602082840312156131f157600080fd5b81356001600160401b0381111561320757600080fd5b611261848285016131c7565b8351815260208085015190820152600060a08201604060a0604085015281865180845260c08601915060c08160051b8701019350602080890160005b8381101561328e5788870360bf1901855281518051885283015183880187905261327b87890182612fe5565b975050938201939082019060010161324f565b50508751606088015250505060208501516080850152509050611261565b6000606082840312156131d957600080fd5b60008083601f8401126132d057600080fd5b5081356001600160401b038111156132e757600080fd5b602083019150836020828501011115612d2857600080fd5b600080600080600080600060e0888a03121561331a57600080fd5b61332489896132ac565b96506060880135955060808801356001600160401b038082111561334757600080fd5b6133538b838c016132be565b909750955060a08a013591506133688261310f565b90935060c0890135908082111561337e57600080fd5b5061338b8a828b016132be565b989b979a50959850939692959293505050565b6000602082840312156133b057600080fd5b8135610fe98161310f565b6000806000606084860312156133d057600080fd5b83356133db8161310f565b925060208401356133eb8161310f565b929592945050506040919091013590565b803563ffffffff8116811461341057600080fd5b919050565b60006020828403121561342757600080fd5b610fe9826133fc565b6000806040838503121561344357600080fd5b6131b9836133fc565b8015158114611ce957600080fd5b6000806040838503121561346d57600080fd5b82356001600160401b0381111561348357600080fd5b61348f858286016131c7565b92505060208301356134a08161344c565b809150509250929050565b815181526020808301519082015260408101610d5f565b803561ffff8116811461341057600080fd5b6000602082840312156134e657600080fd5b610fe9826134c2565b6000806040838503121561350257600080fd5b61350b836133fc565b9150613519602084016134c2565b90509250929050565b60008060006060848603121561353757600080fd5b613540846133fc565b925061354e602085016134c2565b915060408401356131908161344c565b60008060008060a0858703121561357457600080fd5b61357e86866132ac565b935060608501356001600160401b0381111561359957600080fd5b6135a5878288016132be565b90945092505060808501356135b98161310f565b939692955090935050565b60008083601f8401126135d657600080fd5b5081356001600160401b038111156135ed57600080fd5b6020830191508360208260051b8501011115612d2857600080fd5b6000806020838503121561361b57600080fd5b82356001600160401b0381111561363157600080fd5b61363d858286016135c4565b90969095509350505050565b6000806000806060858703121561365f57600080fd5b613668856133fc565b9350613676602086016134c2565b925060408501356001600160401b0381111561369157600080fd5b61369d878288016132be565b95989497509550505050565b600080600083850360808112156136bf57600080fd5b84356001600160401b038111156136d557600080fd5b6136e1878288016131c7565b9450506040601f19820112156136f657600080fd5b5060208401915060608401356131908161310f565b600060c082019050835182526001600160401b0360208501511660208301526040840151613746604084018280518252602090810151910152565b5082516080830152602083015160a0830152610fe9565b6000806040838503121561377057600080fd5b823561377b8161310f565b915060208301356134a08161310f565b60006060828403121561379d57600080fd5b610fe983836132ac565b600181811c908216806137bb57607f821691505b6020821081036131d957634e487b7160e01b600052602260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b8082028115828204841417610d5f57610d5f6137db565b60008261382557634e487b7160e01b600052601260045260246000fd5b500490565b634e487b7160e01b600052603260045260246000fd5b60008235605e1983360301811261385657600080fd5b9190910192915050565b6000808335601e1984360301811261387757600080fd5b8301803591506001600160401b0382111561389157600080fd5b602001915036819003821315612d2857600080fd5b601f821115611d4e576000816000526020600020601f850160051c810160208610156138cf5750805b601f850160051c820191505b818110156138ee578281556001016138db565b505050505050565b6001600160401b0383111561390d5761390d613024565b6139218361391b83546137a7565b836138a6565b6000601f841160018114613955576000851561393d5750838201355b600019600387901b1c1916600186901b178355611b00565b600083815260209020601f19861690835b828110156139865786850135825560209485019460019092019101613966565b50868210156139a35760001960f88860031b161c19848701351681555b505060018560011b0183555050505050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b60208082528181018390526000906040808401600586901b8501820187855b88811015613ab457878303603f190184528135368b9003605e19018112613a2357600080fd5b8a01606063ffffffff613a35836133fc565b16855261ffff613a468984016134c2565b168886015286820135601e19833603018112613a6157600080fd5b9091018781019190356001600160401b03811115613a7e57600080fd5b803603831315613a8d57600080fd5b8188870152613a9f82870182856139b5565b968901969550505091860191506001016139fd565b509098975050505050505050565b60008085851115613ad257600080fd5b83861115613adf57600080fd5b5050820193919092039150565b60008451613afe818460208901612fc1565b8201838582376000930192835250909392505050565b6020815260006112616020830184866139b5565b6000823561013e1983360301811261385657600080fd5b6001600160401b0381168114611ce957600080fd5b63ffffffff613b62896133fc565b1681526020880135602082015260006040890135613b7f81613b3f565b6001600160401b03811660408401525087606083015260e06080830152613baa60e0830187896139b5565b6001600160a01b03861660a084015282810360c0840152613bcc8185876139b5565b9a9950505050505050505050565b600060208284031215613bec57600080fd5b81516001600160401b03811115613c0257600080fd5b8201601f81018413613c1357600080fd5b8051613c216130d882613092565b818152856020838501011115613c3657600080fd5b612289826020830160208601612fc1565b600060208284031215613c5957600080fd5b8135610fe981613b3f565b60018060a01b038516815283602082015261ffff831660408201526080606082015260006110ba6080830184612fe5565b604081526000613ca86040830185612fe5565b82810360208401526122898185612fe5565b600060208284031215613ccc57600080fd5b8151610fe98161344c565b6040815263ffffffff8351166040820152602083015160608201526000604084015160a06080840152613d0d60e0840182612fe5565b90506060850151603f198483030160a0850152613d2a8282612fe5565b60809690960151151560c08501525050506001600160a01b039190911660209091015290565b600060408284031215613d6257600080fd5b613d6a61303a565b9050815181526020820151602082015292915050565b600060408284031215613d9257600080fd5b610fe98383613d50565b6001600160f01b03198135818116916002851015613dc45780818660020360031b1b83161692505b505092915050565b600060408284031215613dde57600080fd5b613de661303a565b82358152602083013560208201528091505092915050565b80356020831015610d5f57600019602084900360031b1b1692915050565b6001600160c01b03198135818116916008851015613dc45760089490940360031b84901b1690921692915050565b6001600160401b0360c01b8560c01b16815263ffffffff60e01b8460e01b16600882015282600c82015260008251613e8981602c850160208701612fc1565b91909101602c0195945050505050565b600060018201613eab57613eab6137db565b5060010190565b8481526001600160401b0360c01b8460c01b16602082015282602882015260008251613ee5816048850160208701612fc1565b9190910160480195945050505050565b81810381811115610d5f57610d5f6137db565b600060808284031215613f1a57600080fd5b604051606081018181106001600160401b0382111715613f3c57613f3c613024565b604052825181526020830151613f5181613b3f565b6020820152613f638460408501613d50565b60408201529392505050565b81516001600160401b03811115613f8857613f88613024565b613f9c81613f9684546137a7565b846138a6565b602080601f831160018114613fd15760008415613fb95750858301515b600019600386901b1c1916600185901b1785556138ee565b600085815260208120601f198616915b8281101561400057888601518255948401946001909101908401613fe1565b508582101561401e5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b80820180821115610d5f57610d5f6137db565b60006020828403121561405357600080fd5b8151610fe98161310f56fe52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace000cb173d183337e25fab6cb85705c15aad6a58cb1d552ed71b9bc628c8a3de80072ab1bc1039b79dc4724ffca13de82c96834302d3c7e0d4252232d4b2dd8f900a2646970667358221220031524f18b86ada60e42e02fdc1e3f7577c3b607cb28a16400194b8b5d17c0a164736f6c634300081600330000000000000000000000006f475642a6e85809b1c36fa62763669b1b48dd5b
Deployed Bytecode
0x60806040526004361061036b5760003560e01c806370a08231116101c6578063bb0b6a53116100f7578063d424388511610095578063e43252d71161006f578063e43252d714610b11578063f2fde38b14610b31578063fc0c546a146106e9578063ff7bd03d14610b5157600080fd5b8063d424388514610abb578063dd62ed3e14610adb578063e1a4521814610afb57600080fd5b8063bd815db0116100d1578063bd815db014610a54578063c7c7f5b314610a67578063ca5eb5e114610a88578063d045a0dc14610aa857600080fd5b8063bb0b6a53146109ce578063bc70b35414610a0e578063bcae25a414610a2e57600080fd5b80638da5cb5b116101645780639f68b9641161013e5780639f68b96414610965578063a9059cbb14610979578063b731ea0a14610999578063b98bd070146109ae57600080fd5b80638da5cb5b1461090757806395d89b411461091c578063963efcaa1461093157600080fd5b806382413eac116101a057806382413eac14610898578063857749b0146105605780638705fcd4146108c75780638ab1d681146108e757600080fd5b806370a0823114610828578063715018a6146108485780637d25a05e1461085d57600080fd5b80633194c180116102a05780635535d4611161023e5780635e280f11116102185780635e280f111461078057806360b71d4e146107b45780636db7bcdb146107e85780636fc1b31e1461080857600080fd5b80635535d461146106fc5780635a0dfe4d1461071c5780635bf9c2261461076057600080fd5b80633b6f743b1161027a5780633b6f743b1461067e5780634488b652146106ab5780634e7ceacb146106cb57806352ae2879146106e957600080fd5b80633194c1801461057c5780633400288b146106255780633af32abf1461064557600080fd5b8063156a0d0f1161030d57806318160ddd116102e757806318160ddd146104ed5780631f5e13341461052b57806323b872dd14610540578063313ce5671461056057600080fd5b8063156a0d0f14610484578063164e68de146104ab57806317442b70146104cb57600080fd5b80630d35b415116103495780630d35b415146103ed578063111ecdad1461041c57806313137d6514610449578063134d4f251461045c57600080fd5b806306fdde0314610370578063077f224a1461039b578063095ea7b3146103bd575b600080fd5b34801561037c57600080fd5b50610385610b71565b6040516103929190613011565b60405180910390f35b3480156103a757600080fd5b506103bb6103b6366004613124565b610c34565b005b3480156103c957600080fd5b506103dd6103d836600461319b565b610d4b565b6040519015158152602001610392565b3480156103f957600080fd5b5061040d6104083660046131df565b610d65565b60405161039293929190613213565b34801561042857600080fd5b50610431610e31565b6040516001600160a01b039091168152602001610392565b6103bb6104573660046132ff565b610e66565b34801561046857600080fd5b50610471600281565b60405161ffff9091168152602001610392565b34801561049057600080fd5b506040805162b9270b60e21b81526001602082015201610392565b3480156104b757600080fd5b506103bb6104c636600461339e565b610f26565b3480156104d757600080fd5b5060408051600181526002602082015201610392565b3480156104f957600080fd5b507f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace02545b604051908152602001610392565b34801561053757600080fd5b50610471600181565b34801561054c57600080fd5b506103dd61055b3660046133bb565b610fca565b34801561056c57600080fd5b5060405160068152602001610392565b34801561058857600080fd5b50610604610597366004613415565b6040805180820182526000808252602091820181905263ffffffff9390931683527f0cb173d183337e25fab6cb85705c15aad6a58cb1d552ed71b9bc628c8a3de80181529181902081518083019092525461ffff8116825262010000900460ff1615159181019190915290565b60408051825161ffff16815260209283015115159281019290925201610392565b34801561063157600080fd5b506103bb610640366004613430565b610ff0565b34801561065157600080fd5b506103dd61066036600461339e565b6001600160a01b031660009081526001602052604090205460ff1690565b34801561068a57600080fd5b5061069e61069936600461345a565b61105d565b60405161039291906134ab565b3480156106b757600080fd5b506103bb6106c63660046134d4565b6110c4565b3480156106d757600080fd5b506000546001600160a01b0316610431565b3480156106f557600080fd5b5030610431565b34801561070857600080fd5b506103856107173660046134ef565b61114b565b34801561072857600080fd5b506103dd610737366004613430565b63ffffffff91909116600090815260008051602061409f83398151915260205260409020541490565b34801561076c57600080fd5b5061051d61077b366004613430565b611226565b34801561078c57600080fd5b506104317f0000000000000000000000006f475642a6e85809b1c36fa62763669b1b48dd5b81565b3480156107c057600080fd5b507f68f1d0d99488c60d21eadee2cca13b58661d56fbcb4e4464d6fc8def1b3422005461051d565b3480156107f457600080fd5b506103bb610803366004613522565b611269565b34801561081457600080fd5b506103bb61082336600461339e565b61133d565b34801561083457600080fd5b5061051d61084336600461339e565b6113b1565b34801561085457600080fd5b506103bb6113d9565b34801561086957600080fd5b50610880610878366004613430565b600092915050565b6040516001600160401b039091168152602001610392565b3480156108a457600080fd5b506103dd6108b336600461355e565b6001600160a01b0381163014949350505050565b3480156108d357600080fd5b506103bb6108e236600461339e565b6113ed565b3480156108f357600080fd5b506103bb61090236600461339e565b611449565b34801561091357600080fd5b50610431611501565b34801561092857600080fd5b5061038561152a565b34801561093d57600080fd5b5061051d7f000000000000000000000000000000000000000000000000000000000000000181565b34801561097157600080fd5b5060006103dd565b34801561098557600080fd5b506103dd61099436600461319b565b611569565b3480156109a557600080fd5b50610431611577565b3480156109ba57600080fd5b506103bb6109c9366004613608565b6115a0565b3480156109da57600080fd5b5061051d6109e9366004613415565b63ffffffff16600090815260008051602061409f833981519152602052604090205490565b348015610a1a57600080fd5b50610385610a29366004613649565b611721565b348015610a3a57600080fd5b5060008051602061407f8339815191525461ffff16610471565b6103bb610a62366004613608565b6118b7565b610a7a610a753660046136a9565b611a4e565b60405161039292919061370b565b348015610a9457600080fd5b506103bb610aa336600461339e565b611a81565b6103bb610ab63660046132ff565b611b07565b348015610ac757600080fd5b506103bb610ad636600461339e565b611b36565b348015610ae757600080fd5b5061051d610af636600461375d565b611baa565b348015610b0757600080fd5b5061047161271081565b348015610b1d57600080fd5b506103bb610b2c36600461339e565b611bf4565b348015610b3d57600080fd5b506103bb610b4c36600461339e565b611cae565b348015610b5d57600080fd5b506103dd610b6c36600461378b565b611cec565b7f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace03805460609160008051602061405f83398151915291610bb0906137a7565b80601f0160208091040260200160405190810160405280929190818152602001828054610bdc906137a7565b8015610c295780601f10610bfe57610100808354040283529160200191610c29565b820191906000526020600020905b815481529060010190602001808311610c0c57829003601f168201915b505050505091505090565b6000610c3e611d0a565b805490915060ff600160401b82041615906001600160401b0316600081158015610c655750825b90506000826001600160401b03166001148015610c815750303b155b905081158015610c8f575080155b15610cad5760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff191660011785558315610cd757845460ff60401b1916600160401b1785555b610ce2888888611d33565b610ceb86611d53565b600080546001600160a01b03191690558315610d4157845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b5050505050505050565b600033610d59818585611d64565b60019150505b92915050565b60408051808201909152600080825260208201526060610d98604051806040016040528060008152602001600081525090565b6040805180820182526000808252600019602080840182905284518381529081019094529195509182610dee565b604080518082019091526000815260606020820152815260200190600190039081610dc65790505b509350600080610e13604089013560608a0135610e0e60208c018c613415565b611d71565b60408051808201909152918252602082015296989597505050505050565b6000807f41db8a78b0206aba5c54bcbfc2bda0d84082a84eb88e680379a57b9e9f653c005b546001600160a01b031692915050565b7f0000000000000000000000006f475642a6e85809b1c36fa62763669b1b48dd5b6001600160a01b03163314610eb6576040516391ac5e4f60e01b81523360048201526024015b60405180910390fd5b60208701803590610ed090610ecb908a613415565b611dc2565b14610f0e57610ee26020880188613415565b60405163309afaf360e21b815263ffffffff909116600482015260208801356024820152604401610ead565b610f1d87878787878787611e0d565b50505050505050565b610f2e611f74565b7f68f1d0d99488c60d21eadee2cca13b58661d56fbcb4e4464d6fc8def1b34220080546000819003610f7357604051630d00db4d60e31b815260040160405180910390fd5b60008255610f82308483611fa6565b826001600160a01b03167f78473f3f373f7673597f4f0fa5873cb4d375fea6d4339ad6b56dbd411513cb3f82604051610fbd91815260200190565b60405180910390a2505050565b600033610fd8858285612005565b610fe3858585611fa6565b60019150505b9392505050565b610ff8611f74565b63ffffffff8216600081815260008051602061409f833981519152602081815260409283902085905582519384528301849052917f238399d427b947898edb290f5ff0f9109849b1c3ba196a42e35f00c50a54b98b91015b60405180910390a1505050565b6040805180820190915260008082526020820152600061108d60408501356060860135610e0e6020880188613415565b91505060008061109d868461206c565b90925090506110ba6110b26020880188613415565b8383886121b1565b9695505050505050565b6110cc611f74565b61271061ffff821611156110f35760405163c6cc5d7f60e01b815260040160405180910390fd5b60008051602061407f833981519152805461ffff191661ffff831690811782556040519081527f9283ddc0c2b59320e00b0ae4a992b110df098c38e3b6ea1d92fe7a6d3504be9b906020015b60405180910390a15050565b63ffffffff821660009081527f8d2bda5d9f6ffb5796910376005392955773acee5548d0fcdb10e7c264ea00006020818152604080842061ffff861685529091529091208054606092919061119f906137a7565b80601f01602080910402602001604051908101604052809291908181526020018280546111cb906137a7565b80156112185780601f106111ed57610100808354040283529160200191611218565b820191906000526020600020905b8154815290600101906020018083116111fb57829003601f168201915b505050505091505092915050565b60008061123284612292565b905061ffff81161561125e5761271061124f61ffff8316856137f1565b6112599190613808565b611261565b60005b949350505050565b611271611f74565b61271061ffff831611156112985760405163c6cc5d7f60e01b815260040160405180910390fd5b600060008051602061407f83398151915260408051808201825261ffff868116808352861515602080850182815263ffffffff8c16600081815260018a0184528890209651875492511515620100000262ffffff1990931696169590951717909455845192835292820152918201529091507f56f0bca120766dba5aeeb89a1cf629c3495dc497c82f426d4e4d58c54b72764c9060600160405180910390a150505050565b611345611f74565b7f41db8a78b0206aba5c54bcbfc2bda0d84082a84eb88e680379a57b9e9f653c0080546001600160a01b0319166001600160a01b03831690811782556040519081527ff0be4f1e87349231d80c36b33f9e8639658eeaf474014dee15a3e6a4d44141979060200161113f565b6001600160a01b0316600090815260008051602061405f833981519152602052604090205490565b6113e1611f74565b6113eb6000612311565b565b6113f5611f74565b600080546001600160a01b0319166001600160a01b0383169081179091556040519081527f0cc4d0c9af0c184a6ba4203a2d8f4a6843759ea43f751b50f516f6fb4241d9df9060200160405180910390a150565b611451611f74565b6001600160a01b03811660009081526001602052604090205460ff166114ab5760405162461bcd60e51b815260206004820152600f60248201526e139bdd081dda1a5d195b1a5cdd1959608a1b6044820152606401610ead565b6001600160a01b0381166000818152600160209081526040808320805460ff19169055519182527ff93f9a76c1bf3444d22400a00cb9fe990e6abe9dbb333fda48859cfee864543d91015b60405180910390a250565b6000807f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300610e56565b7f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace04805460609160008051602061405f83398151915291610bb0906137a7565b600033610d59818585611fa6565b6000807fefb041d771d6daaa55702fff6eb740d63ba559a75d2d1d3e151c78ff2480b600610e56565b6115a8611f74565b7f8d2bda5d9f6ffb5796910376005392955773acee5548d0fcdb10e7c264ea000060005b828110156116ef5761160e8484838181106115e9576115e961382a565b90506020028101906115fb9190613840565b611609906040810190613860565b612382565b8383828181106116205761162061382a565b90506020028101906116329190613840565b611640906040810190613860565b8360008787868181106116555761165561382a565b90506020028101906116679190613840565b611675906020810190613415565b63ffffffff1663ffffffff16815260200190815260200160002060008787868181106116a3576116a361382a565b90506020028101906116b59190613840565b6116c69060408101906020016134d4565b61ffff1681526020810191909152604001600020916116e69190836138f6565b506001016115cc565b507fbe4864a8e820971c0247f5992e2da559595f7bf076a21cb5928d443d2a13b67483836040516110509291906139de565b63ffffffff841660009081527f8d2bda5d9f6ffb5796910376005392955773acee5548d0fcdb10e7c264ea00006020818152604080842061ffff88168552909152822080546060939190611774906137a7565b80601f01602080910402602001604051908101604052809291908181526020018280546117a0906137a7565b80156117ed5780601f106117c2576101008083540402835291602001916117ed565b820191906000526020600020905b8154815290600101906020018083116117d057829003601f168201915b50505050509050805160000361183e5784848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550611261945050505050565b60008490036118505791506112619050565b6002841061189a576118628585612382565b806118708560028189613ac2565b60405160200161188293929190613aec565b60405160208183030381529060405292505050611261565b8484604051639a6d49cd60e01b8152600401610ead929190613b14565b60005b818110156119cd57368383838181106118d5576118d561382a565b90506020028101906118e79190613b28565b90506119276118f96020830183613415565b602083013563ffffffff91909116600090815260008051602061409f83398151915260205260409020541490565b61193157506119c5565b3063d045a0dc60c08301358360a0810135611950610100830183613860565b611961610100890160e08a0161339e565b61196f6101208a018a613860565b6040518963ffffffff1660e01b81526004016119919796959493929190613b54565b6000604051808303818588803b1580156119aa57600080fd5b505af11580156119be573d6000803e3d6000fd5b5050505050505b6001016118ba565b50336001600160a01b0316638e9e70996040518163ffffffff1660e01b8152600401600060405180830381865afa158015611a0c573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611a349190810190613bda565b604051638351eea760e01b8152600401610ead9190613011565b611a56612f7a565b6040805180820190915260008082526020820152611a758585856123c4565b91509150935093915050565b611a89611f74565b60405163ca5eb5e160e01b81526001600160a01b0382811660048301527f0000000000000000000000006f475642a6e85809b1c36fa62763669b1b48dd5b169063ca5eb5e190602401600060405180830381600087803b158015611aec57600080fd5b505af1158015611b00573d6000803e3d6000fd5b5050505050565b333014611b275760405163029a949d60e31b815260040160405180910390fd5b610f1d87878787878787610f0e565b611b3e611f74565b7fefb041d771d6daaa55702fff6eb740d63ba559a75d2d1d3e151c78ff2480b60080546001600160a01b0319166001600160a01b03831690811782556040519081527fd48d879cef83a1c0bdda516f27b13ddb1b3f8bbac1c9e1511bb2a659c24277609060200161113f565b6001600160a01b0391821660009081527f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace016020908152604080832093909416825291909152205490565b611bfc611f74565b6001600160a01b03811660009081526001602052604090205460ff1615611c5b5760405162461bcd60e51b8152602060048201526013602482015272105b1c9958591e481dda1a5d195b1a5cdd1959606a1b6044820152606401610ead565b6001600160a01b038116600081815260016020818152604092839020805460ff19168317905591519081527ff93f9a76c1bf3444d22400a00cb9fe990e6abe9dbb333fda48859cfee864543d91016114f6565b611cb6611f74565b6001600160a01b038116611ce057604051631e4fbdf760e01b815260006004820152602401610ead565b611ce981612311565b50565b600060208201803590611d03906109e99085613415565b1492915050565b6000807ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00610d5f565b611d3b6124bf565b611d4583836124e4565b611d4e816124fa565b505050565b611d5b6124bf565b611ce98161251b565b611d4e8383836001612523565b82600080611d7f8484611226565b9050611d8c81870361260a565b915084821015611db9576040516371c4efed60e01b81526004810183905260248101869052604401610ead565b50935093915050565b63ffffffff8116600090815260008051602061409f8339815191526020819052604082205480610fe95760405163f6ff4fb760e01b815263ffffffff85166004820152602401610ead565b6000611e1f611e1c8787612641565b90565b90506000611e4b82611e39611e348a8a612659565b61267c565b611e4660208d018d613415565b6126b1565b90506028861115611f12576000611e88611e6b60608c0160408d01613c47565b611e7860208d018d613415565b84611e838c8c6126d9565b612724565b604051633e5ac80960e11b81529091506001600160a01b037f0000000000000000000000006f475642a6e85809b1c36fa62763669b1b48dd5b1690637cb5901290611ede9086908d906000908790600401613c64565b600060405180830381600087803b158015611ef857600080fd5b505af1158015611f0c573d6000803e3d6000fd5b50505050505b6001600160a01b038216887fefed6d3500546b29533b128a29e3a94d70788727f0507505ac12eaf2e578fd9c611f4b60208d018d613415565b6040805163ffffffff9092168252602082018690520160405180910390a3505050505050505050565b33611f7d611501565b6001600160a01b0316146113eb5760405163118cdaa760e01b8152336004820152602401610ead565b6001600160a01b038316611fd057604051634b637e8f60e11b815260006004820152602401610ead565b6001600160a01b038216611ffa5760405163ec442f0560e01b815260006004820152602401610ead565b611d4e838383612756565b60006120118484611baa565b9050600019811015612066578181101561205757604051637dc7a0d960e11b81526001600160a01b03841660048201526024810182905260448101839052606401610ead565b61206684848484036000612523565b50505050565b60608060006120c98560200135612082866127e4565b61208f60a0890189613860565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061283e92505050565b90935090506000816120dc5760016120df565b60025b90506120ff6120f16020880188613415565b82610a2960808a018a613860565b7f41db8a78b0206aba5c54bcbfc2bda0d84082a84eb88e680379a57b9e9f653c008054919450906001600160a01b031680156121a65760405163043a78eb60e01b81526001600160a01b0382169063043a78eb906121639089908990600401613c95565b602060405180830381865afa158015612180573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121a49190613cba565b505b505050509250929050565b60408051808201909152600080825260208201527f0000000000000000000000006f475642a6e85809b1c36fa62763669b1b48dd5b6001600160a01b031663ddc28c586040518060a001604052808863ffffffff16815260200161221489611dc2565b8152602001878152602001868152602001851515815250306040518363ffffffff1660e01b8152600401612249929190613cd7565b6040805180830381865afa158015612265573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122899190613d80565b95945050505050565b63ffffffff811660009081527f0cb173d183337e25fab6cb85705c15aad6a58cb1d552ed71b9bc628c8a3de8016020908152604080832081518083019092525461ffff8116825262010000900460ff16151591810182905260008051602061407f8339815191529161230957815461ffff16611261565b519392505050565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930080546001600160a01b031981166001600160a01b03848116918217845560405192169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3505050565b60006123916002828486613ac2565b61239a91613d9c565b60f01c905060038114611d4e578282604051639a6d49cd60e01b8152600401610ead929190613b14565b6123cc612f7a565b604080518082019091526000808252602082015260008061240333604089013560608a01356123fe60208c018c613415565b6128b8565b91509150600080612414898461206c565b909250905061244061242960208b018b613415565b838361243a368d90038d018d613dcc565b8b6129ec565b60408051808201909152858152602080820186905282519298509096503391907f85496b760a4b7f8d66384b9df21b381f5d1b1e79f229a47aaf4c232edc2fe59a9061248e908d018d613415565b6040805163ffffffff909216825260208201899052810187905260600160405180910390a350505050935093915050565b6124c7612af7565b6113eb57604051631afcd79f60e31b815260040160405180910390fd5b6124ec6124bf565b6124f68282612b11565b5050565b6125026124bf565b61250b81612b62565b612513612b73565b611ce9612b73565b611cb66124bf565b60008051602061405f8339815191526001600160a01b03851661255c5760405163e602df0560e01b815260006004820152602401610ead565b6001600160a01b03841661258657604051634a1406b160e11b815260006004820152602401610ead565b6001600160a01b03808616600090815260018301602090815260408083209388168352929052208390558115611b0057836001600160a01b0316856001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925856040516125fb91815260200190565b60405180910390a35050505050565b60007f00000000000000000000000000000000000000000000000000000000000000016126378184613808565b610d5f91906137f1565b60006126506020828486613ac2565b610fe991613dfe565b6000612669602860208486613ac2565b61267291613e1c565b60c01c9392505050565b6000610d5f7f00000000000000000000000000000000000000000000000000000000000000016001600160401b0384166137f1565b60006001600160a01b0384166126c75761dead93505b6126d18484612b7b565b509092915050565b60606126e88260288186613ac2565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929695505050505050565b60608484848460405160200161273d9493929190613e4a565b6040516020818303038152906040529050949350505050565b612761838383612bb1565b6002805490600061277183613e99565b9190505550600254826001600160a01b0316846001600160a01b03167f6d16356255ebed8e5918262476684aaa5f8054befd93154494221a6026157aa5846127b8886113b1565b6127c1886113b1565b6040805193845260208401929092529082015260600160405180910390a4505050565b6000806128117f000000000000000000000000000000000000000000000000000000000000000184613808565b90506001600160401b03811115610d5f5760405163e2ce941360e01b815260048101829052602401610ead565b805160609015158061288757848460405160200161287392919091825260c01b6001600160c01b031916602082015260280190565b6040516020818303038152906040526128ae565b8484338560405160200161289e9493929190613eb2565b6040516020818303038152906040525b9150935093915050565b6001600160a01b038416600090815260016020526040812054819060ff166128ea576128e5858585611d71565b6128f4565b6128f48585612cef565b9092509050818111156129645760405162461bcd60e51b815260206004820152603260248201527f416d6f756e742072656365697665642063616e6e6f74206265206772656174656044820152711c881d1a185b88185b5bdd5b9d081cd95b9d60721b6064820152608401610ead565b60006129708284613ef5565b905080156129d8576000546001600160a01b03166129c0577f68f1d0d99488c60d21eadee2cca13b58661d56fbcb4e4464d6fc8def1b3422008054820181556129ba883084611fa6565b506129d8565b6000546129d89088906001600160a01b031683611fa6565b6129e28783612d2f565b5094509492505050565b6129f4612f7a565b6000612a038460000151612d65565b602085015190915015612a1d57612a1d8460200151612d8d565b7f0000000000000000000000006f475642a6e85809b1c36fa62763669b1b48dd5b6001600160a01b0316632637a450826040518060a001604052808b63ffffffff168152602001612a6d8c611dc2565b81526020018a815260200189815260200160008960200151111515815250866040518463ffffffff1660e01b8152600401612aa9929190613cd7565b60806040518083038185885af1158015612ac7573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190612aec9190613f08565b979650505050505050565b6000612b01611d0a565b54600160401b900460ff16919050565b612b196124bf565b60008051602061405f8339815191527f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace03612b538482613f6f565b50600481016120668382613f6f565b612b6a6124bf565b61250b81612e6f565b6113eb6124bf565b6001600160a01b038216612ba55760405163ec442f0560e01b815260006004820152602401610ead565b6124f660008383612756565b60008051602061405f8339815191526001600160a01b038416612bed5781816002016000828254612be2919061402e565b90915550612c5f9050565b6001600160a01b03841660009081526020829052604090205482811015612c405760405163391434e360e21b81526001600160a01b03861660048201526024810182905260448101849052606401610ead565b6001600160a01b03851660009081526020839052604090209083900390555b6001600160a01b038316612c7d576002810180548390039055612c9c565b6001600160a01b03831660009081526020829052604090208054830190555b826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051612ce191815260200190565b60405180910390a350505050565b816000612cfb8261260a565b905082811015612d28576040516371c4efed60e01b81526004810182905260248101849052604401610ead565b9250929050565b6001600160a01b038216612d5957604051634b637e8f60e11b815260006004820152602401610ead565b6124f682600083612756565b6000813414612d89576040516304fb820960e51b8152346004820152602401610ead565b5090565b60007f0000000000000000000000006f475642a6e85809b1c36fa62763669b1b48dd5b6001600160a01b031663e4fe1d946040518163ffffffff1660e01b8152600401602060405180830381865afa158015612ded573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e119190614041565b90506001600160a01b038116612e3a576040516329b99a9560e11b815260040160405180910390fd5b6124f66001600160a01b038216337f0000000000000000000000006f475642a6e85809b1c36fa62763669b1b48dd5b85612e80565b612e776124bf565b611ce981612eda565b604080516001600160a01b0385811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b179052612066908590612f09565b612ee26124bf565b6001600160a01b038116611a8957604051632d618d8160e21b815260040160405180910390fd5b600080602060008451602086016000885af180612f2c576040513d6000823e3d81fd5b50506000513d91508115612f44578060011415612f51565b6001600160a01b0384163b155b1561206657604051635274afe760e01b81526001600160a01b0385166004820152602401610ead565b60405180606001604052806000801916815260200160006001600160401b03168152602001612fbc604051806040016040528060008152602001600081525090565b905290565b60005b83811015612fdc578181015183820152602001612fc4565b50506000910152565b60008151808452612ffd816020860160208601612fc1565b601f01601f19169290920160200192915050565b602081526000610fe96020830184612fe5565b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b038111828210171561305c5761305c613024565b60405290565b604051601f8201601f191681016001600160401b038111828210171561308a5761308a613024565b604052919050565b60006001600160401b038211156130ab576130ab613024565b50601f01601f191660200190565b600082601f8301126130ca57600080fd5b81356130dd6130d882613092565b613062565b8181528460208386010111156130f257600080fd5b816020850160208301376000918101602001919091529392505050565b6001600160a01b0381168114611ce957600080fd5b60008060006060848603121561313957600080fd5b83356001600160401b038082111561315057600080fd5b61315c878388016130b9565b9450602086013591508082111561317257600080fd5b5061317f868287016130b9565b92505060408401356131908161310f565b809150509250925092565b600080604083850312156131ae57600080fd5b82356131b98161310f565b946020939093013593505050565b600060e082840312156131d957600080fd5b50919050565b6000602082840312156131f157600080fd5b81356001600160401b0381111561320757600080fd5b611261848285016131c7565b8351815260208085015190820152600060a08201604060a0604085015281865180845260c08601915060c08160051b8701019350602080890160005b8381101561328e5788870360bf1901855281518051885283015183880187905261327b87890182612fe5565b975050938201939082019060010161324f565b50508751606088015250505060208501516080850152509050611261565b6000606082840312156131d957600080fd5b60008083601f8401126132d057600080fd5b5081356001600160401b038111156132e757600080fd5b602083019150836020828501011115612d2857600080fd5b600080600080600080600060e0888a03121561331a57600080fd5b61332489896132ac565b96506060880135955060808801356001600160401b038082111561334757600080fd5b6133538b838c016132be565b909750955060a08a013591506133688261310f565b90935060c0890135908082111561337e57600080fd5b5061338b8a828b016132be565b989b979a50959850939692959293505050565b6000602082840312156133b057600080fd5b8135610fe98161310f565b6000806000606084860312156133d057600080fd5b83356133db8161310f565b925060208401356133eb8161310f565b929592945050506040919091013590565b803563ffffffff8116811461341057600080fd5b919050565b60006020828403121561342757600080fd5b610fe9826133fc565b6000806040838503121561344357600080fd5b6131b9836133fc565b8015158114611ce957600080fd5b6000806040838503121561346d57600080fd5b82356001600160401b0381111561348357600080fd5b61348f858286016131c7565b92505060208301356134a08161344c565b809150509250929050565b815181526020808301519082015260408101610d5f565b803561ffff8116811461341057600080fd5b6000602082840312156134e657600080fd5b610fe9826134c2565b6000806040838503121561350257600080fd5b61350b836133fc565b9150613519602084016134c2565b90509250929050565b60008060006060848603121561353757600080fd5b613540846133fc565b925061354e602085016134c2565b915060408401356131908161344c565b60008060008060a0858703121561357457600080fd5b61357e86866132ac565b935060608501356001600160401b0381111561359957600080fd5b6135a5878288016132be565b90945092505060808501356135b98161310f565b939692955090935050565b60008083601f8401126135d657600080fd5b5081356001600160401b038111156135ed57600080fd5b6020830191508360208260051b8501011115612d2857600080fd5b6000806020838503121561361b57600080fd5b82356001600160401b0381111561363157600080fd5b61363d858286016135c4565b90969095509350505050565b6000806000806060858703121561365f57600080fd5b613668856133fc565b9350613676602086016134c2565b925060408501356001600160401b0381111561369157600080fd5b61369d878288016132be565b95989497509550505050565b600080600083850360808112156136bf57600080fd5b84356001600160401b038111156136d557600080fd5b6136e1878288016131c7565b9450506040601f19820112156136f657600080fd5b5060208401915060608401356131908161310f565b600060c082019050835182526001600160401b0360208501511660208301526040840151613746604084018280518252602090810151910152565b5082516080830152602083015160a0830152610fe9565b6000806040838503121561377057600080fd5b823561377b8161310f565b915060208301356134a08161310f565b60006060828403121561379d57600080fd5b610fe983836132ac565b600181811c908216806137bb57607f821691505b6020821081036131d957634e487b7160e01b600052602260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b8082028115828204841417610d5f57610d5f6137db565b60008261382557634e487b7160e01b600052601260045260246000fd5b500490565b634e487b7160e01b600052603260045260246000fd5b60008235605e1983360301811261385657600080fd5b9190910192915050565b6000808335601e1984360301811261387757600080fd5b8301803591506001600160401b0382111561389157600080fd5b602001915036819003821315612d2857600080fd5b601f821115611d4e576000816000526020600020601f850160051c810160208610156138cf5750805b601f850160051c820191505b818110156138ee578281556001016138db565b505050505050565b6001600160401b0383111561390d5761390d613024565b6139218361391b83546137a7565b836138a6565b6000601f841160018114613955576000851561393d5750838201355b600019600387901b1c1916600186901b178355611b00565b600083815260209020601f19861690835b828110156139865786850135825560209485019460019092019101613966565b50868210156139a35760001960f88860031b161c19848701351681555b505060018560011b0183555050505050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b60208082528181018390526000906040808401600586901b8501820187855b88811015613ab457878303603f190184528135368b9003605e19018112613a2357600080fd5b8a01606063ffffffff613a35836133fc565b16855261ffff613a468984016134c2565b168886015286820135601e19833603018112613a6157600080fd5b9091018781019190356001600160401b03811115613a7e57600080fd5b803603831315613a8d57600080fd5b8188870152613a9f82870182856139b5565b968901969550505091860191506001016139fd565b509098975050505050505050565b60008085851115613ad257600080fd5b83861115613adf57600080fd5b5050820193919092039150565b60008451613afe818460208901612fc1565b8201838582376000930192835250909392505050565b6020815260006112616020830184866139b5565b6000823561013e1983360301811261385657600080fd5b6001600160401b0381168114611ce957600080fd5b63ffffffff613b62896133fc565b1681526020880135602082015260006040890135613b7f81613b3f565b6001600160401b03811660408401525087606083015260e06080830152613baa60e0830187896139b5565b6001600160a01b03861660a084015282810360c0840152613bcc8185876139b5565b9a9950505050505050505050565b600060208284031215613bec57600080fd5b81516001600160401b03811115613c0257600080fd5b8201601f81018413613c1357600080fd5b8051613c216130d882613092565b818152856020838501011115613c3657600080fd5b612289826020830160208601612fc1565b600060208284031215613c5957600080fd5b8135610fe981613b3f565b60018060a01b038516815283602082015261ffff831660408201526080606082015260006110ba6080830184612fe5565b604081526000613ca86040830185612fe5565b82810360208401526122898185612fe5565b600060208284031215613ccc57600080fd5b8151610fe98161344c565b6040815263ffffffff8351166040820152602083015160608201526000604084015160a06080840152613d0d60e0840182612fe5565b90506060850151603f198483030160a0850152613d2a8282612fe5565b60809690960151151560c08501525050506001600160a01b039190911660209091015290565b600060408284031215613d6257600080fd5b613d6a61303a565b9050815181526020820151602082015292915050565b600060408284031215613d9257600080fd5b610fe98383613d50565b6001600160f01b03198135818116916002851015613dc45780818660020360031b1b83161692505b505092915050565b600060408284031215613dde57600080fd5b613de661303a565b82358152602083013560208201528091505092915050565b80356020831015610d5f57600019602084900360031b1b1692915050565b6001600160c01b03198135818116916008851015613dc45760089490940360031b84901b1690921692915050565b6001600160401b0360c01b8560c01b16815263ffffffff60e01b8460e01b16600882015282600c82015260008251613e8981602c850160208701612fc1565b91909101602c0195945050505050565b600060018201613eab57613eab6137db565b5060010190565b8481526001600160401b0360c01b8460c01b16602082015282602882015260008251613ee5816048850160208701612fc1565b9190910160480195945050505050565b81810381811115610d5f57610d5f6137db565b600060808284031215613f1a57600080fd5b604051606081018181106001600160401b0382111715613f3c57613f3c613024565b604052825181526020830151613f5181613b3f565b6020820152613f638460408501613d50565b60408201529392505050565b81516001600160401b03811115613f8857613f88613024565b613f9c81613f9684546137a7565b846138a6565b602080601f831160018114613fd15760008415613fb95750858301515b600019600386901b1c1916600185901b1785556138ee565b600085815260208120601f198616915b8281101561400057888601518255948401946001909101908401613fe1565b508582101561401e5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b80820180821115610d5f57610d5f6137db565b60006020828403121561405357600080fd5b8151610fe98161310f56fe52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace000cb173d183337e25fab6cb85705c15aad6a58cb1d552ed71b9bc628c8a3de80072ab1bc1039b79dc4724ffca13de82c96834302d3c7e0d4252232d4b2dd8f900a2646970667358221220031524f18b86ada60e42e02fdc1e3f7577c3b607cb28a16400194b8b5d17c0a164736f6c63430008160033
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:3406:52:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2697:144:37;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;864:254:52;;;;;;;;;;-1:-1:-1;864:254:52;;;;;:::i;:::-;;:::i;:::-;;5114:186:37;;;;;;;;;;-1:-1:-1;5114:186:37;;;;;:::i;:::-;;:::i;:::-;;;3409:14:67;;3402:22;3384:41;;3372:2;3357:18;5114:186:37;3244:187:67;6517:1259:28;;;;;;;;;;-1:-1:-1;6517:1259:28;;;;;:::i;:::-;;:::i;:::-;;;;;;;;;:::i;4798:149::-;;;;;;;;;;;;;:::i;:::-;;;-1:-1:-1;;;;;5623:32:67;;;5605:51;;5593:2;5578:18;4798:149:28;5459:203:67;4921:708:11;;;;;;:::i;:::-;;:::i;2777:40:28:-;;;;;;;;;;;;2816:1;2777:40;;;;;7403:6:67;7391:19;;;7373:38;;7361:2;7346:18;2777:40:28;7229:188:67;3987:140:28;;;;;;;;;;-1:-1:-1;3987:140:28;;;-1:-1:-1;;;7592:52:67;;4118:1:28;7675:2:67;7660:18;;7653:59;7565:18;3987:140:28;7422:296:67;4512:325:29;;;;;;;;;;-1:-1:-1;4512:325:29;;;;;:::i;:::-;;:::i;1951:257:13:-;;;;;;;;;;-1:-1:-1;1951:257:13;;;887:1:12;8182:34:67;;759:1:11;8247:2:67;8232:18;;8225:43;8118:18;1951:257:13;7975:299:67;3850:152:37;;;;;;;;;;-1:-1:-1;3981:14:37;;3850:152;;;8425:25:67;;;8413:2;8398:18;3850:152:37;8279:177:67;2740:31:28;;;;;;;;;;;;2770:1;2740:31;;5892:244:37;;;;;;;;;;-1:-1:-1;5892:244:37;;;;;:::i;:::-;;:::i;3398:89:52:-;;;;;;;;;;-1:-1:-1;3398:89:52;;3479:1;9064:36:67;;9052:2;9037:18;3398:89:52;8922:184:67;3150:211:25;;;;;;;;;;-1:-1:-1;3150:211:25;;;;;:::i;:::-;-1:-1:-1;;;;;;;;;;;;;;;;;;;3314:17:25;;;;;;;:8;:17;;;;;;3288:43;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3150:211;;;;;9690:13:67;;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:67;3028:202:10;;;;;;;;;;-1:-1:-1;3028:202:10;;;;;:::i;:::-;;:::i;1814:111:52:-;;;;;;;;;;-1:-1:-1;1814:111:52;;;;;:::i;:::-;-1:-1:-1;;;;;1899:19:52;1876:4;1899:19;;;:9;:19;;;;;;;;;1814:111;8227:774:28;;;;;;;;;;-1:-1:-1;8227:774:28;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;1553:257:25:-;;;;;;;;;;-1:-1:-1;1553:257:25;;;;;:::i;:::-;;:::i;1271:97:52:-;;;;;;;;;;-1:-1:-1;1325:7:52;1351:10;-1:-1:-1;;;;;1351:10:52;1271: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:28:-;;;;;;;;;;-1:-1:-1;17277:132:28;;;;;:::i;:::-;2485:13:10;;;;;17359:4:28;2485:13:10;;;-1:-1:-1;;;;;;;;;;;2485:13:10;;;;;;17382:20:28;;17277:132;2346:270:25;;;;;;;;;;-1:-1:-1;2346:270:25;;;;;:::i;:::-;;:::i;1035:46:10:-;;;;;;;;;;;;;;;799:143:29;;;;;;;;;;-1:-1:-1;753:24:29;923:12;799:143;;1928:316:25;;;;;;;;;;-1:-1:-1;1928:316:25;;;;;:::i;:::-;;:::i;5989:222:28:-;;;;;;;;;;-1:-1:-1;5989:222:28;;;;;:::i;:::-;;:::i;4035:171:37:-;;;;;;;;;;-1:-1:-1;4035:171:37;;;;;:::i;:::-;;:::i;3155:101:35:-;;;;;;;;;;;;;:::i;4060:128:11:-;;;;;;;;;;-1:-1:-1;4060:128:11;;;;;:::i;:::-;4149:12;4060:128;;;;;;;;-1:-1:-1;;;;;12817:31:67;;;12799:50;;12787:2;12772:18;4060:128:11;12655:200:67;2566:216:11;;;;;;;;;;-1:-1:-1;2566:216:11;;;;;:::i;:::-;-1:-1:-1;;;;;2751:24:11;;2770:4;2751:24;2566:216;;;;;;;1124:141:52;;;;;;;;;;-1:-1:-1;1124:141:52;;;;;:::i;:::-;;:::i;1593:215::-;;;;;;;;;;-1:-1:-1;1593:215:52;;;;;:::i;:::-;;:::i;2441:144:35:-;;;;;;;;;;;;;:::i;2954:148:37:-;;;;;;;;;;;;;:::i;2434:46:28:-;;;;;;;;;;;;;;;2026:94:30;;;;;;;;;;-1:-1:-1;2085:4:30;2026:94;;4401:178:37;;;;;;;;;;-1:-1:-1;4401:178:37;;;;;:::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:28:-;;;;;;:::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:37:-;;;;;;;;;;-1:-1:-1;4612:195:37;;;;;:::i;:::-;;:::i;530:47:25:-;;;;;;;;;;;;571:6;530:47;;1374:213:52;;;;;;;;;;-1:-1:-1;1374:213:52;;;;;:::i;:::-;;:::i;3405:215:35:-;;;;;;;;;;-1:-1:-1;3405:215:35;;;;;:::i;:::-;;:::i;3324:149:11:-;;;;;;;;;;-1:-1:-1;3324:149:11;;;;;:::i;:::-;;:::i;2697:144:37:-;2827:7;2820:14;;2742:13;;-1:-1:-1;;;;;;;;;;;2064:20:37;2820:14;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2697:144;:::o;864:254:52:-;4158:30:36;4191:26;:24;:26::i;:::-;4302:15;;4158:59;;-1:-1:-1;4302:15:36;-1:-1:-1;;;4302:15:36;;;4301:16;;-1:-1:-1;;;;;4348:14:36;4279:19;4724:16;;:34;;;;;4744:14;4724:34;4704:54;;4768:17;4788:11;-1:-1:-1;;;;;4788:16:36;4803:1;4788:16;:50;;;;-1:-1:-1;4816:4:36;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:36;;;;;;;;;;;4849:91;4949:18;;-1:-1:-1;;4949:18:36;4966:1;4949:18;;;4977:67;;;;5011:22;;-1:-1:-1;;;;5011:22:36;-1:-1:-1;;;5011:22:36;;;4977:67;1006:37:52::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:52::1;::::0;;5064:101:36;;;;5098:23;;-1:-1:-1;;;;5098:23:36;;;5140:14;;-1:-1:-1;12799:50:67;;5140:14:36;;12787:2:67;12772:18;5140:14:36;;;;;;;5064:101;4092:1079;;;;;864:254:52;;;:::o;5114:186:37:-;5187:4;966:10:38;5241:31:37;966:10:38;5257:7:37;5266:5;5241:8;:31::i;:::-;5289:4;5282:11;;;5114:186;;;;;:::o;6517:1259:28:-;-1:-1:-1;;;;;;;;;;;;;;;;;6669:35:28;6706:28;-1:-1:-1;;;;;;;;;;;;;;;;;;;6706:28:28;6925:34;;;;;;;;-1:-1:-1;6925:34:28;;;-1:-1:-1;;6925:34:28;;;;;;;7076:21;;;;;;;;;;;6925:34;;-1:-1:-1;;;7076:21:28;;;-1:-1:-1;;;;;;;;;;;;;;;;;7076:21:28;;;;;;;;;;;;;;;-1:-1:-1;7060:37:28;-1:-1:-1;7534:20:28;;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:28:o;4798:149::-;4843:7;;2993:25;4889:20;4926:14;-1:-1:-1;;;;;4926:14:28;;4798:149;-1:-1:-1;;4798:149:28: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:67;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;;18392:10:67;18380:23;;;5449:40:11;;;18362:42:67;5474:14:11;;;;18420:18:67;;;18413:34;18335:18;;5449:40:11;18190:263:67;5386:103:11;5563:59;5574:7;5583:5;5590:8;;5600:9;5611:10;;5563;:59::i;:::-;4921:708;;;;;;;:::o;4512:325:29:-;2334:13:35;:11;:13::i;:::-;753:24:29;4649:12;;4576:23:::1;4675:12:::0;;;4671:43:::1;;4696:18;;-1:-1:-1::0;;;4696:18:29::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:29::1;;4822:7;4804:26;;;;8425:25:67::0;;8413:2;8398:18;;8279:177;4804:26:29::1;;;;;;;;4566:271;;4512:325:::0;:::o;5892:244:37:-;5979:4;966:10:38;6035:37:37;6051:4;966:10:38;6066:5:37;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:35;:11;:13::i;:::-;3167::10::1;::::0;::::1;3108:25;3167:13:::0;;;-1:-1:-1;;;;;;;;;;;3167:13:10::1;::::0;;;;;;;;:21;;;3203:20;;18362:42:67;;;18420:18;;18413:34;;;926:26:10;3203:20:::1;::::0;18335:18:67;3203:20:10::1;;;;;;;;3098:132;3028:202:::0;;:::o;8227:774:28:-;-1:-1:-1;;;;;;;;;;;;;;;;;8561:24:28;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:28;-1:-1:-1;8936:58:28;8943:17;;;;:10;:17;:::i;:::-;8962:7;8971;8980:13;8936:6;:58::i;:::-;8929:65;8227:774;-1:-1:-1;;;;;;8227:774:28:o;1553:257:25:-;2334:13:35;: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:67;;;1778:25:25::1;::::0;7361:2:67;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:35;: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;;19177:42:67;;;19235:18;;;19228:47;19291:18;;;19284:50;2137:8:25;;-1:-1:-1;2200:37:25::1;::::0;19165:2:67;19150:18;2200:37:25::1;;;;;;;2013:231;1928:316:::0;;;:::o;5989:222:28:-;2334:13:35;:11;:13::i;:::-;2993:25:28;6129:30;;-1:-1:-1;;;;;;6129:30:28::1;-1:-1:-1::0;;;;;6129:30:28;::::1;::::0;;::::1;::::0;;6174::::1;::::0;5605:51:67;;;6174:30:28::1;::::0;5593:2:67;5578:18;6174:30:28::1;5459:203:67::0;4035:171:37;-1:-1:-1;;;;;4179:20:37;4100:7;4179:20;;;-1:-1:-1;;;;;;;;;;;4179:20:37;;;;;;;4035:171::o;3155:101:35:-;2334:13;:11;:13::i;:::-;3219:30:::1;3246:1;3219:18;:30::i;:::-;3155:101::o:0;1124:141:52:-;2334:13:35;:11;:13::i;:::-;1197:10:52::1;:24:::0;;-1:-1:-1;;;;;;1197:24:52::1;-1:-1:-1::0;;;;;1197:24:52;::::1;::::0;;::::1;::::0;;;1236:22:::1;::::0;5605:51:67;;;1236:22:52::1;::::0;5593:2:67;5578:18;1236:22:52::1;;;;;;;1124:141:::0;:::o;1593:215::-;2334:13:35;:11;:13::i;:::-;-1:-1:-1;;;;;1677:19:52;::::1;;::::0;;;:9:::1;:19;::::0;;;;;::::1;;1669:47;;;::::0;-1:-1:-1;;;1669:47:52;;19547:2:67;1669:47:52::1;::::0;::::1;19529:21:67::0;19586:2;19566:18;;;19559:30;-1:-1:-1;;;19605:18:67;;;19598:45;19660:18;;1669:47:52::1;19345:339:67::0;1669:47:52::1;-1:-1:-1::0;;;;;1726:19:52;::::1;1748:5;1726:19:::0;;;:9:::1;:19;::::0;;;;;;;:27;;-1:-1:-1;;1726:27:52::1;::::0;;1768:33;3384:41:67;;;1768:33:52::1;::::0;3357:18:67;1768:33:52::1;;;;;;;;1593:215:::0;:::o;2441:144:35:-;2487:7;;1313:22;2533:20;1192:159;2954:148:37;3086:9;3079:16;;3001:13;;-1:-1:-1;;;;;;;;;;;2064:20:37;3079:16;;;:::i;4401:178::-;4470:4;966:10:38;4524:27:37;966:10:38;4541:2:37;4545:5;4524:9;:27::i;1596:180:15:-;1648:7;;1200:41;1708:34;1050:207;2513:600:14;2334:13:35;: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:28;2485:13:10;;;-1:-1:-1;;;;;;;;;;;2485:13:10;;;;;;17382:20:28;;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:28:-;9850:34;;:::i;:::-;-1:-1:-1;;;;;;;;;;;;;;;;;9933:39:28;9939:10;9951:4;9957:14;9933:5;:39::i;:::-;9926:46;;;;9689:290;;;;;;:::o;4123:105:10:-;2334:13:35;:11;:13::i;:::-;4190:31:10::1;::::0;-1:-1:-1;;;4190:31:10;;-1:-1:-1;;;;;5623:32:67;;;4190:31:10::1;::::0;::::1;5605:51:67::0;4190:8:10::1;:20;::::0;::::1;::::0;5578:18:67;;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:35;: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:67;;;2490:22:15::1;::::0;5593:2:67;5578:18;2490:22:15::1;5459:203:67::0;4612:195:37;-1:-1:-1;;;;;4771:20:37;;;4692:7;4771:20;;;:13;:20;;;;;;;;:29;;;;;;;;;;;;;4612:195::o;1374:213:52:-;2334:13:35;:11;:13::i;:::-;-1:-1:-1;;;;;1454:19:52;::::1;;::::0;;;:9:::1;:19;::::0;;;;;::::1;;1453:20;1445:52;;;::::0;-1:-1:-1;;;1445:52:52;;28172:2:67;1445:52:52::1;::::0;::::1;28154:21:67::0;28211:2;28191:18;;;28184:30;-1:-1:-1;;;28230:18:67;;;28223:49;28289:18;;1445:52:52::1;27970:343:67::0;1445:52:52::1;-1:-1:-1::0;;;;;1507:19:52;::::1;;::::0;;;1529:4:::1;1507:19;::::0;;;;;;;;:26;;-1:-1:-1;;1507:26:52::1;::::0;::::1;::::0;;1548:32;;3384:41:67;;;1548:32:52::1;::::0;3357:18:67;1548:32:52::1;3244:187:67::0;3405:215:35;2334:13;:11;:13::i;:::-;-1:-1:-1;;;;;3489:22:35;::::1;3485:91;;3534:31;::::0;-1:-1:-1;;;3534:31:35;;3562:1:::1;3534:31;::::0;::::1;5605:51:67::0;5578:18;;3534:31:35::1;5459:203:67::0;3485:91:35::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:36:-;9129:30;;3147:66;9186:27;8819:122;1160:189:30;6929:20:36;:18;:20::i;:::-;1279:28:30::1;1292:5;1299:7;1279:12;:28::i;:::-;1317:25;1332:9;1317:14;:25::i;:::-;1160:189:::0;;;:::o;1847:127:35:-;6929:20:36;:18;:20::i;:::-;1929:38:35::1;1954:12;1929:24;:38::i;9905:128:37:-:0;9989:37;9998:5;10005:7;10014:5;10021:4;9989:8;:37::i;2335:691:29:-;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:29;;;;;28492:25:67;;;28533:18;;;28526:34;;;28465:18;;2961:48:29;28318:248:67;2903:117:29;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;;28745:10:67;28733:23;;3745:12:10;;;28715:42:67;28688:18;;3745:12:10;28571:192:67;14070:1806:28;14547:17;14567:36;:17;:8;;:15;:17::i;:::-;2891:2:34;2780:123;14567:36:28;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:34;-1:-1:-1;;14836:955:28;;;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:28;;14940:201;;-1:-1:-1;;;;;;15688:8:28;:20;;;;:92;;15709:9;;15720:5;;15727:1;;14940:201;;15688:92;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;14863:928;14836:955;-1:-1:-1;;;;;15806:63:28;;15818:5;15806:63;15825:14;;;;:7;:14;:::i;:::-;15806:63;;;18392:10:67;18380:23;;;18362:42;;18435:2;18420:18;;18413:34;;;18335:18;15806:63:28;;;;;;;14373:1503;;14070:1806;;;;;;;:::o;2658:162:35:-;966:10:38;2717:7:35;:5;:7::i;:::-;-1:-1:-1;;;;;2717:23:35;;2713:101;;2763:40;;-1:-1:-1;;;2763:40:35;;966:10:38;2763:40:35;;;5605:51:67;5578:18;;2763:40:35;5459:203:67;6509:300:37;-1:-1:-1;;;;;6592:18:37;;6588:86;;6633:30;;-1:-1:-1;;;6633:30:37;;6660:1;6633:30;;;5605:51:67;5578:18;;6633:30:37;5459:203:67;6588:86:37;-1:-1:-1;;;;;6687:16:37;;6683:86;;6726:32;;-1:-1:-1;;;6726:32:37;;6755:1;6726:32;;;5605:51:67;5578:18;;6726:32:37;5459:203:67;6683:86:37;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:37;:36;11810:309;;;11889:5;11870:16;:24;11866:130;;;11921:60;;-1:-1:-1;;;11921:60:37;;-1:-1:-1;;;;;29990:32:67;;11921:60:37;;;29972:51:67;30039:18;;;30032:34;;;30082:18;;;30075:34;;;29945:18;;11921:60:37;29770:345:67;11866:130:37;12037:57;12046:5;12053:7;12081:5;12062:16;:24;12088:5;12037:8;:57::i;:::-;11738:387;11649:476;;;:::o;12056:1496:28:-;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:28;;-1:-1:-1;;;12413:324:28:i;:::-;12389:348;;-1:-1:-1;12389:348:28;-1:-1:-1;12817:14:28;12389:348;12834:33;;2770:1;12834:33;;;2816:1;12834:33;12817:50;-1:-1:-1;12989:67:28;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:28;-1:-1:-1;;;;;13372:14:28;13466:23;;13462:83;;13491:54;;-1:-1:-1;;;13491:54:28;;-1:-1:-1;;;;;13491:36:28;;;;;: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;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:35:-;1313:22;3923:8;;-1:-1:-1;;;;;;3941:19:35;;-1:-1:-1;;;;;3941:19:35;;;;;;;;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:28:-;10583:34;;:::i;:::-;-1:-1:-1;;;;;;;;;;;;;;;;;10981:20:28;;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:28;-1:-1:-1;11478:66:28;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:28;;-1:-1:-1;11712:10:28;;11676:15;11668:87;;11693:17;;;;:10;:17;:::i;:::-;11668:87;;;33101:10:67;33089:23;;;33071:42;;33144:2;33129:18;;33122:34;;;33172:18;;33165:34;;;33059:2;33044:18;11668:87:28;;;;;;;10649:1113;;;;10429:1333;;;;;;:::o;7082:141:36:-;7149:17;:15;:17::i;:::-;7144:73;;7189:17;;-1:-1:-1;;;7189:17:36;;;;;;;;;;;2263:147:37;6929:20:36;:18;:20::i;:::-;2365:38:37::1;2388:5;2395:7;2365:22;:38::i;:::-;2263:147:::0;;:::o;4539:183:28:-;6929:20:36;:18;:20::i;:::-;4618:22:28::1;4630:9;4618:11;:22::i;:::-;4650:30;:28;:30::i;:::-;4690:25;:23;:25::i;1980:235:35:-:0;6929:20:36;:18;:20::i;10880:487:37:-;-1:-1:-1;;;;;;;;;;;;;;;;11045:19:37;;11041:89;;11087:32;;-1:-1:-1;;;11087:32:37;;11116:1;11087:32;;;5605:51:67;5578:18;;11087:32:37;5459:203:67;11041:89:37;-1:-1:-1;;;;;11143:21:37;;11139:90;;11187:31;;-1:-1:-1;;;11187:31:37;;11215:1;11187:31;;;5605:51:67;5578:18;;11187:31:37;5459:203:67;11139:90:37;-1:-1:-1;;;;;11238:20:37;;;;;;;:13;;;:20;;;;;;;;:29;;;;;;;;;:37;;;11285:76;;;;11335:7;-1:-1:-1;;;;;11319:31:37;11328:5;-1:-1:-1;;;;;11319:31:37;;11344:5;11319:31;;;;8425:25:67;;8413:2;8398:18;;8279:177;11319:31:37;;;;;;;;10978:389;10880:487;;;;:::o;17803:172:28:-;17874:16;17947:21;17910:33;17947:21;17910:9;:33;:::i;:::-;17909:59;;;;:::i;1573:123:34:-;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:34:o;18199:139:28:-;18263:16;18298:33;18310:21;-1:-1:-1;;;;;18298:33:28;;;:::i;3505:462:30:-;3639:24;-1:-1:-1;;;;;3679:19:30;;3675:46;;3714:6;3700:21;;3675:46;3817:21;3823:3;3828:9;3817:5;:21::i;:::-;-1:-1:-1;3951:9:30;;3505:462;-1:-1:-1;;3505:462:30:o;2186:130:34:-;2250:12;2281:28;:4;243:2;2281:4;;:28;:::i;:::-;2274:35;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;2274:35:34;;2186:130;-1:-1:-1;;;;;;2186:130:34:o;640:284:33:-;824:17;877:6;885:7;894:9;905:11;860:57;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;853:64;;640:284;;;;;;:::o;3493:229:52:-;3587:30;3601:4;3607:2;3611:5;3587:13;:30::i;:::-;3627:5;:7;;;:5;:7;;;:::i;:::-;;;;;;3670:5;;3666:2;-1:-1:-1;;;;;3649:66:52;3660:4;-1:-1:-1;;;;;3649:66:52;;3677:5;3684:15;3694:4;3684:9;:15::i;:::-;3701:13;3711:2;3701:9;:13::i;:::-;3649:66;;;34721:25:67;;;34777:2;34762:18;;34755:34;;;;34805:18;;;34798:34;34709:2;34694:18;3649:66:52;;;;;;;3493:229;;;:::o;18738:266:28:-;18803:15;;18850:33;18862:21;18850:9;:33;:::i;:::-;18830:53;-1:-1:-1;;;;;;18897:28:28;;18893:70;;;18934:29;;-1:-1:-1;;;18934:29:28;;;;;8425:25:67;;;8398:18;;18934:29:28;8279:177:67;598:506:34;791:18;;732:17;;791:22;;;934:163;;1074:7;1083:13;1057:40;;;;;;;;34998:19:67;;;35073:3;35051:16;-1:-1:-1;;;;;;35047:51:67;35042:2;35033:12;;35026:73;35124:2;35115:12;;34843:290;1057:40:34;;;;;;;;;;;;;934:163;;;976:7;985:13;1017:10;1030:11;959:83;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;934:163;927:170;;598:506;;;;;;:::o;1931:1036:52:-;-1:-1:-1;;;;;2185:16:52;;2092:20;2185:16;;;:9;:16;;;;;;2092:20;;2185:16;;:130;;2271:44;2282:9;2293:12;2307:7;2271:10;:44::i;:::-;2185:130;;;2216:40;2232:9;2243:12;2216:15;:40::i;:::-;2150:165;;-1:-1:-1;2150:165:52;-1:-1:-1;2329:31:52;;;2325:122;;;2376:60;;-1:-1:-1;;;2376:60:52;;35877:2:67;2376:60:52;;;35859:21:67;35916:2;35896:18;;;35889:30;35955:34;35935:18;;;35928:62;-1:-1:-1;;;36006:18:67;;;35999:48;36064:19;;2376:60:52;35675:414:67;2325:122:52;2456:11;2470:31;2485:16;2470:12;:31;:::i;:::-;2456:45;-1:-1:-1;2516:7:52;;2512:409;;2565:1;2543:10;-1:-1:-1;;;;;2543:10:52;2539:372;;753:24:29;2682:19:52;;;;;;2737:36;2747:5;2762:4;2682:19;2737:9;:36::i;:::-;2569:219;2539:372;;;2880:10;;2863:33;;2873:5;;-1:-1:-1;;;;;2880:10:52;2892:3;2863:9;:33::i;:::-;2930:30;2936:5;2943:16;2930:5;:30::i;:::-;2140:827;1931: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:36:-;8535:4;8558:26;:24;:26::i;:::-;:40;-1:-1:-1;;;8558:40:36;;;;;;-1:-1:-1;8485:120:36:o;2416:216:37:-;6929:20:36;:18;:20::i;:::-;-1:-1:-1;;;;;;;;;;;2581:7:37;:15:::1;2591:5:::0;2581:7;:15:::1;:::i;:::-;-1:-1:-1::0;2606:9:37::1;::::0;::::1;:19;2618:7:::0;2606:9;:19:::1;:::i;1456:189:13:-:0;6929:20:36;:18;:20::i;:::-;1532:26:13::1;1548:9;1532:15;:26::i;1438:68:15:-:0;6929:20:36;:18;:20::i;8637:208:37:-;-1:-1:-1;;;;;8707:21:37;;8703:91;;8751:32;;-1:-1:-1;;;8751:32:37;;8780:1;8751:32;;;5605:51:67;5578:18;;8751:32:37;5459:203:67;8703:91:37;8803:35;8819:1;8823:7;8832:5;8803:7;:35::i;7124:1170::-;-1:-1:-1;;;;;;;;;;;;;;;;7266:18:37;;7262:546;;7420:5;7402:1;:14;;;:23;;;;;;;:::i;:::-;;;;-1:-1:-1;7262:546:37;;-1:-1:-1;7262:546:37;;-1:-1:-1;;;;;7478:17:37;;7456:19;7478:17;;;;;;;;;;;7513:19;;;7509:115;;;7559:50;;-1:-1:-1;;;7559:50:37;;-1:-1:-1;;;;;29990:32:67;;7559:50:37;;;29972:51:67;30039:18;;;30032:34;;;30082:18;;;30075:34;;;29945:18;;7559:50:37;29770:345:67;7509:115:37;-1:-1:-1;;;;;7744:17:37;;:11;:17;;;;;;;;;;7764:19;;;;7744:39;;7262:546;-1:-1:-1;;;;;7822:16:37;;7818:429;;7985:14;;;:23;;;;;;;7818:429;;;-1:-1:-1;;;;;8198:15:37;;:11;:15;;;;;;;;;;:24;;;;;;7818:429;8277:2;-1:-1:-1;;;;;8262:25:37;8271:4;-1:-1:-1;;;;;8262:25:37;;8281:5;8262:25;;;;8425::67;;8413:2;8398:18;;8279:177;8262:25:37;;;;;;;;7199:1095;7124:1170;;;:::o;2973:419:52:-;3165:9;3092:20;3227:22;3165:9;3227:11;:22::i;:::-;3208:41;;3292:12;3273:16;:31;3269:117;;;3327:48;;-1:-1:-1;;;3327:48:52;;;;;28492:25:67;;;28533:18;;;28526:34;;;28465:18;;3327:48:52;28318:248:67;3269:117:52;2973:419;;;;;:::o;9163:206:37:-;-1:-1:-1;;;;;9233:21:37;;9229:89;;9277:30;;-1:-1:-1;;;9277:30:37;;9304:1;9277:30;;;5605:51:67;5578:18;;9277:30:37;5459:203:67;9229:89:37;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:67;8398:18;;5293:26:12;8279:177:67;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:36;:18;:20::i;:::-;1867:36:10::1;1893:9;1867:25;:36::i;1618:188:47:-:0;1745:53;;;-1:-1:-1;;;;;38905:15:67;;;1745:53:47;;;38887:34:67;38957:15;;38937:18;;;38930:43;38989:18;;;;38982:34;;;1745:53:47;;;;;;;;;;38822:18:67;;;;1745:53:47;;;;;;;;-1:-1:-1;;;;;1745:53:47;-1:-1:-1;;;1745:53:47;;;1718:81;;1738:5;;1718:19;:81::i;1916:191:10:-;6929:20:36;:18;:20::i;:::-;-1:-1:-1;;;;;2010:23:10;::::1;2006:53;;2042:17;;-1:-1:-1::0;;;2042:17:10::1;;;;;;;;;;;8370:720:47::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:47;8910:8;8866:16;;-1:-1:-1;8942:15:47;;:68;;8994:11;9009:1;8994:16;;8942:68;;;-1:-1:-1;;;;;8960:26:47;;;:31;8942:68;8938:146;;;9033:40;;-1:-1:-1;;;9033:40:47;;-1:-1:-1;;;;;5623:32:67;;9033:40:47;;;5605:51:67;5578:18;;9033:40:47;5459:203:67;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;14:250:67:-;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:67;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:67;488:39;;;;529:4;484:50;;269:271;-1:-1:-1;;269:271:67: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:67;;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:67;1265:40;;-1:-1:-1;;;;;1320:34:67;;1356:22;;;1317:62;1314:88;;;1382:18;;:::i;:::-;1418:2;1411:22;1164:275;;-1:-1:-1;1164:275:67:o;1444:187::-;1493:4;-1:-1:-1;;;;;1518:6:67;1515:30;1512:56;;;1548:18;;:::i;:::-;-1:-1:-1;1614:2:67;1593:15;-1:-1:-1;;1589:29:67;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:67:o;2105:131::-;-1:-1:-1;;;;;2180:31:67;;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:67;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:67: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:67;3436:158;-1:-1:-1;3436:158:67: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:67;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:67;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:67;;;;5305:15;;;;4969:1;4962:9;4933:429;;;-1:-1:-1;;4038:12:67;;5444:2;5429:18;;4026:25;-1:-1:-1;;;4100:4:67;4089:16;;4083:23;4067:14;;;4060:47;-1:-1:-1;5379:6:67;-1:-1:-1;5394:54:67;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:67;;-1:-1:-1;;;;;6014:30:67;;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:67;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:67;-1:-1:-1;6897:3:67;6882:19;;6869:33;;-1:-1:-1;6911:31:67;6869:33;6911:31;:::i;:::-;6961:5;;-1:-1:-1;7019:3:67;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:67;;-1:-1:-1;6178:1046:67;;;;7078:86;;-1:-1:-1;;;6178:1046:67: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:67;8773:18;;8760:32;8801:33;8760:32;8801:33;:::i;:::-;8461:456;;8853:7;;-1:-1:-1;;;8907:2:67;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:67;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:159;11002:20;;11062:6;11051:18;;11041:29;;11031:57;;11084:1;11081;11074:12;11099:184;11157:6;11210:2;11198:9;11189:7;11185:23;11181:32;11178:52;;;11226:1;11223;11216:12;11178:52;11249:28;11267:9;11249:28;:::i;11288:256::-;11354:6;11362;11415:2;11403:9;11394:7;11390:23;11386:32;11383:52;;;11431:1;11428;11421:12;11383:52;11454:28;11472:9;11454:28;:::i;:::-;11444:38;;11501:37;11534:2;11523:9;11519:18;11501:37;:::i;:::-;11491:47;;11288:256;;;;;:::o;12265:385::-;12337:6;12345;12353;12406:2;12394:9;12385:7;12381:23;12377:32;12374:52;;;12422:1;12419;12412:12;12374:52;12445:28;12463:9;12445:28;:::i;:::-;12435:38;;12492:37;12525:2;12514:9;12510:18;12492:37;:::i;:::-;12482:47;;12579:2;12568:9;12564:18;12551:32;12592:28;12614:5;12592:28;:::i;12860:668::-;12972:6;12980;12988;12996;13049:3;13037:9;13028:7;13024:23;13020:33;13017:53;;;13066:1;13063;13056:12;13017:53;13089;13134:7;13123:9;13089:53;:::i;:::-;13079:63;;13193:2;13182:9;13178:18;13165:32;-1:-1:-1;;;;;13212:6:67;13209:30;13206:50;;;13252:1;13249;13242:12;13206:50;13291:58;13341:7;13332:6;13321:9;13317:22;13291:58;:::i;:::-;13368:8;;-1:-1:-1;13265:84:67;-1:-1:-1;;13453:3:67;13438:19;;13425:33;13467:31;13425:33;13467:31;:::i;:::-;12860:668;;;;-1:-1:-1;12860:668:67;;-1:-1:-1;;12860:668:67:o;13533:395::-;13624:8;13634:6;13688:3;13681:4;13673:6;13669:17;13665:27;13655:55;;13706:1;13703;13696:12;13655:55;-1:-1:-1;13729:20:67;;-1:-1:-1;;;;;13761:30:67;;13758:50;;;13804:1;13801;13794:12;13758:50;13841:4;13833:6;13829:17;13817:29;;13901:3;13894:4;13884:6;13881:1;13877:14;13869:6;13865:27;13861:38;13858:47;13855:67;;;13918:1;13915;13908:12;13933:504;14058:6;14066;14119:2;14107:9;14098:7;14094:23;14090:32;14087:52;;;14135:1;14132;14125:12;14087:52;14175:9;14162:23;-1:-1:-1;;;;;14200:6:67;14197:30;14194:50;;;14240:1;14237;14230:12;14194:50;14279:98;14369:7;14360:6;14349:9;14345:22;14279:98;:::i;:::-;14396:8;;14253:124;;-1:-1:-1;13933:504:67;-1:-1:-1;;;;13933:504:67:o;14624:553::-;14710:6;14718;14726;14734;14787:2;14775:9;14766:7;14762:23;14758:32;14755:52;;;14803:1;14800;14793:12;14755:52;14826:28;14844:9;14826:28;:::i;:::-;14816:38;;14873:37;14906:2;14895:9;14891:18;14873:37;:::i;:::-;14863:47;;14961:2;14950:9;14946:18;14933:32;-1:-1:-1;;;;;14980:6:67;14977:30;14974:50;;;15020:1;15017;15010:12;14974:50;15059:58;15109:7;15100:6;15089:9;15085:22;15059:58;:::i;:::-;14624:553;;;;-1:-1:-1;15136:8:67;-1:-1:-1;;;;14624:553:67:o;15685:655::-;15821:6;15829;15837;15881:9;15872:7;15868:23;15911:3;15907:2;15903:12;15900:32;;;15928:1;15925;15918:12;15900:32;15968:9;15955:23;-1:-1:-1;;;;;15993:6:67;15990:30;15987:50;;;16033:1;16030;16023:12;15987:50;16056:69;16117:7;16108:6;16097:9;16093:22;16056:69;:::i;:::-;16046:79;-1:-1:-1;;16159:2:67;-1:-1:-1;;16141:16:67;;16137:25;16134:45;;;16175:1;16172;16165:12;16134:45;;16213:2;16202:9;16198:18;16188:28;;16266:2;16255:9;16251:18;16238:32;16279:31;16304:5;16279:31;:::i;16345:609::-;16585:4;16627:3;16616:9;16612:19;16604:27;;16664:6;16658:13;16647:9;16640:32;-1:-1:-1;;;;;16732:4:67;16724:6;16720:17;16714:24;16710:49;16703:4;16692:9;16688:20;16681:79;16807:4;16799:6;16795:17;16789:24;16822:62;16878:4;16867:9;16863:20;16849:12;4038;;4026:25;;4100:4;4089:16;;;4083:23;4067:14;;4060:47;3964:149;16822:62;-1:-1:-1;4038:12:67;;16943:3;16928:19;;4026:25;4100:4;4089:16;;4083:23;4067:14;;;4060:47;16893:55;3964:149;16959:388;17027:6;17035;17088:2;17076:9;17067:7;17063:23;17059:32;17056:52;;;17104:1;17101;17094:12;17056:52;17143:9;17130:23;17162:31;17187:5;17162:31;:::i;:::-;17212:5;-1:-1:-1;17269:2:67;17254:18;;17241:32;17282:33;17241:32;17282:33;:::i;17352:234::-;17435:6;17488:2;17476:9;17467:7;17463:23;17459:32;17456:52;;;17504:1;17501;17494:12;17456:52;17527:53;17572:7;17561:9;17527:53;:::i;17591:380::-;17670:1;17666:12;;;;17713;;;17734:61;;17788:4;17780:6;17776:17;17766:27;;17734:61;17841:2;17833:6;17830:14;17810:18;17807:38;17804:161;;17887:10;17882:3;17878:20;17875:1;17868:31;17922:4;17919:1;17912:15;17950:4;17947:1;17940:15;18458:127;18519:10;18514:3;18510:20;18507:1;18500:31;18550:4;18547:1;18540:15;18574:4;18571:1;18564:15;18590:168;18663:9;;;18694;;18711:15;;;18705:22;;18691:37;18681:71;;18732:18;;:::i;18763:217::-;18803:1;18829;18819:132;;18873:10;18868:3;18864:20;18861:1;18854:31;18908:4;18905:1;18898:15;18936:4;18933:1;18926:15;18819:132;-1:-1:-1;18965:9:67;;18763:217::o;19689:127::-;19750:10;19745:3;19741:20;19738:1;19731:31;19781:4;19778:1;19771:15;19805:4;19802:1;19795:15;19821:336;19926:4;19984:11;19971:25;20078:2;20074:7;20063:8;20047:14;20043:29;20039:43;20019:18;20015:68;20005:96;;20097:1;20094;20087:12;20005:96;20118:33;;;;;19821:336;-1:-1:-1;;19821:336:67:o;20162:521::-;20239:4;20245:6;20305:11;20292:25;20399:2;20395:7;20384:8;20368:14;20364:29;20360:43;20340:18;20336:68;20326:96;;20418:1;20415;20408:12;20326:96;20445:33;;20497:20;;;-1:-1:-1;;;;;;20529:30:67;;20526:50;;;20572:1;20569;20562:12;20526:50;20605:4;20593:17;;-1:-1:-1;20636:14:67;20632:27;;;20622:38;;20619:58;;;20673:1;20670;20663:12;20813:542;20914:2;20909:3;20906:11;20903:446;;;20950:1;20974:5;20971:1;20964:16;21018:4;21015:1;21005:18;21088:2;21076:10;21072:19;21069:1;21065:27;21059:4;21055:38;21124:4;21112:10;21109:20;21106:47;;;-1:-1:-1;21147:4:67;21106:47;21202:2;21197:3;21193:12;21190:1;21186:20;21180:4;21176:31;21166:41;;21257:82;21275:2;21268:5;21265:13;21257:82;;;21320:17;;;21301:1;21290:13;21257:82;;;21261:3;;;20813:542;;;:::o;21531:1202::-;-1:-1:-1;;;;;21648:3:67;21645:27;21642:53;;;21675:18;;:::i;:::-;21704:93;21793:3;21753:38;21785:4;21779:11;21753:38;:::i;:::-;21747:4;21704:93;:::i;:::-;21823:1;21848:2;21843:3;21840:11;21865:1;21860:615;;;;22519:1;22536:3;22533:93;;;-1:-1:-1;22592:19:67;;;22579:33;22533:93;-1:-1:-1;;21488:1:67;21484:11;;;21480:24;21476:29;21466:40;21512:1;21508:11;;;21463:57;22639:78;;21833:894;;21860:615;20760:1;20753:14;;;20797:4;20784:18;;-1:-1:-1;;21896:17:67;;;21996:9;22018:229;22032:7;22029:1;22026:14;22018:229;;;22121:19;;;22108:33;22093:49;;22228:4;22213:20;;;;22181:1;22169:14;;;;22048:12;22018:229;;;22022:3;22275;22266:7;22263:16;22260:159;;;22399:1;22395:6;22389:3;22383;22380:1;22376:11;22372:21;22368:34;22364:39;22351:9;22346:3;22342:19;22329:33;22325:79;22317:6;22310:95;22260:159;;;22462:1;22456:3;22453:1;22449:11;22445:19;22439:4;22432:33;21833:894;;21531:1202;;;:::o;22738:266::-;22826:6;22821:3;22814:19;22878:6;22871:5;22864:4;22859:3;22855:14;22842:43;-1:-1:-1;22930:1:67;22905:16;;;22923:4;22901:27;;;22894:38;;;;22986:2;22965:15;;;-1:-1:-1;;22961:29:67;22952:39;;;22948:50;;22738:266::o;23009:1774::-;23266:2;23318:21;;;23291:18;;;23374:22;;;23237:4;;23415:2;23433:18;;;23497:1;23493:14;;;23478:30;;23474:39;;23536:6;23237:4;23570:1184;23584:6;23581:1;23578:13;23570:1184;;;23649:22;;;-1:-1:-1;;23645:36:67;23633:49;;23721:20;;23796:14;23792:27;;;-1:-1:-1;;23788:41:67;23764:66;;23754:94;;23844:1;23841;23834:12;23754:94;23874:31;;23928:4;23990:10;23964:24;23874:31;23964:24;:::i;:::-;23960:41;23952:6;23945:57;24078:6;24043:33;24072:2;24065:5;24061:14;24043:33;:::i;:::-;24039:46;24034:2;24026:6;24022:15;24015:71;24151:2;24144:5;24140:14;24127:28;24240:2;24236:7;24228:5;24212:14;24208:26;24204:40;24182:20;24178:67;24168:95;;24259:1;24256;24249:12;24168:95;24291:32;;;24399:16;;;;-1:-1:-1;24350:21:67;-1:-1:-1;;;;;24431:30:67;;24428:50;;;24474:1;24471;24464:12;24428:50;24527:6;24511:14;24507:27;24498:7;24494:41;24491:61;;;24548:1;24545;24538:12;24491:61;24589:2;24584;24576:6;24572:15;24565:27;24615:59;24670:2;24662:6;24658:15;24650:6;24641:7;24615:59;:::i;:::-;24732:12;;;;24605:69;-1:-1:-1;;;24697:15:67;;;;-1:-1:-1;23606:1:67;23599:9;23570:1184;;;-1:-1:-1;24771:6:67;;23009:1774;-1:-1:-1;;;;;;;;23009:1774:67:o;24788:331::-;24893:9;24904;24946:8;24934:10;24931:24;24928:44;;;24968:1;24965;24958:12;24928:44;24997:6;24987:8;24984:20;24981:40;;;25017:1;25014;25007:12;24981:40;-1:-1:-1;;25043:23:67;;;25088:25;;;;;-1:-1:-1;24788:331:67:o;25124:476::-;25315:3;25353:6;25347:13;25369:66;25428:6;25423:3;25416:4;25408:6;25404:17;25369:66;:::i;:::-;25457:16;;25510:6;25502;25457:16;25482:35;25574:1;25536:18;;25563:13;;;-1:-1:-1;25536:18:67;;25124:476;-1:-1:-1;;;25124:476:67:o;25605:244::-;25762:2;25751:9;25744:21;25725:4;25782:61;25839:2;25828:9;25824:18;25816:6;25808;25782:61;:::i;25854:331::-;25953:4;26011:11;25998:25;26105:3;26101:8;26090;26074:14;26070:29;26066:44;26046:18;26042:69;26032:97;;26125:1;26122;26115:12;26190:129;-1:-1:-1;;;;;26268:5:67;26264:30;26257:5;26254:41;26244:69;;26309:1;26306;26299:12;26324:988;26698:10;26671:25;26689:6;26671:25;:::i;:::-;26667:42;26656:9;26649:61;26773:4;26765:6;26761:17;26748:31;26741:4;26730:9;26726:20;26719:61;26630:4;26827;26819:6;26815:17;26802:31;26842:30;26866:5;26842:30;:::i;:::-;-1:-1:-1;;;;;26914:5:67;26910:30;26903:4;26892:9;26888:20;26881:60;;26977:6;26972:2;26961:9;26957:18;26950:34;27021:3;27015;27004:9;27000:19;26993:32;27048:62;27105:3;27094:9;27090:19;27082:6;27074;27048:62;:::i;:::-;-1:-1:-1;;;;;27147:32:67;;27167:3;27126:19;;27119:61;27217:22;;;27211:3;27196:19;;27189:51;27257:49;27221:6;27291;27283;27257:49;:::i;:::-;27249:57;26324:988;-1:-1:-1;;;;;;;;;;26324:988:67:o;27317:648::-;27396:6;27449:2;27437:9;27428:7;27424:23;27420:32;27417:52;;;27465:1;27462;27455:12;27417:52;27498:9;27492:16;-1:-1:-1;;;;;27523:6:67;27520:30;27517:50;;;27563:1;27560;27553:12;27517:50;27586:22;;27639:4;27631:13;;27627:27;-1:-1:-1;27617:55:67;;27668:1;27665;27658:12;27617:55;27697:2;27691:9;27722:49;27738:32;27767:2;27738:32;:::i;27722:49::-;27794:2;27787:5;27780:17;27834:7;27829:2;27824;27820;27816:11;27812:20;27809:33;27806:53;;;27855:1;27852;27845:12;27806:53;27868:67;27932:2;27927;27920:5;27916:14;27911:2;27907;27903:11;27868:67;:::i;28768:245::-;28826:6;28879:2;28867:9;28858:7;28854:23;28850:32;28847:52;;;28895:1;28892;28885:12;28847:52;28934:9;28921:23;28953:30;28977:5;28953:30;:::i;29018:479::-;29285:1;29281;29276:3;29272:11;29268:19;29260:6;29256:32;29245:9;29238:51;29325:6;29320:2;29309:9;29305:18;29298:34;29380:6;29372;29368:19;29363:2;29352:9;29348:18;29341:47;29424:3;29419:2;29408:9;29404:18;29397:31;29219:4;29445:46;29486:3;29475:9;29471:19;29463:6;29445:46;:::i;30120:379::-;30313:2;30302:9;30295:21;30276:4;30339:45;30380:2;30369:9;30365:18;30357:6;30339:45;:::i;:::-;30432:9;30424:6;30420:22;30415:2;30404:9;30400:18;30393:50;30460:33;30486:6;30478;30460:33;:::i;30504:245::-;30571:6;30624:2;30612:9;30603:7;30599:23;30595:32;30592:52;;;30640:1;30637;30630:12;30592:52;30672:9;30666:16;30691:28;30713:5;30691:28;:::i;30754:887::-;30973:2;30962:9;30955:21;31031:10;31022:6;31016:13;31012:30;31007:2;30996:9;30992:18;30985:58;31097:4;31089:6;31085:17;31079:24;31074:2;31063:9;31059:18;31052:52;30936:4;31151:2;31143:6;31139:15;31133:22;31192:4;31186:3;31175:9;31171:19;31164:33;31220:52;31267:3;31256:9;31252:19;31238:12;31220:52;:::i;:::-;31206:66;;31321:2;31313:6;31309:15;31303:22;31395:2;31391:7;31379:9;31371:6;31367:22;31363:36;31356:4;31345:9;31341:20;31334:66;31423:41;31457:6;31441:14;31423:41;:::i;:::-;31533:3;31521:16;;;;31515:23;31508:31;31501:39;31495:3;31480:19;;31473:68;-1:-1:-1;;;;;;;;31602:32:67;;;;31595:4;31580:20;;;31573:62;31409:55;30754:887::o;31646:284::-;31716:5;31764:4;31752:9;31747:3;31743:19;31739:30;31736:50;;;31782:1;31779;31772:12;31736:50;31804:22;;:::i;:::-;31795:31;;31855:9;31849:16;31842:5;31835:31;31919:2;31908:9;31904:18;31898:25;31893:2;31886:5;31882:14;31875:49;31646:284;;;;:::o;31935:257::-;32033:6;32086:2;32074:9;32065:7;32061:23;32057:32;32054:52;;;32102:1;32099;32092:12;32054:52;32125:61;32178:7;32167:9;32125:61;:::i;32197:318::-;-1:-1:-1;;;;;;32317:19:67;;32388:11;;;;32419:1;32411:10;;32408:101;;;32496:2;32490;32483:3;32480:1;32476:11;32473:1;32469:19;32465:28;32461:2;32457:37;32453:46;32444:55;;32408:101;;;32197:318;;;;:::o;32520:346::-;32607:6;32660:2;32648:9;32639:7;32635:23;32631:32;32628:52;;;32676:1;32673;32666:12;32628:52;32702:22;;:::i;:::-;32760:9;32747:23;32740:5;32733:38;32831:2;32820:9;32816:18;32803:32;32798:2;32791:5;32787:14;32780:56;32855:5;32845:15;;;32520:346;;;;:::o;33210:255::-;33330:19;;33369:2;33361:11;;33358:101;;;-1:-1:-1;;33430:2:67;33426:12;;;33423:1;33419:20;33415:33;33404:45;33210:255;;;;:::o;33470:331::-;-1:-1:-1;;;;;;33590:19:67;;33674:11;;;;33705:1;33697:10;;33694:101;;;33766:1;33762:11;;;;33759:1;33755:19;33751:28;;;33743:37;33739:46;;;;33470:331;-1:-1:-1;;33470:331:67:o;33806:568::-;-1:-1:-1;;;;;34071:3:67;34067:28;34058:6;34053:3;34049:16;34045:51;34040:3;34033:64;34157:10;34152:3;34148:20;34139:6;34134:3;34130:16;34126:43;34122:1;34117:3;34113:11;34106:64;34200:6;34195:2;34190:3;34186:12;34179:28;34015:3;34236:6;34230:13;34252:75;34320:6;34315:2;34310:3;34306:12;34299:4;34291:6;34287:17;34252:75;:::i;:::-;34347:16;;;;34365:2;34343:25;;33806:568;-1:-1:-1;;;;;33806:568:67:o;34379:135::-;34418:3;34439:17;;;34436:43;;34459:18;;:::i;:::-;-1:-1:-1;34506:1:67;34495:13;;34379:135::o;35138:532::-;35379:6;35374:3;35367:19;-1:-1:-1;;;;;35442:3:67;35438:28;35429:6;35424:3;35420:16;35416:51;35411:2;35406:3;35402:12;35395:73;35498:6;35493:2;35488:3;35484:12;35477:28;35349:3;35534:6;35528:13;35550:73;35616:6;35611:2;35606:3;35602:12;35597:2;35589:6;35585:15;35550:73;:::i;:::-;35643:16;;;;35661:2;35639:25;;35138:532;-1:-1:-1;;;;;35138:532:67:o;36094:128::-;36161:9;;;36182:11;;;36179:37;;;36196:18;;:::i;36227:681::-;36329:6;36382:3;36370:9;36361:7;36357:23;36353:33;36350:53;;;36399:1;36396;36389:12;36350:53;36432:2;36426:9;36474:4;36466:6;36462:17;36545:6;36533:10;36530:22;-1:-1:-1;;;;;36497:10:67;36494:34;36491:62;36488:88;;;36556:18;;:::i;:::-;36592:2;36585:22;36631:16;;36616:32;;36691:2;36676:18;;36670:25;36704:30;36670:25;36704:30;:::i;:::-;36762:2;36750:15;;36743:30;36806:70;36868:7;36863:2;36848:18;;36806:70;:::i;:::-;36801:2;36789:15;;36782:95;36793:6;36227:681;-1:-1:-1;;;36227:681:67:o;36913:1343::-;37039:3;37033:10;-1:-1:-1;;;;;37058:6:67;37055:30;37052:56;;;37088:18;;:::i;:::-;37117:96;37206:6;37166:38;37198:4;37192:11;37166:38;:::i;:::-;37160:4;37117:96;:::i;:::-;37268:4;;37325:2;37314:14;;37342:1;37337:662;;;;38043:1;38060:6;38057:89;;;-1:-1:-1;38112:19:67;;;38106:26;38057:89;-1:-1:-1;;21488:1:67;21484:11;;;21480:24;21476:29;21466:40;21512:1;21508:11;;;21463:57;38159:81;;37307:943;;37337:662;20760:1;20753:14;;;20797:4;20784:18;;-1:-1:-1;;37373:20:67;;;37490:236;37504:7;37501:1;37498:14;37490:236;;;37593:19;;;37587:26;37572:42;;37685:27;;;;37653:1;37641:14;;;;37520:19;;37490:236;;;37494:3;37754:6;37745:7;37742:19;37739:201;;;37815:19;;;37809:26;-1:-1:-1;;37898:1:67;37894:14;;;37910:3;37890:24;37886:37;37882:42;37867:58;37852:74;;37739:201;-1:-1:-1;;;;;37986:1:67;37970:14;;;37966:22;37953:36;;-1:-1:-1;36913:1343:67:o;38261:125::-;38326:9;;;38347:10;;;38344:36;;;38360:18;;:::i;38391:251::-;38461:6;38514:2;38502:9;38493:7;38489:23;38485:32;38482:52;;;38530:1;38527;38520:12;38482:52;38562:9;38556:16;38581:31;38606:5;38581:31;:::i
Swarm Source
ipfs://031524f18b86ada60e42e02fdc1e3f7577c3b607cb28a16400194b8b5d17c0a1
Loading...
Loading
Loading...
Loading
Loading...
Loading
Loading...
Loading
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.