账户
0x2c...f843
0x2c...F843

0x2c...F843

$500
此合同的源代码已经过验证!
合同元数据
编译器
0.8.24+commit.e11b9ed9
语言
Solidity
合同源代码
文件 1 的 1:Bera_Capsule.sol
// Sources flattened with hardhat v2.22.13 https://hardhat.org
  
  // SPDX-License-Identifier: Apache-2.0 AND LZBL-1.2 AND MIT AND UNLICENSED
  
  // File @layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/IMessageLibManager.sol@v3.0.6
  
  // Original license: SPDX_License_Identifier: MIT
  
  pragma solidity >=0.8.0;
  
  struct SetConfigParam {
      uint32 eid;
      uint32 configType;
      bytes config;
  }
  
  interface IMessageLibManager {
      struct Timeout {
          address lib;
          uint256 expiry;
      }
  
      event LibraryRegistered(address newLib);
      event DefaultSendLibrarySet(uint32 eid, address newLib);
      event DefaultReceiveLibrarySet(uint32 eid, address newLib);
      event DefaultReceiveLibraryTimeoutSet(uint32 eid, address oldLib, uint256 expiry);
      event SendLibrarySet(address sender, uint32 eid, address newLib);
      event ReceiveLibrarySet(address receiver, uint32 eid, address newLib);
      event ReceiveLibraryTimeoutSet(address receiver, uint32 eid, address oldLib, uint256 timeout);
  
      function registerLibrary(address _lib) external;
  
      function isRegisteredLibrary(address _lib) external view returns (bool);
  
      function getRegisteredLibraries() external view returns (address[] memory);
  
      function setDefaultSendLibrary(uint32 _eid, address _newLib) external;
  
      function defaultSendLibrary(uint32 _eid) external view returns (address);
  
      function setDefaultReceiveLibrary(uint32 _eid, address _newLib, uint256 _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);
  }
  
  
  // File @layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/IMessagingChannel.sol@v3.0.6
  
  // Original license: SPDX_License_Identifier: MIT
  
  pragma solidity >=0.8.0;
  
  interface IMessagingChannel {
      event InboundNonceSkipped(uint32 srcEid, bytes32 sender, address receiver, uint64 nonce);
      event PacketNilified(uint32 srcEid, bytes32 sender, address receiver, uint64 nonce, bytes32 payloadHash);
      event PacketBurnt(uint32 srcEid, bytes32 sender, address receiver, uint64 nonce, bytes32 payloadHash);
  
      function eid() external view returns (uint32);
  
      // this is an emergency function if a message cannot be verified for some reasons
      // required to provide _nextNonce to avoid race condition
      function skip(address _oapp, uint32 _srcEid, bytes32 _sender, uint64 _nonce) external;
  
      function nilify(address _oapp, uint32 _srcEid, bytes32 _sender, uint64 _nonce, bytes32 _payloadHash) external;
  
      function burn(address _oapp, uint32 _srcEid, bytes32 _sender, uint64 _nonce, bytes32 _payloadHash) external;
  
      function nextGuid(address _sender, uint32 _dstEid, bytes32 _receiver) external view returns (bytes32);
  
      function inboundNonce(address _receiver, uint32 _srcEid, bytes32 _sender) external view returns (uint64);
  
      function outboundNonce(address _sender, uint32 _dstEid, bytes32 _receiver) external view returns (uint64);
  
      function inboundPayloadHash(
          address _receiver,
          uint32 _srcEid,
          bytes32 _sender,
          uint64 _nonce
      ) external view returns (bytes32);
  
      function lazyInboundNonce(address _receiver, uint32 _srcEid, bytes32 _sender) external view returns (uint64);
  }
  
  
  // File @layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/IMessagingComposer.sol@v3.0.6
  
  // Original license: SPDX_License_Identifier: MIT
  
  pragma solidity >=0.8.0;
  
  interface IMessagingComposer {
      event ComposeSent(address from, address to, bytes32 guid, uint16 index, bytes message);
      event ComposeDelivered(address from, address to, bytes32 guid, uint16 index);
      event LzComposeAlert(
          address indexed from,
          address indexed to,
          address indexed executor,
          bytes32 guid,
          uint16 index,
          uint256 gas,
          uint256 value,
          bytes message,
          bytes extraData,
          bytes reason
      );
  
      function composeQueue(
          address _from,
          address _to,
          bytes32 _guid,
          uint16 _index
      ) external view returns (bytes32 messageHash);
  
      function sendCompose(address _to, bytes32 _guid, uint16 _index, bytes calldata _message) external;
  
      function lzCompose(
          address _from,
          address _to,
          bytes32 _guid,
          uint16 _index,
          bytes calldata _message,
          bytes calldata _extraData
      ) external payable;
  }
  
  
  // File @layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/IMessagingContext.sol@v3.0.6
  
  // Original license: SPDX_License_Identifier: MIT
  
  pragma solidity >=0.8.0;
  
  interface IMessagingContext {
      function isSendingMessage() external view returns (bool);
  
      function getSendContext() external view returns (uint32 dstEid, address sender);
  }
  
  
  // File @layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroEndpointV2.sol@v3.0.6
  
  // Original license: SPDX_License_Identifier: MIT
  
  pragma solidity >=0.8.0;
  
  
  
  
  struct MessagingParams {
      uint32 dstEid;
      bytes32 receiver;
      bytes message;
      bytes options;
      bool payInLzToken;
  }
  
  struct MessagingReceipt {
      bytes32 guid;
      uint64 nonce;
      MessagingFee fee;
  }
  
  struct MessagingFee {
      uint256 nativeFee;
      uint256 lzTokenFee;
  }
  
  struct Origin {
      uint32 srcEid;
      bytes32 sender;
      uint64 nonce;
  }
  
  interface ILayerZeroEndpointV2 is IMessageLibManager, IMessagingComposer, IMessagingChannel, IMessagingContext {
      event PacketSent(bytes encodedPayload, bytes options, address sendLibrary);
  
      event PacketVerified(Origin origin, address receiver, bytes32 payloadHash);
  
      event PacketDelivered(Origin origin, address receiver);
  
      event LzReceiveAlert(
          address indexed receiver,
          address indexed executor,
          Origin origin,
          bytes32 guid,
          uint256 gas,
          uint256 value,
          bytes message,
          bytes extraData,
          bytes reason
      );
  
      event LzTokenSet(address token);
  
      event DelegateSet(address sender, address delegate);
  
      function quote(MessagingParams calldata _params, address _sender) external view returns (MessagingFee memory);
  
      function send(
          MessagingParams calldata _params,
          address _refundAddress
      ) external payable returns (MessagingReceipt memory);
  
      function verify(Origin calldata _origin, address _receiver, bytes32 _payloadHash) external;
  
      function verifiable(Origin calldata _origin, address _receiver) external view returns (bool);
  
      function initializable(Origin calldata _origin, address _receiver) external view returns (bool);
  
      function lzReceive(
          Origin calldata _origin,
          address _receiver,
          bytes32 _guid,
          bytes calldata _message,
          bytes calldata _extraData
      ) external payable;
  
      // oapp can burn messages partially by calling this function with its own business logic if messages are verified in order
      function clear(address _oapp, Origin calldata _origin, bytes32 _guid, bytes calldata _message) external;
  
      function setLzToken(address _lzToken) external;
  
      function lzToken() external view returns (address);
  
      function nativeToken() external view returns (address);
  
      function setDelegate(address _delegate) external;
  }
  
  
  // File @layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroReceiver.sol@v3.0.6
  
  // Original license: SPDX_License_Identifier: MIT
  
  pragma solidity >=0.8.0;
  
  interface ILayerZeroReceiver {
      function allowInitializePath(Origin calldata _origin) external view returns (bool);
  
      function nextNonce(uint32 _eid, bytes32 _sender) external view returns (uint64);
  
      function lzReceive(
          Origin calldata _origin,
          bytes32 _guid,
          bytes calldata _message,
          address _executor,
          bytes calldata _extraData
      ) external payable;
  }
  
  
  // File @openzeppelin/contracts/utils/introspection/IERC165.sol@v5.1.0
  
  // Original license: SPDX_License_Identifier: MIT
  // OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol)
  
  pragma solidity ^0.8.20;
  
  /**
   * @dev Interface of the ERC-165 standard, as defined in the
   * https://eips.ethereum.org/EIPS/eip-165[ERC].
   *
   * Implementers can declare support of contract interfaces, which can then be
   * queried by others ({ERC165Checker}).
   *
   * For an implementation, see {ERC165}.
   */
  interface IERC165 {
      /**
       * @dev Returns true if this contract implements the interface defined by
       * `interfaceId`. See the corresponding
       * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]
       * to learn more about how these ids are created.
       *
       * This function call must use less than 30 000 gas.
       */
      function supportsInterface(bytes4 interfaceId) external view returns (bool);
  }
  
  
  // File @layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/IMessageLib.sol@v3.0.6
  
  // Original license: SPDX_License_Identifier: MIT
  
  pragma solidity >=0.8.0;
  
  enum MessageLibType {
      Send,
      Receive,
      SendAndReceive
  }
  
  interface IMessageLib is IERC165 {
      function setConfig(address _oapp, SetConfigParam[] calldata _config) external;
  
      function getConfig(uint32 _eid, address _oapp, uint32 _configType) external view returns (bytes memory config);
  
      function isSupportedEid(uint32 _eid) external view returns (bool);
  
      // message libs of same major version are compatible
      function version() external view returns (uint64 major, uint8 minor, uint8 endpointVersion);
  
      function messageLibType() external view returns (MessageLibType);
  }
  
  
  // File @layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ISendLib.sol@v3.0.6
  
  // Original license: SPDX_License_Identifier: MIT
  
  pragma solidity >=0.8.0;
  
  
  struct Packet {
      uint64 nonce;
      uint32 srcEid;
      address sender;
      uint32 dstEid;
      bytes32 receiver;
      bytes32 guid;
      bytes message;
  }
  
  interface ISendLib is IMessageLib {
      function send(
          Packet calldata _packet,
          bytes calldata _options,
          bool _payInLzToken
      ) external returns (MessagingFee memory, bytes memory encodedPacket);
  
      function quote(
          Packet calldata _packet,
          bytes calldata _options,
          bool _payInLzToken
      ) external view returns (MessagingFee memory);
  
      function setTreasury(address _treasury) external;
  
      function withdrawFee(address _to, uint256 _amount) external;
  
      function withdrawLzTokenFee(address _lzToken, address _to, uint256 _amount) external;
  }
  
  
  // File @layerzerolabs/lz-evm-protocol-v2/contracts/libs/AddressCast.sol@v3.0.6
  
  // Original license: SPDX_License_Identifier: LZBL-1.2
  
  pragma solidity ^0.8.20;
  
  library AddressCast {
      error AddressCast_InvalidSizeForAddress();
      error AddressCast_InvalidAddress();
  
      function toBytes32(bytes calldata _addressBytes) internal pure returns (bytes32 result) {
          if (_addressBytes.length > 32) revert AddressCast_InvalidAddress();
          result = bytes32(_addressBytes);
          unchecked {
              uint256 offset = 32 - _addressBytes.length;
              result = result >> (offset * 8);
          }
      }
  
      function toBytes32(address _address) internal pure returns (bytes32 result) {
          result = bytes32(uint256(uint160(_address)));
      }
  
      function toBytes(bytes32 _addressBytes32, uint256 _size) internal pure returns (bytes memory result) {
          if (_size == 0 || _size > 32) revert AddressCast_InvalidSizeForAddress();
          result = new bytes(_size);
          unchecked {
              uint256 offset = 256 - _size * 8;
              assembly {
                  mstore(add(result, 32), shl(offset, _addressBytes32))
              }
          }
      }
  
      function toAddress(bytes32 _addressBytes32) internal pure returns (address result) {
          result = address(uint160(uint256(_addressBytes32)));
      }
  
      function toAddress(bytes calldata _addressBytes) internal pure returns (address result) {
          if (_addressBytes.length != 20) revert AddressCast_InvalidAddress();
          result = address(bytes20(_addressBytes));
      }
  }
  
  
  // File @layerzerolabs/lz-evm-protocol-v2/contracts/messagelib/libs/PacketV1Codec.sol@v3.0.6
  
  // Original license: SPDX_License_Identifier: LZBL-1.2
  
  pragma solidity ^0.8.20;
  
  
  library PacketV1Codec {
      using AddressCast for address;
      using AddressCast for bytes32;
  
      uint8 internal constant PACKET_VERSION = 1;
  
      // header (version + nonce + path)
      // version
      uint256 private constant PACKET_VERSION_OFFSET = 0;
      //    nonce
      uint256 private constant NONCE_OFFSET = 1;
      //    path
      uint256 private constant SRC_EID_OFFSET = 9;
      uint256 private constant SENDER_OFFSET = 13;
      uint256 private constant DST_EID_OFFSET = 45;
      uint256 private constant RECEIVER_OFFSET = 49;
      // payload (guid + message)
      uint256 private constant GUID_OFFSET = 81; // keccak256(nonce + path)
      uint256 private constant MESSAGE_OFFSET = 113;
  
      function encode(Packet memory _packet) internal pure returns (bytes memory encodedPacket) {
          encodedPacket = abi.encodePacked(
              PACKET_VERSION,
              _packet.nonce,
              _packet.srcEid,
              _packet.sender.toBytes32(),
              _packet.dstEid,
              _packet.receiver,
              _packet.guid,
              _packet.message
          );
      }
  
      function encodePacketHeader(Packet memory _packet) internal pure returns (bytes memory) {
          return
              abi.encodePacked(
                  PACKET_VERSION,
                  _packet.nonce,
                  _packet.srcEid,
                  _packet.sender.toBytes32(),
                  _packet.dstEid,
                  _packet.receiver
              );
      }
  
      function encodePayload(Packet memory _packet) internal pure returns (bytes memory) {
          return abi.encodePacked(_packet.guid, _packet.message);
      }
  
      function header(bytes calldata _packet) internal pure returns (bytes calldata) {
          return _packet[0:GUID_OFFSET];
      }
  
      function version(bytes calldata _packet) internal pure returns (uint8) {
          return uint8(bytes1(_packet[PACKET_VERSION_OFFSET:NONCE_OFFSET]));
      }
  
      function nonce(bytes calldata _packet) internal pure returns (uint64) {
          return uint64(bytes8(_packet[NONCE_OFFSET:SRC_EID_OFFSET]));
      }
  
      function srcEid(bytes calldata _packet) internal pure returns (uint32) {
          return uint32(bytes4(_packet[SRC_EID_OFFSET:SENDER_OFFSET]));
      }
  
      function sender(bytes calldata _packet) internal pure returns (bytes32) {
          return bytes32(_packet[SENDER_OFFSET:DST_EID_OFFSET]);
      }
  
      function senderAddressB20(bytes calldata _packet) internal pure returns (address) {
          return sender(_packet).toAddress();
      }
  
      function dstEid(bytes calldata _packet) internal pure returns (uint32) {
          return uint32(bytes4(_packet[DST_EID_OFFSET:RECEIVER_OFFSET]));
      }
  
      function receiver(bytes calldata _packet) internal pure returns (bytes32) {
          return bytes32(_packet[RECEIVER_OFFSET:GUID_OFFSET]);
      }
  
      function receiverB20(bytes calldata _packet) internal pure returns (address) {
          return receiver(_packet).toAddress();
      }
  
      function guid(bytes calldata _packet) internal pure returns (bytes32) {
          return bytes32(_packet[GUID_OFFSET:MESSAGE_OFFSET]);
      }
  
      function message(bytes calldata _packet) internal pure returns (bytes calldata) {
          return bytes(_packet[MESSAGE_OFFSET:]);
      }
  
      function payload(bytes calldata _packet) internal pure returns (bytes calldata) {
          return bytes(_packet[GUID_OFFSET:]);
      }
  
      function payloadHash(bytes calldata _packet) internal pure returns (bytes32) {
          return keccak256(payload(_packet));
      }
  }
  
  
  // File @layerzerolabs/oapp-evm/contracts/oapp/interfaces/IOAppCore.sol@v0.0.4
  
  // Original license: SPDX_License_Identifier: MIT
  
  pragma solidity ^0.8.20;
  
  /**
   * @title IOAppCore
   */
  interface IOAppCore {
      // Custom error messages
      error OnlyPeer(uint32 eid, bytes32 sender);
      error NoPeer(uint32 eid);
      error InvalidEndpointCall();
      error InvalidDelegate();
  
      // Event emitted when a peer (OApp) is set for a corresponding endpoint
      event PeerSet(uint32 eid, bytes32 peer);
  
      /**
       * @notice Retrieves the OApp version information.
       * @return senderVersion The version of the OAppSender.sol contract.
       * @return receiverVersion The version of the OAppReceiver.sol contract.
       */
      function oAppVersion() external view returns (uint64 senderVersion, uint64 receiverVersion);
  
      /**
       * @notice Retrieves the LayerZero endpoint associated with the OApp.
       * @return iEndpoint The LayerZero endpoint as an interface.
       */
      function endpoint() external view returns (ILayerZeroEndpointV2 iEndpoint);
  
      /**
       * @notice Retrieves the peer (OApp) associated with a corresponding endpoint.
       * @param _eid The endpoint ID.
       * @return peer The peer address (OApp instance) associated with the corresponding endpoint.
       */
      function peers(uint32 _eid) external view returns (bytes32 peer);
  
      /**
       * @notice Sets the peer address (OApp instance) for a corresponding endpoint.
       * @param _eid The endpoint ID.
       * @param _peer The address of the peer to be associated with the corresponding endpoint.
       */
      function setPeer(uint32 _eid, bytes32 _peer) external;
  
      /**
       * @notice Sets the delegate address for the OApp Core.
       * @param _delegate The address of the delegate to be set.
       */
      function setDelegate(address _delegate) external;
  }
  
  
  // File @layerzerolabs/oapp-evm/contracts/oapp/interfaces/IOAppReceiver.sol@v0.0.4
  
  // Original license: SPDX_License_Identifier: MIT
  pragma solidity ^0.8.20;
  
  interface IOAppReceiver is ILayerZeroReceiver {
      /**
       * @notice Indicates whether an address is an approved composeMsg sender to the Endpoint.
       * @param _origin The origin information containing the source endpoint and sender address.
       *  - srcEid: The source chain endpoint ID.
       *  - sender: The sender address on the src chain.
       *  - nonce: The nonce of the message.
       * @param _message The lzReceive payload.
       * @param _sender The sender address.
       * @return isSender Is a valid sender.
       *
       * @dev Applications can optionally choose to implement a separate composeMsg sender that is NOT the bridging layer.
       * @dev The default sender IS the OAppReceiver implementer.
       */
      function isComposeMsgSender(
          Origin calldata _origin,
          bytes calldata _message,
          address _sender
      ) external view returns (bool isSender);
  }
  
  
  // File @layerzerolabs/oapp-evm/contracts/oapp/interfaces/IOAppOptionsType3.sol@v0.0.4
  
  // Original license: SPDX_License_Identifier: MIT
  
  pragma solidity ^0.8.20;
  
  /**
   * @dev Struct representing enforced option parameters.
   */
  struct EnforcedOptionParam {
      uint32 eid; // Endpoint ID
      uint16 msgType; // Message Type
      bytes options; // Additional options
  }
  
  /**
   * @title IOAppOptionsType3
   * @dev Interface for the OApp with Type 3 Options, allowing the setting and combining of enforced options.
   */
  interface IOAppOptionsType3 {
      // Custom error message for invalid options
      error InvalidOptions(bytes options);
  
      // Event emitted when enforced options are set
      event EnforcedOptionSet(EnforcedOptionParam[] _enforcedOptions);
  
      /**
       * @notice Sets enforced options for specific endpoint and message type combinations.
       * @param _enforcedOptions An array of EnforcedOptionParam structures specifying enforced options.
       */
      function setEnforcedOptions(EnforcedOptionParam[] calldata _enforcedOptions) external;
  
      /**
       * @notice Combines options for a given endpoint and message type.
       * @param _eid The endpoint ID.
       * @param _msgType The OApp message type.
       * @param _extraOptions Additional options passed by the caller.
       * @return options The combination of caller specified options AND enforced options.
       */
      function combineOptions(
          uint32 _eid,
          uint16 _msgType,
          bytes calldata _extraOptions
      ) external view returns (bytes memory options);
  }
  
  
  // File @openzeppelin/contracts/utils/Context.sol@v5.1.0
  
  // Original license: 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;
      }
  }
  
  
  // File @openzeppelin/contracts/access/Ownable.sol@v5.1.0
  
  // Original license: SPDX_License_Identifier: MIT
  // OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)
  
  pragma solidity ^0.8.20;
  
  /**
   * @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);
      }
  }
  
  
  // File @layerzerolabs/oapp-evm/contracts/oapp/libs/OAppOptionsType3.sol@v0.0.4
  
  // Original license: SPDX_License_Identifier: MIT
  
  pragma solidity ^0.8.20;
  
  
  /**
   * @title OAppOptionsType3
   * @dev Abstract contract implementing the IOAppOptionsType3 interface with type 3 options.
   */
  abstract contract OAppOptionsType3 is IOAppOptionsType3, Ownable {
      uint16 internal constant OPTION_TYPE_3 = 3;
  
      // @dev The "msgType" should be defined in the child contract.
      mapping(uint32 eid => mapping(uint16 msgType => bytes enforcedOption)) public enforcedOptions;
  
      /**
       * @dev Sets the enforced options for specific endpoint and message type combinations.
       * @param _enforcedOptions An array of EnforcedOptionParam structures specifying enforced options.
       *
       * @dev Only the owner/admin of the OApp can call this function.
       * @dev Provides a way for the OApp to enforce things like paying for PreCrime, AND/OR minimum dst lzReceive gas amounts etc.
       * @dev These enforced options can vary as the potential options/execution on the remote may differ as per the msgType.
       * eg. Amount of lzReceive() gas necessary to deliver a lzCompose() message adds overhead you dont want to pay
       * if you are only making a standard LayerZero message ie. lzReceive() WITHOUT sendCompose().
       */
      function setEnforcedOptions(EnforcedOptionParam[] calldata _enforcedOptions) public virtual onlyOwner {
          _setEnforcedOptions(_enforcedOptions);
      }
  
      /**
       * @dev Sets the enforced options for specific endpoint and message type combinations.
       * @param _enforcedOptions An array of EnforcedOptionParam structures specifying enforced options.
       *
       * @dev Provides a way for the OApp to enforce things like paying for PreCrime, AND/OR minimum dst lzReceive gas amounts etc.
       * @dev These enforced options can vary as the potential options/execution on the remote may differ as per the msgType.
       * eg. Amount of lzReceive() gas necessary to deliver a lzCompose() message adds overhead you dont want to pay
       * if you are only making a standard LayerZero message ie. lzReceive() WITHOUT sendCompose().
       */
      function _setEnforcedOptions(EnforcedOptionParam[] memory _enforcedOptions) internal virtual {
          for (uint256 i = 0; i < _enforcedOptions.length; i++) {
              // @dev Enforced options are only available for optionType 3, as type 1 and 2 dont support combining.
              _assertOptionsType3(_enforcedOptions[i].options);
              enforcedOptions[_enforcedOptions[i].eid][_enforcedOptions[i].msgType] = _enforcedOptions[i].options;
          }
  
          emit EnforcedOptionSet(_enforcedOptions);
      }
  
      /**
       * @notice Combines options for a given endpoint and message type.
       * @param _eid The endpoint ID.
       * @param _msgType The OAPP message type.
       * @param _extraOptions Additional options passed by the caller.
       * @return options The combination of caller specified options AND enforced options.
       *
       * @dev If there is an enforced lzReceive option:
       * - {gasLimit: 200k, msg.value: 1 ether} AND a caller supplies a lzReceive option: {gasLimit: 100k, msg.value: 0.5 ether}
       * - The resulting options will be {gasLimit: 300k, msg.value: 1.5 ether} when the message is executed on the remote lzReceive() function.
       * @dev This presence of duplicated options is handled off-chain in the verifier/executor.
       */
      function combineOptions(
          uint32 _eid,
          uint16 _msgType,
          bytes calldata _extraOptions
      ) public view virtual returns (bytes memory) {
          bytes memory enforced = enforcedOptions[_eid][_msgType];
  
          // No enforced options, pass whatever the caller supplied, even if it's empty or legacy type 1/2 options.
          if (enforced.length == 0) return _extraOptions;
  
          // No caller options, return enforced
          if (_extraOptions.length == 0) return enforced;
  
          // @dev If caller provided _extraOptions, must be type 3 as its the ONLY type that can be combined.
          if (_extraOptions.length >= 2) {
              _assertOptionsType3(_extraOptions);
              // @dev Remove the first 2 bytes containing the type from the _extraOptions and combine with enforced.
              return bytes.concat(enforced, _extraOptions[2:]);
          }
  
          // No valid set of options was found.
          revert InvalidOptions(_extraOptions);
      }
  
      /**
       * @dev Internal function to assert that options are of type 3.
       * @param _options The options to be checked.
       */
      function _assertOptionsType3(bytes memory _options) internal pure virtual {
          uint16 optionsType;
          assembly {
              optionsType := mload(add(_options, 2))
          }
          if (optionsType != OPTION_TYPE_3) revert InvalidOptions(_options);
      }
  }
  
  
  // File @layerzerolabs/oapp-evm/contracts/oapp/OAppCore.sol@v0.0.4
  
  // Original license: SPDX_License_Identifier: MIT
  
  pragma solidity ^0.8.20;
  
  
  /**
   * @title OAppCore
   * @dev Abstract contract implementing the IOAppCore interface with basic OApp configurations.
   */
  abstract contract OAppCore is IOAppCore, Ownable {
      // The LayerZero endpoint associated with the given OApp
      ILayerZeroEndpointV2 public immutable endpoint;
  
      // Mapping to store peers associated with corresponding endpoints
      mapping(uint32 eid => bytes32 peer) public peers;
  
      /**
       * @dev Constructor to initialize the OAppCore with the provided endpoint and delegate.
       * @param _endpoint The address of the LOCAL Layer Zero endpoint.
       * @param _delegate The delegate capable of making OApp configurations inside of the endpoint.
       *
       * @dev The delegate typically should be set as the owner of the contract.
       */
      constructor(address _endpoint, address _delegate) {
          endpoint = ILayerZeroEndpointV2(_endpoint);
  
          if (_delegate == address(0)) revert InvalidDelegate();
          endpoint.setDelegate(_delegate);
      }
  
      /**
       * @notice Sets the peer address (OApp instance) for a corresponding endpoint.
       * @param _eid The endpoint ID.
       * @param _peer The address of the peer to be associated with the corresponding endpoint.
       *
       * @dev Only the owner/admin of the OApp can call this function.
       * @dev Indicates that the peer is trusted to send LayerZero messages to this OApp.
       * @dev Set this to bytes32(0) to remove the peer address.
       * @dev Peer is a bytes32 to accommodate non-evm chains.
       */
      function setPeer(uint32 _eid, bytes32 _peer) public virtual onlyOwner {
          _setPeer(_eid, _peer);
      }
  
      /**
       * @notice Sets the peer address (OApp instance) for a corresponding endpoint.
       * @param _eid The endpoint ID.
       * @param _peer The address of the peer to be associated with the corresponding endpoint.
       *
       * @dev Indicates that the peer is trusted to send LayerZero messages to this OApp.
       * @dev Set this to bytes32(0) to remove the peer address.
       * @dev Peer is a bytes32 to accommodate non-evm chains.
       */
      function _setPeer(uint32 _eid, bytes32 _peer) internal virtual {
          peers[_eid] = _peer;
          emit PeerSet(_eid, _peer);
      }
  
      /**
       * @notice Internal function to get the peer address associated with a specific endpoint; reverts if NOT set.
       * ie. the peer is set to bytes32(0).
       * @param _eid The endpoint ID.
       * @return peer The address of the peer associated with the specified endpoint.
       */
      function _getPeerOrRevert(uint32 _eid) internal view virtual returns (bytes32) {
          bytes32 peer = peers[_eid];
          if (peer == bytes32(0)) revert NoPeer(_eid);
          return peer;
      }
  
      /**
       * @notice Sets the delegate address for the OApp.
       * @param _delegate The address of the delegate to be set.
       *
       * @dev Only the owner/admin of the OApp can call this function.
       * @dev Provides the ability for a delegate to set configs, on behalf of the OApp, directly on the Endpoint contract.
       */
      function setDelegate(address _delegate) public onlyOwner {
          endpoint.setDelegate(_delegate);
      }
  }
  
  
  // File @layerzerolabs/oapp-evm/contracts/oapp/OAppReceiver.sol@v0.0.4
  
  // Original license: SPDX_License_Identifier: MIT
  
  pragma solidity ^0.8.20;
  
  
  /**
   * @title OAppReceiver
   * @dev Abstract contract implementing the ILayerZeroReceiver interface and extending OAppCore for OApp receivers.
   */
  abstract contract OAppReceiver is IOAppReceiver, OAppCore {
      // Custom error message for when the caller is not the registered endpoint/
      error OnlyEndpoint(address addr);
  
      // @dev The version of the OAppReceiver implementation.
      // @dev Version is bumped when changes are made to this contract.
      uint64 internal constant RECEIVER_VERSION = 2;
  
      /**
       * @notice Retrieves the OApp version information.
       * @return senderVersion The version of the OAppSender.sol contract.
       * @return receiverVersion The version of the OAppReceiver.sol contract.
       *
       * @dev Providing 0 as the default for OAppSender version. Indicates that the OAppSender is not implemented.
       * ie. this is a RECEIVE only OApp.
       * @dev If the OApp uses both OAppSender and OAppReceiver, then this needs to be override returning the correct versions.
       */
      function oAppVersion() public view virtual returns (uint64 senderVersion, uint64 receiverVersion) {
          return (0, RECEIVER_VERSION);
      }
  
      /**
       * @notice Indicates whether an address is an approved composeMsg sender to the Endpoint.
       * @dev _origin The origin information containing the source endpoint and sender address.
       *  - srcEid: The source chain endpoint ID.
       *  - sender: The sender address on the src chain.
       *  - nonce: The nonce of the message.
       * @dev _message The lzReceive payload.
       * @param _sender The sender address.
       * @return isSender Is a valid sender.
       *
       * @dev Applications can optionally choose to implement separate composeMsg senders that are NOT the bridging layer.
       * @dev The default sender IS the OAppReceiver implementer.
       */
      function isComposeMsgSender(
          Origin calldata /*_origin*/,
          bytes calldata /*_message*/,
          address _sender
      ) public view virtual returns (bool) {
          return _sender == address(this);
      }
  
      /**
       * @notice Checks if the path initialization is allowed based on the provided origin.
       * @param origin The origin information containing the source endpoint and sender address.
       * @return Whether the path has been initialized.
       *
       * @dev This indicates to the endpoint that the OApp has enabled msgs for this particular path to be received.
       * @dev This defaults to assuming if a peer has been set, its initialized.
       * Can be overridden by the OApp if there is other logic to determine this.
       */
      function allowInitializePath(Origin calldata origin) public view virtual returns (bool) {
          return peers[origin.srcEid] == origin.sender;
      }
  
      /**
       * @notice Retrieves the next nonce for a given source endpoint and sender address.
       * @dev _srcEid The source endpoint ID.
       * @dev _sender The sender address.
       * @return nonce The next nonce.
       *
       * @dev The path nonce starts from 1. If 0 is returned it means that there is NO nonce ordered enforcement.
       * @dev Is required by the off-chain executor to determine the OApp expects msg execution is ordered.
       * @dev This is also enforced by the OApp.
       * @dev By default this is NOT enabled. ie. nextNonce is hardcoded to return 0.
       */
      function nextNonce(uint32 /*_srcEid*/, bytes32 /*_sender*/) public view virtual returns (uint64 nonce) {
          return 0;
      }
  
      /**
       * @dev Entry point for receiving messages or packets from the endpoint.
       * @param _origin The origin information containing the source endpoint and sender address.
       *  - srcEid: The source chain endpoint ID.
       *  - sender: The sender address on the src chain.
       *  - nonce: The nonce of the message.
       * @param _guid The unique identifier for the received LayerZero message.
       * @param _message The payload of the received message.
       * @param _executor The address of the executor for the received message.
       * @param _extraData Additional arbitrary data provided by the corresponding executor.
       *
       * @dev Entry point for receiving msg/packet from the LayerZero endpoint.
       */
      function lzReceive(
          Origin calldata _origin,
          bytes32 _guid,
          bytes calldata _message,
          address _executor,
          bytes calldata _extraData
      ) public payable virtual {
          // Ensures that only the endpoint can attempt to lzReceive() messages to this OApp.
          if (address(endpoint) != msg.sender) revert OnlyEndpoint(msg.sender);
  
          // Ensure that the sender matches the expected peer for the source endpoint.
          if (_getPeerOrRevert(_origin.srcEid) != _origin.sender) revert OnlyPeer(_origin.srcEid, _origin.sender);
  
          // Call the internal OApp implementation of lzReceive.
          _lzReceive(_origin, _guid, _message, _executor, _extraData);
      }
  
      /**
       * @dev Internal function to implement lzReceive logic without needing to copy the basic parameter validation.
       */
      function _lzReceive(
          Origin calldata _origin,
          bytes32 _guid,
          bytes calldata _message,
          address _executor,
          bytes calldata _extraData
      ) internal virtual;
  }
  
  
  // File @openzeppelin/contracts/interfaces/IERC165.sol@v5.1.0
  
  // Original license: SPDX_License_Identifier: MIT
  // OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC165.sol)
  
  pragma solidity ^0.8.20;
  
  
  // File @openzeppelin/contracts/token/ERC20/IERC20.sol@v5.1.0
  
  // Original license: SPDX_License_Identifier: MIT
  // OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/IERC20.sol)
  
  pragma solidity ^0.8.20;
  
  /**
   * @dev Interface of the ERC-20 standard as defined in the ERC.
   */
  interface IERC20 {
      /**
       * @dev Emitted when `value` tokens are moved from one account (`from`) to
       * another (`to`).
       *
       * Note that `value` may be zero.
       */
      event Transfer(address indexed from, address indexed to, uint256 value);
  
      /**
       * @dev Emitted when the allowance of a `spender` for an `owner` is set by
       * a call to {approve}. `value` is the new allowance.
       */
      event Approval(address indexed owner, address indexed spender, uint256 value);
  
      /**
       * @dev Returns the value of tokens in existence.
       */
      function totalSupply() external view returns (uint256);
  
      /**
       * @dev Returns the value of tokens owned by `account`.
       */
      function balanceOf(address account) external view returns (uint256);
  
      /**
       * @dev Moves a `value` amount of tokens from the caller's account to `to`.
       *
       * Returns a boolean value indicating whether the operation succeeded.
       *
       * Emits a {Transfer} event.
       */
      function transfer(address to, uint256 value) external returns (bool);
  
      /**
       * @dev Returns the remaining number of tokens that `spender` will be
       * allowed to spend on behalf of `owner` through {transferFrom}. This is
       * zero by default.
       *
       * This value changes when {approve} or {transferFrom} are called.
       */
      function allowance(address owner, address spender) external view returns (uint256);
  
      /**
       * @dev Sets a `value` amount of tokens as the allowance of `spender` over the
       * caller's tokens.
       *
       * Returns a boolean value indicating whether the operation succeeded.
       *
       * IMPORTANT: Beware that changing an allowance with this method brings the risk
       * that someone may use both the old and the new allowance by unfortunate
       * transaction ordering. One possible solution to mitigate this race
       * condition is to first reduce the spender's allowance to 0 and set the
       * desired value afterwards:
       * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
       *
       * Emits an {Approval} event.
       */
      function approve(address spender, uint256 value) external returns (bool);
  
      /**
       * @dev Moves a `value` amount of tokens from `from` to `to` using the
       * allowance mechanism. `value` is then deducted from the caller's
       * allowance.
       *
       * Returns a boolean value indicating whether the operation succeeded.
       *
       * Emits a {Transfer} event.
       */
      function transferFrom(address from, address to, uint256 value) external returns (bool);
  }
  
  
  // File @openzeppelin/contracts/interfaces/IERC20.sol@v5.1.0
  
  // Original license: SPDX_License_Identifier: MIT
  // OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC20.sol)
  
  pragma solidity ^0.8.20;
  
  
  // File @openzeppelin/contracts/interfaces/IERC1363.sol@v5.1.0
  
  // Original license: SPDX_License_Identifier: MIT
  // OpenZeppelin Contracts (last updated v5.1.0) (interfaces/IERC1363.sol)
  
  pragma solidity ^0.8.20;
  
  
  /**
   * @title IERC1363
   * @dev Interface of the ERC-1363 standard as defined in the https://eips.ethereum.org/EIPS/eip-1363[ERC-1363].
   *
   * Defines an extension interface for ERC-20 tokens that supports executing code on a recipient contract
   * after `transfer` or `transferFrom`, or code on a spender contract after `approve`, in a single transaction.
   */
  interface IERC1363 is IERC20, IERC165 {
      /*
       * Note: the ERC-165 identifier for this interface is 0xb0202a11.
       * 0xb0202a11 ===
       *   bytes4(keccak256('transferAndCall(address,uint256)')) ^
       *   bytes4(keccak256('transferAndCall(address,uint256,bytes)')) ^
       *   bytes4(keccak256('transferFromAndCall(address,address,uint256)')) ^
       *   bytes4(keccak256('transferFromAndCall(address,address,uint256,bytes)')) ^
       *   bytes4(keccak256('approveAndCall(address,uint256)')) ^
       *   bytes4(keccak256('approveAndCall(address,uint256,bytes)'))
       */
  
      /**
       * @dev Moves a `value` amount of tokens from the caller's account to `to`
       * and then calls {IERC1363Receiver-onTransferReceived} on `to`.
       * @param to The address which you want to transfer to.
       * @param value The amount of tokens to be transferred.
       * @return A boolean value indicating whether the operation succeeded unless throwing.
       */
      function transferAndCall(address to, uint256 value) external returns (bool);
  
      /**
       * @dev Moves a `value` amount of tokens from the caller's account to `to`
       * and then calls {IERC1363Receiver-onTransferReceived} on `to`.
       * @param to The address which you want to transfer to.
       * @param value The amount of tokens to be transferred.
       * @param data Additional data with no specified format, sent in call to `to`.
       * @return A boolean value indicating whether the operation succeeded unless throwing.
       */
      function transferAndCall(address to, uint256 value, bytes calldata data) external returns (bool);
  
      /**
       * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism
       * and then calls {IERC1363Receiver-onTransferReceived} on `to`.
       * @param from The address which you want to send tokens from.
       * @param to The address which you want to transfer to.
       * @param value The amount of tokens to be transferred.
       * @return A boolean value indicating whether the operation succeeded unless throwing.
       */
      function transferFromAndCall(address from, address to, uint256 value) external returns (bool);
  
      /**
       * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism
       * and then calls {IERC1363Receiver-onTransferReceived} on `to`.
       * @param from The address which you want to send tokens from.
       * @param to The address which you want to transfer to.
       * @param value The amount of tokens to be transferred.
       * @param data Additional data with no specified format, sent in call to `to`.
       * @return A boolean value indicating whether the operation succeeded unless throwing.
       */
      function transferFromAndCall(address from, address to, uint256 value, bytes calldata data) external returns (bool);
  
      /**
       * @dev Sets a `value` amount of tokens as the allowance of `spender` over the
       * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.
       * @param spender The address which will spend the funds.
       * @param value The amount of tokens to be spent.
       * @return A boolean value indicating whether the operation succeeded unless throwing.
       */
      function approveAndCall(address spender, uint256 value) external returns (bool);
  
      /**
       * @dev Sets a `value` amount of tokens as the allowance of `spender` over the
       * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.
       * @param spender The address which will spend the funds.
       * @param value The amount of tokens to be spent.
       * @param data Additional data with no specified format, sent in call to `spender`.
       * @return A boolean value indicating whether the operation succeeded unless throwing.
       */
      function approveAndCall(address spender, uint256 value, bytes calldata data) external returns (bool);
  }
  
  
  // File @openzeppelin/contracts/utils/Errors.sol@v5.1.0
  
  // Original license: SPDX_License_Identifier: MIT
  // OpenZeppelin Contracts (last updated v5.1.0) (utils/Errors.sol)
  
  pragma solidity ^0.8.20;
  
  /**
   * @dev Collection of common custom errors used in multiple contracts
   *
   * IMPORTANT: Backwards compatibility is not guaranteed in future versions of the library.
   * It is recommended to avoid relying on the error API for critical functionality.
   *
   * _Available since v5.1._
   */
  library Errors {
      /**
       * @dev The ETH balance of the account is not enough to perform the operation.
       */
      error InsufficientBalance(uint256 balance, uint256 needed);
  
      /**
       * @dev A call to an address target failed. The target may have reverted.
       */
      error FailedCall();
  
      /**
       * @dev The deployment failed.
       */
      error FailedDeployment();
  
      /**
       * @dev A necessary precompile is missing.
       */
      error MissingPrecompile(address);
  }
  
  
  // File @openzeppelin/contracts/utils/Address.sol@v5.1.0
  
  // Original license: SPDX_License_Identifier: MIT
  // OpenZeppelin Contracts (last updated v5.1.0) (utils/Address.sol)
  
  pragma solidity ^0.8.20;
  
  /**
   * @dev Collection of functions related to the address type
   */
  library Address {
      /**
       * @dev There's no code at `target` (it is not a contract).
       */
      error AddressEmptyCode(address target);
  
      /**
       * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
       * `recipient`, forwarding all available gas and reverting on errors.
       *
       * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
       * of certain opcodes, possibly making contracts go over the 2300 gas limit
       * imposed by `transfer`, making them unable to receive funds via
       * `transfer`. {sendValue} removes this limitation.
       *
       * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].
       *
       * IMPORTANT: because control is transferred to `recipient`, care must be
       * taken to not create reentrancy vulnerabilities. Consider using
       * {ReentrancyGuard} or the
       * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
       */
      function sendValue(address payable recipient, uint256 amount) internal {
          if (address(this).balance < amount) {
              revert Errors.InsufficientBalance(address(this).balance, amount);
          }
  
          (bool success, ) = recipient.call{value: amount}("");
          if (!success) {
              revert Errors.FailedCall();
          }
      }
  
      /**
       * @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 or custom error, it is bubbled
       * up by this function (like regular Solidity function calls). However, if
       * the call reverted with no returned reason, this function reverts with a
       * {Errors.FailedCall} error.
       *
       * 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.
       */
      function functionCall(address target, bytes memory data) internal returns (bytes memory) {
          return functionCallWithValue(target, data, 0);
      }
  
      /**
       * @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`.
       */
      function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
          if (address(this).balance < value) {
              revert Errors.InsufficientBalance(address(this).balance, value);
          }
          (bool success, bytes memory returndata) = target.call{value: value}(data);
          return verifyCallResultFromTarget(target, success, returndata);
      }
  
      /**
       * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
       * but performing a static call.
       */
      function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
          (bool success, bytes memory returndata) = target.staticcall(data);
          return verifyCallResultFromTarget(target, success, returndata);
      }
  
      /**
       * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
       * but performing a delegate call.
       */
      function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
          (bool success, bytes memory returndata) = target.delegatecall(data);
          return verifyCallResultFromTarget(target, success, returndata);
      }
  
      /**
       * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target
       * was not a contract or bubbling up the revert reason (falling back to {Errors.FailedCall}) in case
       * of an unsuccessful call.
       */
      function verifyCallResultFromTarget(
          address target,
          bool success,
          bytes memory returndata
      ) internal view returns (bytes memory) {
          if (!success) {
              _revert(returndata);
          } else {
              // only check if target is a contract if the call was successful and the return data is empty
              // otherwise we already know that it was a contract
              if (returndata.length == 0 && target.code.length == 0) {
                  revert AddressEmptyCode(target);
              }
              return returndata;
          }
      }
  
      /**
       * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the
       * revert reason or with a default {Errors.FailedCall} error.
       */
      function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {
          if (!success) {
              _revert(returndata);
          } else {
              return returndata;
          }
      }
  
      /**
       * @dev Reverts with returndata if present. Otherwise reverts with {Errors.FailedCall}.
       */
      function _revert(bytes memory returndata) private pure {
          // Look for revert reason and bubble it up if present
          if (returndata.length > 0) {
              // The easiest way to bubble the revert reason is using memory via assembly
              assembly ("memory-safe") {
                  let returndata_size := mload(returndata)
                  revert(add(32, returndata), returndata_size)
              }
          } else {
              revert Errors.FailedCall();
          }
      }
  }
  
  
  // File @openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol@v5.1.0
  
  // Original license: SPDX_License_Identifier: MIT
  // OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/utils/SafeERC20.sol)
  
  pragma solidity ^0.8.20;
  
  
  
  /**
   * @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 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);
      }
  }
  
  
  // File @layerzerolabs/oapp-evm/contracts/oapp/OAppSender.sol@v0.0.4
  
  // Original license: SPDX_License_Identifier: MIT
  
  pragma solidity ^0.8.20;
  
  
  
  /**
   * @title OAppSender
   * @dev Abstract contract implementing the OAppSender functionality for sending messages to a LayerZero endpoint.
   */
  abstract contract OAppSender is OAppCore {
      using SafeERC20 for IERC20;
  
      // Custom error messages
      error NotEnoughNative(uint256 msgValue);
      error LzTokenUnavailable();
  
      // @dev The version of the OAppSender implementation.
      // @dev Version is bumped when changes are made to this contract.
      uint64 internal constant SENDER_VERSION = 1;
  
      /**
       * @notice Retrieves the OApp version information.
       * @return senderVersion The version of the OAppSender.sol contract.
       * @return receiverVersion The version of the OAppReceiver.sol contract.
       *
       * @dev Providing 0 as the default for OAppReceiver version. Indicates that the OAppReceiver is not implemented.
       * ie. this is a SEND only OApp.
       * @dev If the OApp uses both OAppSender and OAppReceiver, then this needs to be override returning the correct versions
       */
      function oAppVersion() public view virtual returns (uint64 senderVersion, uint64 receiverVersion) {
          return (SENDER_VERSION, 0);
      }
  
      /**
       * @dev Internal function to interact with the LayerZero EndpointV2.quote() for fee calculation.
       * @param _dstEid The destination endpoint ID.
       * @param _message The message payload.
       * @param _options Additional options for the message.
       * @param _payInLzToken Flag indicating whether to pay the fee in LZ tokens.
       * @return fee The calculated MessagingFee for the message.
       *      - nativeFee: The native fee for the message.
       *      - lzTokenFee: The LZ token fee for the message.
       */
      function _quote(
          uint32 _dstEid,
          bytes memory _message,
          bytes memory _options,
          bool _payInLzToken
      ) internal view virtual returns (MessagingFee memory fee) {
          return
              endpoint.quote(
                  MessagingParams(_dstEid, _getPeerOrRevert(_dstEid), _message, _options, _payInLzToken),
                  address(this)
              );
      }
  
      /**
       * @dev Internal function to interact with the LayerZero EndpointV2.send() for sending a message.
       * @param _dstEid The destination endpoint ID.
       * @param _message The message payload.
       * @param _options Additional options for the message.
       * @param _fee The calculated LayerZero fee for the message.
       *      - nativeFee: The native fee.
       *      - lzTokenFee: The lzToken fee.
       * @param _refundAddress The address to receive any excess fee values sent to the endpoint.
       * @return receipt The receipt for the sent message.
       *      - guid: The unique identifier for the sent message.
       *      - nonce: The nonce of the sent message.
       *      - fee: The LayerZero fee incurred for the message.
       */
      function _lzSend(
          uint32 _dstEid,
          bytes memory _message,
          bytes memory _options,
          MessagingFee memory _fee,
          address _refundAddress
      ) internal virtual returns (MessagingReceipt memory receipt) {
          // @dev Push corresponding fees to the endpoint, any excess is sent back to the _refundAddress from the endpoint.
          uint256 messageValue = _payNative(_fee.nativeFee);
          if (_fee.lzTokenFee > 0) _payLzToken(_fee.lzTokenFee);
  
          return
              // solhint-disable-next-line check-send-result
              endpoint.send{ value: messageValue }(
                  MessagingParams(_dstEid, _getPeerOrRevert(_dstEid), _message, _options, _fee.lzTokenFee > 0),
                  _refundAddress
              );
      }
  
      /**
       * @dev Internal function to pay the native fee associated with the message.
       * @param _nativeFee The native fee to be paid.
       * @return nativeFee The amount of native currency paid.
       *
       * @dev If the OApp needs to initiate MULTIPLE LayerZero messages in a single transaction,
       * this will need to be overridden because msg.value would contain multiple lzFees.
       * @dev Should be overridden in the event the LayerZero endpoint requires a different native currency.
       * @dev Some EVMs use an ERC20 as a method for paying transactions/gasFees.
       * @dev The endpoint is EITHER/OR, ie. it will NOT support both types of native payment at a time.
       */
      function _payNative(uint256 _nativeFee) internal virtual returns (uint256 nativeFee) {
          if (msg.value != _nativeFee) revert NotEnoughNative(msg.value);
          return _nativeFee;
      }
  
      /**
       * @dev Internal function to pay the LZ token fee associated with the message.
       * @param _lzTokenFee The LZ token fee to be paid.
       *
       * @dev If the caller is trying to pay in the specified lzToken, then the lzTokenFee is passed to the endpoint.
       * @dev Any excess sent, is passed back to the specified _refundAddress in the _lzSend().
       */
      function _payLzToken(uint256 _lzTokenFee) internal virtual {
          // @dev Cannot cache the token because it is not immutable in the endpoint.
          address lzToken = endpoint.lzToken();
          if (lzToken == address(0)) revert LzTokenUnavailable();
  
          // Pay LZ token fee by sending tokens to the endpoint.
          IERC20(lzToken).safeTransferFrom(msg.sender, address(endpoint), _lzTokenFee);
      }
  }
  
  
  // File @layerzerolabs/oapp-evm/contracts/oapp/OApp.sol@v0.0.4
  
  // Original license: SPDX_License_Identifier: MIT
  
  pragma solidity ^0.8.20;
  
  // @dev Import the 'MessagingFee' and 'MessagingReceipt' so it's exposed to OApp implementers
  // solhint-disable-next-line no-unused-import
  
  // @dev Import the 'Origin' so it's exposed to OApp implementers
  // solhint-disable-next-line no-unused-import
  
  
  /**
   * @title OApp
   * @dev Abstract contract serving as the base for OApp implementation, combining OAppSender and OAppReceiver functionality.
   */
  abstract contract OApp is OAppSender, OAppReceiver {
      /**
       * @dev Constructor to initialize the OApp with the provided endpoint and owner.
       * @param _endpoint The address of the LOCAL LayerZero endpoint.
       * @param _delegate The delegate capable of making OApp configurations inside of the endpoint.
       */
      constructor(address _endpoint, address _delegate) OAppCore(_endpoint, _delegate) {}
  
      /**
       * @notice Retrieves the OApp version information.
       * @return senderVersion The version of the OAppSender.sol implementation.
       * @return receiverVersion The version of the OAppReceiver.sol implementation.
       */
      function oAppVersion()
          public
          pure
          virtual
          override(OAppSender, OAppReceiver)
          returns (uint64 senderVersion, uint64 receiverVersion)
      {
          return (SENDER_VERSION, RECEIVER_VERSION);
      }
  }
  
  
  // File @layerzerolabs/oapp-evm/contracts/precrime/libs/Packet.sol@v0.0.4
  
  // Original license: SPDX_License_Identifier: MIT
  
  pragma solidity ^0.8.20;
  
  
  /**
   * @title InboundPacket
   * @dev Structure representing an inbound packet received by the contract.
   */
  struct InboundPacket {
      Origin origin; // Origin information of the packet.
      uint32 dstEid; // Destination endpointId of the packet.
      address receiver; // Receiver address for the packet.
      bytes32 guid; // Unique identifier of the packet.
      uint256 value; // msg.value of the packet.
      address executor; // Executor address for the packet.
      bytes message; // Message payload of the packet.
      bytes extraData; // Additional arbitrary data for the packet.
  }
  
  /**
   * @title PacketDecoder
   * @dev Library for decoding LayerZero packets.
   */
  library PacketDecoder {
      using PacketV1Codec for bytes;
  
      /**
       * @dev Decode an inbound packet from the given packet data.
       * @param _packet The packet data to decode.
       * @return packet An InboundPacket struct representing the decoded packet.
       */
      function decode(bytes calldata _packet) internal pure returns (InboundPacket memory packet) {
          packet.origin = Origin(_packet.srcEid(), _packet.sender(), _packet.nonce());
          packet.dstEid = _packet.dstEid();
          packet.receiver = _packet.receiverB20();
          packet.guid = _packet.guid();
          packet.message = _packet.message();
      }
  
      /**
       * @dev Decode multiple inbound packets from the given packet data and associated message values.
       * @param _packets An array of packet data to decode.
       * @param _packetMsgValues An array of associated message values for each packet.
       * @return packets An array of InboundPacket structs representing the decoded packets.
       */
      function decode(
          bytes[] calldata _packets,
          uint256[] memory _packetMsgValues
      ) internal pure returns (InboundPacket[] memory packets) {
          packets = new InboundPacket[](_packets.length);
          for (uint256 i = 0; i < _packets.length; i++) {
              bytes calldata packet = _packets[i];
              packets[i] = PacketDecoder.decode(packet);
              // @dev Allows the verifier to specify the msg.value that gets passed in lzReceive.
              packets[i].value = _packetMsgValues[i];
          }
      }
  }
  
  
  // File @layerzerolabs/oapp-evm/contracts/precrime/interfaces/IOAppPreCrimeSimulator.sol@v0.0.4
  
  // Original license: SPDX_License_Identifier: MIT
  
  pragma solidity ^0.8.20;
  
  // @dev Import the Origin so it's exposed to OAppPreCrimeSimulator implementers.
  // solhint-disable-next-line no-unused-import
  
  /**
   * @title IOAppPreCrimeSimulator Interface
   * @dev Interface for the preCrime simulation functionality in an OApp.
   */
  interface IOAppPreCrimeSimulator {
      // @dev simulation result used in PreCrime implementation
      error SimulationResult(bytes result);
      error OnlySelf();
  
      /**
       * @dev Emitted when the preCrime contract address is set.
       * @param preCrimeAddress The address of the preCrime contract.
       */
      event PreCrimeSet(address preCrimeAddress);
  
      /**
       * @dev Retrieves the address of the preCrime contract implementation.
       * @return The address of the preCrime contract.
       */
      function preCrime() external view returns (address);
  
      /**
       * @dev Retrieves the address of the OApp contract.
       * @return The address of the OApp contract.
       */
      function oApp() external view returns (address);
  
      /**
       * @dev Sets the preCrime contract address.
       * @param _preCrime The address of the preCrime contract.
       */
      function setPreCrime(address _preCrime) external;
  
      /**
       * @dev Mocks receiving a packet, then reverts with a series of data to infer the state/result.
       * @param _packets An array of LayerZero InboundPacket objects representing received packets.
       */
      function lzReceiveAndRevert(InboundPacket[] calldata _packets) external payable;
  
      /**
       * @dev checks if the specified peer is considered 'trusted' by the OApp.
       * @param _eid The endpoint Id to check.
       * @param _peer The peer to check.
       * @return Whether the peer passed is considered 'trusted' by the OApp.
       */
      function isPeer(uint32 _eid, bytes32 _peer) external view returns (bool);
  }
  
  
  // File @layerzerolabs/oapp-evm/contracts/precrime/interfaces/IPreCrime.sol@v0.0.4
  
  // Original license: SPDX_License_Identifier: MIT
  
  pragma solidity ^0.8.20;
  struct PreCrimePeer {
      uint32 eid;
      bytes32 preCrime;
      bytes32 oApp;
  }
  
  // TODO not done yet
  interface IPreCrime {
      error OnlyOffChain();
  
      // for simulate()
      error PacketOversize(uint256 max, uint256 actual);
      error PacketUnsorted();
      error SimulationFailed(bytes reason);
  
      // for preCrime()
      error SimulationResultNotFound(uint32 eid);
      error InvalidSimulationResult(uint32 eid, bytes reason);
      error CrimeFound(bytes crime);
  
      function getConfig(bytes[] calldata _packets, uint256[] calldata _packetMsgValues) external returns (bytes memory);
  
      function simulate(
          bytes[] calldata _packets,
          uint256[] calldata _packetMsgValues
      ) external payable returns (bytes memory);
  
      function buildSimulationResult() external view returns (bytes memory);
  
      function preCrime(
          bytes[] calldata _packets,
          uint256[] calldata _packetMsgValues,
          bytes[] calldata _simulations
      ) external;
  
      function version() external view returns (uint64 major, uint8 minor);
  }
  
  
  // File @layerzerolabs/oapp-evm/contracts/precrime/OAppPreCrimeSimulator.sol@v0.0.4
  
  // Original license: SPDX_License_Identifier: MIT
  
  pragma solidity ^0.8.20;
  
  
  
  /**
   * @title OAppPreCrimeSimulator
   * @dev Abstract contract serving as the base for preCrime simulation functionality in an OApp.
   */
  abstract contract OAppPreCrimeSimulator is IOAppPreCrimeSimulator, Ownable {
      // The address of the preCrime implementation.
      address public preCrime;
  
      /**
       * @dev Retrieves the address of the OApp contract.
       * @return The address of the OApp contract.
       *
       * @dev The simulator contract is the base contract for the OApp by default.
       * @dev If the simulator is a separate contract, override this function.
       */
      function oApp() external view virtual returns (address) {
          return address(this);
      }
  
      /**
       * @dev Sets the preCrime contract address.
       * @param _preCrime The address of the preCrime contract.
       */
      function setPreCrime(address _preCrime) public virtual onlyOwner {
          preCrime = _preCrime;
          emit PreCrimeSet(_preCrime);
      }
  
      /**
       * @dev Interface for pre-crime simulations. Always reverts at the end with the simulation results.
       * @param _packets An array of InboundPacket objects representing received packets to be delivered.
       *
       * @dev WARNING: MUST revert at the end with the simulation results.
       * @dev Gives the preCrime implementation the ability to mock sending packets to the lzReceive function,
       * WITHOUT actually executing them.
       */
      function lzReceiveAndRevert(InboundPacket[] calldata _packets) public payable virtual {
          for (uint256 i = 0; i < _packets.length; i++) {
              InboundPacket calldata packet = _packets[i];
  
              // Ignore packets that are not from trusted peers.
              if (!isPeer(packet.origin.srcEid, packet.origin.sender)) continue;
  
              // @dev Because a verifier is calling this function, it doesnt have access to executor params:
              //  - address _executor
              //  - bytes calldata _extraData
              // preCrime will NOT work for OApps that rely on these two parameters inside of their _lzReceive().
              // They are instead stubbed to default values, address(0) and bytes("")
              // @dev Calling this.lzReceiveSimulate removes ability for assembly return 0 callstack exit,
              // which would cause the revert to be ignored.
              this.lzReceiveSimulate{ value: packet.value }(
                  packet.origin,
                  packet.guid,
                  packet.message,
                  packet.executor,
                  packet.extraData
              );
          }
  
          // @dev Revert with the simulation results. msg.sender must implement IPreCrime.buildSimulationResult().
          revert SimulationResult(IPreCrime(msg.sender).buildSimulationResult());
      }
  
      /**
       * @dev Is effectively an internal function because msg.sender must be address(this).
       * Allows resetting the call stack for 'internal' calls.
       * @param _origin The origin information containing the source endpoint and sender address.
       *  - srcEid: The source chain endpoint ID.
       *  - sender: The sender address on the src chain.
       *  - nonce: The nonce of the message.
       * @param _guid The unique identifier of the packet.
       * @param _message The message payload of the packet.
       * @param _executor The executor address for the packet.
       * @param _extraData Additional data for the packet.
       */
      function lzReceiveSimulate(
          Origin calldata _origin,
          bytes32 _guid,
          bytes calldata _message,
          address _executor,
          bytes calldata _extraData
      ) external payable virtual {
          // @dev Ensure ONLY can be called 'internally'.
          if (msg.sender != address(this)) revert OnlySelf();
          _lzReceiveSimulate(_origin, _guid, _message, _executor, _extraData);
      }
  
      /**
       * @dev Internal function to handle the OAppPreCrimeSimulator simulated receive.
       * @param _origin The origin information.
       *  - srcEid: The source chain endpoint ID.
       *  - sender: The sender address from the src chain.
       *  - nonce: The nonce of the LayerZero message.
       * @param _guid The GUID of the LayerZero message.
       * @param _message The LayerZero message.
       * @param _executor The address of the off-chain executor.
       * @param _extraData Arbitrary data passed by the msg executor.
       *
       * @dev Enables the preCrime simulator to mock sending lzReceive() messages,
       * routes the msg down from the OAppPreCrimeSimulator, and back up to the OAppReceiver.
       */
      function _lzReceiveSimulate(
          Origin calldata _origin,
          bytes32 _guid,
          bytes calldata _message,
          address _executor,
          bytes calldata _extraData
      ) internal virtual;
  
      /**
       * @dev checks if the specified peer is considered 'trusted' by the OApp.
       * @param _eid The endpoint Id to check.
       * @param _peer The peer to check.
       * @return Whether the peer passed is considered 'trusted' by the OApp.
       */
      function isPeer(uint32 _eid, bytes32 _peer) public view virtual returns (bool);
  }
  
  
  // File @layerzerolabs/onft-evm/contracts/onft721/interfaces/IONFT721.sol@v0.0.7
  
  // Original license: SPDX_License_Identifier: MIT
  
  pragma solidity ^0.8.22;
  
  /**
   * @dev Struct representing token parameters for the ONFT send() operation.
   */
  struct SendParam {
      uint32 dstEid; // Destination LayerZero EndpointV2 ID.
      bytes32 to; // Recipient address.
      uint256 tokenId;
      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 onftCmd; // The ONFT command to be executed, unused in default ONFT implementations.
  }
  
  /**
   * @title IONFT
   * @dev Interface for the ONFT721 token.
   * @dev Does not inherit ERC721 to accommodate usage by OFT721Adapter.
   */
  interface IONFT721 {
      // Custom error messages
      error InvalidReceiver();
      error OnlyNFTOwner(address caller, address owner);
  
      // Events
      event ONFTSent(
          bytes32 indexed guid, // GUID of the ONFT message.
          uint32 dstEid, // Destination Endpoint ID.
          address indexed fromAddress, // Address of the sender on the src chain.
          uint256 tokenId // ONFT ID sent.
      );
  
      event ONFTReceived(
          bytes32 indexed guid, // GUID of the ONFT message.
          uint32 srcEid, // Source Endpoint ID.
          address indexed toAddress, // Address of the recipient on the dst chain.
          uint256 tokenId // ONFT ID received.
      );
  
      /**
       * @notice Retrieves interfaceID and the version of the ONFT.
       * @return interfaceId The interface ID.
       * @return version The version.
       * @dev interfaceId: This specific interface ID is '0x94642228'.
       * @dev version: Indicates a cross-chain compatible msg encoding with other ONFTs.
       * @dev If a new feature is added to the ONFT cross-chain msg encoding, the version will be incremented.
       * ie. localONFT version(x,1) CAN send messages to remoteONFT version(x,1)
       */
      function onftVersion() external view returns (bytes4 interfaceId, uint64 version);
  
      /**
       * @notice Retrieves the address of the token associated with the ONFT.
       * @return token The address of the ERC721 token implementation.
       */
      function token() external view returns (address);
  
      /**
       * @notice Indicates whether the ONFT 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 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.
       * @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);
  }
  
  
  // File @layerzerolabs/oapp-evm/contracts/oapp/interfaces/IOAppMsgInspector.sol@v0.0.4
  
  // Original license: SPDX_License_Identifier: MIT
  
  pragma solidity ^0.8.20;
  
  /**
   * @title IOAppMsgInspector
   * @dev Interface for the OApp Message Inspector, allowing examination of message and options contents.
   */
  interface IOAppMsgInspector {
      // Custom error message for inspection failure
      error InspectionFailed(bytes message, bytes options);
  
      /**
       * @notice Allows the inspector to examine LayerZero message contents and optionally throw a revert if invalid.
       * @param _message The message payload to be inspected.
       * @param _options Additional options or parameters for inspection.
       * @return valid A boolean indicating whether the inspection passed (true) or failed (false).
       *
       * @dev Optionally done as a revert, OR use the boolean provided to handle the failure.
       */
      function inspect(bytes calldata _message, bytes calldata _options) external view returns (bool valid);
  }
  
  
  // File @layerzerolabs/onft-evm/contracts/libs/ONFTComposeMsgCodec.sol@v0.0.7
  
  // Original license: SPDX_License_Identifier: MIT
  
  pragma solidity ^0.8.22;
  
  /**
   * @title ONFT Composed Message Codec
   * @notice Library for encoding and decoding ONFT composed messages.
   */
  library ONFTComposeMsgCodec {
      // Offset constants for decoding composed messages
      uint8 private constant NONCE_OFFSET = 8;
      uint8 private constant SRC_EID_OFFSET = 12;
      uint8 private constant COMPOSE_FROM_OFFSET = 44;
  
      /**
       * @dev Encodes a ONFT721 composed message.
       * @param _nonce The nonce value.
       * @param _srcEid The source LayerZero endpoint ID.
       * @param _composeMsg The composed message.
       * @return The encoded payload, including the composed message.
       */
      function encode(
          uint64 _nonce,
          uint32 _srcEid,
          bytes memory _composeMsg // 0x[composeFrom][composeMsg]
      ) internal pure returns (bytes memory) {
          return abi.encodePacked(_nonce, _srcEid, _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 LayerZero endpoint ID for the composed message.
       * @param _msg The message.
       * @return The source LayerZero endpoint ID.
       */
      function srcEid(bytes calldata _msg) internal pure returns (uint32) {
          return uint32(bytes4(_msg[NONCE_OFFSET:SRC_EID_OFFSET]));
      }
  
      /**
       * @dev Retrieves the composeFrom value from the composed message.
       * @param _msg The message.
       * @return The composeFrom value as bytes32.
       */
      function composeFrom(bytes calldata _msg) internal pure returns (bytes32) {
          return bytes32(_msg[SRC_EID_OFFSET:COMPOSE_FROM_OFFSET]);
      }
  
      /**
       * @dev Retrieves the composed message.
       * @param _msg The message.
       * @return The composed message.
       */
      function composeMsg(bytes calldata _msg) internal pure returns (bytes memory) {
          return _msg[COMPOSE_FROM_OFFSET:];
      }
  
      /**
       * @dev Converts an address to bytes32.
       * @param _addr The address to convert.
       * @return The bytes32 representation of the address.
       */
      function addressToBytes32(address _addr) internal pure returns (bytes32) {
          return bytes32(uint256(uint160(_addr)));
      }
  
      /**
       * @dev Converts bytes32 to an address.
       * @param _b The bytes32 value to convert.
       * @return The address representation of bytes32.
       */
      function bytes32ToAddress(bytes32 _b) internal pure returns (address) {
          return address(uint160(uint256(_b)));
      }
  }
  
  
  // File @layerzerolabs/onft-evm/contracts/onft721/libs/ONFT721MsgCodec.sol@v0.0.7
  
  // Original license: SPDX_License_Identifier: MIT
  
  pragma solidity ^0.8.22;
  
  /**
   * @title ONFT721MsgCodec
   * @notice Library for encoding and decoding ONFT721 LayerZero messages.
   */
  library ONFT721MsgCodec {
      uint8 private constant SEND_TO_OFFSET = 32;
      uint8 private constant TOKEN_ID_OFFSET = 64;
  
      /**
       * @dev Encodes an ONFT721 LayerZero message payload.
       * @param _sendTo The recipient address.
       * @param _tokenId The ID of the token to transfer.
       * @param _composeMsg The composed payload.
       * @return payload The encoded message payload.
       * @return hasCompose A boolean indicating whether the message payload contains a composed payload.
       */
      function encode(
          bytes32 _sendTo,
          uint256 _tokenId,
          bytes memory _composeMsg
      ) internal view returns (bytes memory payload, bool hasCompose) {
          hasCompose = _composeMsg.length > 0;
          payload = hasCompose
              ? abi.encodePacked(_sendTo, _tokenId, addressToBytes32(msg.sender), _composeMsg)
              : abi.encodePacked(_sendTo, _tokenId);
      }
  
      /**
       * @dev Decodes sendTo from the ONFT LayerZero message.
       * @param _msg The message.
       * @return The recipient address in bytes32 format.
       */
      function sendTo(bytes calldata _msg) internal pure returns (bytes32) {
          return bytes32(_msg[:SEND_TO_OFFSET]);
      }
  
      /**
       * @dev Decodes tokenId from the ONFT LayerZero message.
       * @param _msg The message.
       * @return The ID of the tokens to transfer.
       */
      function tokenId(bytes calldata _msg) internal pure returns (uint256) {
          return uint256(bytes32(_msg[SEND_TO_OFFSET:TOKEN_ID_OFFSET]));
      }
  
      /**
       * @dev Decodes whether there is a composed payload.
       * @param _msg The message.
       * @return A boolean indicating whether the message has a composed payload.
       */
      function isComposed(bytes calldata _msg) internal pure returns (bool) {
          return _msg.length > TOKEN_ID_OFFSET;
      }
  
      /**
       * @dev Decodes the composed message.
       * @param _msg The message.
       * @return The composed message.
       */
      function composeMsg(bytes calldata _msg) internal pure returns (bytes memory) {
          return _msg[TOKEN_ID_OFFSET:];
      }
  
      /**
       * @dev Converts an address to bytes32.
       * @param _addr The address to convert.
       * @return The bytes32 representation of the address.
       */
      function addressToBytes32(address _addr) internal pure returns (bytes32) {
          return bytes32(uint256(uint160(_addr)));
      }
  
      /**
       * @dev Converts bytes32 to an address.
       * @param _b The bytes32 value to convert.
       * @return The address representation of bytes32.
       */
      function bytes32ToAddress(bytes32 _b) internal pure returns (address) {
          return address(uint160(uint256(_b)));
      }
  }
  
  
  // File @layerzerolabs/onft-evm/contracts/onft721/ONFT721Core.sol@v0.0.7
  
  // Original license: SPDX_License_Identifier: MIT
  
  pragma solidity ^0.8.22;
  
  
  
  
  
  
  /**
   * @title ONFT721Core
   * @dev Abstract contract for an ONFT721 token.
   */
  abstract contract ONFT721Core is IONFT721, OApp, OAppPreCrimeSimulator, OAppOptionsType3 {
      using ONFT721MsgCodec for bytes;
      using ONFT721MsgCodec for bytes32;
  
      // @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_COMPOSE = 2;
  
      // Address of an optional contract to inspect both 'message' and 'options'
      address public msgInspector;
  
      event MsgInspectorSet(address inspector);
  
      /**
       * @dev Constructor.
       * @param _lzEndpoint The address of the LayerZero endpoint.
       * @param _delegate The delegate capable of making OApp configurations inside of the endpoint.
       */
      constructor(address _lzEndpoint, address _delegate) Ownable(_delegate) OApp(_lzEndpoint, _delegate) {}
  
      /**
       * @notice Retrieves interfaceID and the version of the ONFT.
       * @return interfaceId The interface ID (0x23e18da6).
       * @return version The version.
       * @dev version: Indicates a cross-chain compatible msg encoding with other ONFTs.
       * @dev If a new feature is added to the ONFT cross-chain msg encoding, the version will be incremented.
       * @dev ie. localONFT version(x,1) CAN send messages to remoteONFT version(x,1)
       */
      function onftVersion() external pure virtual returns (bytes4 interfaceId, uint64 version) {
          return (type(IONFT721).interfaceId, 1);
      }
  
      /**
       * @notice Sets the message inspector address for the OFT.
       * @param _msgInspector The address of the message inspector.
       * @dev This is an optional contract that can be used to inspect both 'message' and 'options'.
       * @dev Set it to address(0) to disable it, or set it to a contract address to enable it.
       */
      function setMsgInspector(address _msgInspector) public virtual onlyOwner {
          msgInspector = _msgInspector;
          emit MsgInspectorSet(_msgInspector);
      }
  
      function quoteSend(
          SendParam calldata _sendParam,
          bool _payInLzToken
      ) external view virtual returns (MessagingFee memory msgFee) {
          (bytes memory message, bytes memory options) = _buildMsgAndOptions(_sendParam);
          return _quote(_sendParam.dstEid, message, options, _payInLzToken);
      }
  
      function send(
          SendParam calldata _sendParam,
          MessagingFee calldata _fee,
          address _refundAddress
      ) external payable virtual returns (MessagingReceipt memory msgReceipt) {
          _debit(msg.sender, _sendParam.tokenId, _sendParam.dstEid);
  
          (bytes memory message, bytes memory options) = _buildMsgAndOptions(_sendParam);
  
          // @dev Sends the message to the LayerZero Endpoint, returning the MessagingReceipt.
          msgReceipt = _lzSend(_sendParam.dstEid, message, options, _fee, _refundAddress);
          emit ONFTSent(msgReceipt.guid, _sendParam.dstEid, msg.sender, _sendParam.tokenId);
      }
  
      /**
       * @dev Internal function to build the message and options.
       * @param _sendParam The parameters for the send() operation.
       * @return message The encoded message.
       * @return options The encoded options.
       */
      function _buildMsgAndOptions(
          SendParam calldata _sendParam
      ) internal view virtual returns (bytes memory message, bytes memory options) {
          if (_sendParam.to == bytes32(0)) revert InvalidReceiver();
          bool hasCompose;
          (message, hasCompose) = ONFT721MsgCodec.encode(_sendParam.to, _sendParam.tokenId, _sendParam.composeMsg);
          uint16 msgType = hasCompose ? SEND_AND_COMPOSE : SEND;
  
          options = combineOptions(_sendParam.dstEid, msgType, _sendParam.extraOptions);
  
          // @dev Optionally inspect the message and options depending if the OApp owner has set a msg inspector.
          // @dev If it fails inspection, needs to revert in the implementation. ie. does not rely on return boolean
          address inspector = msgInspector; // caches the msgInspector to avoid potential double storage read
          if (inspector != address(0)) IOAppMsgInspector(inspector).inspect(message, options);
      }
  
      /**
       * @dev Internal function to handle the receive on the LayerZero endpoint.
       * @param _origin The origin information.
       *  - srcEid: The source chain endpoint ID.
       *  - sender: The sender address from the src chain.
       *  - nonce: The nonce of the LayerZero message.
       * @param _guid The unique identifier for the received LayerZero message.
       * @param _message The encoded message.
       * @dev _executor The address of the executor.
       * @dev _extraData Additional data.
       */
      function _lzReceive(
          Origin calldata _origin,
          bytes32 _guid,
          bytes calldata _message,
          address /*_executor*/, // @dev unused in the default implementation.
          bytes calldata /*_extraData*/ // @dev unused in the default implementation.
      ) internal virtual override {
          address toAddress = _message.sendTo().bytes32ToAddress();
          uint256 tokenId = _message.tokenId();
  
          _credit(toAddress, tokenId, _origin.srcEid);
  
          if (_message.isComposed()) {
              bytes memory composeMsg = ONFTComposeMsgCodec.encode(_origin.nonce, _origin.srcEid, _message.composeMsg());
              // @dev As batching is not implemented, the compose index is always 0.
              // @dev If batching is added, the index will need to be tracked.
              endpoint.sendCompose(toAddress, _guid, 0 /* the index of composed message*/, composeMsg);
          }
  
          emit ONFTReceived(_guid, _origin.srcEid, toAddress, tokenId);
      }
  
      /*
       * @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;
      }
  
      function _debit(address /*_from*/, uint256 /*_tokenId*/, uint32 /*_dstEid*/) internal virtual;
  
      function _credit(address /*_to*/, uint256 /*_tokenId*/, uint32 /*_srcEid*/) internal virtual;
  }
  
  
  // File @openzeppelin/contracts/interfaces/draft-IERC6093.sol@v5.1.0
  
  // Original license: SPDX_License_Identifier: MIT
  // OpenZeppelin Contracts (last updated v5.1.0) (interfaces/draft-IERC6093.sol)
  pragma solidity ^0.8.20;
  
  /**
   * @dev Standard ERC-20 Errors
   * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-20 tokens.
   */
  interface IERC20Errors {
      /**
       * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.
       * @param sender Address whose tokens are being transferred.
       * @param balance Current balance for the interacting account.
       * @param needed Minimum amount required to perform a transfer.
       */
      error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed);
  
      /**
       * @dev Indicates a failure with the token `sender`. Used in transfers.
       * @param sender Address whose tokens are being transferred.
       */
      error ERC20InvalidSender(address sender);
  
      /**
       * @dev Indicates a failure with the token `receiver`. Used in transfers.
       * @param receiver Address to which tokens are being transferred.
       */
      error ERC20InvalidReceiver(address receiver);
  
      /**
       * @dev Indicates a failure with the `spender`’s `allowance`. Used in transfers.
       * @param spender Address that may be allowed to operate on tokens without being their owner.
       * @param allowance Amount of tokens a `spender` is allowed to operate with.
       * @param needed Minimum amount required to perform a transfer.
       */
      error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed);
  
      /**
       * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
       * @param approver Address initiating an approval operation.
       */
      error ERC20InvalidApprover(address approver);
  
      /**
       * @dev Indicates a failure with the `spender` to be approved. Used in approvals.
       * @param spender Address that may be allowed to operate on tokens without being their owner.
       */
      error ERC20InvalidSpender(address spender);
  }
  
  /**
   * @dev Standard ERC-721 Errors
   * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-721 tokens.
   */
  interface IERC721Errors {
      /**
       * @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in ERC-20.
       * Used in balance queries.
       * @param owner Address of the current owner of a token.
       */
      error ERC721InvalidOwner(address owner);
  
      /**
       * @dev Indicates a `tokenId` whose `owner` is the zero address.
       * @param tokenId Identifier number of a token.
       */
      error ERC721NonexistentToken(uint256 tokenId);
  
      /**
       * @dev Indicates an error related to the ownership over a particular token. Used in transfers.
       * @param sender Address whose tokens are being transferred.
       * @param tokenId Identifier number of a token.
       * @param owner Address of the current owner of a token.
       */
      error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner);
  
      /**
       * @dev Indicates a failure with the token `sender`. Used in transfers.
       * @param sender Address whose tokens are being transferred.
       */
      error ERC721InvalidSender(address sender);
  
      /**
       * @dev Indicates a failure with the token `receiver`. Used in transfers.
       * @param receiver Address to which tokens are being transferred.
       */
      error ERC721InvalidReceiver(address receiver);
  
      /**
       * @dev Indicates a failure with the `operator`’s approval. Used in transfers.
       * @param operator Address that may be allowed to operate on tokens without being their owner.
       * @param tokenId Identifier number of a token.
       */
      error ERC721InsufficientApproval(address operator, uint256 tokenId);
  
      /**
       * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
       * @param approver Address initiating an approval operation.
       */
      error ERC721InvalidApprover(address approver);
  
      /**
       * @dev Indicates a failure with the `operator` to be approved. Used in approvals.
       * @param operator Address that may be allowed to operate on tokens without being their owner.
       */
      error ERC721InvalidOperator(address operator);
  }
  
  /**
   * @dev Standard ERC-1155 Errors
   * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-1155 tokens.
   */
  interface IERC1155Errors {
      /**
       * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.
       * @param sender Address whose tokens are being transferred.
       * @param balance Current balance for the interacting account.
       * @param needed Minimum amount required to perform a transfer.
       * @param tokenId Identifier number of a token.
       */
      error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId);
  
      /**
       * @dev Indicates a failure with the token `sender`. Used in transfers.
       * @param sender Address whose tokens are being transferred.
       */
      error ERC1155InvalidSender(address sender);
  
      /**
       * @dev Indicates a failure with the token `receiver`. Used in transfers.
       * @param receiver Address to which tokens are being transferred.
       */
      error ERC1155InvalidReceiver(address receiver);
  
      /**
       * @dev Indicates a failure with the `operator`’s approval. Used in transfers.
       * @param operator Address that may be allowed to operate on tokens without being their owner.
       * @param owner Address of the current owner of a token.
       */
      error ERC1155MissingApprovalForAll(address operator, address owner);
  
      /**
       * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
       * @param approver Address initiating an approval operation.
       */
      error ERC1155InvalidApprover(address approver);
  
      /**
       * @dev Indicates a failure with the `operator` to be approved. Used in approvals.
       * @param operator Address that may be allowed to operate on tokens without being their owner.
       */
      error ERC1155InvalidOperator(address operator);
  
      /**
       * @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation.
       * Used in batch transfers.
       * @param idsLength Length of the array of token identifiers
       * @param valuesLength Length of the array of token amounts
       */
      error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength);
  }
  
  
  // File @openzeppelin/contracts/token/ERC721/IERC721.sol@v5.1.0
  
  // Original license: SPDX_License_Identifier: MIT
  // OpenZeppelin Contracts (last updated v5.1.0) (token/ERC721/IERC721.sol)
  
  pragma solidity ^0.8.20;
  
  /**
   * @dev Required interface of an ERC-721 compliant contract.
   */
  interface IERC721 is IERC165 {
      /**
       * @dev Emitted when `tokenId` token is transferred from `from` to `to`.
       */
      event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
  
      /**
       * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
       */
      event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
  
      /**
       * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.
       */
      event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
  
      /**
       * @dev Returns the number of tokens in ``owner``'s account.
       */
      function balanceOf(address owner) external view returns (uint256 balance);
  
      /**
       * @dev Returns the owner of the `tokenId` token.
       *
       * Requirements:
       *
       * - `tokenId` must exist.
       */
      function ownerOf(uint256 tokenId) external view returns (address owner);
  
      /**
       * @dev Safely transfers `tokenId` token from `from` to `to`.
       *
       * Requirements:
       *
       * - `from` cannot be the zero address.
       * - `to` cannot be the zero address.
       * - `tokenId` token must exist and be owned by `from`.
       * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
       * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon
       *   a safe transfer.
       *
       * Emits a {Transfer} event.
       */
      function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;
  
      /**
       * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
       * are aware of the ERC-721 protocol to prevent tokens from being forever locked.
       *
       * Requirements:
       *
       * - `from` cannot be the zero address.
       * - `to` cannot be the zero address.
       * - `tokenId` token must exist and be owned by `from`.
       * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or
       *   {setApprovalForAll}.
       * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon
       *   a safe transfer.
       *
       * Emits a {Transfer} event.
       */
      function safeTransferFrom(address from, address to, uint256 tokenId) external;
  
      /**
       * @dev Transfers `tokenId` token from `from` to `to`.
       *
       * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC-721
       * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must
       * understand this adds an external call which potentially creates a reentrancy vulnerability.
       *
       * Requirements:
       *
       * - `from` cannot be the zero address.
       * - `to` cannot be the zero address.
       * - `tokenId` token must be owned by `from`.
       * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
       *
       * Emits a {Transfer} event.
       */
      function transferFrom(address from, address to, uint256 tokenId) external;
  
      /**
       * @dev Gives permission to `to` to transfer `tokenId` token to another account.
       * The approval is cleared when the token is transferred.
       *
       * Only a single account can be approved at a time, so approving the zero address clears previous approvals.
       *
       * Requirements:
       *
       * - The caller must own the token or be an approved operator.
       * - `tokenId` must exist.
       *
       * Emits an {Approval} event.
       */
      function approve(address to, uint256 tokenId) external;
  
      /**
       * @dev Approve or remove `operator` as an operator for the caller.
       * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.
       *
       * Requirements:
       *
       * - The `operator` cannot be the address zero.
       *
       * Emits an {ApprovalForAll} event.
       */
      function setApprovalForAll(address operator, bool approved) external;
  
      /**
       * @dev Returns the account approved for `tokenId` token.
       *
       * Requirements:
       *
       * - `tokenId` must exist.
       */
      function getApproved(uint256 tokenId) external view returns (address operator);
  
      /**
       * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
       *
       * See {setApprovalForAll}
       */
      function isApprovedForAll(address owner, address operator) external view returns (bool);
  }
  
  
  // File @openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol@v5.1.0
  
  // Original license: SPDX_License_Identifier: MIT
  // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/extensions/IERC721Metadata.sol)
  
  pragma solidity ^0.8.20;
  
  /**
   * @title ERC-721 Non-Fungible Token Standard, optional metadata extension
   * @dev See https://eips.ethereum.org/EIPS/eip-721
   */
  interface IERC721Metadata is IERC721 {
      /**
       * @dev Returns the token collection name.
       */
      function name() external view returns (string memory);
  
      /**
       * @dev Returns the token collection symbol.
       */
      function symbol() external view returns (string memory);
  
      /**
       * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.
       */
      function tokenURI(uint256 tokenId) external view returns (string memory);
  }
  
  
  // File @openzeppelin/contracts/token/ERC721/IERC721Receiver.sol@v5.1.0
  
  // Original license: SPDX_License_Identifier: MIT
  // OpenZeppelin Contracts (last updated v5.1.0) (token/ERC721/IERC721Receiver.sol)
  
  pragma solidity ^0.8.20;
  
  /**
   * @title ERC-721 token receiver interface
   * @dev Interface for any contract that wants to support safeTransfers
   * from ERC-721 asset contracts.
   */
  interface IERC721Receiver {
      /**
       * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}
       * by `operator` from `from`, this function is called.
       *
       * It must return its Solidity selector to confirm the token transfer.
       * If any other value is returned or the interface is not implemented by the recipient, the transfer will be
       * reverted.
       *
       * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.
       */
      function onERC721Received(
          address operator,
          address from,
          uint256 tokenId,
          bytes calldata data
      ) external returns (bytes4);
  }
  
  
  // File @openzeppelin/contracts/token/ERC721/utils/ERC721Utils.sol@v5.1.0
  
  // Original license: SPDX_License_Identifier: MIT
  // OpenZeppelin Contracts (last updated v5.1.0) (token/ERC721/utils/ERC721Utils.sol)
  
  pragma solidity ^0.8.20;
  
  
  /**
   * @dev Library that provide common ERC-721 utility functions.
   *
   * See https://eips.ethereum.org/EIPS/eip-721[ERC-721].
   *
   * _Available since v5.1._
   */
  library ERC721Utils {
      /**
       * @dev Performs an acceptance check for the provided `operator` by calling {IERC721-onERC721Received}
       * on the `to` address. The `operator` is generally the address that initiated the token transfer (i.e. `msg.sender`).
       *
       * The acceptance call is not executed and treated as a no-op if the target address doesn't contain code (i.e. an EOA).
       * Otherwise, the recipient must implement {IERC721Receiver-onERC721Received} and return the acceptance magic value to accept
       * the transfer.
       */
      function checkOnERC721Received(
          address operator,
          address from,
          address to,
          uint256 tokenId,
          bytes memory data
      ) internal {
          if (to.code.length > 0) {
              try IERC721Receiver(to).onERC721Received(operator, from, tokenId, data) returns (bytes4 retval) {
                  if (retval != IERC721Receiver.onERC721Received.selector) {
                      // Token rejected
                      revert IERC721Errors.ERC721InvalidReceiver(to);
                  }
              } catch (bytes memory reason) {
                  if (reason.length == 0) {
                      // non-IERC721Receiver implementer
                      revert IERC721Errors.ERC721InvalidReceiver(to);
                  } else {
                      assembly ("memory-safe") {
                          revert(add(32, reason), mload(reason))
                      }
                  }
              }
          }
      }
  }
  
  
  // File @openzeppelin/contracts/utils/introspection/ERC165.sol@v5.1.0
  
  // Original license: SPDX_License_Identifier: MIT
  // OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/ERC165.sol)
  
  pragma solidity ^0.8.20;
  
  /**
   * @dev Implementation of the {IERC165} interface.
   *
   * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check
   * for the additional interface id that will be supported. For example:
   *
   * ```solidity
   * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
   *     return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
   * }
   * ```
   */
  abstract contract ERC165 is IERC165 {
      /**
       * @dev See {IERC165-supportsInterface}.
       */
      function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {
          return interfaceId == type(IERC165).interfaceId;
      }
  }
  
  
  // File @openzeppelin/contracts/utils/math/SafeCast.sol@v5.1.0
  
  // Original license: SPDX_License_Identifier: MIT
  // OpenZeppelin Contracts (last updated v5.1.0) (utils/math/SafeCast.sol)
  // This file was procedurally generated from scripts/generate/templates/SafeCast.js.
  
  pragma solidity ^0.8.20;
  
  /**
   * @dev Wrappers over Solidity's uintXX/intXX/bool casting operators with added overflow
   * checks.
   *
   * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can
   * easily result in undesired exploitation or bugs, since developers usually
   * assume that overflows raise errors. `SafeCast` restores this intuition by
   * reverting the transaction when such an operation overflows.
   *
   * Using this library instead of the unchecked operations eliminates an entire
   * class of bugs, so it's recommended to use it always.
   */
  library SafeCast {
      /**
       * @dev Value doesn't fit in an uint of `bits` size.
       */
      error SafeCastOverflowedUintDowncast(uint8 bits, uint256 value);
  
      /**
       * @dev An int value doesn't fit in an uint of `bits` size.
       */
      error SafeCastOverflowedIntToUint(int256 value);
  
      /**
       * @dev Value doesn't fit in an int of `bits` size.
       */
      error SafeCastOverflowedIntDowncast(uint8 bits, int256 value);
  
      /**
       * @dev An uint value doesn't fit in an int of `bits` size.
       */
      error SafeCastOverflowedUintToInt(uint256 value);
  
      /**
       * @dev Returns the downcasted uint248 from uint256, reverting on
       * overflow (when the input is greater than largest uint248).
       *
       * Counterpart to Solidity's `uint248` operator.
       *
       * Requirements:
       *
       * - input must fit into 248 bits
       */
      function toUint248(uint256 value) internal pure returns (uint248) {
          if (value > type(uint248).max) {
              revert SafeCastOverflowedUintDowncast(248, value);
          }
          return uint248(value);
      }
  
      /**
       * @dev Returns the downcasted uint240 from uint256, reverting on
       * overflow (when the input is greater than largest uint240).
       *
       * Counterpart to Solidity's `uint240` operator.
       *
       * Requirements:
       *
       * - input must fit into 240 bits
       */
      function toUint240(uint256 value) internal pure returns (uint240) {
          if (value > type(uint240).max) {
              revert SafeCastOverflowedUintDowncast(240, value);
          }
          return uint240(value);
      }
  
      /**
       * @dev Returns the downcasted uint232 from uint256, reverting on
       * overflow (when the input is greater than largest uint232).
       *
       * Counterpart to Solidity's `uint232` operator.
       *
       * Requirements:
       *
       * - input must fit into 232 bits
       */
      function toUint232(uint256 value) internal pure returns (uint232) {
          if (value > type(uint232).max) {
              revert SafeCastOverflowedUintDowncast(232, value);
          }
          return uint232(value);
      }
  
      /**
       * @dev Returns the downcasted uint224 from uint256, reverting on
       * overflow (when the input is greater than largest uint224).
       *
       * Counterpart to Solidity's `uint224` operator.
       *
       * Requirements:
       *
       * - input must fit into 224 bits
       */
      function toUint224(uint256 value) internal pure returns (uint224) {
          if (value > type(uint224).max) {
              revert SafeCastOverflowedUintDowncast(224, value);
          }
          return uint224(value);
      }
  
      /**
       * @dev Returns the downcasted uint216 from uint256, reverting on
       * overflow (when the input is greater than largest uint216).
       *
       * Counterpart to Solidity's `uint216` operator.
       *
       * Requirements:
       *
       * - input must fit into 216 bits
       */
      function toUint216(uint256 value) internal pure returns (uint216) {
          if (value > type(uint216).max) {
              revert SafeCastOverflowedUintDowncast(216, value);
          }
          return uint216(value);
      }
  
      /**
       * @dev Returns the downcasted uint208 from uint256, reverting on
       * overflow (when the input is greater than largest uint208).
       *
       * Counterpart to Solidity's `uint208` operator.
       *
       * Requirements:
       *
       * - input must fit into 208 bits
       */
      function toUint208(uint256 value) internal pure returns (uint208) {
          if (value > type(uint208).max) {
              revert SafeCastOverflowedUintDowncast(208, value);
          }
          return uint208(value);
      }
  
      /**
       * @dev Returns the downcasted uint200 from uint256, reverting on
       * overflow (when the input is greater than largest uint200).
       *
       * Counterpart to Solidity's `uint200` operator.
       *
       * Requirements:
       *
       * - input must fit into 200 bits
       */
      function toUint200(uint256 value) internal pure returns (uint200) {
          if (value > type(uint200).max) {
              revert SafeCastOverflowedUintDowncast(200, value);
          }
          return uint200(value);
      }
  
      /**
       * @dev Returns the downcasted uint192 from uint256, reverting on
       * overflow (when the input is greater than largest uint192).
       *
       * Counterpart to Solidity's `uint192` operator.
       *
       * Requirements:
       *
       * - input must fit into 192 bits
       */
      function toUint192(uint256 value) internal pure returns (uint192) {
          if (value > type(uint192).max) {
              revert SafeCastOverflowedUintDowncast(192, value);
          }
          return uint192(value);
      }
  
      /**
       * @dev Returns the downcasted uint184 from uint256, reverting on
       * overflow (when the input is greater than largest uint184).
       *
       * Counterpart to Solidity's `uint184` operator.
       *
       * Requirements:
       *
       * - input must fit into 184 bits
       */
      function toUint184(uint256 value) internal pure returns (uint184) {
          if (value > type(uint184).max) {
              revert SafeCastOverflowedUintDowncast(184, value);
          }
          return uint184(value);
      }
  
      /**
       * @dev Returns the downcasted uint176 from uint256, reverting on
       * overflow (when the input is greater than largest uint176).
       *
       * Counterpart to Solidity's `uint176` operator.
       *
       * Requirements:
       *
       * - input must fit into 176 bits
       */
      function toUint176(uint256 value) internal pure returns (uint176) {
          if (value > type(uint176).max) {
              revert SafeCastOverflowedUintDowncast(176, value);
          }
          return uint176(value);
      }
  
      /**
       * @dev Returns the downcasted uint168 from uint256, reverting on
       * overflow (when the input is greater than largest uint168).
       *
       * Counterpart to Solidity's `uint168` operator.
       *
       * Requirements:
       *
       * - input must fit into 168 bits
       */
      function toUint168(uint256 value) internal pure returns (uint168) {
          if (value > type(uint168).max) {
              revert SafeCastOverflowedUintDowncast(168, value);
          }
          return uint168(value);
      }
  
      /**
       * @dev Returns the downcasted uint160 from uint256, reverting on
       * overflow (when the input is greater than largest uint160).
       *
       * Counterpart to Solidity's `uint160` operator.
       *
       * Requirements:
       *
       * - input must fit into 160 bits
       */
      function toUint160(uint256 value) internal pure returns (uint160) {
          if (value > type(uint160).max) {
              revert SafeCastOverflowedUintDowncast(160, value);
          }
          return uint160(value);
      }
  
      /**
       * @dev Returns the downcasted uint152 from uint256, reverting on
       * overflow (when the input is greater than largest uint152).
       *
       * Counterpart to Solidity's `uint152` operator.
       *
       * Requirements:
       *
       * - input must fit into 152 bits
       */
      function toUint152(uint256 value) internal pure returns (uint152) {
          if (value > type(uint152).max) {
              revert SafeCastOverflowedUintDowncast(152, value);
          }
          return uint152(value);
      }
  
      /**
       * @dev Returns the downcasted uint144 from uint256, reverting on
       * overflow (when the input is greater than largest uint144).
       *
       * Counterpart to Solidity's `uint144` operator.
       *
       * Requirements:
       *
       * - input must fit into 144 bits
       */
      function toUint144(uint256 value) internal pure returns (uint144) {
          if (value > type(uint144).max) {
              revert SafeCastOverflowedUintDowncast(144, value);
          }
          return uint144(value);
      }
  
      /**
       * @dev Returns the downcasted uint136 from uint256, reverting on
       * overflow (when the input is greater than largest uint136).
       *
       * Counterpart to Solidity's `uint136` operator.
       *
       * Requirements:
       *
       * - input must fit into 136 bits
       */
      function toUint136(uint256 value) internal pure returns (uint136) {
          if (value > type(uint136).max) {
              revert SafeCastOverflowedUintDowncast(136, value);
          }
          return uint136(value);
      }
  
      /**
       * @dev Returns the downcasted uint128 from uint256, reverting on
       * overflow (when the input is greater than largest uint128).
       *
       * Counterpart to Solidity's `uint128` operator.
       *
       * Requirements:
       *
       * - input must fit into 128 bits
       */
      function toUint128(uint256 value) internal pure returns (uint128) {
          if (value > type(uint128).max) {
              revert SafeCastOverflowedUintDowncast(128, value);
          }
          return uint128(value);
      }
  
      /**
       * @dev Returns the downcasted uint120 from uint256, reverting on
       * overflow (when the input is greater than largest uint120).
       *
       * Counterpart to Solidity's `uint120` operator.
       *
       * Requirements:
       *
       * - input must fit into 120 bits
       */
      function toUint120(uint256 value) internal pure returns (uint120) {
          if (value > type(uint120).max) {
              revert SafeCastOverflowedUintDowncast(120, value);
          }
          return uint120(value);
      }
  
      /**
       * @dev Returns the downcasted uint112 from uint256, reverting on
       * overflow (when the input is greater than largest uint112).
       *
       * Counterpart to Solidity's `uint112` operator.
       *
       * Requirements:
       *
       * - input must fit into 112 bits
       */
      function toUint112(uint256 value) internal pure returns (uint112) {
          if (value > type(uint112).max) {
              revert SafeCastOverflowedUintDowncast(112, value);
          }
          return uint112(value);
      }
  
      /**
       * @dev Returns the downcasted uint104 from uint256, reverting on
       * overflow (when the input is greater than largest uint104).
       *
       * Counterpart to Solidity's `uint104` operator.
       *
       * Requirements:
       *
       * - input must fit into 104 bits
       */
      function toUint104(uint256 value) internal pure returns (uint104) {
          if (value > type(uint104).max) {
              revert SafeCastOverflowedUintDowncast(104, value);
          }
          return uint104(value);
      }
  
      /**
       * @dev Returns the downcasted uint96 from uint256, reverting on
       * overflow (when the input is greater than largest uint96).
       *
       * Counterpart to Solidity's `uint96` operator.
       *
       * Requirements:
       *
       * - input must fit into 96 bits
       */
      function toUint96(uint256 value) internal pure returns (uint96) {
          if (value > type(uint96).max) {
              revert SafeCastOverflowedUintDowncast(96, value);
          }
          return uint96(value);
      }
  
      /**
       * @dev Returns the downcasted uint88 from uint256, reverting on
       * overflow (when the input is greater than largest uint88).
       *
       * Counterpart to Solidity's `uint88` operator.
       *
       * Requirements:
       *
       * - input must fit into 88 bits
       */
      function toUint88(uint256 value) internal pure returns (uint88) {
          if (value > type(uint88).max) {
              revert SafeCastOverflowedUintDowncast(88, value);
          }
          return uint88(value);
      }
  
      /**
       * @dev Returns the downcasted uint80 from uint256, reverting on
       * overflow (when the input is greater than largest uint80).
       *
       * Counterpart to Solidity's `uint80` operator.
       *
       * Requirements:
       *
       * - input must fit into 80 bits
       */
      function toUint80(uint256 value) internal pure returns (uint80) {
          if (value > type(uint80).max) {
              revert SafeCastOverflowedUintDowncast(80, value);
          }
          return uint80(value);
      }
  
      /**
       * @dev Returns the downcasted uint72 from uint256, reverting on
       * overflow (when the input is greater than largest uint72).
       *
       * Counterpart to Solidity's `uint72` operator.
       *
       * Requirements:
       *
       * - input must fit into 72 bits
       */
      function toUint72(uint256 value) internal pure returns (uint72) {
          if (value > type(uint72).max) {
              revert SafeCastOverflowedUintDowncast(72, value);
          }
          return uint72(value);
      }
  
      /**
       * @dev Returns the downcasted uint64 from uint256, reverting on
       * overflow (when the input is greater than largest uint64).
       *
       * Counterpart to Solidity's `uint64` operator.
       *
       * Requirements:
       *
       * - input must fit into 64 bits
       */
      function toUint64(uint256 value) internal pure returns (uint64) {
          if (value > type(uint64).max) {
              revert SafeCastOverflowedUintDowncast(64, value);
          }
          return uint64(value);
      }
  
      /**
       * @dev Returns the downcasted uint56 from uint256, reverting on
       * overflow (when the input is greater than largest uint56).
       *
       * Counterpart to Solidity's `uint56` operator.
       *
       * Requirements:
       *
       * - input must fit into 56 bits
       */
      function toUint56(uint256 value) internal pure returns (uint56) {
          if (value > type(uint56).max) {
              revert SafeCastOverflowedUintDowncast(56, value);
          }
          return uint56(value);
      }
  
      /**
       * @dev Returns the downcasted uint48 from uint256, reverting on
       * overflow (when the input is greater than largest uint48).
       *
       * Counterpart to Solidity's `uint48` operator.
       *
       * Requirements:
       *
       * - input must fit into 48 bits
       */
      function toUint48(uint256 value) internal pure returns (uint48) {
          if (value > type(uint48).max) {
              revert SafeCastOverflowedUintDowncast(48, value);
          }
          return uint48(value);
      }
  
      /**
       * @dev Returns the downcasted uint40 from uint256, reverting on
       * overflow (when the input is greater than largest uint40).
       *
       * Counterpart to Solidity's `uint40` operator.
       *
       * Requirements:
       *
       * - input must fit into 40 bits
       */
      function toUint40(uint256 value) internal pure returns (uint40) {
          if (value > type(uint40).max) {
              revert SafeCastOverflowedUintDowncast(40, value);
          }
          return uint40(value);
      }
  
      /**
       * @dev Returns the downcasted uint32 from uint256, reverting on
       * overflow (when the input is greater than largest uint32).
       *
       * Counterpart to Solidity's `uint32` operator.
       *
       * Requirements:
       *
       * - input must fit into 32 bits
       */
      function toUint32(uint256 value) internal pure returns (uint32) {
          if (value > type(uint32).max) {
              revert SafeCastOverflowedUintDowncast(32, value);
          }
          return uint32(value);
      }
  
      /**
       * @dev Returns the downcasted uint24 from uint256, reverting on
       * overflow (when the input is greater than largest uint24).
       *
       * Counterpart to Solidity's `uint24` operator.
       *
       * Requirements:
       *
       * - input must fit into 24 bits
       */
      function toUint24(uint256 value) internal pure returns (uint24) {
          if (value > type(uint24).max) {
              revert SafeCastOverflowedUintDowncast(24, value);
          }
          return uint24(value);
      }
  
      /**
       * @dev Returns the downcasted uint16 from uint256, reverting on
       * overflow (when the input is greater than largest uint16).
       *
       * Counterpart to Solidity's `uint16` operator.
       *
       * Requirements:
       *
       * - input must fit into 16 bits
       */
      function toUint16(uint256 value) internal pure returns (uint16) {
          if (value > type(uint16).max) {
              revert SafeCastOverflowedUintDowncast(16, value);
          }
          return uint16(value);
      }
  
      /**
       * @dev Returns the downcasted uint8 from uint256, reverting on
       * overflow (when the input is greater than largest uint8).
       *
       * Counterpart to Solidity's `uint8` operator.
       *
       * Requirements:
       *
       * - input must fit into 8 bits
       */
      function toUint8(uint256 value) internal pure returns (uint8) {
          if (value > type(uint8).max) {
              revert SafeCastOverflowedUintDowncast(8, value);
          }
          return uint8(value);
      }
  
      /**
       * @dev Converts a signed int256 into an unsigned uint256.
       *
       * Requirements:
       *
       * - input must be greater than or equal to 0.
       */
      function toUint256(int256 value) internal pure returns (uint256) {
          if (value < 0) {
              revert SafeCastOverflowedIntToUint(value);
          }
          return uint256(value);
      }
  
      /**
       * @dev Returns the downcasted int248 from int256, reverting on
       * overflow (when the input is less than smallest int248 or
       * greater than largest int248).
       *
       * Counterpart to Solidity's `int248` operator.
       *
       * Requirements:
       *
       * - input must fit into 248 bits
       */
      function toInt248(int256 value) internal pure returns (int248 downcasted) {
          downcasted = int248(value);
          if (downcasted != value) {
              revert SafeCastOverflowedIntDowncast(248, value);
          }
      }
  
      /**
       * @dev Returns the downcasted int240 from int256, reverting on
       * overflow (when the input is less than smallest int240 or
       * greater than largest int240).
       *
       * Counterpart to Solidity's `int240` operator.
       *
       * Requirements:
       *
       * - input must fit into 240 bits
       */
      function toInt240(int256 value) internal pure returns (int240 downcasted) {
          downcasted = int240(value);
          if (downcasted != value) {
              revert SafeCastOverflowedIntDowncast(240, value);
          }
      }
  
      /**
       * @dev Returns the downcasted int232 from int256, reverting on
       * overflow (when the input is less than smallest int232 or
       * greater than largest int232).
       *
       * Counterpart to Solidity's `int232` operator.
       *
       * Requirements:
       *
       * - input must fit into 232 bits
       */
      function toInt232(int256 value) internal pure returns (int232 downcasted) {
          downcasted = int232(value);
          if (downcasted != value) {
              revert SafeCastOverflowedIntDowncast(232, value);
          }
      }
  
      /**
       * @dev Returns the downcasted int224 from int256, reverting on
       * overflow (when the input is less than smallest int224 or
       * greater than largest int224).
       *
       * Counterpart to Solidity's `int224` operator.
       *
       * Requirements:
       *
       * - input must fit into 224 bits
       */
      function toInt224(int256 value) internal pure returns (int224 downcasted) {
          downcasted = int224(value);
          if (downcasted != value) {
              revert SafeCastOverflowedIntDowncast(224, value);
          }
      }
  
      /**
       * @dev Returns the downcasted int216 from int256, reverting on
       * overflow (when the input is less than smallest int216 or
       * greater than largest int216).
       *
       * Counterpart to Solidity's `int216` operator.
       *
       * Requirements:
       *
       * - input must fit into 216 bits
       */
      function toInt216(int256 value) internal pure returns (int216 downcasted) {
          downcasted = int216(value);
          if (downcasted != value) {
              revert SafeCastOverflowedIntDowncast(216, value);
          }
      }
  
      /**
       * @dev Returns the downcasted int208 from int256, reverting on
       * overflow (when the input is less than smallest int208 or
       * greater than largest int208).
       *
       * Counterpart to Solidity's `int208` operator.
       *
       * Requirements:
       *
       * - input must fit into 208 bits
       */
      function toInt208(int256 value) internal pure returns (int208 downcasted) {
          downcasted = int208(value);
          if (downcasted != value) {
              revert SafeCastOverflowedIntDowncast(208, value);
          }
      }
  
      /**
       * @dev Returns the downcasted int200 from int256, reverting on
       * overflow (when the input is less than smallest int200 or
       * greater than largest int200).
       *
       * Counterpart to Solidity's `int200` operator.
       *
       * Requirements:
       *
       * - input must fit into 200 bits
       */
      function toInt200(int256 value) internal pure returns (int200 downcasted) {
          downcasted = int200(value);
          if (downcasted != value) {
              revert SafeCastOverflowedIntDowncast(200, value);
          }
      }
  
      /**
       * @dev Returns the downcasted int192 from int256, reverting on
       * overflow (when the input is less than smallest int192 or
       * greater than largest int192).
       *
       * Counterpart to Solidity's `int192` operator.
       *
       * Requirements:
       *
       * - input must fit into 192 bits
       */
      function toInt192(int256 value) internal pure returns (int192 downcasted) {
          downcasted = int192(value);
          if (downcasted != value) {
              revert SafeCastOverflowedIntDowncast(192, value);
          }
      }
  
      /**
       * @dev Returns the downcasted int184 from int256, reverting on
       * overflow (when the input is less than smallest int184 or
       * greater than largest int184).
       *
       * Counterpart to Solidity's `int184` operator.
       *
       * Requirements:
       *
       * - input must fit into 184 bits
       */
      function toInt184(int256 value) internal pure returns (int184 downcasted) {
          downcasted = int184(value);
          if (downcasted != value) {
              revert SafeCastOverflowedIntDowncast(184, value);
          }
      }
  
      /**
       * @dev Returns the downcasted int176 from int256, reverting on
       * overflow (when the input is less than smallest int176 or
       * greater than largest int176).
       *
       * Counterpart to Solidity's `int176` operator.
       *
       * Requirements:
       *
       * - input must fit into 176 bits
       */
      function toInt176(int256 value) internal pure returns (int176 downcasted) {
          downcasted = int176(value);
          if (downcasted != value) {
              revert SafeCastOverflowedIntDowncast(176, value);
          }
      }
  
      /**
       * @dev Returns the downcasted int168 from int256, reverting on
       * overflow (when the input is less than smallest int168 or
       * greater than largest int168).
       *
       * Counterpart to Solidity's `int168` operator.
       *
       * Requirements:
       *
       * - input must fit into 168 bits
       */
      function toInt168(int256 value) internal pure returns (int168 downcasted) {
          downcasted = int168(value);
          if (downcasted != value) {
              revert SafeCastOverflowedIntDowncast(168, value);
          }
      }
  
      /**
       * @dev Returns the downcasted int160 from int256, reverting on
       * overflow (when the input is less than smallest int160 or
       * greater than largest int160).
       *
       * Counterpart to Solidity's `int160` operator.
       *
       * Requirements:
       *
       * - input must fit into 160 bits
       */
      function toInt160(int256 value) internal pure returns (int160 downcasted) {
          downcasted = int160(value);
          if (downcasted != value) {
              revert SafeCastOverflowedIntDowncast(160, value);
          }
      }
  
      /**
       * @dev Returns the downcasted int152 from int256, reverting on
       * overflow (when the input is less than smallest int152 or
       * greater than largest int152).
       *
       * Counterpart to Solidity's `int152` operator.
       *
       * Requirements:
       *
       * - input must fit into 152 bits
       */
      function toInt152(int256 value) internal pure returns (int152 downcasted) {
          downcasted = int152(value);
          if (downcasted != value) {
              revert SafeCastOverflowedIntDowncast(152, value);
          }
      }
  
      /**
       * @dev Returns the downcasted int144 from int256, reverting on
       * overflow (when the input is less than smallest int144 or
       * greater than largest int144).
       *
       * Counterpart to Solidity's `int144` operator.
       *
       * Requirements:
       *
       * - input must fit into 144 bits
       */
      function toInt144(int256 value) internal pure returns (int144 downcasted) {
          downcasted = int144(value);
          if (downcasted != value) {
              revert SafeCastOverflowedIntDowncast(144, value);
          }
      }
  
      /**
       * @dev Returns the downcasted int136 from int256, reverting on
       * overflow (when the input is less than smallest int136 or
       * greater than largest int136).
       *
       * Counterpart to Solidity's `int136` operator.
       *
       * Requirements:
       *
       * - input must fit into 136 bits
       */
      function toInt136(int256 value) internal pure returns (int136 downcasted) {
          downcasted = int136(value);
          if (downcasted != value) {
              revert SafeCastOverflowedIntDowncast(136, value);
          }
      }
  
      /**
       * @dev Returns the downcasted int128 from int256, reverting on
       * overflow (when the input is less than smallest int128 or
       * greater than largest int128).
       *
       * Counterpart to Solidity's `int128` operator.
       *
       * Requirements:
       *
       * - input must fit into 128 bits
       */
      function toInt128(int256 value) internal pure returns (int128 downcasted) {
          downcasted = int128(value);
          if (downcasted != value) {
              revert SafeCastOverflowedIntDowncast(128, value);
          }
      }
  
      /**
       * @dev Returns the downcasted int120 from int256, reverting on
       * overflow (when the input is less than smallest int120 or
       * greater than largest int120).
       *
       * Counterpart to Solidity's `int120` operator.
       *
       * Requirements:
       *
       * - input must fit into 120 bits
       */
      function toInt120(int256 value) internal pure returns (int120 downcasted) {
          downcasted = int120(value);
          if (downcasted != value) {
              revert SafeCastOverflowedIntDowncast(120, value);
          }
      }
  
      /**
       * @dev Returns the downcasted int112 from int256, reverting on
       * overflow (when the input is less than smallest int112 or
       * greater than largest int112).
       *
       * Counterpart to Solidity's `int112` operator.
       *
       * Requirements:
       *
       * - input must fit into 112 bits
       */
      function toInt112(int256 value) internal pure returns (int112 downcasted) {
          downcasted = int112(value);
          if (downcasted != value) {
              revert SafeCastOverflowedIntDowncast(112, value);
          }
      }
  
      /**
       * @dev Returns the downcasted int104 from int256, reverting on
       * overflow (when the input is less than smallest int104 or
       * greater than largest int104).
       *
       * Counterpart to Solidity's `int104` operator.
       *
       * Requirements:
       *
       * - input must fit into 104 bits
       */
      function toInt104(int256 value) internal pure returns (int104 downcasted) {
          downcasted = int104(value);
          if (downcasted != value) {
              revert SafeCastOverflowedIntDowncast(104, value);
          }
      }
  
      /**
       * @dev Returns the downcasted int96 from int256, reverting on
       * overflow (when the input is less than smallest int96 or
       * greater than largest int96).
       *
       * Counterpart to Solidity's `int96` operator.
       *
       * Requirements:
       *
       * - input must fit into 96 bits
       */
      function toInt96(int256 value) internal pure returns (int96 downcasted) {
          downcasted = int96(value);
          if (downcasted != value) {
              revert SafeCastOverflowedIntDowncast(96, value);
          }
      }
  
      /**
       * @dev Returns the downcasted int88 from int256, reverting on
       * overflow (when the input is less than smallest int88 or
       * greater than largest int88).
       *
       * Counterpart to Solidity's `int88` operator.
       *
       * Requirements:
       *
       * - input must fit into 88 bits
       */
      function toInt88(int256 value) internal pure returns (int88 downcasted) {
          downcasted = int88(value);
          if (downcasted != value) {
              revert SafeCastOverflowedIntDowncast(88, value);
          }
      }
  
      /**
       * @dev Returns the downcasted int80 from int256, reverting on
       * overflow (when the input is less than smallest int80 or
       * greater than largest int80).
       *
       * Counterpart to Solidity's `int80` operator.
       *
       * Requirements:
       *
       * - input must fit into 80 bits
       */
      function toInt80(int256 value) internal pure returns (int80 downcasted) {
          downcasted = int80(value);
          if (downcasted != value) {
              revert SafeCastOverflowedIntDowncast(80, value);
          }
      }
  
      /**
       * @dev Returns the downcasted int72 from int256, reverting on
       * overflow (when the input is less than smallest int72 or
       * greater than largest int72).
       *
       * Counterpart to Solidity's `int72` operator.
       *
       * Requirements:
       *
       * - input must fit into 72 bits
       */
      function toInt72(int256 value) internal pure returns (int72 downcasted) {
          downcasted = int72(value);
          if (downcasted != value) {
              revert SafeCastOverflowedIntDowncast(72, value);
          }
      }
  
      /**
       * @dev Returns the downcasted int64 from int256, reverting on
       * overflow (when the input is less than smallest int64 or
       * greater than largest int64).
       *
       * Counterpart to Solidity's `int64` operator.
       *
       * Requirements:
       *
       * - input must fit into 64 bits
       */
      function toInt64(int256 value) internal pure returns (int64 downcasted) {
          downcasted = int64(value);
          if (downcasted != value) {
              revert SafeCastOverflowedIntDowncast(64, value);
          }
      }
  
      /**
       * @dev Returns the downcasted int56 from int256, reverting on
       * overflow (when the input is less than smallest int56 or
       * greater than largest int56).
       *
       * Counterpart to Solidity's `int56` operator.
       *
       * Requirements:
       *
       * - input must fit into 56 bits
       */
      function toInt56(int256 value) internal pure returns (int56 downcasted) {
          downcasted = int56(value);
          if (downcasted != value) {
              revert SafeCastOverflowedIntDowncast(56, value);
          }
      }
  
      /**
       * @dev Returns the downcasted int48 from int256, reverting on
       * overflow (when the input is less than smallest int48 or
       * greater than largest int48).
       *
       * Counterpart to Solidity's `int48` operator.
       *
       * Requirements:
       *
       * - input must fit into 48 bits
       */
      function toInt48(int256 value) internal pure returns (int48 downcasted) {
          downcasted = int48(value);
          if (downcasted != value) {
              revert SafeCastOverflowedIntDowncast(48, value);
          }
      }
  
      /**
       * @dev Returns the downcasted int40 from int256, reverting on
       * overflow (when the input is less than smallest int40 or
       * greater than largest int40).
       *
       * Counterpart to Solidity's `int40` operator.
       *
       * Requirements:
       *
       * - input must fit into 40 bits
       */
      function toInt40(int256 value) internal pure returns (int40 downcasted) {
          downcasted = int40(value);
          if (downcasted != value) {
              revert SafeCastOverflowedIntDowncast(40, value);
          }
      }
  
      /**
       * @dev Returns the downcasted int32 from int256, reverting on
       * overflow (when the input is less than smallest int32 or
       * greater than largest int32).
       *
       * Counterpart to Solidity's `int32` operator.
       *
       * Requirements:
       *
       * - input must fit into 32 bits
       */
      function toInt32(int256 value) internal pure returns (int32 downcasted) {
          downcasted = int32(value);
          if (downcasted != value) {
              revert SafeCastOverflowedIntDowncast(32, value);
          }
      }
  
      /**
       * @dev Returns the downcasted int24 from int256, reverting on
       * overflow (when the input is less than smallest int24 or
       * greater than largest int24).
       *
       * Counterpart to Solidity's `int24` operator.
       *
       * Requirements:
       *
       * - input must fit into 24 bits
       */
      function toInt24(int256 value) internal pure returns (int24 downcasted) {
          downcasted = int24(value);
          if (downcasted != value) {
              revert SafeCastOverflowedIntDowncast(24, value);
          }
      }
  
      /**
       * @dev Returns the downcasted int16 from int256, reverting on
       * overflow (when the input is less than smallest int16 or
       * greater than largest int16).
       *
       * Counterpart to Solidity's `int16` operator.
       *
       * Requirements:
       *
       * - input must fit into 16 bits
       */
      function toInt16(int256 value) internal pure returns (int16 downcasted) {
          downcasted = int16(value);
          if (downcasted != value) {
              revert SafeCastOverflowedIntDowncast(16, value);
          }
      }
  
      /**
       * @dev Returns the downcasted int8 from int256, reverting on
       * overflow (when the input is less than smallest int8 or
       * greater than largest int8).
       *
       * Counterpart to Solidity's `int8` operator.
       *
       * Requirements:
       *
       * - input must fit into 8 bits
       */
      function toInt8(int256 value) internal pure returns (int8 downcasted) {
          downcasted = int8(value);
          if (downcasted != value) {
              revert SafeCastOverflowedIntDowncast(8, value);
          }
      }
  
      /**
       * @dev Converts an unsigned uint256 into a signed int256.
       *
       * Requirements:
       *
       * - input must be less than or equal to maxInt256.
       */
      function toInt256(uint256 value) internal pure returns (int256) {
          // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive
          if (value > uint256(type(int256).max)) {
              revert SafeCastOverflowedUintToInt(value);
          }
          return int256(value);
      }
  
      /**
       * @dev Cast a boolean (false or true) to a uint256 (0 or 1) with no jump.
       */
      function toUint(bool b) internal pure returns (uint256 u) {
          assembly ("memory-safe") {
              u := iszero(iszero(b))
          }
      }
  }
  
  
  // File @openzeppelin/contracts/utils/Panic.sol@v5.1.0
  
  // Original license: SPDX_License_Identifier: MIT
  // OpenZeppelin Contracts (last updated v5.1.0) (utils/Panic.sol)
  
  pragma solidity ^0.8.20;
  
  /**
   * @dev Helper library for emitting standardized panic codes.
   *
   * ```solidity
   * contract Example {
   *      using Panic for uint256;
   *
   *      // Use any of the declared internal constants
   *      function foo() { Panic.GENERIC.panic(); }
   *
   *      // Alternatively
   *      function foo() { Panic.panic(Panic.GENERIC); }
   * }
   * ```
   *
   * Follows the list from https://github.com/ethereum/solidity/blob/v0.8.24/libsolutil/ErrorCodes.h[libsolutil].
   *
   * _Available since v5.1._
   */
  // slither-disable-next-line unused-state
  library Panic {
      /// @dev generic / unspecified error
      uint256 internal constant GENERIC = 0x00;
      /// @dev used by the assert() builtin
      uint256 internal constant ASSERT = 0x01;
      /// @dev arithmetic underflow or overflow
      uint256 internal constant UNDER_OVERFLOW = 0x11;
      /// @dev division or modulo by zero
      uint256 internal constant DIVISION_BY_ZERO = 0x12;
      /// @dev enum conversion error
      uint256 internal constant ENUM_CONVERSION_ERROR = 0x21;
      /// @dev invalid encoding in storage
      uint256 internal constant STORAGE_ENCODING_ERROR = 0x22;
      /// @dev empty array pop
      uint256 internal constant EMPTY_ARRAY_POP = 0x31;
      /// @dev array out of bounds access
      uint256 internal constant ARRAY_OUT_OF_BOUNDS = 0x32;
      /// @dev resource error (too large allocation or too large array)
      uint256 internal constant RESOURCE_ERROR = 0x41;
      /// @dev calling invalid internal function
      uint256 internal constant INVALID_INTERNAL_FUNCTION = 0x51;
  
      /// @dev Reverts with a panic code. Recommended to use with
      /// the internal constants with predefined codes.
      function panic(uint256 code) internal pure {
          assembly ("memory-safe") {
              mstore(0x00, 0x4e487b71)
              mstore(0x20, code)
              revert(0x1c, 0x24)
          }
      }
  }
  
  
  // File @openzeppelin/contracts/utils/math/Math.sol@v5.1.0
  
  // Original license: SPDX_License_Identifier: MIT
  // OpenZeppelin Contracts (last updated v5.1.0) (utils/math/Math.sol)
  
  pragma solidity ^0.8.20;
  
  
  /**
   * @dev Standard math utilities missing in the Solidity language.
   */
  library Math {
      enum Rounding {
          Floor, // Toward negative infinity
          Ceil, // Toward positive infinity
          Trunc, // Toward zero
          Expand // Away from zero
      }
  
      /**
       * @dev Returns the addition of two unsigned integers, with an success flag (no overflow).
       */
      function tryAdd(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {
          unchecked {
              uint256 c = a + b;
              if (c < a) return (false, 0);
              return (true, c);
          }
      }
  
      /**
       * @dev Returns the subtraction of two unsigned integers, with an success flag (no overflow).
       */
      function trySub(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {
          unchecked {
              if (b > a) return (false, 0);
              return (true, a - b);
          }
      }
  
      /**
       * @dev Returns the multiplication of two unsigned integers, with an success flag (no overflow).
       */
      function tryMul(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {
          unchecked {
              // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
              // benefit is lost if 'b' is also tested.
              // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
              if (a == 0) return (true, 0);
              uint256 c = a * b;
              if (c / a != b) return (false, 0);
              return (true, c);
          }
      }
  
      /**
       * @dev Returns the division of two unsigned integers, with a success flag (no division by zero).
       */
      function tryDiv(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {
          unchecked {
              if (b == 0) return (false, 0);
              return (true, a / b);
          }
      }
  
      /**
       * @dev Returns the remainder of dividing two unsigned integers, with a success flag (no division by zero).
       */
      function tryMod(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {
          unchecked {
              if (b == 0) return (false, 0);
              return (true, a % b);
          }
      }
  
      /**
       * @dev Branchless ternary evaluation for `a ? b : c`. Gas costs are constant.
       *
       * IMPORTANT: This function may reduce bytecode size and consume less gas when used standalone.
       * However, the compiler may optimize Solidity ternary operations (i.e. `a ? b : c`) to only compute
       * one branch when needed, making this function more expensive.
       */
      function ternary(bool condition, uint256 a, uint256 b) internal pure returns (uint256) {
          unchecked {
              // branchless ternary works because:
              // b ^ (a ^ b) == a
              // b ^ 0 == b
              return b ^ ((a ^ b) * SafeCast.toUint(condition));
          }
      }
  
      /**
       * @dev Returns the largest of two numbers.
       */
      function max(uint256 a, uint256 b) internal pure returns (uint256) {
          return ternary(a > b, a, b);
      }
  
      /**
       * @dev Returns the smallest of two numbers.
       */
      function min(uint256 a, uint256 b) internal pure returns (uint256) {
          return ternary(a < b, a, b);
      }
  
      /**
       * @dev Returns the average of two numbers. The result is rounded towards
       * zero.
       */
      function average(uint256 a, uint256 b) internal pure returns (uint256) {
          // (a + b) / 2 can overflow.
          return (a & b) + (a ^ b) / 2;
      }
  
      /**
       * @dev Returns the ceiling of the division of two numbers.
       *
       * This differs from standard division with `/` in that it rounds towards infinity instead
       * of rounding towards zero.
       */
      function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
          if (b == 0) {
              // Guarantee the same behavior as in a regular Solidity division.
              Panic.panic(Panic.DIVISION_BY_ZERO);
          }
  
          // The following calculation ensures accurate ceiling division without overflow.
          // Since a is non-zero, (a - 1) / b will not overflow.
          // The largest possible result occurs when (a - 1) / b is type(uint256).max,
          // but the largest value we can obtain is type(uint256).max - 1, which happens
          // when a = type(uint256).max and b = 1.
          unchecked {
              return SafeCast.toUint(a > 0) * ((a - 1) / b + 1);
          }
      }
  
      /**
       * @dev Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or
       * denominator == 0.
       *
       * Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) with further edits by
       * Uniswap Labs also under MIT license.
       */
      function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {
          unchecked {
              // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2²⁵⁶ and mod 2²⁵⁶ - 1, then use
              // the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
              // variables such that product = prod1 * 2²⁵⁶ + prod0.
              uint256 prod0 = x * y; // Least significant 256 bits of the product
              uint256 prod1; // Most significant 256 bits of the product
              assembly {
                  let mm := mulmod(x, y, not(0))
                  prod1 := sub(sub(mm, prod0), lt(mm, prod0))
              }
  
              // Handle non-overflow cases, 256 by 256 division.
              if (prod1 == 0) {
                  // Solidity will revert if denominator == 0, unlike the div opcode on its own.
                  // The surrounding unchecked block does not change this fact.
                  // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.
                  return prod0 / denominator;
              }
  
              // Make sure the result is less than 2²⁵⁶. Also prevents denominator == 0.
              if (denominator <= prod1) {
                  Panic.panic(ternary(denominator == 0, Panic.DIVISION_BY_ZERO, Panic.UNDER_OVERFLOW));
              }
  
              ///////////////////////////////////////////////
              // 512 by 256 division.
              ///////////////////////////////////////////////
  
              // Make division exact by subtracting the remainder from [prod1 prod0].
              uint256 remainder;
              assembly {
                  // Compute remainder using mulmod.
                  remainder := mulmod(x, y, denominator)
  
                  // Subtract 256 bit number from 512 bit number.
                  prod1 := sub(prod1, gt(remainder, prod0))
                  prod0 := sub(prod0, remainder)
              }
  
              // Factor powers of two out of denominator and compute largest power of two divisor of denominator.
              // Always >= 1. See https://cs.stackexchange.com/q/138556/92363.
  
              uint256 twos = denominator & (0 - denominator);
              assembly {
                  // Divide denominator by twos.
                  denominator := div(denominator, twos)
  
                  // Divide [prod1 prod0] by twos.
                  prod0 := div(prod0, twos)
  
                  // Flip twos such that it is 2²⁵⁶ / twos. If twos is zero, then it becomes one.
                  twos := add(div(sub(0, twos), twos), 1)
              }
  
              // Shift in bits from prod1 into prod0.
              prod0 |= prod1 * twos;
  
              // Invert denominator mod 2²⁵⁶. Now that denominator is an odd number, it has an inverse modulo 2²⁵⁶ such
              // that denominator * inv ≡ 1 mod 2²⁵⁶. Compute the inverse by starting with a seed that is correct for
              // four bits. That is, denominator * inv ≡ 1 mod 2⁴.
              uint256 inverse = (3 * denominator) ^ 2;
  
              // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also
              // works in modular arithmetic, doubling the correct bits in each step.
              inverse *= 2 - denominator * inverse; // inverse mod 2⁸
              inverse *= 2 - denominator * inverse; // inverse mod 2¹⁶
              inverse *= 2 - denominator * inverse; // inverse mod 2³²
              inverse *= 2 - denominator * inverse; // inverse mod 2⁶⁴
              inverse *= 2 - denominator * inverse; // inverse mod 2¹²⁸
              inverse *= 2 - denominator * inverse; // inverse mod 2²⁵⁶
  
              // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
              // This will give us the correct result modulo 2²⁵⁶. Since the preconditions guarantee that the outcome is
              // less than 2²⁵⁶, this is the final result. We don't need to compute the high bits of the result and prod1
              // is no longer required.
              result = prod0 * inverse;
              return result;
          }
      }
  
      /**
       * @dev Calculates x * y / denominator with full precision, following the selected rounding direction.
       */
      function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {
          return mulDiv(x, y, denominator) + SafeCast.toUint(unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0);
      }
  
      /**
       * @dev Calculate the modular multiplicative inverse of a number in Z/nZ.
       *
       * If n is a prime, then Z/nZ is a field. In that case all elements are inversible, except 0.
       * If n is not a prime, then Z/nZ is not a field, and some elements might not be inversible.
       *
       * If the input value is not inversible, 0 is returned.
       *
       * NOTE: If you know for sure that n is (big) a prime, it may be cheaper to use Fermat's little theorem and get the
       * inverse using `Math.modExp(a, n - 2, n)`. See {invModPrime}.
       */
      function invMod(uint256 a, uint256 n) internal pure returns (uint256) {
          unchecked {
              if (n == 0) return 0;
  
              // The inverse modulo is calculated using the Extended Euclidean Algorithm (iterative version)
              // Used to compute integers x and y such that: ax + ny = gcd(a, n).
              // When the gcd is 1, then the inverse of a modulo n exists and it's x.
              // ax + ny = 1
              // ax = 1 + (-y)n
              // ax ≡ 1 (mod n) # x is the inverse of a modulo n
  
              // If the remainder is 0 the gcd is n right away.
              uint256 remainder = a % n;
              uint256 gcd = n;
  
              // Therefore the initial coefficients are:
              // ax + ny = gcd(a, n) = n
              // 0a + 1n = n
              int256 x = 0;
              int256 y = 1;
  
              while (remainder != 0) {
                  uint256 quotient = gcd / remainder;
  
                  (gcd, remainder) = (
                      // The old remainder is the next gcd to try.
                      remainder,
                      // Compute the next remainder.
                      // Can't overflow given that (a % gcd) * (gcd // (a % gcd)) <= gcd
                      // where gcd is at most n (capped to type(uint256).max)
                      gcd - remainder * quotient
                  );
  
                  (x, y) = (
                      // Increment the coefficient of a.
                      y,
                      // Decrement the coefficient of n.
                      // Can overflow, but the result is casted to uint256 so that the
                      // next value of y is "wrapped around" to a value between 0 and n - 1.
                      x - y * int256(quotient)
                  );
              }
  
              if (gcd != 1) return 0; // No inverse exists.
              return ternary(x < 0, n - uint256(-x), uint256(x)); // Wrap the result if it's negative.
          }
      }
  
      /**
       * @dev Variant of {invMod}. More efficient, but only works if `p` is known to be a prime greater than `2`.
       *
       * From https://en.wikipedia.org/wiki/Fermat%27s_little_theorem[Fermat's little theorem], we know that if p is
       * prime, then `a**(p-1) ≡ 1 mod p`. As a consequence, we have `a * a**(p-2) ≡ 1 mod p`, which means that
       * `a**(p-2)` is the modular multiplicative inverse of a in Fp.
       *
       * NOTE: this function does NOT check that `p` is a prime greater than `2`.
       */
      function invModPrime(uint256 a, uint256 p) internal view returns (uint256) {
          unchecked {
              return Math.modExp(a, p - 2, p);
          }
      }
  
      /**
       * @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m)
       *
       * Requirements:
       * - modulus can't be zero
       * - underlying staticcall to precompile must succeed
       *
       * IMPORTANT: The result is only valid if the underlying call succeeds. When using this function, make
       * sure the chain you're using it on supports the precompiled contract for modular exponentiation
       * at address 0x05 as specified in https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise,
       * the underlying function will succeed given the lack of a revert, but the result may be incorrectly
       * interpreted as 0.
       */
      function modExp(uint256 b, uint256 e, uint256 m) internal view returns (uint256) {
          (bool success, uint256 result) = tryModExp(b, e, m);
          if (!success) {
              Panic.panic(Panic.DIVISION_BY_ZERO);
          }
          return result;
      }
  
      /**
       * @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m).
       * It includes a success flag indicating if the operation succeeded. Operation will be marked as failed if trying
       * to operate modulo 0 or if the underlying precompile reverted.
       *
       * IMPORTANT: The result is only valid if the success flag is true. When using this function, make sure the chain
       * you're using it on supports the precompiled contract for modular exponentiation at address 0x05 as specified in
       * https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise, the underlying function will succeed given the lack
       * of a revert, but the result may be incorrectly interpreted as 0.
       */
      function tryModExp(uint256 b, uint256 e, uint256 m) internal view returns (bool success, uint256 result) {
          if (m == 0) return (false, 0);
          assembly ("memory-safe") {
              let ptr := mload(0x40)
              // | Offset    | Content    | Content (Hex)                                                      |
              // |-----------|------------|--------------------------------------------------------------------|
              // | 0x00:0x1f | size of b  | 0x0000000000000000000000000000000000000000000000000000000000000020 |
              // | 0x20:0x3f | size of e  | 0x0000000000000000000000000000000000000000000000000000000000000020 |
              // | 0x40:0x5f | size of m  | 0x0000000000000000000000000000000000000000000000000000000000000020 |
              // | 0x60:0x7f | value of b | 0x<.............................................................b> |
              // | 0x80:0x9f | value of e | 0x<.............................................................e> |
              // | 0xa0:0xbf | value of m | 0x<.............................................................m> |
              mstore(ptr, 0x20)
              mstore(add(ptr, 0x20), 0x20)
              mstore(add(ptr, 0x40), 0x20)
              mstore(add(ptr, 0x60), b)
              mstore(add(ptr, 0x80), e)
              mstore(add(ptr, 0xa0), m)
  
              // Given the result < m, it's guaranteed to fit in 32 bytes,
              // so we can use the memory scratch space located at offset 0.
              success := staticcall(gas(), 0x05, ptr, 0xc0, 0x00, 0x20)
              result := mload(0x00)
          }
      }
  
      /**
       * @dev Variant of {modExp} that supports inputs of arbitrary length.
       */
      function modExp(bytes memory b, bytes memory e, bytes memory m) internal view returns (bytes memory) {
          (bool success, bytes memory result) = tryModExp(b, e, m);
          if (!success) {
              Panic.panic(Panic.DIVISION_BY_ZERO);
          }
          return result;
      }
  
      /**
       * @dev Variant of {tryModExp} that supports inputs of arbitrary length.
       */
      function tryModExp(
          bytes memory b,
          bytes memory e,
          bytes memory m
      ) internal view returns (bool success, bytes memory result) {
          if (_zeroBytes(m)) return (false, new bytes(0));
  
          uint256 mLen = m.length;
  
          // Encode call args in result and move the free memory pointer
          result = abi.encodePacked(b.length, e.length, mLen, b, e, m);
  
          assembly ("memory-safe") {
              let dataPtr := add(result, 0x20)
              // Write result on top of args to avoid allocating extra memory.
              success := staticcall(gas(), 0x05, dataPtr, mload(result), dataPtr, mLen)
              // Overwrite the length.
              // result.length > returndatasize() is guaranteed because returndatasize() == m.length
              mstore(result, mLen)
              // Set the memory pointer after the returned data.
              mstore(0x40, add(dataPtr, mLen))
          }
      }
  
      /**
       * @dev Returns whether the provided byte array is zero.
       */
      function _zeroBytes(bytes memory byteArray) private pure returns (bool) {
          for (uint256 i = 0; i < byteArray.length; ++i) {
              if (byteArray[i] != 0) {
                  return false;
              }
          }
          return true;
      }
  
      /**
       * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded
       * towards zero.
       *
       * This method is based on Newton's method for computing square roots; the algorithm is restricted to only
       * using integer operations.
       */
      function sqrt(uint256 a) internal pure returns (uint256) {
          unchecked {
              // Take care of easy edge cases when a == 0 or a == 1
              if (a <= 1) {
                  return a;
              }
  
              // In this function, we use Newton's method to get a root of `f(x) := x² - a`. It involves building a
              // sequence x_n that converges toward sqrt(a). For each iteration x_n, we also define the error between
              // the current value as `ε_n = | x_n - sqrt(a) |`.
              //
              // For our first estimation, we consider `e` the smallest power of 2 which is bigger than the square root
              // of the target. (i.e. `2**(e-1) ≤ sqrt(a) < 2**e`). We know that `e ≤ 128` because `(2¹²⁸)² = 2²⁵⁶` is
              // bigger than any uint256.
              //
              // By noticing that
              // `2**(e-1) ≤ sqrt(a) < 2**e → (2**(e-1))² ≤ a < (2**e)² → 2**(2*e-2) ≤ a < 2**(2*e)`
              // we can deduce that `e - 1` is `log2(a) / 2`. We can thus compute `x_n = 2**(e-1)` using a method similar
              // to the msb function.
              uint256 aa = a;
              uint256 xn = 1;
  
              if (aa >= (1 << 128)) {
                  aa >>= 128;
                  xn <<= 64;
              }
              if (aa >= (1 << 64)) {
                  aa >>= 64;
                  xn <<= 32;
              }
              if (aa >= (1 << 32)) {
                  aa >>= 32;
                  xn <<= 16;
              }
              if (aa >= (1 << 16)) {
                  aa >>= 16;
                  xn <<= 8;
              }
              if (aa >= (1 << 8)) {
                  aa >>= 8;
                  xn <<= 4;
              }
              if (aa >= (1 << 4)) {
                  aa >>= 4;
                  xn <<= 2;
              }
              if (aa >= (1 << 2)) {
                  xn <<= 1;
              }
  
              // We now have x_n such that `x_n = 2**(e-1) ≤ sqrt(a) < 2**e = 2 * x_n`. This implies ε_n ≤ 2**(e-1).
              //
              // We can refine our estimation by noticing that the middle of that interval minimizes the error.
              // If we move x_n to equal 2**(e-1) + 2**(e-2), then we reduce the error to ε_n ≤ 2**(e-2).
              // This is going to be our x_0 (and ε_0)
              xn = (3 * xn) >> 1; // ε_0 := | x_0 - sqrt(a) | ≤ 2**(e-2)
  
              // From here, Newton's method give us:
              // x_{n+1} = (x_n + a / x_n) / 2
              //
              // One should note that:
              // x_{n+1}² - a = ((x_n + a / x_n) / 2)² - a
              //              = ((x_n² + a) / (2 * x_n))² - a
              //              = (x_n⁴ + 2 * a * x_n² + a²) / (4 * x_n²) - a
              //              = (x_n⁴ + 2 * a * x_n² + a² - 4 * a * x_n²) / (4 * x_n²)
              //              = (x_n⁴ - 2 * a * x_n² + a²) / (4 * x_n²)
              //              = (x_n² - a)² / (2 * x_n)²
              //              = ((x_n² - a) / (2 * x_n))²
              //              ≥ 0
              // Which proves that for all n ≥ 1, sqrt(a) ≤ x_n
              //
              // This gives us the proof of quadratic convergence of the sequence:
              // ε_{n+1} = | x_{n+1} - sqrt(a) |
              //         = | (x_n + a / x_n) / 2 - sqrt(a) |
              //         = | (x_n² + a - 2*x_n*sqrt(a)) / (2 * x_n) |
              //         = | (x_n - sqrt(a))² / (2 * x_n) |
              //         = | ε_n² / (2 * x_n) |
              //         = ε_n² / | (2 * x_n) |
              //
              // For the first iteration, we have a special case where x_0 is known:
              // ε_1 = ε_0² / | (2 * x_0) |
              //     ≤ (2**(e-2))² / (2 * (2**(e-1) + 2**(e-2)))
              //     ≤ 2**(2*e-4) / (3 * 2**(e-1))
              //     ≤ 2**(e-3) / 3
              //     ≤ 2**(e-3-log2(3))
              //     ≤ 2**(e-4.5)
              //
              // For the following iterations, we use the fact that, 2**(e-1) ≤ sqrt(a) ≤ x_n:
              // ε_{n+1} = ε_n² / | (2 * x_n) |
              //         ≤ (2**(e-k))² / (2 * 2**(e-1))
              //         ≤ 2**(2*e-2*k) / 2**e
              //         ≤ 2**(e-2*k)
              xn = (xn + a / xn) >> 1; // ε_1 := | x_1 - sqrt(a) | ≤ 2**(e-4.5)  -- special case, see above
              xn = (xn + a / xn) >> 1; // ε_2 := | x_2 - sqrt(a) | ≤ 2**(e-9)    -- general case with k = 4.5
              xn = (xn + a / xn) >> 1; // ε_3 := | x_3 - sqrt(a) | ≤ 2**(e-18)   -- general case with k = 9
              xn = (xn + a / xn) >> 1; // ε_4 := | x_4 - sqrt(a) | ≤ 2**(e-36)   -- general case with k = 18
              xn = (xn + a / xn) >> 1; // ε_5 := | x_5 - sqrt(a) | ≤ 2**(e-72)   -- general case with k = 36
              xn = (xn + a / xn) >> 1; // ε_6 := | x_6 - sqrt(a) | ≤ 2**(e-144)  -- general case with k = 72
  
              // Because e ≤ 128 (as discussed during the first estimation phase), we know have reached a precision
              // ε_6 ≤ 2**(e-144) < 1. Given we're operating on integers, then we can ensure that xn is now either
              // sqrt(a) or sqrt(a) + 1.
              return xn - SafeCast.toUint(xn > a / xn);
          }
      }
  
      /**
       * @dev Calculates sqrt(a), following the selected rounding direction.
       */
      function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
          unchecked {
              uint256 result = sqrt(a);
              return result + SafeCast.toUint(unsignedRoundsUp(rounding) && result * result < a);
          }
      }
  
      /**
       * @dev Return the log in base 2 of a positive value rounded towards zero.
       * Returns 0 if given 0.
       */
      function log2(uint256 value) internal pure returns (uint256) {
          uint256 result = 0;
          uint256 exp;
          unchecked {
              exp = 128 * SafeCast.toUint(value > (1 << 128) - 1);
              value >>= exp;
              result += exp;
  
              exp = 64 * SafeCast.toUint(value > (1 << 64) - 1);
              value >>= exp;
              result += exp;
  
              exp = 32 * SafeCast.toUint(value > (1 << 32) - 1);
              value >>= exp;
              result += exp;
  
              exp = 16 * SafeCast.toUint(value > (1 << 16) - 1);
              value >>= exp;
              result += exp;
  
              exp = 8 * SafeCast.toUint(value > (1 << 8) - 1);
              value >>= exp;
              result += exp;
  
              exp = 4 * SafeCast.toUint(value > (1 << 4) - 1);
              value >>= exp;
              result += exp;
  
              exp = 2 * SafeCast.toUint(value > (1 << 2) - 1);
              value >>= exp;
              result += exp;
  
              result += SafeCast.toUint(value > 1);
          }
          return result;
      }
  
      /**
       * @dev Return the log in base 2, following the selected rounding direction, of a positive value.
       * Returns 0 if given 0.
       */
      function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
          unchecked {
              uint256 result = log2(value);
              return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << result < value);
          }
      }
  
      /**
       * @dev Return the log in base 10 of a positive value rounded towards zero.
       * Returns 0 if given 0.
       */
      function log10(uint256 value) internal pure returns (uint256) {
          uint256 result = 0;
          unchecked {
              if (value >= 10 ** 64) {
                  value /= 10 ** 64;
                  result += 64;
              }
              if (value >= 10 ** 32) {
                  value /= 10 ** 32;
                  result += 32;
              }
              if (value >= 10 ** 16) {
                  value /= 10 ** 16;
                  result += 16;
              }
              if (value >= 10 ** 8) {
                  value /= 10 ** 8;
                  result += 8;
              }
              if (value >= 10 ** 4) {
                  value /= 10 ** 4;
                  result += 4;
              }
              if (value >= 10 ** 2) {
                  value /= 10 ** 2;
                  result += 2;
              }
              if (value >= 10 ** 1) {
                  result += 1;
              }
          }
          return result;
      }
  
      /**
       * @dev Return the log in base 10, following the selected rounding direction, of a positive value.
       * Returns 0 if given 0.
       */
      function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
          unchecked {
              uint256 result = log10(value);
              return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 10 ** result < value);
          }
      }
  
      /**
       * @dev Return the log in base 256 of a positive value rounded towards zero.
       * Returns 0 if given 0.
       *
       * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
       */
      function log256(uint256 value) internal pure returns (uint256) {
          uint256 result = 0;
          uint256 isGt;
          unchecked {
              isGt = SafeCast.toUint(value > (1 << 128) - 1);
              value >>= isGt * 128;
              result += isGt * 16;
  
              isGt = SafeCast.toUint(value > (1 << 64) - 1);
              value >>= isGt * 64;
              result += isGt * 8;
  
              isGt = SafeCast.toUint(value > (1 << 32) - 1);
              value >>= isGt * 32;
              result += isGt * 4;
  
              isGt = SafeCast.toUint(value > (1 << 16) - 1);
              value >>= isGt * 16;
              result += isGt * 2;
  
              result += SafeCast.toUint(value > (1 << 8) - 1);
          }
          return result;
      }
  
      /**
       * @dev Return the log in base 256, following the selected rounding direction, of a positive value.
       * Returns 0 if given 0.
       */
      function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
          unchecked {
              uint256 result = log256(value);
              return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << (result << 3) < value);
          }
      }
  
      /**
       * @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers.
       */
      function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) {
          return uint8(rounding) % 2 == 1;
      }
  }
  
  
  // File @openzeppelin/contracts/utils/math/SignedMath.sol@v5.1.0
  
  // Original license: SPDX_License_Identifier: MIT
  // OpenZeppelin Contracts (last updated v5.1.0) (utils/math/SignedMath.sol)
  
  pragma solidity ^0.8.20;
  
  /**
   * @dev Standard signed math utilities missing in the Solidity language.
   */
  library SignedMath {
      /**
       * @dev Branchless ternary evaluation for `a ? b : c`. Gas costs are constant.
       *
       * IMPORTANT: This function may reduce bytecode size and consume less gas when used standalone.
       * However, the compiler may optimize Solidity ternary operations (i.e. `a ? b : c`) to only compute
       * one branch when needed, making this function more expensive.
       */
      function ternary(bool condition, int256 a, int256 b) internal pure returns (int256) {
          unchecked {
              // branchless ternary works because:
              // b ^ (a ^ b) == a
              // b ^ 0 == b
              return b ^ ((a ^ b) * int256(SafeCast.toUint(condition)));
          }
      }
  
      /**
       * @dev Returns the largest of two signed numbers.
       */
      function max(int256 a, int256 b) internal pure returns (int256) {
          return ternary(a > b, a, b);
      }
  
      /**
       * @dev Returns the smallest of two signed numbers.
       */
      function min(int256 a, int256 b) internal pure returns (int256) {
          return ternary(a < b, a, b);
      }
  
      /**
       * @dev Returns the average of two signed numbers without overflow.
       * The result is rounded towards zero.
       */
      function average(int256 a, int256 b) internal pure returns (int256) {
          // Formula from the book "Hacker's Delight"
          int256 x = (a & b) + ((a ^ b) >> 1);
          return x + (int256(uint256(x) >> 255) & (a ^ b));
      }
  
      /**
       * @dev Returns the absolute unsigned value of a signed value.
       */
      function abs(int256 n) internal pure returns (uint256) {
          unchecked {
              // Formula from the "Bit Twiddling Hacks" by Sean Eron Anderson.
              // Since `n` is a signed integer, the generated bytecode will use the SAR opcode to perform the right shift,
              // taking advantage of the most significant (or "sign" bit) in two's complement representation.
              // This opcode adds new most significant bits set to the value of the previous most significant bit. As a result,
              // the mask will either be `bytes32(0)` (if n is positive) or `~bytes32(0)` (if n is negative).
              int256 mask = n >> 255;
  
              // A `bytes32(0)` mask leaves the input unchanged, while a `~bytes32(0)` mask complements it.
              return uint256((n + mask) ^ mask);
          }
      }
  }
  
  
  // File @openzeppelin/contracts/utils/Strings.sol@v5.1.0
  
  // Original license: SPDX_License_Identifier: MIT
  // OpenZeppelin Contracts (last updated v5.1.0) (utils/Strings.sol)
  
  pragma solidity ^0.8.20;
  
  
  /**
   * @dev String operations.
   */
  library Strings {
      bytes16 private constant HEX_DIGITS = "0123456789abcdef";
      uint8 private constant ADDRESS_LENGTH = 20;
  
      /**
       * @dev The `value` string doesn't fit in the specified `length`.
       */
      error StringsInsufficientHexLength(uint256 value, uint256 length);
  
      /**
       * @dev Converts a `uint256` to its ASCII `string` decimal representation.
       */
      function toString(uint256 value) internal pure returns (string memory) {
          unchecked {
              uint256 length = Math.log10(value) + 1;
              string memory buffer = new string(length);
              uint256 ptr;
              assembly ("memory-safe") {
                  ptr := add(buffer, add(32, length))
              }
              while (true) {
                  ptr--;
                  assembly ("memory-safe") {
                      mstore8(ptr, byte(mod(value, 10), HEX_DIGITS))
                  }
                  value /= 10;
                  if (value == 0) break;
              }
              return buffer;
          }
      }
  
      /**
       * @dev Converts a `int256` to its ASCII `string` decimal representation.
       */
      function toStringSigned(int256 value) internal pure returns (string memory) {
          return string.concat(value < 0 ? "-" : "", toString(SignedMath.abs(value)));
      }
  
      /**
       * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
       */
      function toHexString(uint256 value) internal pure returns (string memory) {
          unchecked {
              return toHexString(value, Math.log256(value) + 1);
          }
      }
  
      /**
       * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
       */
      function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
          uint256 localValue = value;
          bytes memory buffer = new bytes(2 * length + 2);
          buffer[0] = "0";
          buffer[1] = "x";
          for (uint256 i = 2 * length + 1; i > 1; --i) {
              buffer[i] = HEX_DIGITS[localValue & 0xf];
              localValue >>= 4;
          }
          if (localValue != 0) {
              revert StringsInsufficientHexLength(value, length);
          }
          return string(buffer);
      }
  
      /**
       * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal
       * representation.
       */
      function toHexString(address addr) internal pure returns (string memory) {
          return toHexString(uint256(uint160(addr)), ADDRESS_LENGTH);
      }
  
      /**
       * @dev Converts an `address` with fixed length of 20 bytes to its checksummed ASCII `string` hexadecimal
       * representation, according to EIP-55.
       */
      function toChecksumHexString(address addr) internal pure returns (string memory) {
          bytes memory buffer = bytes(toHexString(addr));
  
          // hash the hex part of buffer (skip length + 2 bytes, length 40)
          uint256 hashValue;
          assembly ("memory-safe") {
              hashValue := shr(96, keccak256(add(buffer, 0x22), 40))
          }
  
          for (uint256 i = 41; i > 1; --i) {
              // possible values for buffer[i] are 48 (0) to 57 (9) and 97 (a) to 102 (f)
              if (hashValue & 0xf > 7 && uint8(buffer[i]) > 96) {
                  // case shift by xoring with 0x20
                  buffer[i] ^= 0x20;
              }
              hashValue >>= 4;
          }
          return string(buffer);
      }
  
      /**
       * @dev Returns true if the two strings are equal.
       */
      function equal(string memory a, string memory b) internal pure returns (bool) {
          return bytes(a).length == bytes(b).length && keccak256(bytes(a)) == keccak256(bytes(b));
      }
  }
  
  
  // File @openzeppelin/contracts/token/ERC721/ERC721.sol@v5.1.0
  
  // Original license: SPDX_License_Identifier: MIT
  // OpenZeppelin Contracts (last updated v5.1.0) (token/ERC721/ERC721.sol)
  
  pragma solidity ^0.8.20;
  
  
  
  
  
  
  
  /**
   * @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC-721] Non-Fungible Token Standard, including
   * the Metadata extension, but not including the Enumerable extension, which is available separately as
   * {ERC721Enumerable}.
   */
  abstract contract ERC721 is Context, ERC165, IERC721, IERC721Metadata, IERC721Errors {
      using Strings for uint256;
  
      // Token name
      string private _name;
  
      // Token symbol
      string private _symbol;
  
      mapping(uint256 tokenId => address) private _owners;
  
      mapping(address owner => uint256) private _balances;
  
      mapping(uint256 tokenId => address) private _tokenApprovals;
  
      mapping(address owner => mapping(address operator => bool)) private _operatorApprovals;
  
      /**
       * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.
       */
      constructor(string memory name_, string memory symbol_) {
          _name = name_;
          _symbol = symbol_;
      }
  
      /**
       * @dev See {IERC165-supportsInterface}.
       */
      function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {
          return
              interfaceId == type(IERC721).interfaceId ||
              interfaceId == type(IERC721Metadata).interfaceId ||
              super.supportsInterface(interfaceId);
      }
  
      /**
       * @dev See {IERC721-balanceOf}.
       */
      function balanceOf(address owner) public view virtual returns (uint256) {
          if (owner == address(0)) {
              revert ERC721InvalidOwner(address(0));
          }
          return _balances[owner];
      }
  
      /**
       * @dev See {IERC721-ownerOf}.
       */
      function ownerOf(uint256 tokenId) public view virtual returns (address) {
          return _requireOwned(tokenId);
      }
  
      /**
       * @dev See {IERC721Metadata-name}.
       */
      function name() public view virtual returns (string memory) {
          return _name;
      }
  
      /**
       * @dev See {IERC721Metadata-symbol}.
       */
      function symbol() public view virtual returns (string memory) {
          return _symbol;
      }
  
      /**
       * @dev See {IERC721Metadata-tokenURI}.
       */
      function tokenURI(uint256 tokenId) public view virtual returns (string memory) {
          _requireOwned(tokenId);
  
          string memory baseURI = _baseURI();
          return bytes(baseURI).length > 0 ? string.concat(baseURI, tokenId.toString()) : "";
      }
  
      /**
       * @dev Base URI for computing {tokenURI}. If set, the resulting URI for each
       * token will be the concatenation of the `baseURI` and the `tokenId`. Empty
       * by default, can be overridden in child contracts.
       */
      function _baseURI() internal view virtual returns (string memory) {
          return "";
      }
  
      /**
       * @dev See {IERC721-approve}.
       */
      function approve(address to, uint256 tokenId) public virtual {
          _approve(to, tokenId, _msgSender());
      }
  
      /**
       * @dev See {IERC721-getApproved}.
       */
      function getApproved(uint256 tokenId) public view virtual returns (address) {
          _requireOwned(tokenId);
  
          return _getApproved(tokenId);
      }
  
      /**
       * @dev See {IERC721-setApprovalForAll}.
       */
      function setApprovalForAll(address operator, bool approved) public virtual {
          _setApprovalForAll(_msgSender(), operator, approved);
      }
  
      /**
       * @dev See {IERC721-isApprovedForAll}.
       */
      function isApprovedForAll(address owner, address operator) public view virtual returns (bool) {
          return _operatorApprovals[owner][operator];
      }
  
      /**
       * @dev See {IERC721-transferFrom}.
       */
      function transferFrom(address from, address to, uint256 tokenId) public virtual {
          if (to == address(0)) {
              revert ERC721InvalidReceiver(address(0));
          }
          // Setting an "auth" arguments enables the `_isAuthorized` check which verifies that the token exists
          // (from != 0). Therefore, it is not needed to verify that the return value is not 0 here.
          address previousOwner = _update(to, tokenId, _msgSender());
          if (previousOwner != from) {
              revert ERC721IncorrectOwner(from, tokenId, previousOwner);
          }
      }
  
      /**
       * @dev See {IERC721-safeTransferFrom}.
       */
      function safeTransferFrom(address from, address to, uint256 tokenId) public {
          safeTransferFrom(from, to, tokenId, "");
      }
  
      /**
       * @dev See {IERC721-safeTransferFrom}.
       */
      function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory data) public virtual {
          transferFrom(from, to, tokenId);
          ERC721Utils.checkOnERC721Received(_msgSender(), from, to, tokenId, data);
      }
  
      /**
       * @dev Returns the owner of the `tokenId`. Does NOT revert if token doesn't exist
       *
       * IMPORTANT: Any overrides to this function that add ownership of tokens not tracked by the
       * core ERC-721 logic MUST be matched with the use of {_increaseBalance} to keep balances
       * consistent with ownership. The invariant to preserve is that for any address `a` the value returned by
       * `balanceOf(a)` must be equal to the number of tokens such that `_ownerOf(tokenId)` is `a`.
       */
      function _ownerOf(uint256 tokenId) internal view virtual returns (address) {
          return _owners[tokenId];
      }
  
      /**
       * @dev Returns the approved address for `tokenId`. Returns 0 if `tokenId` is not minted.
       */
      function _getApproved(uint256 tokenId) internal view virtual returns (address) {
          return _tokenApprovals[tokenId];
      }
  
      /**
       * @dev Returns whether `spender` is allowed to manage `owner`'s tokens, or `tokenId` in
       * particular (ignoring whether it is owned by `owner`).
       *
       * WARNING: This function assumes that `owner` is the actual owner of `tokenId` and does not verify this
       * assumption.
       */
      function _isAuthorized(address owner, address spender, uint256 tokenId) internal view virtual returns (bool) {
          return
              spender != address(0) &&
              (owner == spender || isApprovedForAll(owner, spender) || _getApproved(tokenId) == spender);
      }
  
      /**
       * @dev Checks if `spender` can operate on `tokenId`, assuming the provided `owner` is the actual owner.
       * Reverts if:
       * - `spender` does not have approval from `owner` for `tokenId`.
       * - `spender` does not have approval to manage all of `owner`'s assets.
       *
       * WARNING: This function assumes that `owner` is the actual owner of `tokenId` and does not verify this
       * assumption.
       */
      function _checkAuthorized(address owner, address spender, uint256 tokenId) internal view virtual {
          if (!_isAuthorized(owner, spender, tokenId)) {
              if (owner == address(0)) {
                  revert ERC721NonexistentToken(tokenId);
              } else {
                  revert ERC721InsufficientApproval(spender, tokenId);
              }
          }
      }
  
      /**
       * @dev Unsafe write access to the balances, used by extensions that "mint" tokens using an {ownerOf} override.
       *
       * NOTE: the value is limited to type(uint128).max. This protect against _balance overflow. It is unrealistic that
       * a uint256 would ever overflow from increments when these increments are bounded to uint128 values.
       *
       * WARNING: Increasing an account's balance using this function tends to be paired with an override of the
       * {_ownerOf} function to resolve the ownership of the corresponding tokens so that balances and ownership
       * remain consistent with one another.
       */
      function _increaseBalance(address account, uint128 value) internal virtual {
          unchecked {
              _balances[account] += value;
          }
      }
  
      /**
       * @dev Transfers `tokenId` from its current owner to `to`, or alternatively mints (or burns) if the current owner
       * (or `to`) is the zero address. Returns the owner of the `tokenId` before the update.
       *
       * The `auth` argument is optional. If the value passed is non 0, then this function will check that
       * `auth` is either the owner of the token, or approved to operate on the token (by the owner).
       *
       * Emits a {Transfer} event.
       *
       * NOTE: If overriding this function in a way that tracks balances, see also {_increaseBalance}.
       */
      function _update(address to, uint256 tokenId, address auth) internal virtual returns (address) {
          address from = _ownerOf(tokenId);
  
          // Perform (optional) operator check
          if (auth != address(0)) {
              _checkAuthorized(from, auth, tokenId);
          }
  
          // Execute the update
          if (from != address(0)) {
              // Clear approval. No need to re-authorize or emit the Approval event
              _approve(address(0), tokenId, address(0), false);
  
              unchecked {
                  _balances[from] -= 1;
              }
          }
  
          if (to != address(0)) {
              unchecked {
                  _balances[to] += 1;
              }
          }
  
          _owners[tokenId] = to;
  
          emit Transfer(from, to, tokenId);
  
          return from;
      }
  
      /**
       * @dev Mints `tokenId` and transfers it to `to`.
       *
       * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible
       *
       * Requirements:
       *
       * - `tokenId` must not exist.
       * - `to` cannot be the zero address.
       *
       * Emits a {Transfer} event.
       */
      function _mint(address to, uint256 tokenId) internal {
          if (to == address(0)) {
              revert ERC721InvalidReceiver(address(0));
          }
          address previousOwner = _update(to, tokenId, address(0));
          if (previousOwner != address(0)) {
              revert ERC721InvalidSender(address(0));
          }
      }
  
      /**
       * @dev Mints `tokenId`, transfers it to `to` and checks for `to` acceptance.
       *
       * Requirements:
       *
       * - `tokenId` must not exist.
       * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
       *
       * Emits a {Transfer} event.
       */
      function _safeMint(address to, uint256 tokenId) internal {
          _safeMint(to, tokenId, "");
      }
  
      /**
       * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is
       * forwarded in {IERC721Receiver-onERC721Received} to contract recipients.
       */
      function _safeMint(address to, uint256 tokenId, bytes memory data) internal virtual {
          _mint(to, tokenId);
          ERC721Utils.checkOnERC721Received(_msgSender(), address(0), to, tokenId, data);
      }
  
      /**
       * @dev Destroys `tokenId`.
       * The approval is cleared when the token is burned.
       * This is an internal function that does not check if the sender is authorized to operate on the token.
       *
       * Requirements:
       *
       * - `tokenId` must exist.
       *
       * Emits a {Transfer} event.
       */
      function _burn(uint256 tokenId) internal {
          address previousOwner = _update(address(0), tokenId, address(0));
          if (previousOwner == address(0)) {
              revert ERC721NonexistentToken(tokenId);
          }
      }
  
      /**
       * @dev Transfers `tokenId` from `from` to `to`.
       *  As opposed to {transferFrom}, this imposes no restrictions on msg.sender.
       *
       * Requirements:
       *
       * - `to` cannot be the zero address.
       * - `tokenId` token must be owned by `from`.
       *
       * Emits a {Transfer} event.
       */
      function _transfer(address from, address to, uint256 tokenId) internal {
          if (to == address(0)) {
              revert ERC721InvalidReceiver(address(0));
          }
          address previousOwner = _update(to, tokenId, address(0));
          if (previousOwner == address(0)) {
              revert ERC721NonexistentToken(tokenId);
          } else if (previousOwner != from) {
              revert ERC721IncorrectOwner(from, tokenId, previousOwner);
          }
      }
  
      /**
       * @dev Safely transfers `tokenId` token from `from` to `to`, checking that contract recipients
       * are aware of the ERC-721 standard to prevent tokens from being forever locked.
       *
       * `data` is additional data, it has no specified format and it is sent in call to `to`.
       *
       * This internal function is like {safeTransferFrom} in the sense that it invokes
       * {IERC721Receiver-onERC721Received} on the receiver, and can be used to e.g.
       * implement alternative mechanisms to perform token transfer, such as signature-based.
       *
       * Requirements:
       *
       * - `tokenId` token must exist and be owned by `from`.
       * - `to` cannot be the zero address.
       * - `from` cannot be the zero address.
       * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
       *
       * Emits a {Transfer} event.
       */
      function _safeTransfer(address from, address to, uint256 tokenId) internal {
          _safeTransfer(from, to, tokenId, "");
      }
  
      /**
       * @dev Same as {xref-ERC721-_safeTransfer-address-address-uint256-}[`_safeTransfer`], with an additional `data` parameter which is
       * forwarded in {IERC721Receiver-onERC721Received} to contract recipients.
       */
      function _safeTransfer(address from, address to, uint256 tokenId, bytes memory data) internal virtual {
          _transfer(from, to, tokenId);
          ERC721Utils.checkOnERC721Received(_msgSender(), from, to, tokenId, data);
      }
  
      /**
       * @dev Approve `to` to operate on `tokenId`
       *
       * The `auth` argument is optional. If the value passed is non 0, then this function will check that `auth` is
       * either the owner of the token, or approved to operate on all tokens held by this owner.
       *
       * Emits an {Approval} event.
       *
       * Overrides to this logic should be done to the variant with an additional `bool emitEvent` argument.
       */
      function _approve(address to, uint256 tokenId, address auth) internal {
          _approve(to, tokenId, auth, true);
      }
  
      /**
       * @dev Variant of `_approve` with an optional flag to enable or disable the {Approval} event. The event is not
       * emitted in the context of transfers.
       */
      function _approve(address to, uint256 tokenId, address auth, bool emitEvent) internal virtual {
          // Avoid reading the owner unless necessary
          if (emitEvent || auth != address(0)) {
              address owner = _requireOwned(tokenId);
  
              // We do not use _isAuthorized because single-token approvals should not be able to call approve
              if (auth != address(0) && owner != auth && !isApprovedForAll(owner, auth)) {
                  revert ERC721InvalidApprover(auth);
              }
  
              if (emitEvent) {
                  emit Approval(owner, to, tokenId);
              }
          }
  
          _tokenApprovals[tokenId] = to;
      }
  
      /**
       * @dev Approve `operator` to operate on all of `owner` tokens
       *
       * Requirements:
       * - operator can't be the address zero.
       *
       * Emits an {ApprovalForAll} event.
       */
      function _setApprovalForAll(address owner, address operator, bool approved) internal virtual {
          if (operator == address(0)) {
              revert ERC721InvalidOperator(operator);
          }
          _operatorApprovals[owner][operator] = approved;
          emit ApprovalForAll(owner, operator, approved);
      }
  
      /**
       * @dev Reverts if the `tokenId` doesn't have a current owner (it hasn't been minted, or it has been burned).
       * Returns the owner.
       *
       * Overrides to ownership logic should be done to {_ownerOf}.
       */
      function _requireOwned(uint256 tokenId) internal view returns (address) {
          address owner = _ownerOf(tokenId);
          if (owner == address(0)) {
              revert ERC721NonexistentToken(tokenId);
          }
          return owner;
      }
  }
  
  
  // File @pythnetwork/pyth-sdk-solidity/IPythEvents.sol@v4.0.0
  
  // Original license: SPDX_License_Identifier: Apache-2.0
  pragma solidity ^0.8.0;
  
  /// @title IPythEvents contains the events that Pyth contract emits.
  /// @dev This interface can be used for listening to the updates for off-chain and testing purposes.
  interface IPythEvents {
      /// @dev Emitted when the price feed with `id` has received a fresh update.
      /// @param id The Pyth Price Feed ID.
      /// @param publishTime Publish time of the given price update.
      /// @param price Price of the given price update.
      /// @param conf Confidence interval of the given price update.
      event PriceFeedUpdate(
          bytes32 indexed id,
          uint64 publishTime,
          int64 price,
          uint64 conf
      );
  }
  
  
  // File @pythnetwork/pyth-sdk-solidity/PythStructs.sol@v4.0.0
  
  // Original license: SPDX_License_Identifier: Apache-2.0
  pragma solidity ^0.8.0;
  
  contract PythStructs {
      // A price with a degree of uncertainty, represented as a price +- a confidence interval.
      //
      // The confidence interval roughly corresponds to the standard error of a normal distribution.
      // Both the price and confidence are stored in a fixed-point numeric representation,
      // `x * (10^expo)`, where `expo` is the exponent.
      //
      // Please refer to the documentation at https://docs.pyth.network/documentation/pythnet-price-feeds/best-practices for how
      // to how this price safely.
      struct Price {
          // Price
          int64 price;
          // Confidence interval around the price
          uint64 conf;
          // Price exponent
          int32 expo;
          // Unix timestamp describing when the price was published
          uint publishTime;
      }
  
      // PriceFeed represents a current aggregate price from pyth publisher feeds.
      struct PriceFeed {
          // The price ID.
          bytes32 id;
          // Latest available price
          Price price;
          // Latest available exponentially-weighted moving average price
          Price emaPrice;
      }
  }
  
  
  // File @pythnetwork/pyth-sdk-solidity/IPyth.sol@v4.0.0
  
  // Original license: SPDX_License_Identifier: Apache-2.0
  pragma solidity ^0.8.0;
  
  
  /// @title Consume prices from the Pyth Network (https://pyth.network/).
  /// @dev Please refer to the guidance at https://docs.pyth.network/documentation/pythnet-price-feeds/best-practices for how to consume prices safely.
  /// @author Pyth Data Association
  interface IPyth is IPythEvents {
      /// @notice Returns the price of a price feed without any sanity checks.
      /// @dev This function returns the most recent price update in this contract without any recency checks.
      /// This function is unsafe as the returned price update may be arbitrarily far in the past.
      ///
      /// Users of this function should check the `publishTime` in the price to ensure that the returned price is
      /// sufficiently recent for their application. If you are considering using this function, it may be
      /// safer / easier to use `getPriceNoOlderThan`.
      /// @return price - please read the documentation of PythStructs.Price to understand how to use this safely.
      function getPriceUnsafe(
          bytes32 id
      ) external view returns (PythStructs.Price memory price);
  
      /// @notice Returns the price that is no older than `age` seconds of the current time.
      /// @dev This function is a sanity-checked version of `getPriceUnsafe` which is useful in
      /// applications that require a sufficiently-recent price. Reverts if the price wasn't updated sufficiently
      /// recently.
      /// @return price - please read the documentation of PythStructs.Price to understand how to use this safely.
      function getPriceNoOlderThan(
          bytes32 id,
          uint age
      ) external view returns (PythStructs.Price memory price);
  
      /// @notice Returns the exponentially-weighted moving average price of a price feed without any sanity checks.
      /// @dev This function returns the same price as `getEmaPrice` in the case where the price is available.
      /// However, if the price is not recent this function returns the latest available price.
      ///
      /// The returned price can be from arbitrarily far in the past; this function makes no guarantees that
      /// the returned price is recent or useful for any particular application.
      ///
      /// Users of this function should check the `publishTime` in the price to ensure that the returned price is
      /// sufficiently recent for their application. If you are considering using this function, it may be
      /// safer / easier to use either `getEmaPrice` or `getEmaPriceNoOlderThan`.
      /// @return price - please read the documentation of PythStructs.Price to understand how to use this safely.
      function getEmaPriceUnsafe(
          bytes32 id
      ) external view returns (PythStructs.Price memory price);
  
      /// @notice Returns the exponentially-weighted moving average price that is no older than `age` seconds
      /// of the current time.
      /// @dev This function is a sanity-checked version of `getEmaPriceUnsafe` which is useful in
      /// applications that require a sufficiently-recent price. Reverts if the price wasn't updated sufficiently
      /// recently.
      /// @return price - please read the documentation of PythStructs.Price to understand how to use this safely.
      function getEmaPriceNoOlderThan(
          bytes32 id,
          uint age
      ) external view returns (PythStructs.Price memory price);
  
      /// @notice Update price feeds with given update messages.
      /// This method requires the caller to pay a fee in wei; the required fee can be computed by calling
      /// `getUpdateFee` with the length of the `updateData` array.
      /// Prices will be updated if they are more recent than the current stored prices.
      /// The call will succeed even if the update is not the most recent.
      /// @dev Reverts if the transferred fee is not sufficient or the updateData is invalid.
      /// @param updateData Array of price update data.
      function updatePriceFeeds(bytes[] calldata updateData) external payable;
  
      /// @notice Wrapper around updatePriceFeeds that rejects fast if a price update is not necessary. A price update is
      /// necessary if the current on-chain publishTime is older than the given publishTime. It relies solely on the
      /// given `publishTimes` for the price feeds and does not read the actual price update publish time within `updateData`.
      ///
      /// This method requires the caller to pay a fee in wei; the required fee can be computed by calling
      /// `getUpdateFee` with the length of the `updateData` array.
      ///
      /// `priceIds` and `publishTimes` are two arrays with the same size that correspond to senders known publishTime
      /// of each priceId when calling this method. If all of price feeds within `priceIds` have updated and have
      /// a newer or equal publish time than the given publish time, it will reject the transaction to save gas.
      /// Otherwise, it calls updatePriceFeeds method to update the prices.
      ///
      /// @dev Reverts if update is not needed or the transferred fee is not sufficient or the updateData is invalid.
      /// @param updateData Array of price update data.
      /// @param priceIds Array of price ids.
      /// @param publishTimes Array of publishTimes. `publishTimes[i]` corresponds to known `publishTime` of `priceIds[i]`
      function updatePriceFeedsIfNecessary(
          bytes[] calldata updateData,
          bytes32[] calldata priceIds,
          uint64[] calldata publishTimes
      ) external payable;
  
      /// @notice Returns the required fee to update an array of price updates.
      /// @param updateData Array of price update data.
      /// @return feeAmount The required fee in Wei.
      function getUpdateFee(
          bytes[] calldata updateData
      ) external view returns (uint feeAmount);
  
      /// @notice Parse `updateData` and return price feeds of the given `priceIds` if they are all published
      /// within `minPublishTime` and `maxPublishTime`.
      ///
      /// You can use this method if you want to use a Pyth price at a fixed time and not the most recent price;
      /// otherwise, please consider using `updatePriceFeeds`. This method may store the price updates on-chain, if they
      /// are more recent than the current stored prices.
      ///
      /// This method requires the caller to pay a fee in wei; the required fee can be computed by calling
      /// `getUpdateFee` with the length of the `updateData` array.
      ///
      ///
      /// @dev Reverts if the transferred fee is not sufficient or the updateData is invalid or there is
      /// no update for any of the given `priceIds` within the given time range.
      /// @param updateData Array of price update data.
      /// @param priceIds Array of price ids.
      /// @param minPublishTime minimum acceptable publishTime for the given `priceIds`.
      /// @param maxPublishTime maximum acceptable publishTime for the given `priceIds`.
      /// @return priceFeeds Array of the price feeds corresponding to the given `priceIds` (with the same order).
      function parsePriceFeedUpdates(
          bytes[] calldata updateData,
          bytes32[] calldata priceIds,
          uint64 minPublishTime,
          uint64 maxPublishTime
      ) external payable returns (PythStructs.PriceFeed[] memory priceFeeds);
  
      /// @notice Similar to `parsePriceFeedUpdates` but ensures the updates returned are
      /// the first updates published in minPublishTime. That is, if there are multiple updates for a given timestamp,
      /// this method will return the first update. This method may store the price updates on-chain, if they
      /// are more recent than the current stored prices.
      ///
      ///
      /// @dev Reverts if the transferred fee is not sufficient or the updateData is invalid or there is
      /// no update for any of the given `priceIds` within the given time range and uniqueness condition.
      /// @param updateData Array of price update data.
      /// @param priceIds Array of price ids.
      /// @param minPublishTime minimum acceptable publishTime for the given `priceIds`.
      /// @param maxPublishTime maximum acceptable publishTime for the given `priceIds`.
      /// @return priceFeeds Array of the price feeds corresponding to the given `priceIds` (with the same order).
      function parsePriceFeedUpdatesUnique(
          bytes[] calldata updateData,
          bytes32[] calldata priceIds,
          uint64 minPublishTime,
          uint64 maxPublishTime
      ) external payable returns (PythStructs.PriceFeed[] memory priceFeeds);
  }
  
  
  // File contracts/main-contracts/KingdomlyFeeContract.sol
  
  // Original license: SPDX_License_Identifier: UNLICENSED
  pragma solidity ^0.8.24;
  
  
  error InsufficientUpdateFee(uint256 requiredFee);
  error ContractNotVerified(address contractAddress);
  
  contract KingdomlyFeeContract is Ownable {
      uint256 private cachedOneDollarInWei;
      uint256 private maxPriceAgeInSeconds;
  
      IPyth pyth;
      bytes32 ethUsdPriceId;
  
      constructor(address _pyth, bytes32 _ethUsdPriceId) Ownable(msg.sender) {
          pyth = IPyth(_pyth);
          ethUsdPriceId = _ethUsdPriceId;
          maxPriceAgeInSeconds = 60 * 60 * 24;
      }
  
      function getOneDollarInWei() public view returns (uint256) {
          try pyth.getPriceNoOlderThan(ethUsdPriceId, maxPriceAgeInSeconds) returns (PythStructs.Price memory price) {
              uint256 ethPrice18Decimals =
                  (uint256(uint64(price.price)) * (10 ** 18)) / (10 ** uint8(uint32(-1 * price.expo)));
              uint256 oneDollarInWei = ((10 ** 18) * (10 ** 18)) / ethPrice18Decimals;
  
              return oneDollarInWei;
          } catch {
              return cachedOneDollarInWei;
          }
      }
  
      function updateOracleAndGetOneDollarInWei(bytes[] calldata pythPriceUpdate) public payable returns (uint256) {
          uint256 updateFee = pyth.getUpdateFee(pythPriceUpdate);
  
          if (msg.value != updateFee) {
              revert InsufficientUpdateFee(updateFee);
          }
  
          pyth.updatePriceFeeds{value: msg.value}(pythPriceUpdate);
  
          cachedOneDollarInWei = getOneDollarInWei();
  
          return cachedOneDollarInWei;
      }
  
      function updateMaxPriceAgeInSeconds(uint256 _maxPriceAgeInSeconds) public onlyOwner {
          maxPriceAgeInSeconds = _maxPriceAgeInSeconds;
      }
  }
  
  
  // File contracts/main-contracts/Bera_Capsule.sol
  
  // Original license: SPDX_License_Identifier: MIT
  
  pragma solidity ^0.8.24;
  
  
  
  
  
  contract Bera_Capsule is ONFT721Core, ERC721 {
      // ########## EVENTS ##########
      event KingdomlyFeeContractChanged(address feeContractAddress);
  
      event BatchMetadataUpdate(uint256 indexed fromTokenId, uint256 indexed toTokenId);
  
      // ########## ERRORS ##########
  
      error UnauthorizedAccess();
      error MaxBatchSendSizeExceeded(uint256 maxBatchSendSize);
      error InvalidBatchSendSize(uint256 batchSendSize);
      error InsufficientBatchSendFee();
      error InvalidKingdomlyFeeContract();
  
      string public baseURI;
  
      //Bridge variables
      KingdomlyFeeContract public kingdomlyFeeContract;
      address public kingdomlyAdmin;
  
      uint256 public immutable bridgeFeeInCents;
  
      constructor(
          string memory _name,
          string memory _symbol,
          string memory _initialBaseURI,
          address _lzEndpoint,
          address _kingdomlyAdmin,
          KingdomlyFeeContract _kingdomlyFeeContract
      )
          ERC721(_name, _symbol)
          ONFT721Core(_lzEndpoint, msg.sender) // Deployer of the Contract will be the delegate
      {
          baseURI = _initialBaseURI;
  
          //Bridge variables
          kingdomlyAdmin = _kingdomlyAdmin;
          kingdomlyFeeContract = _kingdomlyFeeContract;
  
          bridgeFeeInCents = 0; // $0 * 100 = 0
      }
  
      // ###################### Modifiers ######################
  
      /**
       * @dev Ensures the caller is the Kingdomly Admin.
       */
      modifier isKingdomlyAdmin() {
          if (msg.sender != kingdomlyAdmin) {
              revert UnauthorizedAccess();
          }
  
          _;
      }
  
      function setBaseURI(string memory newBaseURI) external onlyOwner {
          baseURI = newBaseURI;
          emit BatchMetadataUpdate(1, type(uint256).max); // Signal that all token metadata has been updated
      }
  
      function _baseURI() internal view override(ERC721) returns (string memory) {
          return baseURI;
      }
  
      /**
       * @notice Retrieves the address of the underlying ERC721 implementation (ie. this contract).
       */
      function token() external view returns (address) {
          return address(this);
      }
  
      /**
       * @notice Indicates whether the ONFT721 contract requires approval of the 'token()' to send.
       * @dev In the case of ONFT where the contract IS the token, approval is NOT required.
       * @return requiresApproval Needs approval of the underlying token implementation.
       */
      function approvalRequired() external pure virtual returns (bool) {
          return false;
      }
  
      function _debit(address _from, uint256 _tokenId, uint32 /*_dstEid*/ ) internal virtual override {
          if (_from != ERC721.ownerOf(_tokenId)) {
              revert OnlyNFTOwner(_from, ERC721.ownerOf(_tokenId));
          }
          _burn(_tokenId);
      }
  
      function _credit(address _to, uint256 _tokenId, uint32 /*_srcEid*/ ) internal virtual override {
          _mint(_to, _tokenId);
      }
  
      //===================================START Bridge Functions===================================//
  
      function quoteSend(SendParam calldata _sendParam, bool _payInLzToken)
          public
          view
          override
          returns (MessagingFee memory msgFee)
      {
          (bytes memory message, bytes memory options) = _buildMsgAndOptions(_sendParam);
  
          MessagingFee memory _lzFee = _quote(_sendParam.dstEid, message, options, _payInLzToken);
  
          uint256 bridgeNativeFee = getBridgeNativeFee();
  
          return MessagingFee({nativeFee: _lzFee.nativeFee + bridgeNativeFee, lzTokenFee: _lzFee.lzTokenFee});
      }
  
      function send(SendParam calldata _sendParam, MessagingFee calldata _fee, address _refundAddress)
          external
          payable
          override(ONFT721Core)
          returns (MessagingReceipt memory msgReceipt)
      {
          _debit(msg.sender, _sendParam.tokenId, _sendParam.dstEid);
  
          (bytes memory message, bytes memory options) = _buildMsgAndOptions(_sendParam);
  
          // @dev Sends the message to the LayerZero Endpoint, returning the MessagingReceipt.
          msgReceipt = _lzSend(
              _sendParam.dstEid,
              message,
              options,
              _fee,
              kingdomlyAdmin // Admin becomes the refund Address
          );
          emit ONFTSent(msgReceipt.guid, _sendParam.dstEid, msg.sender, _sendParam.tokenId);
      }
  
      function _lzSendBatch(
          uint32 _dstEid,
          bytes memory _message,
          bytes memory _options,
          MessagingFee memory _fee,
          address _refundAddress
      ) internal virtual returns (MessagingReceipt memory receipt) {
          // @dev We remove the _payNative check because the main check is already done in the batchSend function.
          uint256 messageValue = _fee.nativeFee;
          if (_fee.lzTokenFee > 0) _payLzToken(_fee.lzTokenFee);
  
          return endpoint.send{value: messageValue}(
              // solhint-disable-next-line check-send-result
              MessagingParams(_dstEid, _getPeerOrRevert(_dstEid), _message, _options, _fee.lzTokenFee > 0),
              _refundAddress
          );
      }
  
      function quoteBatchSend(SendParam[] calldata _sendParams, bool _payInLzToken)
          public
          view
          returns (MessagingFee memory totalBatchMsgFee, MessagingFee[] memory msgFees)
      {
          if (_sendParams.length > 300) revert MaxBatchSendSizeExceeded(300);
          if (_sendParams.length == 0) revert InvalidBatchSendSize(0);
  
          uint256 totalNativeFee = 0;
          uint256 totalLzTokenFee = 0;
  
          MessagingFee[] memory _msgFees = new MessagingFee[](_sendParams.length);
  
          for (uint256 i = 0; i < _sendParams.length;) {
              MessagingFee memory fees = quoteSend(_sendParams[i], _payInLzToken);
              totalNativeFee += fees.nativeFee;
              totalLzTokenFee += fees.lzTokenFee;
              _msgFees[i] = fees;
              unchecked {
                  i++;
              }
          }
          return (MessagingFee({nativeFee: totalNativeFee, lzTokenFee: totalLzTokenFee}), _msgFees);
      }
  
      function batchSend(
          SendParam[] calldata _sendParams,
          MessagingFee calldata _fee,
          address _refundAddress,
          bool _payInLzToken
      ) external payable {
          uint256 sendParamsLength = _sendParams.length;
  
          if (sendParamsLength > 100) revert MaxBatchSendSizeExceeded(100);
          if (sendParamsLength == 0) revert InvalidBatchSendSize(0);
  
          (MessagingFee memory totalBatchMsgFee, MessagingFee[] memory msgFees) =
              quoteBatchSend(_sendParams, _payInLzToken);
  
          if (_fee.nativeFee != totalBatchMsgFee.nativeFee || _fee.lzTokenFee != totalBatchMsgFee.lzTokenFee) {
              revert InsufficientBatchSendFee();
          }
  
          if (msg.value != totalBatchMsgFee.nativeFee) {
              revert InsufficientBatchSendFee();
          }
  
          for (uint256 i = 0; i < sendParamsLength; i++) {
              _debit(msg.sender, _sendParams[i].tokenId, _sendParams[i].dstEid);
  
              (bytes memory message, bytes memory options) = _buildMsgAndOptions(_sendParams[i]);
  
              // @dev Sends the message to the LayerZero Endpoint, returning the MessagingReceipt.
              MessagingReceipt memory msgReceipt = _lzSendBatch(
                  _sendParams[i].dstEid,
                  message,
                  options,
                  msgFees[i],
                  kingdomlyAdmin // Admin becomes the refund Address
              );
  
              emit ONFTSent(msgReceipt.guid, _sendParams[i].dstEid, msg.sender, _sendParams[i].tokenId);
          }
      }
  
      function hasPeer(uint32 _eid) public view returns (bool) {
          bytes32 peer = peers[_eid];
          if (peer == bytes32(0)) return false;
  
          return true;
      }
  
      //===================================END Bridge Functions===================================//
  
      // ###################### Kingdomly Admin Functions ######################
  
      function setNewKingdomlyFeeContract(KingdomlyFeeContract _kingdomlyFeeContract) external isKingdomlyAdmin {
          if (address(_kingdomlyFeeContract) == address(0)) {
              revert InvalidKingdomlyFeeContract();
          }
  
          kingdomlyFeeContract = _kingdomlyFeeContract;
  
          emit KingdomlyFeeContractChanged(address(_kingdomlyFeeContract));
      }
  
      function getKingdomlyFeeContract() external view returns (KingdomlyFeeContract) {
          return kingdomlyFeeContract;
      }
  
      // ###################### Fee Functions ######################
  
      function getOneDollarInWei() internal view returns (uint256) {
          return kingdomlyFeeContract.getOneDollarInWei();
      }
  
      function getBridgeNativeFee() public view returns (uint256) {
          return (getOneDollarInWei() * bridgeFeeInCents) / 100;
      }
  }
  
设置
{
  "compilationTarget": {
    "Bera_Capsule.sol": "Bera_Capsule"
  },
  "evmVersion": "shanghai",
  "libraries": {},
  "metadata": {
    "bytecodeHash": "ipfs"
  },
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "remappings": []
}
ABI
[{"inputs":[{"internalType":"string","name":"_name","type":"string"},{"internalType":"string","name":"_symbol","type":"string"},{"internalType":"string","name":"_initialBaseURI","type":"string"},{"internalType":"address","name":"_lzEndpoint","type":"address"},{"internalType":"address","name":"_kingdomlyAdmin","type":"address"},{"internalType":"contract KingdomlyFeeContract","name":"_kingdomlyFeeContract","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"owner","type":"address"}],"name":"ERC721IncorrectOwner","type":"error"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ERC721InsufficientApproval","type":"error"},{"inputs":[{"internalType":"address","name":"approver","type":"address"}],"name":"ERC721InvalidApprover","type":"error"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"ERC721InvalidOperator","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"ERC721InvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC721InvalidReceiver","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"ERC721InvalidSender","type":"error"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ERC721NonexistentToken","type":"error"},{"inputs":[],"name":"InsufficientBatchSendFee","type":"error"},{"inputs":[{"internalType":"uint256","name":"batchSendSize","type":"uint256"}],"name":"InvalidBatchSendSize","type":"error"},{"inputs":[],"name":"InvalidDelegate","type":"error"},{"inputs":[],"name":"InvalidEndpointCall","type":"error"},{"inputs":[],"name":"InvalidKingdomlyFeeContract","type":"error"},{"inputs":[{"internalType":"bytes","name":"options","type":"bytes"}],"name":"InvalidOptions","type":"error"},{"inputs":[],"name":"InvalidReceiver","type":"error"},{"inputs":[],"name":"LzTokenUnavailable","type":"error"},{"inputs":[{"internalType":"uint256","name":"maxBatchSendSize","type":"uint256"}],"name":"MaxBatchSendSizeExceeded","type":"error"},{"inputs":[{"internalType":"uint32","name":"eid","type":"uint32"}],"name":"NoPeer","type":"error"},{"inputs":[{"internalType":"uint256","name":"msgValue","type":"uint256"}],"name":"NotEnoughNative","type":"error"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"OnlyEndpoint","type":"error"},{"inputs":[{"internalType":"address","name":"caller","type":"address"},{"internalType":"address","name":"owner","type":"address"}],"name":"OnlyNFTOwner","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":[],"name":"UnauthorizedAccess","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"fromTokenId","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"toTokenId","type":"uint256"}],"name":"BatchMetadataUpdate","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":"feeContractAddress","type":"address"}],"name":"KingdomlyFeeContractChanged","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":"tokenId","type":"uint256"}],"name":"ONFTReceived","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":"tokenId","type":"uint256"}],"name":"ONFTSent","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":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"SEND","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SEND_AND_COMPOSE","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint32","name":"srcEid","type":"uint32"},{"internalType":"bytes32","name":"sender","type":"bytes32"},{"internalType":"uint64","name":"nonce","type":"uint64"}],"internalType":"struct Origin","name":"origin","type":"tuple"}],"name":"allowInitializePath","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"approvalRequired","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint32","name":"dstEid","type":"uint32"},{"internalType":"bytes32","name":"to","type":"bytes32"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"extraOptions","type":"bytes"},{"internalType":"bytes","name":"composeMsg","type":"bytes"},{"internalType":"bytes","name":"onftCmd","type":"bytes"}],"internalType":"struct SendParam[]","name":"_sendParams","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"},{"internalType":"bool","name":"_payInLzToken","type":"bool"}],"name":"batchSend","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"bridgeFeeInCents","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":"endpoint","outputs":[{"internalType":"contract ILayerZeroEndpointV2","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"eid","type":"uint32"},{"internalType":"uint16","name":"msgType","type":"uint16"}],"name":"enforcedOptions","outputs":[{"internalType":"bytes","name":"enforcedOption","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getBridgeNativeFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getKingdomlyFeeContract","outputs":[{"internalType":"contract KingdomlyFeeContract","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"_eid","type":"uint32"}],"name":"hasPeer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"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":[],"name":"kingdomlyAdmin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"kingdomlyFeeContract","outputs":[{"internalType":"contract KingdomlyFeeContract","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint32","name":"srcEid","type":"uint32"},{"internalType":"bytes32","name":"sender","type":"bytes32"},{"internalType":"uint64","name":"nonce","type":"uint64"}],"internalType":"struct Origin","name":"_origin","type":"tuple"},{"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":"onftVersion","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":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"eid","type":"uint32"}],"name":"peers","outputs":[{"internalType":"bytes32","name":"peer","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"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":"tokenId","type":"uint256"},{"internalType":"bytes","name":"extraOptions","type":"bytes"},{"internalType":"bytes","name":"composeMsg","type":"bytes"},{"internalType":"bytes","name":"onftCmd","type":"bytes"}],"internalType":"struct SendParam[]","name":"_sendParams","type":"tuple[]"},{"internalType":"bool","name":"_payInLzToken","type":"bool"}],"name":"quoteBatchSend","outputs":[{"components":[{"internalType":"uint256","name":"nativeFee","type":"uint256"},{"internalType":"uint256","name":"lzTokenFee","type":"uint256"}],"internalType":"struct MessagingFee","name":"totalBatchMsgFee","type":"tuple"},{"components":[{"internalType":"uint256","name":"nativeFee","type":"uint256"},{"internalType":"uint256","name":"lzTokenFee","type":"uint256"}],"internalType":"struct MessagingFee[]","name":"msgFees","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint32","name":"dstEid","type":"uint32"},{"internalType":"bytes32","name":"to","type":"bytes32"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"extraOptions","type":"bytes"},{"internalType":"bytes","name":"composeMsg","type":"bytes"},{"internalType":"bytes","name":"onftCmd","type":"bytes"}],"internalType":"struct SendParam","name":"_sendParam","type":"tuple"},{"internalType":"bool","name":"_payInLzToken","type":"bool"}],"name":"quoteSend","outputs":[{"components":[{"internalType":"uint256","name":"nativeFee","type":"uint256"},{"internalType":"uint256","name":"lzTokenFee","type":"uint256"}],"internalType":"struct MessagingFee","name":"msgFee","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint32","name":"dstEid","type":"uint32"},{"internalType":"bytes32","name":"to","type":"bytes32"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"extraOptions","type":"bytes"},{"internalType":"bytes","name":"composeMsg","type":"bytes"},{"internalType":"bytes","name":"onftCmd","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"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"newBaseURI","type":"string"}],"name":"setBaseURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_delegate","type":"address"}],"name":"setDelegate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint32","name":"eid","type":"uint32"},{"internalType":"uint16","name":"msgType","type":"uint16"},{"internalType":"bytes","name":"options","type":"bytes"}],"internalType":"struct EnforcedOptionParam[]","name":"_enforcedOptions","type":"tuple[]"}],"name":"setEnforcedOptions","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_msgInspector","type":"address"}],"name":"setMsgInspector","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract KingdomlyFeeContract","name":"_kingdomlyFeeContract","type":"address"}],"name":"setNewKingdomlyFeeContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"_eid","type":"uint32"},{"internalType":"bytes32","name":"_peer","type":"bytes32"}],"name":"setPeer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_preCrime","type":"address"}],"name":"setPreCrime","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"token","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}]